Fixes #72
- Using custom DNS internally (without TLS) to download Unbound files - Using then Unbound with DNS over TLS internally and system wide - Works even if you host system DNS is broken - Waits a few milliseconds for Unbound to start up
This commit is contained in:
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/qdm12/golibs/command"
|
||||
@@ -75,6 +76,8 @@ func main() {
|
||||
e.FatalOnError(err)
|
||||
|
||||
if allSettings.DNS.Enabled {
|
||||
initialDNSToUse := constants.DNSProviderMapping()[allSettings.DNS.Providers[0]]
|
||||
dnsConf.UseDNSInternally(initialDNSToUse.IPs[0])
|
||||
err = dnsConf.DownloadRootHints(uid, gid)
|
||||
e.FatalOnError(err)
|
||||
err = dnsConf.DownloadRootKey(uid, gid)
|
||||
@@ -84,7 +87,10 @@ func main() {
|
||||
stream, err := dnsConf.Start(allSettings.DNS.VerbosityDetailsLevel)
|
||||
e.FatalOnError(err)
|
||||
go streamMerger.Merge("unbound", stream)
|
||||
err = dnsConf.SetLocalNameserver()
|
||||
dnsConf.UseDNSInternally(net.IP{127, 0, 0, 1}) // use Unbound
|
||||
err = dnsConf.UseDNSSystemWide(net.IP{127, 0, 0, 1}) // use Unbound
|
||||
e.FatalOnError(err)
|
||||
err = dnsConf.WaitForUnbound()
|
||||
e.FatalOnError(err)
|
||||
}
|
||||
|
||||
|
||||
4
go.sum
4
go.sum
@@ -44,8 +44,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/qdm12/golibs v0.0.0-20200208143139-ccf3a2b4be96 h1:TAhod+kjxTQHdqMNnDkg6IbLRrGovtI+3l1Isjd1wbI=
|
||||
github.com/qdm12/golibs v0.0.0-20200208143139-ccf3a2b4be96/go.mod h1:YULaFjj6VGmhjak6f35sUWwEleHUmngN5IQ3kdvd6XE=
|
||||
github.com/qdm12/golibs v0.0.0-20200208153322-66b2eb719e21 h1:Nza/Ar6tPYhDzkiNzbaJZHl4+GUXTqbtjGXuWenkqpQ=
|
||||
github.com/qdm12/golibs v0.0.0-20200208153322-66b2eb719e21/go.mod h1:YULaFjj6VGmhjak6f35sUWwEleHUmngN5IQ3kdvd6XE=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
||||
@@ -2,6 +2,7 @@ package dns
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/qdm12/golibs/command"
|
||||
"github.com/qdm12/golibs/files"
|
||||
@@ -16,8 +17,10 @@ type Configurator interface {
|
||||
DownloadRootHints(uid, gid int) error
|
||||
DownloadRootKey(uid, gid int) error
|
||||
MakeUnboundConf(settings settings.DNS, uid, gid int) (err error)
|
||||
SetLocalNameserver() error
|
||||
UseDNSInternally(IP net.IP)
|
||||
UseDNSSystemWide(IP net.IP) error
|
||||
Start(logLevel uint8) (stdout io.ReadCloser, err error)
|
||||
WaitForUnbound() (err error)
|
||||
Version() (version string, err error)
|
||||
}
|
||||
|
||||
@@ -26,6 +29,7 @@ type configurator struct {
|
||||
client network.Client
|
||||
fileManager files.FileManager
|
||||
commander command.Commander
|
||||
lookupIP func(host string) ([]net.IP, error)
|
||||
}
|
||||
|
||||
func NewConfigurator(logger logging.Logger, client network.Client, fileManager files.FileManager) Configurator {
|
||||
@@ -34,5 +38,6 @@ func NewConfigurator(logger logging.Logger, client network.Client, fileManager f
|
||||
client: client,
|
||||
fileManager: fileManager,
|
||||
commander: command.NewCommander(),
|
||||
lookupIP: net.LookupIP,
|
||||
}
|
||||
}
|
||||
|
||||
47
internal/dns/nameserver.go
Normal file
47
internal/dns/nameserver.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
||||
)
|
||||
|
||||
// UseDNSInternally is to change the Go program DNS only
|
||||
func (c *configurator) UseDNSInternally(IP net.IP) {
|
||||
c.logger.Info("%s: using DNS address %s internally", logPrefix, IP.String())
|
||||
net.DefaultResolver = &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
d := net.Dialer{}
|
||||
return d.DialContext(ctx, "udp", net.JoinHostPort(IP.String(), "53"))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UseDNSSystemWide changes the nameserver to use for DNS system wide
|
||||
func (c *configurator) UseDNSSystemWide(IP net.IP) error {
|
||||
c.logger.Info("%s: using DNS address %s system wide", logPrefix, IP.String())
|
||||
data, err := c.fileManager.ReadFile(string(constants.ResolvConf))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s := strings.TrimSuffix(string(data), "\n")
|
||||
lines := strings.Split(s, "\n")
|
||||
if len(lines) == 1 && lines[0] == "" {
|
||||
lines = nil
|
||||
}
|
||||
found := false
|
||||
for i := range lines {
|
||||
if strings.HasPrefix(lines[i], "nameserver ") {
|
||||
lines[i] = "nameserver " + IP.String()
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
lines = append(lines, "nameserver "+IP.String())
|
||||
}
|
||||
data = []byte(strings.Join(lines, "\n"))
|
||||
return c.fileManager.WriteToFile(string(constants.ResolvConf), data)
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
filesmocks "github.com/qdm12/golibs/files/mocks"
|
||||
@@ -11,7 +12,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_SetLocalNameserver(t *testing.T) {
|
||||
func Test_UseDNSSystemWide(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := map[string]struct {
|
||||
data []byte
|
||||
@@ -53,12 +54,12 @@ func Test_SetLocalNameserver(t *testing.T) {
|
||||
Return(tc.writeErr).Once()
|
||||
}
|
||||
logger := &loggingmocks.Logger{}
|
||||
logger.On("Info", "%s: setting local nameserver to 127.0.0.1", logPrefix).Once()
|
||||
logger.On("Info", "%s: using DNS address %s system wide", logPrefix, "127.0.0.1").Once()
|
||||
c := &configurator{
|
||||
fileManager: fileManager,
|
||||
logger: logger,
|
||||
}
|
||||
err := c.SetLocalNameserver()
|
||||
err := c.UseDNSSystemWide(net.IP{127, 0, 0, 1})
|
||||
if tc.err != nil {
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, tc.err.Error(), err.Error())
|
||||
@@ -1,13 +1,14 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
||||
)
|
||||
|
||||
func (c *configurator) SetLocalNameserver() error {
|
||||
c.logger.Info("%s: setting local nameserver to 127.0.0.1", logPrefix)
|
||||
func (c *configurator) SetNameserver(IP net.IP) error {
|
||||
c.logger.Info("%s: setting local nameserver to %s", logPrefix, IP.String())
|
||||
data, err := c.fileManager.ReadFile(string(constants.ResolvConf))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -20,12 +21,12 @@ func (c *configurator) SetLocalNameserver() error {
|
||||
found := false
|
||||
for i := range lines {
|
||||
if strings.HasPrefix(lines[i], "nameserver ") {
|
||||
lines[i] = "nameserver 127.0.0.1"
|
||||
lines[i] = "nameserver " + IP.String()
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
lines = append(lines, "nameserver 127.0.0.1")
|
||||
lines = append(lines, "nameserver "+IP.String())
|
||||
}
|
||||
data = []byte(strings.Join(lines, "\n"))
|
||||
return c.fileManager.WriteToFile(string(constants.ResolvConf), data)
|
||||
|
||||
20
internal/dns/wait.go
Normal file
20
internal/dns/wait.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *configurator) WaitForUnbound() (err error) {
|
||||
const maxTries = 10
|
||||
const hostToResolve = "github.com"
|
||||
for try := 1; try <= maxTries; try++ {
|
||||
_, err := c.lookupIP(hostToResolve)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
c.logger.Warn("could not resolve %s (try %d of %d)", hostToResolve, try, maxTries)
|
||||
time.Sleep(time.Duration(maxTries * 50 * time.Millisecond))
|
||||
}
|
||||
return fmt.Errorf("Unbound does not seem to be working after %d tries", maxTries)
|
||||
}
|
||||
Reference in New Issue
Block a user