feat: DNS over TLS resolver

This commit is contained in:
Toby 2023-08-04 14:03:23 -07:00
parent 7c94b072ed
commit 6ad44d183e
5 changed files with 54 additions and 4 deletions

View File

@ -101,10 +101,18 @@ type serverConfigResolverUDP struct {
Timeout time.Duration `mapstructure:"timeout"` Timeout time.Duration `mapstructure:"timeout"`
} }
type serverConfigResolverTLS struct {
Addr string `mapstructure:"addr"`
Timeout time.Duration `mapstructure:"timeout"`
SNI string `mapstructure:"sni"`
Insecure bool `mapstructure:"insecure"`
}
type serverConfigResolver struct { type serverConfigResolver struct {
Type string `mapstructure:"type"` Type string `mapstructure:"type"`
TCP serverConfigResolverTCP `mapstructure:"tcp"` TCP serverConfigResolverTCP `mapstructure:"tcp"`
UDP serverConfigResolverUDP `mapstructure:"udp"` UDP serverConfigResolverUDP `mapstructure:"udp"`
TLS serverConfigResolverTLS `mapstructure:"tls"`
} }
type serverConfigMasqueradeFile struct { type serverConfigMasqueradeFile struct {
@ -254,6 +262,11 @@ func (c *serverConfig) fillOutboundConfig(hyConfig *server.Config) error {
return configError{Field: "resolver.udp.addr", Err: errors.New("empty resolver address")} return configError{Field: "resolver.udp.addr", Err: errors.New("empty resolver address")}
} }
ob = outbounds.NewStandardResolverUDP(c.Resolver.UDP.Addr, c.Resolver.UDP.Timeout, ob) ob = outbounds.NewStandardResolverUDP(c.Resolver.UDP.Addr, c.Resolver.UDP.Timeout, ob)
case "tls", "tcp-tls":
if c.Resolver.TLS.Addr == "" {
return configError{Field: "resolver.tls.addr", Err: errors.New("empty resolver address")}
}
ob = outbounds.NewStandardResolverTLS(c.Resolver.TLS.Addr, c.Resolver.TLS.Timeout, c.Resolver.TLS.SNI, c.Resolver.TLS.Insecure, ob)
default: default:
return configError{Field: "resolver.type", Err: errors.New("unsupported resolver type")} return configError{Field: "resolver.type", Err: errors.New("unsupported resolver type")}
} }

View File

@ -71,6 +71,12 @@ func TestServerConfig(t *testing.T) {
Addr: "4.6.8.0:53", Addr: "4.6.8.0:53",
Timeout: 2 * time.Second, Timeout: 2 * time.Second,
}, },
TLS: serverConfigResolverTLS{
Addr: "dot.yolo.com:8853",
Timeout: 10 * time.Second,
SNI: "server1.yolo.net",
Insecure: true,
},
}, },
Masquerade: serverConfigMasquerade{ Masquerade: serverConfigMasquerade{
Type: "proxy", Type: "proxy",

View File

@ -49,6 +49,11 @@ resolver:
udp: udp:
addr: 4.6.8.0:53 addr: 4.6.8.0:53
timeout: 2s timeout: 2s
tls:
addr: dot.yolo.com:8853
timeout: 10s
sni: server1.yolo.net
insecure: true
masquerade: masquerade:
type: proxy type: proxy

View File

@ -41,10 +41,12 @@ auth:
password: some_password password: some_password
# resolver: # resolver:
# type: udp # type: tls
# udp: # tls:
# addr: 8.8.4.4 # addr: dot.yolo.com:8853
# timeout: 2s # timeout: 10s
# sni: server1.yolo.net
# insecure: true
masquerade: masquerade:
type: proxy type: proxy

View File

@ -1,6 +1,7 @@
package outbounds package outbounds
import ( import (
"crypto/tls"
"net" "net"
"time" "time"
@ -42,6 +43,21 @@ func NewStandardResolverTCP(addr string, timeout time.Duration, next PluggableOu
} }
} }
func NewStandardResolverTLS(addr string, timeout time.Duration, sni string, insecure bool, next PluggableOutbound) PluggableOutbound {
return &standardResolver{
Addr: addDefaultPortTLS(addr),
Client: &dns.Client{
Net: "tcp-tls",
Timeout: timeoutOrDefault(timeout),
TLSConfig: &tls.Config{
ServerName: sni,
InsecureSkipVerify: insecure,
},
},
Next: next,
}
}
// addDefaultPort adds the default DNS port (53) to the address if not present. // addDefaultPort adds the default DNS port (53) to the address if not present.
func addDefaultPort(addr string) string { func addDefaultPort(addr string) string {
if _, _, err := net.SplitHostPort(addr); err != nil { if _, _, err := net.SplitHostPort(addr); err != nil {
@ -50,6 +66,14 @@ func addDefaultPort(addr string) string {
return addr return addr
} }
// addDefaultPortTLS adds the default DNS-over-TLS port (853) to the address if not present.
func addDefaultPortTLS(addr string) string {
if _, _, err := net.SplitHostPort(addr); err != nil {
return net.JoinHostPort(addr, "853")
}
return addr
}
func timeoutOrDefault(timeout time.Duration) time.Duration { func timeoutOrDefault(timeout time.Duration) time.Duration {
if timeout == 0 { if timeout == 0 {
return standardResolverDefaultTimeout return standardResolverDefaultTimeout