diff options
| author | Shulhan <ms@kilabit.info> | 2018-09-24 08:13:14 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2018-09-25 08:28:09 +0700 |
| commit | 9fd47e59d2e4bf74b5b1aea525a3b64c301e2aa7 (patch) | |
| tree | af71e60e795a1f8988b4b43ed1900c7ce74918bf | |
| parent | c78c938b264e1232df0fe5e2b75d282fff696b7a (diff) | |
| download | pakakeh.go-9fd47e59d2e4bf74b5b1aea525a3b64c301e2aa7.tar.xz | |
lib/dns: add type server options to configure server
Since we have three mode for server now (UDP, TCP, DoH), more
parameters were added to ListenAndServe. To simplify this we use server
options with struct that can be passed directly to ListenAndServer.
| -rw-r--r-- | lib/dns/dns.go | 11 | ||||
| -rw-r--r-- | lib/dns/dns_test.go | 13 | ||||
| -rw-r--r-- | lib/dns/example_server_test.go | 13 | ||||
| -rw-r--r-- | lib/dns/server.go | 63 | ||||
| -rw-r--r-- | lib/dns/server_options.go | 89 |
5 files changed, 141 insertions, 48 deletions
diff --git a/lib/dns/dns.go b/lib/dns/dns.go index 52211ef5..8fd46e71 100644 --- a/lib/dns/dns.go +++ b/lib/dns/dns.go @@ -22,8 +22,15 @@ import ( libnet "github.com/shuLhan/share/lib/net" ) -// DefaultPort define default DNS remote or listen port. -const DefaultPort uint16 = 53 +const ( + // DefaultPort define default DNS remote or listen port for UDP and + // TCP connection. + DefaultPort uint16 = 53 + + // DefaultDoHPort define default port for DoH. + DefaultDoHPort uint16 = 443 + defaultDoHIdleTimeout time.Duration = 120 * time.Second +) const ( maskPointer byte = 0xC0 diff --git a/lib/dns/dns_test.go b/lib/dns/dns_test.go index cdaa875b..af7465d7 100644 --- a/lib/dns/dns_test.go +++ b/lib/dns/dns_test.go @@ -191,9 +191,18 @@ func TestMain(m *testing.M) { Handler: _testHandler, } + serverOptions := &ServerOptions{ + IPAddress: "127.0.0.1", + UDPPort: 5353, + TCPPort: 5353, + DoHPort: 8443, + DoHCertFile: "testdata/domain.crt", + DoHKeyFile: "testdata/domain.key", + DoHAllowInsecure: true, + } + go func() { - err := _testServer.ListenAndServe(testServerAddress, - "testdata/domain.crt", "testdata/domain.key", true) + err := _testServer.ListenAndServe(serverOptions) if err != nil { log.Fatal("ListenAndServe: ", err) } diff --git a/lib/dns/example_server_test.go b/lib/dns/example_server_test.go index 020e7907..0dcb31c5 100644 --- a/lib/dns/example_server_test.go +++ b/lib/dns/example_server_test.go @@ -194,9 +194,18 @@ func ExampleServer() { Handler: handler, } + serverOptions := &dns.ServerOptions{ + IPAddress: "127.0.0.1", + TCPPort: 5353, + UDPPort: 5353, + DoHPort: 8443, + DoHCertFile: "testdata/domain.crt", + DoHKeyFile: "testdata/domain.key", + DoHAllowInsecure: true, + } + go func() { - err := server.ListenAndServe(serverAddress, - "testdata/domain.crt", "testdata/domain.key", true) + err := server.ListenAndServe(serverOptions) if err != nil { log.Fatal("ListenAndServe: ", err) } diff --git a/lib/dns/server.go b/lib/dns/server.go index 99a93cb8..28ab67d8 100644 --- a/lib/dns/server.go +++ b/lib/dns/server.go @@ -14,8 +14,6 @@ import ( "net/http" "strings" "time" - - libnet "github.com/shuLhan/share/lib/net" ) // @@ -28,37 +26,11 @@ type Server struct { doh *http.Server } -func parseAddress(address string) (udp *net.UDPAddr, tcp, doh *net.TCPAddr, err error) { - ip, port, err := libnet.ParseIPPort(address, DefaultPort) - if err != nil { - return - } - - udp = &net.UDPAddr{ - IP: ip, - Port: int(port), - } - - tcp = &net.TCPAddr{ - IP: ip, - Port: int(port), - } - - doh = &net.TCPAddr{ - IP: ip, - Port: 8443, - } - - return -} - // -// ListenAndServe run DNS server, listening on UDP and TCP connection. +// ListenAndServe run DNS server on UDP, TCP, or DNS over HTTP (DoH). // -func (srv *Server) ListenAndServe(address, certFile, keyFile string, allowInsecure bool) error { - var err error - - udpAddr, tcpAddr, dohAddr, err := parseAddress(address) +func (srv *Server) ListenAndServe(opts *ServerOptions) error { + err := opts.parse() if err != nil { return err } @@ -66,20 +38,22 @@ func (srv *Server) ListenAndServe(address, certFile, keyFile string, allowInsecu cherr := make(chan error, 1) go func() { - err = srv.ListenAndServeTCP(tcpAddr) + err = srv.ListenAndServeTCP(opts.getTCPAddress()) if err != nil { cherr <- err } }() + go func() { - err = srv.ListenAndServeUDP(udpAddr) + err = srv.ListenAndServeUDP(opts.getUDPAddress()) if err != nil { cherr <- err } }() - if len(certFile) > 0 && len(keyFile) > 0 { + + if len(opts.DoHCertFile) > 0 && len(opts.DoHKeyFile) > 0 { go func() { - err = srv.ListenAndServeDoH(dohAddr, certFile, keyFile, allowInsecure) + err = srv.ListenAndServeDoH(opts) if err != nil { cherr <- err } @@ -95,20 +69,25 @@ func (srv *Server) ListenAndServe(address, certFile, keyFile string, allowInsecu // ListenAndServeDoH listen for request over HTTPS using certificate and key // file in parameter. The path to request is static "/dns-query". // -func (srv *Server) ListenAndServeDoH(address *net.TCPAddr, certFile, keyFile string, allowInsecure bool) error { +func (srv *Server) ListenAndServeDoH(opts *ServerOptions) error { + if opts.ip == nil { + err := opts.parse() + if err != nil { + return err + } + } + srv.doh = &http.Server{ - Addr: address.String(), - IdleTimeout: 120 * time.Second, + Addr: opts.getDoHAddress().String(), + IdleTimeout: opts.DoHIdleTimeout, TLSConfig: &tls.Config{ - InsecureSkipVerify: allowInsecure, + InsecureSkipVerify: opts.DoHAllowInsecure, }, } http.Handle("/dns-query", srv) - err := srv.doh.ListenAndServeTLS(certFile, keyFile) - - return err + return srv.doh.ListenAndServeTLS(opts.DoHCertFile, opts.DoHKeyFile) } func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { diff --git a/lib/dns/server_options.go b/lib/dns/server_options.go new file mode 100644 index 00000000..5c44f16a --- /dev/null +++ b/lib/dns/server_options.go @@ -0,0 +1,89 @@ +// Copyright 2018, Shulhan <ms@kilabit.info>. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dns + +import ( + "fmt" + "net" + "time" +) + +// +// ServerOptions describes options for running a DNS server. +// If certificate or key file is empty, server will not run with DoH. +// +type ServerOptions struct { + // IPAddress of server to listen to, without port number. + IPAddress string + + // UDPPort port for UDP server, default to 53. + UDPPort uint16 + + // TCPPort port for TCP server, default to 53. + TCPPort uint16 + + // DoHPort port for DNS over HTTP (DoH), default to 443. + DoHPort uint16 + + // DoHCertFile path to certificate file for serving DoH. + DoHCertFile string + + // DoHKeyFile path to certificate key file for serving DoH. + DoHKeyFile string + + // DoHAllowInsecure options to allow to serve DoH with self-signed + // certificate. + DoHAllowInsecure bool + + // DoHIdleTimeout number of seconds before considering the client of + // DoH connection to be closed. + DoHIdleTimeout time.Duration + + ip net.IP +} + +func (opts *ServerOptions) parse() error { + ip := net.ParseIP(opts.IPAddress) + if ip == nil { + err := fmt.Errorf("Invalid address '%s'\n", opts.IPAddress) + return err + } + + if opts.UDPPort == 0 { + opts.UDPPort = DefaultPort + } + if opts.TCPPort == 0 { + opts.TCPPort = DefaultPort + } + if opts.DoHPort == 0 { + opts.DoHPort = DefaultDoHPort + } + if opts.DoHIdleTimeout <= 0 { + opts.DoHIdleTimeout = defaultDoHIdleTimeout + } + + return nil +} + +func (opts *ServerOptions) getUDPAddress() *net.UDPAddr { + return &net.UDPAddr{ + IP: opts.ip, + Port: int(opts.UDPPort), + } +} + +func (opts *ServerOptions) getTCPAddress() *net.TCPAddr { + return &net.TCPAddr{ + IP: opts.ip, + Port: int(opts.TCPPort), + } +} + +func (opts *ServerOptions) getDoHAddress() *net.TCPAddr { + return &net.TCPAddr{ + IP: opts.ip, + Port: int(opts.DoHPort), + } +} |
