Maintenance: qdm12/dns from v1.4.0 to v1.6.0

This commit is contained in:
Quentin McGaw
2021-05-14 14:06:30 +00:00
parent 7d6763cde7
commit 5dba91c9ab
9 changed files with 185 additions and 167 deletions

View File

@@ -105,7 +105,7 @@ ENV VPNSP=pia \
# DNS over TLS
DOT=on \
DOT_PROVIDERS=cloudflare \
DOT_PRIVATE_ADDRESS=127.0.0.1/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,::1/128,fc00::/7,fe80::/10,::ffff:0:0/96 \
DOT_PRIVATE_ADDRESS=127.0.0.1/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,::1/128,fc00::/7,fe80::/10,::ffff:7f00:1/104,::ffff:a00:0/104,::ffff:a9fe:0/112,::ffff:ac10:0/108,::ffff:c0a8:0/112 \
DOT_VERBOSITY=1 \
DOT_VERBOSITY_DETAILS=0 \
DOT_VALIDATION_LOGLEVEL=0 \

View File

@@ -184,6 +184,9 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
if nonRootUsername != defaultUsername {
logger.Info("using existing username %s corresponding to user id %d", nonRootUsername, puid)
}
// set it for Unbound
// TODO remove this when migrating to qdm12/dns v2
allSettings.DNS.Unbound.Username = nonRootUsername
if err := os.Chown("/etc/unbound", puid, pgid); err != nil {
return err
@@ -292,7 +295,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
unboundLogger := logger.NewChild(logging.Settings{Prefix: "dns over tls: "})
unboundLooper := dns.NewLooper(dnsConf, allSettings.DNS, httpClient,
unboundLogger, nonRootUsername, puid, pgid)
unboundLogger, os.OpenFile)
dnsCtx, dnsDone := dnsWave.Add("unbound", shutdownRoutineTimeout)
// wait for unboundLooper.Restart or its ticker launched with RunRestartTicker
go unboundLooper.Run(dnsCtx, dnsDone)

4
go.mod
View File

