aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2018-09-24 08:13:14 +0700
committerShulhan <ms@kilabit.info>2018-09-25 08:28:09 +0700
commit9fd47e59d2e4bf74b5b1aea525a3b64c301e2aa7 (patch)
treeaf71e60e795a1f8988b4b43ed1900c7ce74918bf
parentc78c938b264e1232df0fe5e2b75d282fff696b7a (diff)
downloadpakakeh.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.go11
-rw-r--r--lib/dns/dns_test.go13
-rw-r--r--lib/dns/example_server_test.go13
-rw-r--r--lib/dns/server.go63
-rw-r--r--lib/dns/server_options.go89
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),
+ }
+}