feat(dns): replace unbound with qdm12/dns@v2.0.0-beta-rc6 (#1742)

- Faster start up
- Clearer error messages
- Allow for more Gluetun-specific customization
- DNSSEC validation is dropped for now (it's sort of unneeded)
- Fix #137
This commit is contained in:
Quentin McGaw
2024-08-21 14:35:41 +02:00
committed by GitHub
parent 3f130931d2
commit 4d60b71583
30 changed files with 387 additions and 762 deletions

View File

@@ -166,9 +166,6 @@ ENV VPN_SERVICE_PROVIDER=pia \
DOT=on \ DOT=on \
DOT_PROVIDERS=cloudflare \ 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:7f00:1/104,::ffff:a00:0/104,::ffff:a9fe:0/112,::ffff:ac10:0/108,::ffff:c0a8:0/112 \ 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 \
DOT_CACHING=on \ DOT_CACHING=on \
DOT_IPV6=off \ DOT_IPV6=off \
BLOCK_MALICIOUS=on \ BLOCK_MALICIOUS=on \
@@ -226,10 +223,9 @@ RUN apk add --no-cache --update -l wget && \
apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.17/main" openvpn\~2.5 && \ apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.17/main" openvpn\~2.5 && \
mv /usr/sbin/openvpn /usr/sbin/openvpn2.5 && \ mv /usr/sbin/openvpn /usr/sbin/openvpn2.5 && \
apk del openvpn && \ apk del openvpn && \
apk add --no-cache --update openvpn ca-certificates iptables iptables-legacy unbound tzdata && \ apk add --no-cache --update openvpn ca-certificates iptables iptables-legacy tzdata && \
mv /usr/sbin/openvpn /usr/sbin/openvpn2.6 && \ mv /usr/sbin/openvpn /usr/sbin/openvpn2.6 && \
rm -rf /var/cache/apk/* /etc/unbound/* /usr/sbin/unbound-* /etc/openvpn/*.sh /usr/lib/openvpn/plugins/openvpn-plugin-down-root.so && \ rm -rf /var/cache/apk/* /etc/openvpn/*.sh /usr/lib/openvpn/plugins/openvpn-plugin-down-root.so && \
deluser openvpn && \ deluser openvpn && \
deluser unbound && \
mkdir /gluetun mkdir /gluetun
COPY --from=build /tmp/gobuild/entrypoint /gluetun-entrypoint COPY --from=build /tmp/gobuild/entrypoint /gluetun-entrypoint

View File

@@ -75,7 +75,6 @@ Lightweight swiss-knife-like VPN client to multiple VPN service providers
- Compatible with amd64, i686 (32 bit), **ARM** 64 bit, ARM 32 bit v6 and v7, and even ppc64le 🎆 - Compatible with amd64, i686 (32 bit), **ARM** 64 bit, ARM 32 bit v6 and v7, and even ppc64le 🎆
- Custom VPN server side port forwarding for [Perfect Privacy](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/perfect-privacy.md#vpn-server-port-forwarding), [Private Internet Access](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/private-internet-access.md#vpn-server-port-forwarding), [PrivateVPN](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/privatevpn.md#vpn-server-port-forwarding) and [ProtonVPN](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/protonvpn.md#vpn-server-port-forwarding) - Custom VPN server side port forwarding for [Perfect Privacy](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/perfect-privacy.md#vpn-server-port-forwarding), [Private Internet Access](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/private-internet-access.md#vpn-server-port-forwarding), [PrivateVPN](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/privatevpn.md#vpn-server-port-forwarding) and [ProtonVPN](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/protonvpn.md#vpn-server-port-forwarding)
- Possibility of split horizon DNS by selecting multiple DNS over TLS providers - Possibility of split horizon DNS by selecting multiple DNS over TLS providers
- Unbound subprogram drops root privileges once launched
- Can work as a Kubernetes sidecar container, thanks @rorph - Can work as a Kubernetes sidecar container, thanks @rorph
## Setup ## Setup

View File

@@ -13,7 +13,6 @@ import (
_ "time/tzdata" _ "time/tzdata"
_ "github.com/breml/rootcerts" _ "github.com/breml/rootcerts"
"github.com/qdm12/dns/pkg/unbound"
"github.com/qdm12/gluetun/internal/alpine" "github.com/qdm12/gluetun/internal/alpine"
"github.com/qdm12/gluetun/internal/cli" "github.com/qdm12/gluetun/internal/cli"
"github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/configuration/settings"
@@ -51,7 +50,6 @@ import (
"github.com/qdm12/goshutdown/order" "github.com/qdm12/goshutdown/order"
"github.com/qdm12/gosplash" "github.com/qdm12/gosplash"
"github.com/qdm12/log" "github.com/qdm12/log"
"github.com/qdm12/updated/pkg/dnscrypto"
) )
//nolint:gochecknoglobals //nolint:gochecknoglobals
@@ -188,7 +186,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
} }
var allSettings settings.Settings var allSettings settings.Settings
err = allSettings.Read(reader) err = allSettings.Read(reader, logger)
if err != nil { if err != nil {
return err return err
} }
@@ -269,16 +267,11 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
ovpnConf := openvpn.New( ovpnConf := openvpn.New(
logger.New(log.SetComponent("openvpn configurator")), logger.New(log.SetComponent("openvpn configurator")),
cmder, puid, pgid) cmder, puid, pgid)
dnsCrypto := dnscrypto.New(httpClient, "", "")
const cacertsPath = "/etc/ssl/certs/ca-certificates.crt"
dnsConf := unbound.NewConfigurator(nil, cmder, dnsCrypto,
"/etc/unbound", "/usr/sbin/unbound", cacertsPath)
err = printVersions(ctx, logger, []printVersionElement{ err = printVersions(ctx, logger, []printVersionElement{
{name: "Alpine", getVersion: alpineConf.Version}, {name: "Alpine", getVersion: alpineConf.Version},
{name: "OpenVPN 2.5", getVersion: ovpnConf.Version25}, {name: "OpenVPN 2.5", getVersion: ovpnConf.Version25},
{name: "OpenVPN 2.6", getVersion: ovpnConf.Version26}, {name: "OpenVPN 2.6", getVersion: ovpnConf.Version26},
{name: "Unbound", getVersion: dnsConf.Version},
{name: "IPtables", getVersion: firewallConf.Version}, {name: "IPtables", getVersion: firewallConf.Version},
}) })
if err != nil { if err != nil {
@@ -306,15 +299,8 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
if nonRootUsername != defaultUsername { if nonRootUsername != defaultUsername {
logger.Info("using existing username " + nonRootUsername + " corresponding to user id " + fmt.Sprint(puid)) logger.Info("using existing username " + nonRootUsername + " corresponding to user id " + fmt.Sprint(puid))
} }
// set it for Unbound
// TODO remove this when migrating to qdm12/dns v2
allSettings.DNS.DoT.Unbound.Username = nonRootUsername
allSettings.VPN.OpenVPN.ProcessUser = nonRootUsername allSettings.VPN.OpenVPN.ProcessUser = nonRootUsername
if err := os.Chown("/etc/unbound", puid, pgid); err != nil {
return err
}
if err := routingConf.Setup(); err != nil { if err := routingConf.Setup(); err != nil {
if strings.Contains(err.Error(), "operation not permitted") { if strings.Contains(err.Error(), "operation not permitted") {
logger.Warn("💡 Tip: Are you passing NET_ADMIN capability to gluetun?") logger.Warn("💡 Tip: Are you passing NET_ADMIN capability to gluetun?")
@@ -396,18 +382,22 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
return fmt.Errorf("starting port forwarding loop: %w", err) return fmt.Errorf("starting port forwarding loop: %w", err)
} }
unboundLogger := logger.New(log.SetComponent("dns")) dnsLogger := logger.New(log.SetComponent("dns"))
unboundLooper := dns.NewLoop(dnsConf, allSettings.DNS, httpClient, dnsLooper, err := dns.NewLoop(allSettings.DNS, httpClient,
unboundLogger) dnsLogger)
if err != nil {
return fmt.Errorf("creating DNS loop: %w", err)
}
dnsHandler, dnsCtx, dnsDone := goshutdown.NewGoRoutineHandler( dnsHandler, dnsCtx, dnsDone := goshutdown.NewGoRoutineHandler(
"unbound", goroutine.OptionTimeout(defaultShutdownTimeout)) "dns", goroutine.OptionTimeout(defaultShutdownTimeout))
// wait for unboundLooper.Restart or its ticker launched with RunRestartTicker // wait for dnsLooper.Restart or its ticker launched with RunRestartTicker
go unboundLooper.Run(dnsCtx, dnsDone) go dnsLooper.Run(dnsCtx, dnsDone)
otherGroupHandler.Add(dnsHandler) otherGroupHandler.Add(dnsHandler)
dnsTickerHandler, dnsTickerCtx, dnsTickerDone := goshutdown.NewGoRoutineHandler( dnsTickerHandler, dnsTickerCtx, dnsTickerDone := goshutdown.NewGoRoutineHandler(
"dns ticker", goroutine.OptionTimeout(defaultShutdownTimeout)) "dns ticker", goroutine.OptionTimeout(defaultShutdownTimeout))
go unboundLooper.RunRestartTicker(dnsTickerCtx, dnsTickerDone) go dnsLooper.RunRestartTicker(dnsTickerCtx, dnsTickerDone)
controlGroupHandler.Add(dnsTickerHandler) controlGroupHandler.Add(dnsTickerHandler)
publicipAPI, _ := pubipapi.ParseProvider(allSettings.PublicIP.API) publicipAPI, _ := pubipapi.ParseProvider(allSettings.PublicIP.API)
@@ -434,7 +424,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
vpnLogger := logger.New(log.SetComponent("vpn")) vpnLogger := logger.New(log.SetComponent("vpn"))
vpnLooper := vpn.NewLoop(allSettings.VPN, ipv6Supported, allSettings.Firewall.VPNInputPorts, vpnLooper := vpn.NewLoop(allSettings.VPN, ipv6Supported, allSettings.Firewall.VPNInputPorts,
providers, storage, ovpnConf, netLinker, firewallConf, routingConf, portForwardLooper, providers, storage, ovpnConf, netLinker, firewallConf, routingConf, portForwardLooper,
cmder, publicIPLooper, unboundLooper, vpnLogger, httpClient, cmder, publicIPLooper, dnsLooper, vpnLogger, httpClient,
buildInfo, *allSettings.Version.Enabled) buildInfo, *allSettings.Version.Enabled)
vpnHandler, vpnCtx, vpnDone := goshutdown.NewGoRoutineHandler( vpnHandler, vpnCtx, vpnDone := goshutdown.NewGoRoutineHandler(
"vpn", goroutine.OptionTimeout(time.Second)) "vpn", goroutine.OptionTimeout(time.Second))
@@ -474,7 +464,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
"http server", goroutine.OptionTimeout(defaultShutdownTimeout)) "http server", goroutine.OptionTimeout(defaultShutdownTimeout))
httpServer, err := server.New(httpServerCtx, controlServerAddress, controlServerLogging, httpServer, err := server.New(httpServerCtx, controlServerAddress, controlServerLogging,
logger.New(log.SetComponent("http server")), logger.New(log.SetComponent("http server")),
buildInfo, vpnLooper, portForwardLooper, unboundLooper, updaterLooper, publicIPLooper, buildInfo, vpnLooper, portForwardLooper, dnsLooper, updaterLooper, publicIPLooper,
storage, ipv6Supported) storage, ipv6Supported)
if err != nil { if err != nil {
return fmt.Errorf("setting up control server: %w", err) return fmt.Errorf("setting up control server: %w", err)

21
go.mod
View File

@@ -8,7 +8,7 @@ require (
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
github.com/klauspost/compress v1.17.9 github.com/klauspost/compress v1.17.9
github.com/klauspost/pgzip v1.2.6 github.com/klauspost/pgzip v1.2.6
github.com/qdm12/dns v1.11.0 github.com/qdm12/dns/v2 v2.0.0-rc6
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6 github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6
github.com/qdm12/gosettings v0.4.2 github.com/qdm12/gosettings v0.4.2
github.com/qdm12/goshutdown v0.3.0 github.com/qdm12/goshutdown v0.3.0
@@ -16,7 +16,6 @@ require (
github.com/qdm12/gotree v0.2.0 github.com/qdm12/gotree v0.2.0
github.com/qdm12/log v0.1.0 github.com/qdm12/log v0.1.0
github.com/qdm12/ss-server v0.6.0 github.com/qdm12/ss-server v0.6.0
github.com/qdm12/updated v0.0.0-20210603204757-205acfe6937e
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/ulikunitz/xz v0.5.11 github.com/ulikunitz/xz v0.5.11
github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netlink v1.2.1-beta.2
@@ -27,29 +26,37 @@ require (
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
gopkg.in/ini.v1 v1.67.0 gopkg.in/ini.v1 v1.67.0
inet.af/netaddr v0.0.0-20220811202034-502d2d690317
) )
require ( require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/go-cmp v0.5.9 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/josharian/native v1.1.0 // indirect github.com/josharian/native v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mdlayher/genetlink v1.3.2 // indirect github.com/mdlayher/genetlink v1.3.2 // indirect
github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/netlink v1.7.2 // indirect
github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/socket v0.4.1 // indirect
github.com/miekg/dns v1.1.40 // indirect github.com/miekg/dns v1.1.55 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect
golang.org/x/crypto v0.26.0 // indirect golang.org/x/crypto v0.26.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sync v0.8.0 // indirect golang.org/x/sync v0.8.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
kernel.org/pub/linux/libs/security/libcap/cap v1.2.69 // indirect kernel.org/pub/linux/libs/security/libcap/cap v1.2.69 // indirect
kernel.org/pub/linux/libs/security/libcap/psx v1.2.69 // indirect kernel.org/pub/linux/libs/security/libcap/psx v1.2.69 // indirect

149
go.sum
View File

@@ -1,65 +1,38 @@
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/breml/rootcerts v0.2.17 h1:0/M2BE2Apw0qEJCXDOkaiu7d5Sx5ObNfe1BkImJ4u1I= github.com/breml/rootcerts v0.2.17 h1:0/M2BE2Apw0qEJCXDOkaiu7d5Sx5ObNfe1BkImJ4u1I=
github.com/breml/rootcerts v0.2.17/go.mod h1:S/PKh+4d1HUn4HQovEB8hPJZO6pUZYrIhmXBhsegfXw= github.com/breml/rootcerts v0.2.17/go.mod h1:S/PKh+4d1HUn4HQovEB8hPJZO6pUZYrIhmXBhsegfXw=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.17.2/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
github.com/go-openapi/runtime v0.17.2/go.mod h1:QO936ZXeisByFmZEO1IS1Dqhtf4QV1sYYFtIq6Ld86Q=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gotify/go-api-client/v2 v2.0.4/go.mod h1:VKiah/UK20bXsr0JObE1eBVLW44zbBouzjuri9iwjFU=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kyokomi/emoji v2.2.4+incompatible/go.mod h1:mZ6aGCD7yk8j6QY6KICwnZ2pxoszVseX1DNoGtU2tBA=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@@ -67,30 +40,33 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw= github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o= github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/miekg/dns v1.1.40 h1:pyyPFfGMnciYUk/mXpKkVmeMQjfXqt3FAJ2hy7tPiLA= github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws= github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc= github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee/go.mod h1:3uODdxMgOaPYeWU7RzZLxVtJHZ/x1f/iHkBZuKJDzuY= github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee/go.mod h1:3uODdxMgOaPYeWU7RzZLxVtJHZ/x1f/iHkBZuKJDzuY=
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/qdm12/dns v1.11.0 h1:jpcD5DZXXQSQe5a263PL09ghukiIdptvXFOZvyKEm6Q= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/qdm12/dns v1.11.0/go.mod h1:FmQsNOUcrrZ4UFzWAiED56AKXeNgaX3ySbmPwEfNjjE= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/qdm12/golibs v0.0.0-20210603202746-e5494e9c2ebb/go.mod h1:15RBzkun0i8XB7ADIoLJWp9ITRgsz3LroEI2FiOXLRg= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/qdm12/golibs v0.0.0-20210723175634-a75ca7fd74c2/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/qdm12/dns/v2 v2.0.0-rc6 h1:h5KpuqZ3IMoSbz2a0OkHzIVc9/jk2vuIm9RoKJuaI78=
github.com/qdm12/dns/v2 v2.0.0-rc6/go.mod h1:Oh34IJIG55BgHoACOf+cgZCgDiFuiJZ6r6gQW58FN+k=
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6 h1:bge5AL7cjHJMPz+5IOz5yF01q/l8No6+lIEBieA8gMg= github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6 h1:bge5AL7cjHJMPz+5IOz5yF01q/l8No6+lIEBieA8gMg=
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg= github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg=
github.com/qdm12/gosettings v0.4.2 h1:Gb39NScPr7OQV+oy0o1OD7A121udITDJuUGa7ljDF58= github.com/qdm12/gosettings v0.4.2 h1:Gb39NScPr7OQV+oy0o1OD7A121udITDJuUGa7ljDF58=
@@ -105,17 +81,11 @@ github.com/qdm12/log v0.1.0 h1:jYBd/xscHYpblzZAd2kjZp2YmuYHjAAfbTViJWxoPTw=
github.com/qdm12/log v0.1.0/go.mod h1:Vchi5M8uBvHfPNIblN4mjXn/oSbiWguQIbsgF1zdQPI= github.com/qdm12/log v0.1.0/go.mod h1:Vchi5M8uBvHfPNIblN4mjXn/oSbiWguQIbsgF1zdQPI=
github.com/qdm12/ss-server v0.6.0 h1:OaOdCIBXx0z3DGHPT6Th0v88vGa3MtAS4oRgUsDHGZE= github.com/qdm12/ss-server v0.6.0 h1:OaOdCIBXx0z3DGHPT6Th0v88vGa3MtAS4oRgUsDHGZE=
github.com/qdm12/ss-server v0.6.0/go.mod h1:0BO/zEmtTiLDlmQEcjtoHTC+w+cWxwItjBuGP6TWM78= github.com/qdm12/ss-server v0.6.0/go.mod h1:0BO/zEmtTiLDlmQEcjtoHTC+w+cWxwItjBuGP6TWM78=
github.com/qdm12/updated v0.0.0-20210603204757-205acfe6937e h1:4q+uFLawkaQRq3yARYLsjJPZd2wYwxn4g6G/5v0xW1g=
github.com/qdm12/updated v0.0.0-20210603204757-205acfe6937e/go.mod h1:UvJRGkZ9XL3/D7e7JiTTVLm1F3Cymd3/gFpD6frEpBo=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= 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/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
@@ -125,63 +95,38 @@ github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0m
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go4.org/intern v0.0.0-20210108033219-3eb7198706b2/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 h1:WJhcL4p+YeDxmZWg141nRm7XC8IDmhz7lk5GpadO1Sg=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 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/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/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-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -191,20 +136,19 @@ golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
@@ -212,25 +156,20 @@ golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uI
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ= gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY= gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY=
inet.af/netaddr v0.0.0-20210511181906-37180328850c/go.mod h1:z0nx+Dh+7N7CC8V5ayHtHGpZpxLQZZxkIaaz6HN65Ls=
inet.af/netaddr v0.0.0-20220811202034-502d2d690317 h1:U2fwK6P2EqmopP/hFLTOAjWTki0qgd4GMJn5X8wOleU=
inet.af/netaddr v0.0.0-20220811202034-502d2d690317/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.69 h1:N0m3tKYbkRMmDobh/47ngz+AWeV7PcfXMDi8xu3Vrag= kernel.org/pub/linux/libs/security/libcap/cap v1.2.69 h1:N0m3tKYbkRMmDobh/47ngz+AWeV7PcfXMDi8xu3Vrag=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.69/go.mod h1:Tk5Ip2TuxaWGpccL7//rAsLRH6RQ/jfqTGxuN/+i/FQ= kernel.org/pub/linux/libs/security/libcap/cap v1.2.69/go.mod h1:Tk5Ip2TuxaWGpccL7//rAsLRH6RQ/jfqTGxuN/+i/FQ=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.69 h1:IdrOs1ZgwGw5CI+BH6GgVVlOt+LAXoPyh7enr8lfaXs= kernel.org/pub/linux/libs/security/libcap/psx v1.2.69 h1:IdrOs1ZgwGw5CI+BH6GgVVlOt+LAXoPyh7enr8lfaXs=

View File

@@ -49,7 +49,7 @@ func (c *CLI) OpenvpnConfig(logger OpenvpnConfigLogger, reader *reader.Reader,
} }
var allSettings settings.Settings var allSettings settings.Settings
err = allSettings.Read(reader) err = allSettings.Read(reader, logger)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -0,0 +1,25 @@
package settings
import (
"slices"
"github.com/qdm12/gosettings/reader"
"golang.org/x/exp/maps"
)
func readObsolete(r *reader.Reader) (warnings []string) {
keyToMessage := map[string]string{
"DOT_VERBOSITY": "DOT_VERBOSITY is obsolete, use LOG_LEVEL instead.",
"DOT_VERBOSITY_DETAILS": "DOT_VERBOSITY_DETAILS is obsolete because it was specific to Unbound.",
"DOT_VALIDATION_LOGLEVEL": "DOT_VALIDATION_LOGLEVEL is obsolete because DNSSEC validation is not implemented.",
}
sortedKeys := maps.Keys(keyToMessage)
slices.Sort(sortedKeys)
warnings = make([]string, 0, len(keyToMessage))
for _, key := range sortedKeys {
if r.Get(key) != nil {
warnings = append(warnings, keyToMessage[key])
}
}
return warnings
}

View File

@@ -3,10 +3,11 @@ package settings
import ( import (
"errors" "errors"
"fmt" "fmt"
"net/http"
"net/netip" "net/netip"
"regexp" "regexp"
"github.com/qdm12/dns/pkg/blacklist" "github.com/qdm12/dns/v2/pkg/blockbuilder"
"github.com/qdm12/gosettings" "github.com/qdm12/gosettings"
"github.com/qdm12/gosettings/reader" "github.com/qdm12/gosettings/reader"
"github.com/qdm12/gotree" "github.com/qdm12/gotree"
@@ -74,16 +75,18 @@ func (b *DNSBlacklist) overrideWith(other DNSBlacklist) {
b.AddBlockedIPPrefixes = gosettings.OverrideWithSlice(b.AddBlockedIPPrefixes, other.AddBlockedIPPrefixes) b.AddBlockedIPPrefixes = gosettings.OverrideWithSlice(b.AddBlockedIPPrefixes, other.AddBlockedIPPrefixes)
} }
func (b DNSBlacklist) ToBlacklistFormat() (settings blacklist.BuilderSettings, err error) { func (b DNSBlacklist) ToBlockBuilderSettings(client *http.Client) (
return blacklist.BuilderSettings{ settings blockbuilder.Settings) {
BlockMalicious: *b.BlockMalicious, return blockbuilder.Settings{
BlockAds: *b.BlockAds, Client: client,
BlockSurveillance: *b.BlockSurveillance, BlockMalicious: b.BlockMalicious,
BlockAds: b.BlockAds,
BlockSurveillance: b.BlockSurveillance,
AllowedHosts: b.AllowedHosts, AllowedHosts: b.AllowedHosts,
AddBlockedHosts: b.AddBlockedHosts, AddBlockedHosts: b.AddBlockedHosts,
AddBlockedIPs: netipAddressesToNetaddrIPs(b.AddBlockedIPs), AddBlockedIPs: b.AddBlockedIPs,
AddBlockedIPPrefixes: netipPrefixesToNetaddrIPPrefixes(b.AddBlockedIPPrefixes), AddBlockedIPPrefixes: b.AddBlockedIPPrefixes,
}, nil }
} }
func (b DNSBlacklist) String() string { func (b DNSBlacklist) String() string {

View File

@@ -3,8 +3,10 @@ package settings
import ( import (
"errors" "errors"
"fmt" "fmt"
"net/netip"
"time" "time"
"github.com/qdm12/dns/v2/pkg/provider"
"github.com/qdm12/gosettings" "github.com/qdm12/gosettings"
"github.com/qdm12/gosettings/reader" "github.com/qdm12/gosettings/reader"
"github.com/qdm12/gotree" "github.com/qdm12/gotree"
@@ -16,14 +18,18 @@ type DoT struct {
// and used. It defaults to true, and cannot be nil // and used. It defaults to true, and cannot be nil
// in the internal state. // in the internal state.
Enabled *bool Enabled *bool
// UpdatePeriod is the period to update DNS block // UpdatePeriod is the period to update DNS block lists.
// lists and cryptographic files for DNSSEC validation.
// It can be set to 0 to disable the update. // It can be set to 0 to disable the update.
// It defaults to 24h and cannot be nil in // It defaults to 24h and cannot be nil in
// the internal state. // the internal state.
UpdatePeriod *time.Duration UpdatePeriod *time.Duration
// Unbound contains settings to configure Unbound. // Providers is a list of DNS over TLS providers
Unbound Unbound Providers []string `json:"providers"`
// Caching is true if the DoT server should cache
// DNS responses.
Caching *bool `json:"caching"`
// IPv6 is true if the DoT server should connect over IPv6.
IPv6 *bool `json:"ipv6"`
// Blacklist contains settings to configure the filter // Blacklist contains settings to configure the filter
// block lists. // block lists.
Blacklist DNSBlacklist Blacklist DNSBlacklist
@@ -40,9 +46,12 @@ func (d DoT) validate() (err error) {
ErrDoTUpdatePeriodTooShort, *d.UpdatePeriod, minUpdatePeriod) ErrDoTUpdatePeriodTooShort, *d.UpdatePeriod, minUpdatePeriod)
} }
err = d.Unbound.validate() providers := provider.NewProviders()
if err != nil { for _, providerName := range d.Providers {
return err _, err := providers.Get(providerName)
if err != nil {
return err
}
} }
err = d.Blacklist.validate() err = d.Blacklist.validate()
@@ -57,7 +66,9 @@ func (d *DoT) copy() (copied DoT) {
return DoT{ return DoT{
Enabled: gosettings.CopyPointer(d.Enabled), Enabled: gosettings.CopyPointer(d.Enabled),
UpdatePeriod: gosettings.CopyPointer(d.UpdatePeriod), UpdatePeriod: gosettings.CopyPointer(d.UpdatePeriod),
Unbound: d.Unbound.copy(), Providers: gosettings.CopySlice(d.Providers),
Caching: gosettings.CopyPointer(d.Caching),
IPv6: gosettings.CopyPointer(d.IPv6),
Blacklist: d.Blacklist.copy(), Blacklist: d.Blacklist.copy(),
} }
} }
@@ -68,7 +79,9 @@ func (d *DoT) copy() (copied DoT) {
func (d *DoT) overrideWith(other DoT) { func (d *DoT) overrideWith(other DoT) {
d.Enabled = gosettings.OverrideWithPointer(d.Enabled, other.Enabled) d.Enabled = gosettings.OverrideWithPointer(d.Enabled, other.Enabled)
d.UpdatePeriod = gosettings.OverrideWithPointer(d.UpdatePeriod, other.UpdatePeriod) d.UpdatePeriod = gosettings.OverrideWithPointer(d.UpdatePeriod, other.UpdatePeriod)
d.Unbound.overrideWith(other.Unbound) d.Providers = gosettings.OverrideWithSlice(d.Providers, other.Providers)
d.Caching = gosettings.OverrideWithPointer(d.Caching, other.Caching)
d.IPv6 = gosettings.OverrideWithPointer(d.IPv6, other.IPv6)
d.Blacklist.overrideWith(other.Blacklist) d.Blacklist.overrideWith(other.Blacklist)
} }
@@ -76,10 +89,26 @@ func (d *DoT) setDefaults() {
d.Enabled = gosettings.DefaultPointer(d.Enabled, true) d.Enabled = gosettings.DefaultPointer(d.Enabled, true)
const defaultUpdatePeriod = 24 * time.Hour const defaultUpdatePeriod = 24 * time.Hour
d.UpdatePeriod = gosettings.DefaultPointer(d.UpdatePeriod, defaultUpdatePeriod) d.UpdatePeriod = gosettings.DefaultPointer(d.UpdatePeriod, defaultUpdatePeriod)
d.Unbound.setDefaults() d.Providers = gosettings.DefaultSlice(d.Providers, []string{
provider.Cloudflare().Name,
})
d.Caching = gosettings.DefaultPointer(d.Caching, true)
d.IPv6 = gosettings.DefaultPointer(d.IPv6, false)
d.Blacklist.setDefaults() d.Blacklist.setDefaults()
} }
func (d DoT) GetFirstPlaintextIPv4() (ipv4 netip.Addr) {
providers := provider.NewProviders()
provider, err := providers.Get(d.Providers[0])
if err != nil {
// Settings should be validated before calling this function,
// so an error happening here is a programming error.
panic(err)
}
return provider.DoT.IPv4[0].Addr()
}
func (d DoT) String() string { func (d DoT) String() string {
return d.toLinesNode().String() return d.toLinesNode().String()
} }
@@ -98,7 +127,14 @@ func (d DoT) toLinesNode() (node *gotree.Node) {
} }
node.Appendf("Update period: %s", update) node.Appendf("Update period: %s", update)
node.AppendNode(d.Unbound.toLinesNode()) upstreamResolvers := node.Appendf("Upstream resolvers:")
for _, provider := range d.Providers {
upstreamResolvers.Appendf(provider)
}
node.Appendf("Caching: %s", gosettings.BoolToYesNo(d.Caching))
node.Appendf("IPv6: %s", gosettings.BoolToYesNo(d.IPv6))
node.AppendNode(d.Blacklist.toLinesNode()) node.AppendNode(d.Blacklist.toLinesNode())
return node return node
@@ -115,7 +151,14 @@ func (d *DoT) read(reader *reader.Reader) (err error) {
return err return err
} }
err = d.Unbound.read(reader) d.Providers = reader.CSV("DOT_PROVIDERS")
d.Caching, err = reader.BoolPtr("DOT_CACHING")
if err != nil {
return err
}
d.IPv6, err = reader.BoolPtr("DOT_IPV6")
if err != nil { if err != nil {
return err return err
} }

View File

@@ -1,4 +1,3 @@
package settings package settings
func boolPtr(b bool) *bool { return &b } func boolPtr(b bool) *bool { return &b }
func uint8Ptr(n uint8) *uint8 { return &n }

View File

@@ -1,36 +0,0 @@
package settings
import (
"net/netip"
"inet.af/netaddr"
)
func netipAddressToNetaddrIP(address netip.Addr) (ip netaddr.IP) {
if address.Is4() {
return netaddr.IPFrom4(address.As4())
}
return netaddr.IPFrom16(address.As16())
}
func netipAddressesToNetaddrIPs(addresses []netip.Addr) (ips []netaddr.IP) {
ips = make([]netaddr.IP, len(addresses))
for i := range addresses {
ips[i] = netipAddressToNetaddrIP(addresses[i])
}
return ips
}
func netipPrefixToNetaddrIPPrefix(prefix netip.Prefix) (ipPrefix netaddr.IPPrefix) {
netaddrIP := netipAddressToNetaddrIP(prefix.Addr())
bits := prefix.Bits()
return netaddr.IPPrefixFrom(netaddrIP, uint8(bits))
}
func netipPrefixesToNetaddrIPPrefixes(prefixes []netip.Prefix) (ipPrefixes []netaddr.IPPrefix) {
ipPrefixes = make([]netaddr.IPPrefix, len(prefixes))
for i := range ipPrefixes {
ipPrefixes[i] = netipPrefixToNetaddrIPPrefix(prefixes[i])
}
return ipPrefixes
}

View File

@@ -184,7 +184,12 @@ func (s Settings) Warnings() (warnings []string) {
return warnings return warnings
} }
func (s *Settings) Read(r *reader.Reader) (err error) { func (s *Settings) Read(r *reader.Reader, warner Warner) (err error) {
warnings := readObsolete(r)
for _, warning := range warnings {
warner.Warn(warning)
}
readFunctions := map[string]func(r *reader.Reader) error{ readFunctions := map[string]func(r *reader.Reader) error{
"control server": s.ControlServer.read, "control server": s.ControlServer.read,
"DNS": s.DNS.read, "DNS": s.DNS.read,

View File

@@ -43,18 +43,10 @@ func Test_Settings_String(t *testing.T) {
| └── DNS over TLS settings: | └── DNS over TLS settings:
| ├── Enabled: yes | ├── Enabled: yes
| ├── Update period: every 24h0m0s | ├── Update period: every 24h0m0s
| ├── Unbound settings: | ├── Upstream resolvers:
| | ── Authoritative servers: | | ── Cloudflare
| | | └── Cloudflare | ├── Caching: yes
| | ├── Caching: yes | ├── IPv6: no
| | ├── IPv6: no
| | ├── Verbosity level: 1
| | ├── Verbosity details level: 0
| | ├── Validation log level: 0
| | ├── System user: root
| | └── Allowed networks:
| | ├── 0.0.0.0/0
| | └── ::/0
| └── DNS filtering settings: | └── DNS filtering settings:
| ├── Block malicious: yes | ├── Block malicious: yes
| ├── Block ads: no | ├── Block ads: no

View File

@@ -1,223 +0,0 @@
package settings
import (
"errors"
"fmt"
"net/netip"
"github.com/qdm12/dns/pkg/provider"
"github.com/qdm12/dns/pkg/unbound"
"github.com/qdm12/gosettings"
"github.com/qdm12/gosettings/reader"
"github.com/qdm12/gotree"
)
// Unbound is settings for the Unbound program.
type Unbound struct {
Providers []string `json:"providers"`
Caching *bool `json:"caching"`
IPv6 *bool `json:"ipv6"`
VerbosityLevel *uint8 `json:"verbosity_level"`
VerbosityDetailsLevel *uint8 `json:"verbosity_details_level"`
ValidationLogLevel *uint8 `json:"validation_log_level"`
Username string `json:"username"`
Allowed []netip.Prefix `json:"allowed"`
}
func (u *Unbound) setDefaults() {
if len(u.Providers) == 0 {
u.Providers = []string{
provider.Cloudflare().String(),
}
}
u.Caching = gosettings.DefaultPointer(u.Caching, true)
u.IPv6 = gosettings.DefaultPointer(u.IPv6, false)
const defaultVerbosityLevel = 1
u.VerbosityLevel = gosettings.DefaultPointer(u.VerbosityLevel, defaultVerbosityLevel)
const defaultVerbosityDetailsLevel = 0
u.VerbosityDetailsLevel = gosettings.DefaultPointer(u.VerbosityDetailsLevel, defaultVerbosityDetailsLevel)
const defaultValidationLogLevel = 0
u.ValidationLogLevel = gosettings.DefaultPointer(u.ValidationLogLevel, defaultValidationLogLevel)
if u.Allowed == nil {
u.Allowed = []netip.Prefix{
netip.PrefixFrom(netip.AddrFrom4([4]byte{}), 0),
netip.PrefixFrom(netip.AddrFrom16([16]byte{}), 0),
}
}
u.Username = gosettings.DefaultComparable(u.Username, "root")
}
var (
ErrUnboundVerbosityLevelNotValid = errors.New("Unbound verbosity level is not valid")
ErrUnboundVerbosityDetailsLevelNotValid = errors.New("Unbound verbosity details level is not valid")
ErrUnboundValidationLogLevelNotValid = errors.New("Unbound validation log level is not valid")
)
func (u Unbound) validate() (err error) {
for _, s := range u.Providers {
_, err := provider.Parse(s)
if err != nil {
return err
}
}
const maxVerbosityLevel = 5
if *u.VerbosityLevel > maxVerbosityLevel {
return fmt.Errorf("%w: %d must be between 0 and %d",
ErrUnboundVerbosityLevelNotValid,
*u.VerbosityLevel,
maxVerbosityLevel)
}
const maxVerbosityDetailsLevel = 4
if *u.VerbosityDetailsLevel > maxVerbosityDetailsLevel {
return fmt.Errorf("%w: %d must be between 0 and %d",
ErrUnboundVerbosityDetailsLevelNotValid,
*u.VerbosityDetailsLevel,
maxVerbosityDetailsLevel)
}
const maxValidationLogLevel = 2
if *u.ValidationLogLevel > maxValidationLogLevel {
return fmt.Errorf("%w: %d must be between 0 and %d",
ErrUnboundValidationLogLevelNotValid,
*u.ValidationLogLevel, maxValidationLogLevel)
}
return nil
}
func (u Unbound) copy() (copied Unbound) {
return Unbound{
Providers: gosettings.CopySlice(u.Providers),
Caching: gosettings.CopyPointer(u.Caching),
IPv6: gosettings.CopyPointer(u.IPv6),
VerbosityLevel: gosettings.CopyPointer(u.VerbosityLevel),
VerbosityDetailsLevel: gosettings.CopyPointer(u.VerbosityDetailsLevel),
ValidationLogLevel: gosettings.CopyPointer(u.ValidationLogLevel),
Username: u.Username,
Allowed: gosettings.CopySlice(u.Allowed),
}
}
func (u *Unbound) overrideWith(other Unbound) {
u.Providers = gosettings.OverrideWithSlice(u.Providers, other.Providers)
u.Caching = gosettings.OverrideWithPointer(u.Caching, other.Caching)
u.IPv6 = gosettings.OverrideWithPointer(u.IPv6, other.IPv6)
u.VerbosityLevel = gosettings.OverrideWithPointer(u.VerbosityLevel, other.VerbosityLevel)
u.VerbosityDetailsLevel = gosettings.OverrideWithPointer(u.VerbosityDetailsLevel, other.VerbosityDetailsLevel)
u.ValidationLogLevel = gosettings.OverrideWithPointer(u.ValidationLogLevel, other.ValidationLogLevel)
u.Username = gosettings.OverrideWithComparable(u.Username, other.Username)
u.Allowed = gosettings.OverrideWithSlice(u.Allowed, other.Allowed)
}
func (u Unbound) ToUnboundFormat() (settings unbound.Settings, err error) {
providers := make([]provider.Provider, len(u.Providers))
for i := range providers {
providers[i], err = provider.Parse(u.Providers[i])
if err != nil {
return settings, err
}
}
const port = 53
return unbound.Settings{
ListeningPort: port,
IPv4: true,
Providers: providers,
Caching: *u.Caching,
IPv6: *u.IPv6,
VerbosityLevel: *u.VerbosityLevel,
VerbosityDetailsLevel: *u.VerbosityDetailsLevel,
ValidationLogLevel: *u.ValidationLogLevel,
AccessControl: unbound.AccessControlSettings{
Allowed: netipPrefixesToNetaddrIPPrefixes(u.Allowed),
},
Username: u.Username,
}, nil
}
var (
ErrConvertingNetip = errors.New("converting net.IP to netip.Addr failed")
)
func (u Unbound) GetFirstPlaintextIPv4() (ipv4 netip.Addr, err error) {
s := u.Providers[0]
provider, err := provider.Parse(s)
if err != nil {
return ipv4, err
}
ip := provider.DNS().IPv4[0]
ipv4, ok := netip.AddrFromSlice(ip)
if !ok {
return ipv4, fmt.Errorf("%w: for ip %s (%#v)",
ErrConvertingNetip, ip, ip)
}
return ipv4.Unmap(), nil
}
func (u Unbound) String() string {
return u.toLinesNode().String()
}
func (u Unbound) toLinesNode() (node *gotree.Node) {
node = gotree.New("Unbound settings:")
authServers := node.Appendf("Authoritative servers:")
for _, provider := range u.Providers {
authServers.Appendf(provider)
}
node.Appendf("Caching: %s", gosettings.BoolToYesNo(u.Caching))
node.Appendf("IPv6: %s", gosettings.BoolToYesNo(u.IPv6))
node.Appendf("Verbosity level: %d", *u.VerbosityLevel)
node.Appendf("Verbosity details level: %d", *u.VerbosityDetailsLevel)
node.Appendf("Validation log level: %d", *u.ValidationLogLevel)
node.Appendf("System user: %s", u.Username)
allowedNetworks := node.Appendf("Allowed networks:")
for _, network := range u.Allowed {
allowedNetworks.Appendf(network.String())
}
return node
}
func (u *Unbound) read(reader *reader.Reader) (err error) {
u.Providers = reader.CSV("DOT_PROVIDERS")
u.Caching, err = reader.BoolPtr("DOT_CACHING")
if err != nil {
return err
}
u.IPv6, err = reader.BoolPtr("DOT_IPV6")
if err != nil {
return err
}
u.VerbosityLevel, err = reader.Uint8Ptr("DOT_VERBOSITY")
if err != nil {
return err
}
u.VerbosityDetailsLevel, err = reader.Uint8Ptr("DOT_VERBOSITY_DETAILS")
if err != nil {
return err
}
u.ValidationLogLevel, err = reader.Uint8Ptr("DOT_VALIDATION_LOGLEVEL")
if err != nil {
return err
}
return nil
}

View File

@@ -1,43 +0,0 @@
package settings
import (
"encoding/json"
"net/netip"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_Unbound_JSON(t *testing.T) {
t.Parallel()
settings := Unbound{
Providers: []string{"cloudflare"},
Caching: boolPtr(true),
IPv6: boolPtr(false),
VerbosityLevel: uint8Ptr(1),
VerbosityDetailsLevel: nil,
ValidationLogLevel: uint8Ptr(0),
Username: "user",
Allowed: []netip.Prefix{
netip.PrefixFrom(netip.AddrFrom4([4]byte{}), 0),
netip.PrefixFrom(netip.AddrFrom16([16]byte{}), 0),
},
}
b, err := json.Marshal(settings)
require.NoError(t, err)
const expected = `{"providers":["cloudflare"],"caching":true,"ipv6":false,` +
`"verbosity_level":1,"verbosity_details_level":null,"validation_log_level":0,` +
`"username":"user","allowed":["0.0.0.0/0","::/0"]}`
assert.Equal(t, expected, string(b))
var resultSettings Unbound
err = json.Unmarshal(b, &resultSettings)
require.NoError(t, err)
assert.Equal(t, settings, resultSettings)
}

View File

@@ -2,10 +2,6 @@ package constants
import "github.com/fatih/color" import "github.com/fatih/color"
func ColorUnbound() *color.Color {
return color.New(color.FgCyan)
}
func ColorOpenvpn() *color.Color { func ColorOpenvpn() *color.Color {
return color.New(color.FgHiMagenta) return color.New(color.FgHiMagenta)
} }

View File

@@ -1,15 +0,0 @@
package dns
import (
"context"
"github.com/qdm12/dns/pkg/unbound"
)
type Configurator interface {
SetupFiles(ctx context.Context) error
MakeUnboundConf(settings unbound.Settings) (err error)
Start(ctx context.Context, verbosityDetailsLevel uint8) (
stdoutLines, stderrLines chan string, waitError chan error, err error)
Version(ctx context.Context) (version string, err error)
}

View File

@@ -1,75 +0,0 @@
package dns
import (
"context"
"regexp"
"strings"
"github.com/qdm12/gluetun/internal/constants"
)
type logLevel uint8
const (
levelDebug logLevel = iota
levelInfo
levelWarn
levelError
)
func (l *Loop) collectLines(ctx context.Context, done chan<- struct{},
stdout, stderr chan string) {
defer close(done)
var line string
for {
select {
case <-ctx.Done():
// Context should only be canceled after stdout and stderr are done
// being written to.
close(stdout)
close(stderr)
return
case line = <-stderr:
case line = <-stdout:
}
line, level := processLogLine(line)
switch level {
case levelDebug:
l.logger.Debug(line)
case levelInfo:
l.logger.Info(line)
case levelWarn:
l.logger.Warn(line)
case levelError:
l.logger.Error(line)
}
}
}
var unboundPrefix = regexp.MustCompile(`\[[0-9]{10}\] unbound\[[0-9]+:[0|1]\] `)
func processLogLine(s string) (filtered string, level logLevel) {
prefix := unboundPrefix.FindString(s)
filtered = s[len(prefix):]
switch {
case strings.HasPrefix(filtered, "notice: "):
filtered = strings.TrimPrefix(filtered, "notice: ")
level = levelInfo
case strings.HasPrefix(filtered, "info: "):
filtered = strings.TrimPrefix(filtered, "info: ")
level = levelInfo
case strings.HasPrefix(filtered, "warn: "):
filtered = strings.TrimPrefix(filtered, "warn: ")
level = levelWarn
case strings.HasPrefix(filtered, "error: "):
filtered = strings.TrimPrefix(filtered, "error: ")
level = levelError
default:
level = levelInfo
}
filtered = constants.ColorUnbound().Sprintf(filtered)
return filtered, level
}

View File

@@ -1,48 +0,0 @@
package dns
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_processLogLine(t *testing.T) {
t.Parallel()
tests := map[string]struct {
s string
filtered string
level logLevel
}{
"empty string": {"", "", levelInfo},
"random string": {"asdasqdb", "asdasqdb", levelInfo},
"unbound notice": {
"[1594595249] unbound[75:0] notice: init module 0: validator",
"init module 0: validator",
levelInfo},
"unbound info": {
"[1594595249] unbound[75:0] info: init module 0: validator",
"init module 0: validator",
levelInfo},
"unbound warn": {
"[1594595249] unbound[75:0] warn: init module 0: validator",
"init module 0: validator",
levelWarn},
"unbound error": {
"[1594595249] unbound[75:0] error: init module 0: validator",
"init module 0: validator",
levelError},
"unbound unknown": {
"[1594595249] unbound[75:0] BLA: init module 0: validator",
"BLA: init module 0: validator",
levelInfo},
}
for name, tc := range tests {
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
filtered, level := processLogLine(tc.s)
assert.Equal(t, tc.filtered, filtered)
assert.Equal(t, tc.level, level)
})
}
}

View File

@@ -2,10 +2,12 @@ package dns
import ( import (
"context" "context"
"fmt"
"net/http" "net/http"
"time" "time"
"github.com/qdm12/dns/pkg/blacklist" "github.com/qdm12/dns/v2/pkg/dot"
"github.com/qdm12/dns/v2/pkg/middlewares/filter/mapfilter"
"github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/dns/state" "github.com/qdm12/gluetun/internal/dns/state"
@@ -16,9 +18,9 @@ import (
type Loop struct { type Loop struct {
statusManager *loopstate.State statusManager *loopstate.State
state *state.State state *state.State
conf Configurator server *dot.Server
filter *mapfilter.Filter
resolvConf string resolvConf string
blockBuilder blacklist.Builder
client *http.Client client *http.Client
logger Logger logger Logger
userTrigger bool userTrigger bool
@@ -34,8 +36,8 @@ type Loop struct {
const defaultBackoffTime = 10 * time.Second const defaultBackoffTime = 10 * time.Second
func NewLoop(conf Configurator, settings settings.DNS, func NewLoop(settings settings.DNS,
client *http.Client, logger Logger) *Loop { client *http.Client, logger Logger) (loop *Loop, err error) {
start := make(chan struct{}) start := make(chan struct{})
running := make(chan models.LoopStatus) running := make(chan models.LoopStatus)
stop := make(chan struct{}) stop := make(chan struct{})
@@ -45,12 +47,17 @@ func NewLoop(conf Configurator, settings settings.DNS,
statusManager := loopstate.New(constants.Stopped, start, running, stop, stopped) statusManager := loopstate.New(constants.Stopped, start, running, stop, stopped)
state := state.New(statusManager, settings, updateTicker) state := state.New(statusManager, settings, updateTicker)
filter, err := mapfilter.New(mapfilter.Settings{})
if err != nil {
return nil, fmt.Errorf("creating map filter: %w", err)
}
return &Loop{ return &Loop{
statusManager: statusManager, statusManager: statusManager,
state: state, state: state,
conf: conf, server: nil,
filter: filter,
resolvConf: "/etc/resolv.conf", resolvConf: "/etc/resolv.conf",
blockBuilder: blacklist.NewBuilder(client),
client: client, client: client,
logger: logger, logger: logger,
userTrigger: true, userTrigger: true,
@@ -62,7 +69,7 @@ func NewLoop(conf Configurator, settings settings.DNS,
backoffTime: defaultBackoffTime, backoffTime: defaultBackoffTime,
timeNow: time.Now, timeNow: time.Now,
timeSince: time.Since, timeSince: time.Since,
} }, nil
} }
func (l *Loop) logAndWait(ctx context.Context, err error) { func (l *Loop) logAndWait(ctx context.Context, err error) {

View File

@@ -2,36 +2,22 @@ package dns
import ( import (
"net/netip" "net/netip"
"time"
"github.com/qdm12/dns/pkg/nameserver" "github.com/qdm12/dns/v2/pkg/nameserver"
) )
func (l *Loop) useUnencryptedDNS(fallback bool) { func (l *Loop) useUnencryptedDNS(fallback bool) {
settings := l.GetSettings() settings := l.GetSettings()
// Try with user provided plaintext ip address // Try with user provided plaintext ip address
// if it's not 127.0.0.1 (default for DoT) // if it's not 127.0.0.1 (default for DoT), otherwise
targetIP := settings.ServerAddress // use the first DoT provider ipv4 address found.
if targetIP.Compare(netip.AddrFrom4([4]byte{127, 0, 0, 1})) != 0 { var targetIP netip.Addr
if fallback { if settings.ServerAddress.Compare(netip.AddrFrom4([4]byte{127, 0, 0, 1})) != 0 {
l.logger.Info("falling back on plaintext DNS at address " + targetIP.String()) targetIP = settings.ServerAddress
} else { } else {
l.logger.Info("using plaintext DNS at address " + targetIP.String()) targetIP = settings.DoT.GetFirstPlaintextIPv4()
}
nameserver.UseDNSInternally(targetIP.AsSlice())
const keepNameserver = false
err := nameserver.UseDNSSystemWide(l.resolvConf, targetIP.AsSlice(), keepNameserver)
if err != nil {
l.logger.Error(err.Error())
}
return
}
// Use first plaintext DNS IPv4 address
targetIP, err := settings.DoT.Unbound.GetFirstPlaintextIPv4()
if err != nil {
// Unbound should always have a default provider
panic(err)
} }
if fallback { if fallback {
@@ -39,9 +25,19 @@ func (l *Loop) useUnencryptedDNS(fallback bool) {
} else { } else {
l.logger.Info("using plaintext DNS at address " + targetIP.String()) l.logger.Info("using plaintext DNS at address " + targetIP.String())
} }
nameserver.UseDNSInternally(targetIP.AsSlice())
const keepNameserver = false const dialTimeout = 3 * time.Second
err = nameserver.UseDNSSystemWide(l.resolvConf, targetIP.AsSlice(), keepNameserver) settingsInternalDNS := nameserver.SettingsInternalDNS{
IP: targetIP,
Timeout: dialTimeout,
}
nameserver.UseDNSInternally(settingsInternalDNS)
settingsSystemWide := nameserver.SettingsSystemDNS{
IP: targetIP,
ResolvPath: l.resolvConf,
}
err := nameserver.UseDNSSystemWide(settingsSystemWide)
if err != nil { if err != nil {
l.logger.Error(err.Error()) l.logger.Error(err.Error())
} }

View File

@@ -26,16 +26,14 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
} }
for ctx.Err() == nil { for ctx.Err() == nil {
// Upper scope variables for Unbound only // Upper scope variables for the DNS over TLS server only
// Their values are to be used if DOT=off // Their values are to be used if DOT=off
waitError := make(chan error) var runError <-chan error
unboundCancel := func() { waitError <- nil }
closeStreams := func() {}
settings := l.GetSettings() settings := l.GetSettings()
for !*settings.KeepNameserver && *settings.DoT.Enabled { for !*settings.KeepNameserver && *settings.DoT.Enabled {
var err error var err error
unboundCancel, waitError, closeStreams, err = l.setupUnbound(ctx) runError, err = l.setupServer(ctx)
if err == nil { if err == nil {
l.backoffTime = defaultBackoffTime l.backoffTime = defaultBackoffTime
l.logger.Info("ready") l.logger.Info("ready")
@@ -49,11 +47,12 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
return return
} }
if !errors.Is(err, errUpdateFiles) { if !errors.Is(err, errUpdateBlockLists) {
const fallback = true const fallback = true
l.useUnencryptedDNS(fallback) l.useUnencryptedDNS(fallback)
} }
l.logAndWait(ctx, err) l.logAndWait(ctx, err)
settings = l.GetSettings()
} }
settings = l.GetSettings() settings = l.GetSettings()
@@ -64,40 +63,44 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
l.userTrigger = false l.userTrigger = false
stayHere := true exitLoop := l.runWait(ctx, runError)
for stayHere { if exitLoop {
select { return
case <-ctx.Done():
unboundCancel()
<-waitError
close(waitError)
closeStreams()
return
case <-l.stop:
l.userTrigger = true
l.logger.Info("stopping")
const fallback = false
l.useUnencryptedDNS(fallback)
unboundCancel()
<-waitError
// do not close waitError or the waitError
// select case will trigger
closeStreams()
l.stopped <- struct{}{}
case <-l.start:
l.userTrigger = true
l.logger.Info("starting")
stayHere = false
case err := <-waitError: // unexpected error
closeStreams()
unboundCancel()
l.statusManager.SetStatus(constants.Crashed)
const fallback = true
l.useUnencryptedDNS(fallback)
l.logAndWait(ctx, err)
stayHere = false
}
} }
} }
} }
func (l *Loop) runWait(ctx context.Context, runError <-chan error) (exitLoop bool) {
for {
select {
case <-ctx.Done():
l.stopServer()
// TODO revert OS and Go nameserver when exiting
return true
case <-l.stop:
l.userTrigger = true
l.logger.Info("stopping")
const fallback = false
l.useUnencryptedDNS(fallback)
l.stopServer()
l.stopped <- struct{}{}
case <-l.start:
l.userTrigger = true
l.logger.Info("starting")
return false
case err := <-runError: // unexpected error
l.statusManager.SetStatus(constants.Crashed)
const fallback = true
l.useUnencryptedDNS(fallback)
l.logAndWait(ctx, err)
return false
}
}
}
func (l *Loop) stopServer() {
stopErr := l.server.Stop()
if stopErr != nil {
l.logger.Error("stopping DoT server: " + stopErr.Error())
}
}

View File

@@ -2,7 +2,14 @@ package dns
import ( import (
"context" "context"
"fmt"
"github.com/qdm12/dns/v2/pkg/dot"
cachemiddleware "github.com/qdm12/dns/v2/pkg/middlewares/cache"
"github.com/qdm12/dns/v2/pkg/middlewares/cache/lru"
filtermiddleware "github.com/qdm12/dns/v2/pkg/middlewares/filter"
"github.com/qdm12/dns/v2/pkg/middlewares/filter/mapfilter"
"github.com/qdm12/dns/v2/pkg/provider"
"github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/configuration/settings"
) )
@@ -12,3 +19,55 @@ func (l *Loop) SetSettings(ctx context.Context, settings settings.DNS) (
outcome string) { outcome string) {
return l.state.SetSettings(ctx, settings) return l.state.SetSettings(ctx, settings)
} }
func buildDoTSettings(settings settings.DNS,
filter *mapfilter.Filter, logger Logger) (
dotSettings dot.ServerSettings, err error) {
var middlewares []dot.Middleware
if *settings.DoT.Caching {
lruCache, err := lru.New(lru.Settings{})
if err != nil {
return dot.ServerSettings{}, fmt.Errorf("creating LRU cache: %w", err)
}
cacheMiddleware, err := cachemiddleware.New(cachemiddleware.Settings{
Cache: lruCache,
})
if err != nil {
return dot.ServerSettings{}, fmt.Errorf("creating cache middleware: %w", err)
}
middlewares = append(middlewares, cacheMiddleware)
}
filterMiddleware, err := filtermiddleware.New(filtermiddleware.Settings{
Filter: filter,
})
if err != nil {
return dot.ServerSettings{}, fmt.Errorf("creating filter middleware: %w", err)
}
middlewares = append(middlewares, filterMiddleware)
providersData := provider.NewProviders()
providers := make([]provider.Provider, len(settings.DoT.Providers))
for i := range settings.DoT.Providers {
var err error
providers[i], err = providersData.Get(settings.DoT.Providers[i])
if err != nil {
panic(err) // this should already had been checked
}
}
ipVersion := "ipv4"
if *settings.DoT.IPv6 {
ipVersion = "ipv6"
}
return dot.ServerSettings{
Resolver: dot.ResolverSettings{
UpstreamResolvers: providers,
IPVersion: ipVersion,
Warner: logger,
},
Middlewares: middlewares,
Logger: logger,
}, nil
}

View File

@@ -4,59 +4,55 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"net"
"github.com/qdm12/dns/pkg/check" "github.com/qdm12/dns/v2/pkg/check"
"github.com/qdm12/dns/pkg/nameserver" "github.com/qdm12/dns/v2/pkg/dot"
"github.com/qdm12/dns/v2/pkg/nameserver"
) )
var errUpdateFiles = errors.New("cannot update files") var errUpdateBlockLists = errors.New("cannot update filter block lists")
// Returning cancel == nil signals we want to re-run setupUnbound func (l *Loop) setupServer(ctx context.Context) (runError <-chan error, err error) {
// Returning err == errUpdateFiles signals we should not fall back
// on the plaintext DNS as DOT is still up and running.
func (l *Loop) setupUnbound(ctx context.Context) (
cancel context.CancelFunc, waitError chan error, closeStreams func(), err error) {
err = l.updateFiles(ctx) err = l.updateFiles(ctx)
if err != nil { if err != nil {
return nil, nil, nil, return nil, fmt.Errorf("%w: %w", errUpdateBlockLists, err)
fmt.Errorf("%w: %s", errUpdateFiles, err)
} }
settings := l.GetSettings() settings := l.GetSettings()
unboundCtx, cancel := context.WithCancel(context.Background()) dotSettings, err := buildDoTSettings(settings, l.filter, l.logger)
stdoutLines, stderrLines, waitError, err := l.conf.Start(unboundCtx,
*settings.DoT.Unbound.VerbosityDetailsLevel)
if err != nil { if err != nil {
cancel() return nil, fmt.Errorf("building DoT settings: %w", err)
return nil, nil, nil, err
} }
linesCollectionCtx, linesCollectionCancel := context.WithCancel(context.Background()) server, err := dot.NewServer(dotSettings)
lineCollectionDone := make(chan struct{}) if err != nil {
go l.collectLines(linesCollectionCtx, lineCollectionDone, return nil, fmt.Errorf("creating DoT server: %w", err)
stdoutLines, stderrLines)
closeStreams = func() {
linesCollectionCancel()
<-lineCollectionDone
} }
// use Unbound runError, err = server.Start()
nameserver.UseDNSInternally(settings.ServerAddress.AsSlice()) if err != nil {
err = nameserver.UseDNSSystemWide(l.resolvConf, settings.ServerAddress.AsSlice(), return nil, fmt.Errorf("starting server: %w", err)
*settings.KeepNameserver) }
l.server = server
// use internal DNS server
nameserver.UseDNSInternally(nameserver.SettingsInternalDNS{
IP: settings.ServerAddress,
})
err = nameserver.UseDNSSystemWide(nameserver.SettingsSystemDNS{
IP: settings.ServerAddress,
ResolvPath: l.resolvConf,
})
if err != nil { if err != nil {
l.logger.Error(err.Error()) l.logger.Error(err.Error())
} }
if err := check.WaitForDNS(ctx, net.DefaultResolver); err != nil { err = check.WaitForDNS(ctx, check.Settings{})
cancel() if err != nil {
<-waitError l.stopServer()
close(waitError) return nil, err
closeStreams()
return nil, nil, nil, err
} }
return cancel, waitError, closeStreams, nil return runError, nil
} }

View File

@@ -34,7 +34,7 @@ func (l *Loop) RunRestartTicker(ctx context.Context, done chan<- struct{}) {
if err := l.updateFiles(ctx); err != nil { if err := l.updateFiles(ctx); err != nil {
l.statusManager.SetStatus(constants.Crashed) l.statusManager.SetStatus(constants.Crashed)
l.logger.Error(err.Error()) l.logger.Error(err.Error())
l.logger.Warn("skipping Unbound restart due to failed files update") l.logger.Warn("skipping DNS server restart due to failed files update")
continue continue
} }
} }

View File

@@ -1,35 +1,46 @@
package dns package dns
import "context" import (
"context"
"fmt"
"github.com/qdm12/dns/v2/pkg/blockbuilder"
"github.com/qdm12/dns/v2/pkg/middlewares/filter/update"
)
func (l *Loop) updateFiles(ctx context.Context) (err error) { func (l *Loop) updateFiles(ctx context.Context) (err error) {
l.logger.Info("downloading DNS over TLS cryptographic files")
if err := l.conf.SetupFiles(ctx); err != nil {
return err
}
settings := l.GetSettings() settings := l.GetSettings()
unboundSettings, err := settings.DoT.Unbound.ToUnboundFormat()
if err != nil {
return err
}
l.logger.Info("downloading hostnames and IP block lists") l.logger.Info("downloading hostnames and IP block lists")
blacklistSettings, err := settings.DoT.Blacklist.ToBlacklistFormat() blacklistSettings := settings.DoT.Blacklist.ToBlockBuilderSettings(l.client)
blockBuilder, err := blockbuilder.New(blacklistSettings)
if err != nil {
return fmt.Errorf("creating block builder: %w", err)
}
result := blockBuilder.BuildAll(ctx)
for _, resultErr := range result.Errors {
if err != nil {
err = fmt.Errorf("%w, %w", err, resultErr)
continue
}
err = resultErr
}
if err != nil { if err != nil {
return err return err
} }
blockedHostnames, blockedIPs, blockedIPPrefixes, errs := updateSettings := update.Settings{
l.blockBuilder.All(ctx, blacklistSettings) IPs: result.BlockedIPs,
for _, err := range errs { IPPrefixes: result.BlockedIPPrefixes,
l.logger.Warn(err.Error()) }
updateSettings.BlockHostnames(result.BlockedHostnames)
err = l.filter.Update(updateSettings)
if err != nil {
return fmt.Errorf("updating filter: %w", err)
} }
// TODO change to BlockHostnames() when migrating to qdm12/dns v2 return nil
unboundSettings.Blacklist.FqdnHostnames = blockedHostnames
unboundSettings.Blacklist.IPs = blockedIPs
unboundSettings.Blacklist.IPPrefixes = blockedIPPrefixes
return l.conf.MakeUnboundConf(unboundSettings)
} }

View File

@@ -12,7 +12,7 @@ func newHandler(ctx context.Context, logger infoWarner, logging bool,
buildInfo models.BuildInformation, buildInfo models.BuildInformation,
vpnLooper VPNLooper, vpnLooper VPNLooper,
pfGetter PortForwardedGetter, pfGetter PortForwardedGetter,
unboundLooper DNSLoop, dnsLooper DNSLoop,
updaterLooper UpdaterLooper, updaterLooper UpdaterLooper,
publicIPLooper PublicIPLoop, publicIPLooper PublicIPLoop,
storage Storage, storage Storage,
@@ -22,11 +22,11 @@ func newHandler(ctx context.Context, logger infoWarner, logging bool,
vpn := newVPNHandler(ctx, vpnLooper, storage, ipv6Supported, logger) vpn := newVPNHandler(ctx, vpnLooper, storage, ipv6Supported, logger)
openvpn := newOpenvpnHandler(ctx, vpnLooper, pfGetter, logger) openvpn := newOpenvpnHandler(ctx, vpnLooper, pfGetter, logger)
dns := newDNSHandler(ctx, unboundLooper, logger) dns := newDNSHandler(ctx, dnsLooper, logger)
updater := newUpdaterHandler(ctx, updaterLooper, logger) updater := newUpdaterHandler(ctx, updaterLooper, logger)
publicip := newPublicIPHandler(publicIPLooper, logger) publicip := newPublicIPHandler(publicIPLooper, logger)
handler.v0 = newHandlerV0(ctx, logger, vpnLooper, unboundLooper, updaterLooper) handler.v0 = newHandlerV0(ctx, logger, vpnLooper, dnsLooper, updaterLooper)
handler.v1 = newHandlerV1(logger, buildInfo, vpn, openvpn, dns, updater, publicip) handler.v1 = newHandlerV1(logger, buildInfo, vpn, openvpn, dns, updater, publicip)
handlerWithLog := withLogMiddleware(handler, logger, logging) handlerWithLog := withLogMiddleware(handler, logger, logging)

View File

@@ -42,7 +42,7 @@ func (h *handlerV0) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if _, err := w.Write([]byte("openvpn restarted, please consider using the /v1/ API in the future.")); err != nil { if _, err := w.Write([]byte("openvpn restarted, please consider using the /v1/ API in the future.")); err != nil {
h.logger.Warn(err.Error()) h.logger.Warn(err.Error())
} }
case "/unbound/actions/restart": case "/unbound/actions/restart": // TODO v4 change to /dns/
outcome, _ := h.dns.ApplyStatus(h.ctx, constants.Stopped) outcome, _ := h.dns.ApplyStatus(h.ctx, constants.Stopped)
h.logger.Info("dns: " + outcome) h.logger.Info("dns: " + outcome)
outcome, _ = h.dns.ApplyStatus(h.ctx, constants.Running) outcome, _ = h.dns.ApplyStatus(h.ctx, constants.Running)

View File

@@ -10,12 +10,12 @@ import (
func New(ctx context.Context, address string, logEnabled bool, logger Logger, func New(ctx context.Context, address string, logEnabled bool, logger Logger,
buildInfo models.BuildInformation, openvpnLooper VPNLooper, buildInfo models.BuildInformation, openvpnLooper VPNLooper,
pfGetter PortForwardedGetter, unboundLooper DNSLoop, pfGetter PortForwardedGetter, dnsLooper DNSLoop,
updaterLooper UpdaterLooper, publicIPLooper PublicIPLoop, storage Storage, updaterLooper UpdaterLooper, publicIPLooper PublicIPLoop, storage Storage,
ipv6Supported bool) ( ipv6Supported bool) (
server *httpserver.Server, err error) { server *httpserver.Server, err error) {
handler := newHandler(ctx, logger, logEnabled, buildInfo, handler := newHandler(ctx, logger, logEnabled, buildInfo,
openvpnLooper, pfGetter, unboundLooper, updaterLooper, publicIPLooper, openvpnLooper, pfGetter, dnsLooper, updaterLooper, publicIPLooper,
storage, ipv6Supported) storage, ipv6Supported)
httpServerSettings := httpserver.Settings{ httpServerSettings := httpserver.Settings{

View File

@@ -1,8 +1,7 @@
# Maintenance # Maintenance
- Rename `UNBLOCK` to `DOT_UNBOUND_UNBLOCK` - Rename `UNBLOCK` to `DNS_HOSTNAMES_UNBLOCKED`
- Change `Run` methods to `Start`+`Stop`, returning channels rather than injecting them - Change `Run` methods to `Start`+`Stop`, returning channels rather than injecting them
- Use DNS v2 beta
- Go 1.18 - Go 1.18
- gofumpt - gofumpt
- Use netip - Use netip