Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ Usage of ./dnsproxy:
Disable secure TLS certificate validation.
--ipv6-disabled
If specified, all AAAA requests will be replied with NoError RCode and empty answer.
--ipv4-disabled
If specified, all A requests will be replied with NoError RCode and empty answer.
--listen=address/-l address
Listening addresses.
--max-go-routines=uint
Expand Down
9 changes: 9 additions & 0 deletions internal/cmd/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const (
verboseIdx
insecureIdx
ipv6DisabledIdx
ipv4DisabledIdx
http3Idx
cacheOptimisticIdx
cacheIdx
Expand Down Expand Up @@ -340,6 +341,13 @@ var commandLineOptions = []*commandLineOption{
short: "",
valueType: "",
},
ipv4DisabledIdx: {
description: "If specified, all A requests will be replied with NoError RCode and " +
"empty answer.",
long: "ipv4-disabled",
short: "",
valueType: "",
},
http3Idx: {
description: "Enable HTTP/3 support.",
long: "http3",
Expand Down Expand Up @@ -440,6 +448,7 @@ func parseCmdLineOptions(conf *configuration) (err error) {
verboseIdx: &conf.Verbose,
insecureIdx: &conf.Insecure,
ipv6DisabledIdx: &conf.IPv6Disabled,
ipv4DisabledIdx: &conf.IPv4Disabled,
http3Idx: &conf.HTTP3,
cacheOptimisticIdx: &conf.CacheOptimistic,
cacheIdx: &conf.Cache,
Expand Down
3 changes: 3 additions & 0 deletions internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ type configuration struct {
// IPv6Disabled makes the server to respond with NODATA to all AAAA queries.
IPv6Disabled bool `yaml:"ipv6-disabled"`

// IPv4Disabled makes the server to respond with NODATA to all A queries.
IPv4Disabled bool `yaml:"ipv4-disabled"`

// HTTP3 controls whether HTTP/3 is enabled for this instance of dnsproxy.
// It enables HTTP/3 support for both the DoH upstreams and the DoH server.
HTTP3 bool `yaml:"http3"`
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func createProxyConfig(
// TODO(e.burkov): Use the configured message constructor.
MessageConstructor: dnsmsg.DefaultMessageConstructor{},
HaltIPv6: conf.IPv6Disabled,
HaltIPv4: conf.IPv4Disabled,
HostsFiles: hosts,
})

Expand Down
10 changes: 10 additions & 0 deletions internal/handler/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ type DefaultConfig struct {
// HaltIPv6 halts the processing of AAAA requests and makes the handler
// reply with NODATA to them, if true.
HaltIPv6 bool

// HaltIPv4 halts the processing of A requests and makes the handler
// reply with NODATA to them.
HaltIPv4 bool
}

// Default implements the default configurable [proxy.RequestHandler].
Expand All @@ -31,6 +35,7 @@ type Default struct {
hosts hostsfile.Storage
logger *slog.Logger
isIPv6Halted bool
isIPv4Halted bool
}

// NewDefault creates a new [Default] handler.
Expand All @@ -45,6 +50,7 @@ func NewDefault(conf *DefaultConfig) (d *Default) {
return &Default{
logger: conf.Logger,
isIPv6Halted: conf.HaltIPv6,
isIPv4Halted: conf.HaltIPv4,
messages: mc,
hosts: conf.HostsFiles,
}
Expand All @@ -64,6 +70,10 @@ func (h *Default) HandleRequest(p *proxy.Proxy, proxyCtx *proxy.DNSContext) (err
return nil
}

if proxyCtx.Res = h.haltA(ctx, proxyCtx.Req); proxyCtx.Res != nil {
return nil
}

if proxyCtx.Res = h.resolveFromHosts(ctx, proxyCtx.Req); proxyCtx.Res != nil {
return nil
}
Expand Down
23 changes: 23 additions & 0 deletions internal/handler/ipv4halt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package handler

import (
"context"

"github.com/miekg/dns"
)

// haltA halts the processing of A requests if IPv4 is disabled. req must
// not be nil.
func (h *Default) haltA(ctx context.Context, req *dns.Msg) (resp *dns.Msg) {
if h.isIPv4Halted && req.Question[0].Qtype == dns.TypeA {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code could panic if req.Question is empty. Consider adding a check to ensure len(req.Question) > 0 before accessing req.Question[0].

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be a problem, as semantically, queries have a question, and in fact the existing IPv6-specific code (which I copy-pasted from) also doesn't include a check.

h.logger.DebugContext(
ctx,
"ipv4 is disabled; replying with empty response",
"req", req.Question[0].Name,
)

return h.messages.NewMsgNODATA(req)
}

return nil
}