@@ -6,10 +6,10 @@ require (
github.com/fatih/color v1.10.0
github.com/golang/mock v1.5.0
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/qdm12/dns v1.4.0
github.com/qdm12/dns v1.6.0
github.com/qdm12/golibs v0.0.0-20210402232648-cfebf1e87d1b
github.com/qdm12/ss-server v0.1.0
github.com/qdm12/updated v0.0.0-20210102005021-dd457d77f94a
github.com/qdm12/updated v0.0.0-20210102012151-76b7f5994638
github.com/stretchr/testify v1.7.0
github.com/vishvananda/netlink v1.1.0
golang.org/x/sys v0.0.0-20201223074533-0d417f636930

12
go.sum
View File

@@ -93,6 +93,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/miekg/dns v1.1.40 h1:pyyPFfGMnciYUk/mXpKkVmeMQjfXqt3FAJ2hy7tPiLA=
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
@@ -111,6 +113,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/qdm12/dns v1.4.0 h1:P8kVMGo7yIEZSk18fA9XQh9faL1CW20aHosWP064MAA=
github.com/qdm12/dns v1.4.0/go.mod h1:WUY4/U8Z2O8888DPrahrIBv8GdYeoIcEy4aUDecZ+UM=
github.com/qdm12/dns v1.6.0 h1:vnEEp9vl4ZkhVa3t/2xuS2oms4sfSMLalCjP56rH/Kg=
github.com/qdm12/dns v1.6.0/go.mod h1:eI5ynIACRn+CHABDe2k/+ymDy6v4yAarJs/JifeuQaE=
github.com/qdm12/golibs v0.0.0-20201227203847-2fd99ffdfdba/go.mod h1:pikkTN7g7zRuuAnERwqW1yAFq6pYmxrxpjiwGvb0Ysc=
github.com/qdm12/golibs v0.0.0-20210124192933-79a950eaf217/go.mod h1:pikkTN7g7zRuuAnERwqW1yAFq6pYmxrxpjiwGvb0Ysc=
github.com/qdm12/golibs v0.0.0-20210402232648-cfebf1e87d1b h1:tSD0qWqssS8AUFTGmlP1JFfbLViOt7xrjIxGZ1AFacY=
@@ -119,6 +123,8 @@ github.com/qdm12/ss-server v0.1.0 h1:WV9MkHCDEWRwe4WpnYFeR/zcZAxYoTbfntLDnw9AQ50
github.com/qdm12/ss-server v0.1.0/go.mod h1:ABVUkxubboL3vqBkOwDV9glX1/x7SnYrckBe5d+M/zw=
github.com/qdm12/updated v0.0.0-20210102005021-dd457d77f94a h1:gkyP+gMEeBgMgyRYGrVNcoy6cL1065IvXsyfB6xboIc=
github.com/qdm12/updated v0.0.0-20210102005021-dd457d77f94a/go.mod h1:bbJGxEYCnsA8WU4vBcXYU6mOoHyzdP458FIKP4mfLJM=
github.com/qdm12/updated v0.0.0-20210102012151-76b7f5994638 h1:dM8OO6LO+uou14C5a/LUrot0oyqzPcoiSho6cEmOROc=
github.com/qdm12/updated v0.0.0-20210102012151-76b7f5994638/go.mod h1:bbJGxEYCnsA8WU4vBcXYU6mOoHyzdP458FIKP4mfLJM=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
@@ -164,6 +170,7 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -172,6 +179,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -180,6 +189,7 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -200,6 +210,8 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -7,21 +7,19 @@ import (
"strings"
"time"
unboundmodels "github.com/qdm12/dns/pkg/models"
unbound "github.com/qdm12/dns/pkg/unbound"
"github.com/qdm12/dns/pkg/blacklist"
"github.com/qdm12/dns/pkg/unbound"
"github.com/qdm12/golibs/params"
)
// DNS contains settings to configure Unbound for DNS over TLS operation.
type DNS struct { //nolint:maligned
Enabled bool
PlaintextAddress net.IP
KeepNameserver bool
BlockMalicious bool
BlockAds bool
BlockSurveillance bool
UpdatePeriod time.Duration
Unbound unboundmodels.Settings
Enabled bool
PlaintextAddress net.IP
KeepNameserver bool
UpdatePeriod time.Duration
Unbound unbound.Settings
BlacklistBuild blacklist.BuilderSettings
}
func (settings *DNS) String() string {
@@ -50,16 +48,9 @@ func (settings *DNS) lines() (lines []string) {
lines = append(lines, indent+indent+indent+line)
}
if settings.BlockMalicious {
lines = append(lines, indent+indent+lastIndent+"Block malicious: enabled")
}
if settings.BlockAds {
lines = append(lines, indent+indent+lastIndent+"Block ads: enabled")
}
if settings.BlockSurveillance {
lines = append(lines, indent+indent+lastIndent+"Block surveillance: enabled")
lines = append(lines, indent+indent+lastIndent+"Blacklist:")
for _, line := range settings.BlacklistBuild.Lines(indent, lastIndent) {
lines = append(lines, indent+indent+indent+line)
}
if settings.UpdatePeriod > 0 {
@@ -71,9 +62,7 @@ func (settings *DNS) lines() (lines []string) {
var (
ErrUnboundSettings = errors.New("failed getting Unbound settings")
ErrDNSProviderNoData = errors.New("DNS provider has no associated data")
ErrDNSProviderNoTLS = errors.New("DNS provider does not support DNS over TLS")
ErrDNSNoIPv6Support = errors.New("no DNS provider supports IPv6")
ErrBlacklistSettings = errors.New("failed getting DNS blacklist settings")
)
func (settings *DNS) read(r reader) (err error) {
@@ -92,46 +81,20 @@ func (settings *DNS) read(r reader) (err error) {
}
// DNS over TLS external settings
settings.BlockMalicious, err = r.env.OnOff("BLOCK_MALICIOUS", params.Default("on"))
if err != nil {
return err
}
settings.BlockSurveillance, err = r.env.OnOff("BLOCK_SURVEILLANCE", params.Default("on"),
params.RetroKeys([]string{"BLOCK_NSA"}, r.onRetroActive))
if err != nil {
return err
}
settings.BlockAds, err = r.env.OnOff("BLOCK_ADS", params.Default("off"))
if err != nil {
return err
if err := settings.readBlacklistBuilding(r); err != nil {
return fmt.Errorf("%w: %s", ErrBlacklistSettings, err)
}
settings.UpdatePeriod, err = r.env.Duration("DNS_UPDATE_PERIOD", params.Default("24h"))
if err != nil {
return err
}
// Unbound settings
if err := settings.readUnbound(r); err != nil {
return fmt.Errorf("%w: %s", ErrUnboundSettings, err)
}
// Consistency check
IPv6Support := false
for _, provider := range settings.Unbound.Providers {
providerData, ok := unbound.GetProviderData(provider)
switch {
case !ok:
return fmt.Errorf("%w: %s", ErrDNSProviderNoData, provider)
case !providerData.SupportsTLS:
return fmt.Errorf("%w: %s", ErrDNSProviderNoTLS, provider)
case providerData.SupportsIPv6:
IPv6Support = true
}
}
if settings.Unbound.IPv6 && !IPv6Support {
return ErrDNSNoIPv6Support
}
return nil
}

View File

@@ -5,7 +5,9 @@ import (
"testing"
"time"
"github.com/qdm12/dns/pkg/models"
"github.com/qdm12/dns/pkg/blacklist"
"github.com/qdm12/dns/pkg/provider"
"github.com/qdm12/dns/pkg/unbound"
"github.com/stretchr/testify/assert"
)
@@ -28,13 +30,17 @@ func Test_DNS_Lines(t *testing.T) {
settings: DNS{
Enabled: true,
KeepNameserver: true,
Unbound: models.Settings{
Providers: []string{"cloudflare"},
Unbound: unbound.Settings{
Providers: []provider.Provider{
provider.Cloudflare(),
},
},
BlockMalicious: true,
BlockAds: true,
BlockSurveillance: true,
UpdatePeriod: time.Hour,
BlacklistBuild: blacklist.BuilderSettings{
BlockMalicious: true,
BlockAds: true,
BlockSurveillance: true,
},
UpdatePeriod: time.Hour,
},
lines: []string{
"|--DNS:",
@@ -42,7 +48,7 @@ func Test_DNS_Lines(t *testing.T) {
" |--DNS over TLS:",
" |--Unbound:",
" |--DNS over TLS providers:",
" |--cloudflare",
" |--Cloudflare",
" |--Listening port: 0",
" |--Access control:",
" |--Allowed:",
@@ -52,12 +58,9 @@ func Test_DNS_Lines(t *testing.T) {
" |--Verbosity level: 0/5",
" |--Verbosity details level: 0/4",
" |--Validation log level: 0/2",
" |--Blocked hostnames:",
" |--Blocked IP addresses:",
" |--Allowed hostnames:",
" |--Block malicious: enabled",
" |--Block ads: enabled",
" |--Block surveillance: enabled",
" |--Username: ",
" |--Blacklist:",
" |--Blocked categories: malicious, surveillance, ads",
" |--Update: every 1h0m0s",
},
},

View File

@@ -0,0 +1,91 @@
package configuration
import (
"errors"
"fmt"
"net"
"github.com/qdm12/golibs/params"
)
func (settings *DNS) readBlacklistBuilding(r reader) (err error) {
settings.BlacklistBuild.BlockMalicious, err = r.env.OnOff("BLOCK_MALICIOUS", params.Default("on"))
if err != nil {
return err
}
settings.BlacklistBuild.BlockSurveillance, err = r.env.OnOff("BLOCK_SURVEILLANCE", params.Default("on"),
params.RetroKeys([]string{"BLOCK_NSA"}, r.onRetroActive))
if err != nil {
return err
}
settings.BlacklistBuild.BlockAds, err = r.env.OnOff("BLOCK_ADS", params.Default("off"))
if err != nil {
return err
}
if err := settings.readPrivateAddresses(r.env); err != nil {
return err
}
if err := settings.readBlacklistUnblockedHostnames(r); err != nil {
return err
}
return nil
}
var (
ErrInvalidPrivateAddress = errors.New("private address is not a valid IP or CIDR range")
)
func (settings *DNS) readPrivateAddresses(env params.Env) (err error) {
privateAddresses, err := env.CSV("DOT_PRIVATE_ADDRESS")
if err != nil {
return err
} else if len(privateAddresses) == 0 {
return nil
}
ips := make([]net.IP, 0, len(privateAddresses))
ipNets := make([]*net.IPNet, 0, len(privateAddresses))
for _, address := range privateAddresses {
ip := net.ParseIP(address)
if ip != nil {
ips = append(ips, ip)
continue
}
_, ipNet, err := net.ParseCIDR(address)
if err == nil && ipNet != nil {
ipNets = append(ipNets, ipNet)
continue
}
return fmt.Errorf("%w: %s", ErrInvalidPrivateAddress, address)
}
settings.BlacklistBuild.AddBlockedIPs = append(settings.BlacklistBuild.AddBlockedIPs, ips...)
settings.BlacklistBuild.AddBlockedIPNets = append(settings.BlacklistBuild.AddBlockedIPNets, ipNets...)
return nil
}
func (settings *DNS) readBlacklistUnblockedHostnames(r reader) (err error) {
hostnames, err := r.env.CSV("UNBLOCK")
if err != nil {
return err
} else if len(hostnames) == 0 {
return nil
}
for _, hostname := range hostnames {
if !r.regex.MatchHostname(hostname) {
return fmt.Errorf("%w: %s", ErrInvalidHostname, hostname)
}
}
settings.BlacklistBuild.AllowedHosts = append(settings.BlacklistBuild.AllowedHosts, hostnames...)
return nil
}

View File

@@ -6,7 +6,7 @@ import (
"net"
"strings"
unbound "github.com/qdm12/dns/pkg/unbound"
"github.com/qdm12/dns/pkg/provider"
"github.com/qdm12/golibs/params"
)
@@ -47,14 +47,6 @@ func (settings *DNS) readUnbound(r reader) (err error) {
}
settings.Unbound.ValidationLogLevel = uint8(validationLogLevel)
if err := settings.readUnboundPrivateAddresses(r.env); err != nil {
return err
}
if err := settings.readUnboundUnblockedHostnames(r); err != nil {
return err
}
settings.Unbound.AccessControl.Allowed = []net.IPNet{
{
IP: net.IPv4zero,
@@ -78,56 +70,16 @@ func (settings *DNS) readUnboundProviders(env params.Env) (err error) {
if err != nil {
return err
}
for _, provider := range strings.Split(s, ",") {
_, ok := unbound.GetProviderData(provider)
if !ok {
return fmt.Errorf("%w: %s", ErrInvalidDNSOverTLSProvider, provider)
for _, field := range strings.Split(s, ",") {
dnsProvider, err := provider.Parse(field)
if err != nil {
return fmt.Errorf("%w: %s", ErrInvalidDNSOverTLSProvider, err)
}
settings.Unbound.Providers = append(settings.Unbound.Providers, provider)
settings.Unbound.Providers = append(settings.Unbound.Providers, dnsProvider)
}
return nil
}
var (
ErrInvalidPrivateAddress = errors.New("private address is not a valid IP or CIDR range")
)
func (settings *DNS) readUnboundPrivateAddresses(env params.Env) (err error) {
privateAddresses, err := env.CSV("DOT_PRIVATE_ADDRESS")
if err != nil {
return err
} else if len(privateAddresses) == 0 {
return nil
}
for _, address := range privateAddresses {
ip := net.ParseIP(address)
_, _, err := net.ParseCIDR(address)
if ip == nil && err != nil {
return fmt.Errorf("%w: %s", ErrInvalidPrivateAddress, address)
}
}
settings.Unbound.BlockedIPs = append(
settings.Unbound.BlockedIPs, privateAddresses...)
return nil
}
var (
ErrInvalidHostname = errors.New("invalid hostname")
)
func (settings *DNS) readUnboundUnblockedHostnames(r reader) (err error) {
hostnames, err := r.env.CSV("UNBLOCK")
if err != nil {
return err
} else if len(hostnames) == 0 {
return nil
}
for _, hostname := range hostnames {
if !r.regex.MatchHostname(hostname) {
return fmt.Errorf("%w: %s", ErrInvalidHostname, hostname)
}
}
settings.Unbound.AllowedHostnames = append(
settings.Unbound.AllowedHostnames, hostnames...)
return nil
}

View File

@@ -9,11 +9,15 @@ import (
"sync"
"time"
"github.com/qdm12/dns/pkg/blacklist"
"github.com/qdm12/dns/pkg/check"
"github.com/qdm12/dns/pkg/nameserver"
"github.com/qdm12/dns/pkg/unbound"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/golibs/logging"
"github.com/qdm12/golibs/os"
)
type Looper interface {
@@ -28,11 +32,9 @@ type Looper interface {
type looper struct {
state state
conf unbound.Configurator
blockBuilder blacklist.Builder
client *http.Client
logger logging.Logger
username string
puid int
pgid int
loopLock sync.Mutex
start chan struct{}
running chan models.LoopStatus
@@ -42,23 +44,22 @@ type looper struct {
backoffTime time.Duration
timeNow func() time.Time
timeSince func(time.Time) time.Duration
openFile os.OpenFileFunc
}
const defaultBackoffTime = 10 * time.Second
func NewLooper(conf unbound.Configurator, settings configuration.DNS, client *http.Client,
logger logging.Logger, username string, puid, pgid int) Looper {
logger logging.Logger, openFile os.OpenFileFunc) Looper {
return &looper{
state: state{
status: constants.Stopped,
settings: settings,
},
conf: conf,
blockBuilder: blacklist.NewBuilder(client),
client: client,
logger: logger,
username: username,
puid: puid,
pgid: pgid,
start: make(chan struct{}),
running: make(chan models.LoopStatus),
stop: make(chan struct{}),
@@ -67,6 +68,7 @@ func NewLooper(conf unbound.Configurator, settings configuration.DNS, client *ht
backoffTime: defaultBackoffTime,
timeNow: time.Now,
timeSince: time.Since,
openFile: openFile,
}
}
@@ -197,12 +199,15 @@ func (l *looper) setupUnbound(ctx context.Context, previousCrashed bool) (
collectLinesDone := make(chan struct{})
go l.collectLines(stdoutLines, stderrLines, collectLinesDone)
l.conf.UseDNSInternally(net.IP{127, 0, 0, 1}) // use Unbound
if err := l.conf.UseDNSSystemWide(net.IP{127, 0, 0, 1}, settings.KeepNameserver); err != nil { // use Unbound
// use Unbound
nameserver.UseDNSInternally(net.IP{127, 0, 0, 1})
err = nameserver.UseDNSSystemWide(l.openFile,
net.IP{127, 0, 0, 1}, settings.KeepNameserver)
if err != nil {
l.logger.Error(err)
}
if err := l.conf.WaitForUnbound(ctx); err != nil {
if err := check.WaitForDNS(ctx, net.DefaultResolver); err != nil {
if !previousCrashed {
l.running <- constants.Crashed
}
@@ -243,34 +248,25 @@ func (l *looper) useUnencryptedDNS(fallback bool) {
} else {
l.logger.Info("using plaintext DNS at address %s", targetIP)
}
l.conf.UseDNSInternally(targetIP)
if err := l.conf.UseDNSSystemWide(targetIP, settings.KeepNameserver); err != nil {
nameserver.UseDNSInternally(targetIP)
if err := nameserver.UseDNSSystemWide(l.openFile,
targetIP, settings.KeepNameserver); err != nil {
l.logger.Error(err)
}
return
}
// Try with any IPv4 address from the providers chosen
for _, provider := range settings.Unbound.Providers {
data, _ := unbound.GetProviderData(provider)
for _, targetIP = range data.IPs {
if targetIP.To4() != nil {
if fallback {
l.logger.Info("falling back on plaintext DNS at address %s", targetIP)
} else {
l.logger.Info("using plaintext DNS at address %s", targetIP)
}
l.conf.UseDNSInternally(targetIP)
if err := l.conf.UseDNSSystemWide(targetIP, settings.KeepNameserver); err != nil {
l.logger.Error(err)
}
return
}
}
provider := settings.Unbound.Providers[0]
targetIP = provider.DoT().IPv4[0]
if fallback {
l.logger.Info("falling back on plaintext DNS at address " + targetIP.String())
} else {
l.logger.Info("using plaintext DNS at address " + targetIP.String())
}
nameserver.UseDNSInternally(targetIP)
if err := nameserver.UseDNSSystemWide(l.openFile, targetIP, settings.KeepNameserver); err != nil {
l.logger.Error(err)
}
// No IPv4 address found
l.logger.Error("no ipv4 DNS address found for providers %s", settings.Unbound.Providers)
}
func (l *looper) RunRestartTicker(ctx context.Context, done chan<- struct{}) {
@@ -339,18 +335,16 @@ func (l *looper) updateFiles(ctx context.Context) (err error) {
settings := l.GetSettings()
l.logger.Info("downloading hostnames and IP block lists")
hostnameLines, ipLines, errs := l.conf.BuildBlocked(ctx, l.client,
settings.BlockMalicious, settings.BlockAds, settings.BlockSurveillance,
settings.Unbound.BlockedHostnames, settings.Unbound.BlockedIPs,
settings.Unbound.AllowedHostnames)
blockedHostnames, blockedIPs, blockedIPNets, errs := l.blockBuilder.All(
ctx, settings.BlacklistBuild)
for _, err := range errs {
l.logger.Warn(err)
}
if err := l.conf.MakeUnboundConf(
settings.Unbound, hostnameLines, ipLines,
l.username, l.puid, l.pgid); err != nil {
return err
}
return nil
// TODO change to BlockHostnames() when migrating to qdm12/dns v2
settings.Unbound.Blacklist.FqdnHostnames = blockedHostnames
settings.Unbound.Blacklist.IPs = blockedIPs
settings.Unbound.Blacklist.IPNets = blockedIPNets
return l.conf.MakeUnboundConf(settings.Unbound)
}