From 2332d9b7c1e2575048c2fe158753a1c7e51260e0 Mon Sep 17 00:00:00 2001 From: Ming Aldrich-Gan Date: Sun, 24 Mar 2019 16:01:32 -0400 Subject: [PATCH] Add local_addr configuration for doh-server (#39) * Add local_addr configuration for doh-server This commit adds a `local_addr` string value to `doh-server.conf`, specifying the IP address and port from which outgoing calls to upstream DNS resolvers should originate. This value is set as the `udpClient`'s and `tcpClient`'s `Dialer.LocalAddr` when initializing a `NewServer`. If the value is left empty in `doh-server.conf`, it defaults to the first `listen` address (which in turn defaults to `"127.0.0.1:8053"`). One use case for this would be if `doh-server` is proxying requests to a local DNS resolver (e.g. `unbound` or Pi-hole). Up to version 2.0.0, all DNS queries from `doh-server` are sent from `127.0.0.1` (even if the `listen` address is set to a different loopback IP address), making it hard to distinguish them from all other local DNS queries from the same machine in the query logs. * Revert defaulting of local_addr to listen address This commit reverts to the existing behavior when `conf.LocalAddr == ""`, i.e. letting `dns.Client` instantiate its own `Dialer` with the default local address. * Fixup comment in configuration file * Log errors from Dialer instantiation (e.g. if LocalAddr port is missing) * Fixup other comment in configuration file * Return error and log fatal --- doh-server/config.go | 1 + doh-server/doh-server.conf | 4 ++++ doh-server/main.go | 5 ++++- doh-server/server.go | 29 ++++++++++++++++++++++++----- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/doh-server/config.go b/doh-server/config.go index e51c07c..f937c14 100644 --- a/doh-server/config.go +++ b/doh-server/config.go @@ -31,6 +31,7 @@ import ( type config struct { Listen []string `toml:"listen"` + LocalAddr string `toml:"local_addr"` Cert string `toml:"cert"` Key string `toml:"key"` Path string `toml:"path"` diff --git a/doh-server/doh-server.conf b/doh-server/doh-server.conf index 335fe86..eaa7f53 100644 --- a/doh-server/doh-server.conf +++ b/doh-server/doh-server.conf @@ -4,6 +4,10 @@ listen = [ "[::1]:8053", ] +# Local address and port for upstream DNS +# If left empty, a local address is automatically chosen. +local_addr = "" + # TLS certification file # If left empty, plain-text HTTP will be used. # You are recommended to leave empty and to use a server load balancer (e.g. diff --git a/doh-server/main.go b/doh-server/main.go index a6c24e5..813bee5 100644 --- a/doh-server/main.go +++ b/doh-server/main.go @@ -110,6 +110,9 @@ func main() { conf.Verbose = true } - server := NewServer(conf) + server, err := NewServer(conf) + if err != nil { + log.Fatalln(err) + } _ = server.Start() } diff --git a/doh-server/server.go b/doh-server/server.go index 22ffce3..e758767 100644 --- a/doh-server/server.go +++ b/doh-server/server.go @@ -56,22 +56,41 @@ type DNSRequest struct { errtext string } -func NewServer(conf *config) (s *Server) { - s = &Server{ +func NewServer(conf *config) (*Server, error) { + timeout := time.Duration(conf.Timeout) * time.Second + s := &Server{ conf: conf, udpClient: &dns.Client{ Net: "udp", UDPSize: dns.DefaultMsgSize, - Timeout: time.Duration(conf.Timeout) * time.Second, + Timeout: timeout, }, tcpClient: &dns.Client{ Net: "tcp", - Timeout: time.Duration(conf.Timeout) * time.Second, + Timeout: timeout, }, servemux: http.NewServeMux(), } + if conf.LocalAddr != "" { + udpLocalAddr, err := net.ResolveUDPAddr("udp", conf.LocalAddr) + if err != nil { + return nil, err + } + tcpLocalAddr, err := net.ResolveTCPAddr("tcp", conf.LocalAddr) + if err != nil { + return nil, err + } + s.udpClient.Dialer = &net.Dialer{ + Timeout: timeout, + LocalAddr: udpLocalAddr, + } + s.tcpClient.Dialer = &net.Dialer{ + Timeout: timeout, + LocalAddr: tcpLocalAddr, + } + } s.servemux.HandleFunc(conf.Path, s.handlerFunc) - return + return s, nil } func (s *Server) Start() error {