Skip to content

Commit cdc019d

Browse files
committed
feat: allow manual configuration of dns resolver
1 parent 714b055 commit cdc019d

5 files changed

Lines changed: 58 additions & 0 deletions

File tree

core/nylon.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package core
22

33
import (
4+
"context"
45
"net"
56
"time"
67

@@ -25,6 +26,27 @@ func (n *Nylon) Init(s *state.State) error {
2526

2627
s.Log.Debug("init nylon")
2728

29+
if len(s.DnsResolvers) != 0 {
30+
s.Log.Debug("setting custom DNS resolvers", "resolvers", s.DnsResolvers)
31+
net.DefaultResolver = &net.Resolver{
32+
PreferGo: true,
33+
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
34+
d := net.Dialer{
35+
Timeout: time.Second * 10,
36+
}
37+
var err error
38+
var conn net.Conn
39+
for _, resolver := range s.DnsResolvers {
40+
conn, err = d.DialContext(ctx, network, resolver)
41+
if err == nil {
42+
return conn, nil
43+
}
44+
}
45+
return conn, err
46+
},
47+
}
48+
}
49+
2850
// add neighbours
2951
for _, peer := range s.GetPeers(s.Id) {
3052
if !s.IsRouter(peer) {

example/sample-node.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ usesystemrouting: false # Default: false - if enabled, Nylon will use the system
66
logpath: "" # Default: "" - If set, Nylon will log to this file
77
interfacename: "" # Default: "" - If set, Nylon will use this interface name instead of the default "nylon" or utunx on macOS
88
disablerouting: false # Default: false - If true, Nylon will not route traffic through this node
9+
dnsresolvers: [] # Default: [] - If set (e.g ["1.1.1.1:53"]), nylon will use these DNS resolvers for its own queries
910
dist: # Optional: If set, Nylon will bootstrap central.yaml from this URL if it does not exist already
1011
url: https://static.example.com/network1.nybundle
1112
key: 7PaN6DmAayz4KnDnsXSXJH+Oy0TFGeoM4FEbQfLriVY=

state/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ type LocalCfg struct {
7474
DisableRouting bool
7575
UseSystemRouting bool
7676
NoNetConfigure bool `yaml:",omitempty"`
77+
DnsResolvers []string
7778
InterfaceName string
7879
LogPath string
7980
}

state/validation.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ func NodeConfigValidator(node *LocalCfg) error {
6161
return err
6262
}
6363
}
64+
if len(node.DnsResolvers) != 0 {
65+
for _, resolver := range node.DnsResolvers {
66+
if _, err := netip.ParseAddrPort(resolver); err != nil {
67+
return fmt.Errorf("dns resolver %s is not a valid ip:port: %v", resolver, err)
68+
}
69+
}
70+
}
6471
return nil
6572
}
6673

state/validation_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,33 @@ func TestNameValidator_Invalid(t *testing.T) {
2323
assert.Error(t, NameValidator(strings.Repeat("a", 200)))
2424
}
2525

26+
func TestNodeConfigValidator_DnsResolver(t *testing.T) {
27+
assert.NoError(t, NodeConfigValidator(&LocalCfg{
28+
Id: "valid-node",
29+
Port: 5,
30+
Key: [32]byte{1},
31+
DnsResolver: "1.1.1.1:53",
32+
}))
33+
assert.Error(t, NodeConfigValidator(&LocalCfg{
34+
Id: "invalid-node",
35+
Port: 5,
36+
Key: [32]byte{1},
37+
DnsResolver: "google.com",
38+
}))
39+
assert.Error(t, NodeConfigValidator(&LocalCfg{
40+
Id: "invalid-node",
41+
Port: 5,
42+
Key: [32]byte{1},
43+
DnsResolver: "google.com:53",
44+
}))
45+
assert.Error(t, NodeConfigValidator(&LocalCfg{
46+
Id: "invalid-node",
47+
Port: 5,
48+
Key: [32]byte{1},
49+
DnsResolver: "1.1.1.1",
50+
}))
51+
}
52+
2653
func TestCentralConfigValidator_OverlappingService(t *testing.T) {
2754
cfg := &CentralCfg{
2855
Services: map[ServiceId]netip.Prefix{

0 commit comments

Comments
 (0)