Maintenance: qdm12/dns from v1.4.0 to v1.6.0
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
},
|
||||
|
||||
91
internal/configuration/dnsblacklist.go
Normal file
91
internal/configuration/dnsblacklist.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user