Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions core/nylon.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package core

import (
"context"
"net"
"time"

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

s.Log.Debug("init nylon")

if len(s.DnsResolvers) != 0 {
s.Log.Debug("setting custom DNS resolvers", "resolvers", s.DnsResolvers)
net.DefaultResolver = &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: time.Second * 10,
}
var err error
var conn net.Conn
for _, resolver := range s.DnsResolvers {
conn, err = d.DialContext(ctx, network, resolver)
if err == nil {
return conn, nil
}
}
return conn, err
},
}
}

// add neighbours
for _, peer := range s.GetPeers(s.Id) {
if !s.IsRouter(peer) {
Expand Down
1 change: 1 addition & 0 deletions example/sample-node.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ usesystemrouting: false # Default: false - if enabled, Nylon will use the system
logpath: "" # Default: "" - If set, Nylon will log to this file
interfacename: "" # Default: "" - If set, Nylon will use this interface name instead of the default "nylon" or utunx on macOS
disablerouting: false # Default: false - If true, Nylon will not route traffic through this node
dnsresolvers: [] # Default: [] - If set (e.g ["1.1.1.1:53"]), nylon will use these DNS resolvers for its own queries
dist: # Optional: If set, Nylon will bootstrap central.yaml from this URL if it does not exist already
url: https://static.example.com/network1.nybundle
key: 7PaN6DmAayz4KnDnsXSXJH+Oy0TFGeoM4FEbQfLriVY=
3 changes: 2 additions & 1 deletion state/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ type LocalCfg struct {
Dist *LocalDistributionCfg `yaml:",omitempty"`
DisableRouting bool
UseSystemRouting bool
NoNetConfigure bool `yaml:",omitempty"`
NoNetConfigure bool `yaml:",omitempty"`
DnsResolvers []string `yaml:",omitempty"`
InterfaceName string
LogPath string
}
Expand Down
7 changes: 7 additions & 0 deletions state/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ func NodeConfigValidator(node *LocalCfg) error {
return err
}
}
if len(node.DnsResolvers) != 0 {
for _, resolver := range node.DnsResolvers {
if _, err := netip.ParseAddrPort(resolver); err != nil {
return fmt.Errorf("dns resolver %s is not a valid ip:port: %v", resolver, err)
}
}
}
return nil
}

Expand Down
32 changes: 32 additions & 0 deletions state/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,38 @@ func TestNameValidator_Invalid(t *testing.T) {
assert.Error(t, NameValidator(strings.Repeat("a", 200)))
}

func TestNodeConfigValidator_DnsResolver(t *testing.T) {
assert.NoError(t, NodeConfigValidator(&LocalCfg{
Id: "valid-node",
Port: 5,
Key: [32]byte{1},
DnsResolvers: []string{"1.1.1.1:53"},
}))
assert.NoError(t, NodeConfigValidator(&LocalCfg{
Id: "valid-node",
Port: 5,
Key: [32]byte{1},
}))
assert.Error(t, NodeConfigValidator(&LocalCfg{
Id: "invalid-node",
Port: 5,
Key: [32]byte{1},
DnsResolvers: []string{"google.com"},
}))
assert.Error(t, NodeConfigValidator(&LocalCfg{
Id: "invalid-node",
Port: 5,
Key: [32]byte{1},
DnsResolvers: []string{"google.com:53"},
}))
assert.Error(t, NodeConfigValidator(&LocalCfg{
Id: "invalid-node",
Port: 5,
Key: [32]byte{1},
DnsResolvers: []string{"1.1.1.1"},
}))
}

func TestCentralConfigValidator_OverlappingService(t *testing.T) {
cfg := &CentralCfg{
Services: map[ServiceId]netip.Prefix{
Expand Down