11package settings
22
33import (
4+ "errors"
45 "fmt"
56 "net/netip"
67
8+ "github.com/qdm12/dns/v2/pkg/nameserver"
79 "github.com/qdm12/gosettings"
810 "github.com/qdm12/gosettings/reader"
911 "github.com/qdm12/gotree"
@@ -17,36 +19,38 @@ type DNS struct {
1719 // DoT server. It cannot be the zero value in the internal
1820 // state.
1921 ServerAddress netip.Addr
20- // KeepNameserver is true if the existing DNS server
21- // found in /etc/resolv.conf should be used
22- // Note setting this to true will likely DNS traffic
23- // outside the VPN tunnel since it would go through
24- // the local DNS server of your Docker/Kubernetes
25- // configuration, which is likely not going through the tunnel.
26- // This will also disable the DNS over TLS server and the
27- // `ServerAddress` field will be ignored.
28- // It defaults to false and cannot be nil in the
29- // internal state.
30- KeepNameserver * bool
3122 // DOT contains settings to configure the DoT
3223 // server.
3324 DoT DoT
25+ // LocalResolvers are IP:port addresses of local DNS resolvers
26+ // to which queries for local domains should be sent.
27+ // By default, it is the private nameservers found in /etc/resolv.conf
28+ // at container start, before the DNS is setup.
29+ LocalResolvers []netip.AddrPort
3430}
3531
32+ var ErrLocalResolverNotPrivate = errors .New ("local resolver is not a private IP address" )
33+
3634func (d DNS ) validate () (err error ) {
3735 err = d .DoT .validate ()
3836 if err != nil {
3937 return fmt .Errorf ("validating DoT settings: %w" , err )
4038 }
4139
40+ for _ , resolver := range d .LocalResolvers {
41+ if ! resolver .Addr ().IsPrivate () && ! resolver .Addr ().IsLoopback () {
42+ return fmt .Errorf ("%w: %s" , ErrLocalResolverNotPrivate , resolver )
43+ }
44+ }
45+
4246 return nil
4347}
4448
4549func (d * DNS ) Copy () (copied DNS ) {
4650 return DNS {
4751 ServerAddress : d .ServerAddress ,
48- KeepNameserver : gosettings .CopyPointer (d .KeepNameserver ),
4952 DoT : d .DoT .copy (),
53+ LocalResolvers : gosettings .CopySlice (d .LocalResolvers ),
5054 }
5155}
5256
@@ -55,15 +59,15 @@ func (d *DNS) Copy() (copied DNS) {
5559// settings.
5660func (d * DNS ) overrideWith (other DNS ) {
5761 d .ServerAddress = gosettings .OverrideWithValidator (d .ServerAddress , other .ServerAddress )
58- d .KeepNameserver = gosettings .OverrideWithPointer (d .KeepNameserver , other .KeepNameserver )
5962 d .DoT .overrideWith (other .DoT )
63+ d .LocalResolvers = gosettings .OverrideWithSlice (d .LocalResolvers , other .LocalResolvers )
6064}
6165
6266func (d * DNS ) setDefaults () {
6367 localhost := netip .AddrFrom4 ([4 ]byte {127 , 0 , 0 , 1 })
6468 d .ServerAddress = gosettings .DefaultValidator (d .ServerAddress , localhost )
65- d .KeepNameserver = gosettings .DefaultPointer (d .KeepNameserver , false )
6669 d .DoT .setDefaults ()
70+ d .LocalResolvers = gosettings .DefaultSlice (d .LocalResolvers , nameserver .GetPrivateDNSServers ())
6771}
6872
6973func (d DNS ) String () string {
@@ -72,12 +76,13 @@ func (d DNS) String() string {
7276
7377func (d DNS ) toLinesNode () (node * gotree.Node ) {
7478 node = gotree .New ("DNS settings:" )
75- node .Appendf ("Keep existing nameserver(s): %s" , gosettings .BoolToYesNo (d .KeepNameserver ))
76- if * d .KeepNameserver {
77- return node
78- }
7979 node .Appendf ("DNS server address to use: %s" , d .ServerAddress )
8080 node .AppendNode (d .DoT .toLinesNode ())
81+ localResolversNode := gotree .New ("Local resolvers:" )
82+ for _ , resolver := range d .LocalResolvers {
83+ localResolversNode .Appendf ("%s" , resolver .String ())
84+ }
85+ node .AppendNode (localResolversNode )
8186 return node
8287}
8388
@@ -87,14 +92,14 @@ func (d *DNS) read(r *reader.Reader) (err error) {
8792 return err
8893 }
8994
90- d . KeepNameserver , err = r . BoolPtr ( "DNS_KEEP_NAMESERVER" )
95+ err = d . DoT . read ( r )
9196 if err != nil {
92- return err
97+ return fmt . Errorf ( "DNS over TLS settings: %w" , err )
9398 }
9499
95- err = d . DoT . read ( r )
100+ d . LocalResolvers , err = r . CSVNetipAddrPorts ( "DNS_LOCAL_RESOLVERS" )
96101 if err != nil {
97- return fmt . Errorf ( "DNS over TLS settings: %w" , err )
102+ return err
98103 }
99104
100105 return nil
0 commit comments