155 lines
3.9 KiB
Go
155 lines
3.9 KiB
Go
package configuration
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
unboundmodels "github.com/qdm12/dns/pkg/models"
|
|
unbound "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
|
|
}
|
|
|
|
func (settings *DNS) String() string {
|
|
return strings.Join(settings.lines(), "\n")
|
|
}
|
|
|
|
func (settings *DNS) lines() (lines []string) {
|
|
lines = append(lines, lastIndent+"DNS:")
|
|
|
|
if settings.PlaintextAddress != nil {
|
|
lines = append(lines, indent+lastIndent+"Plaintext address: "+settings.PlaintextAddress.String())
|
|
}
|
|
|
|
if settings.KeepNameserver {
|
|
lines = append(lines, indent+lastIndent+"Keep nameserver (disabled blocking): yes")
|
|
}
|
|
|
|
if !settings.Enabled {
|
|
return lines
|
|
}
|
|
|
|
lines = append(lines, indent+lastIndent+"DNS over TLS:")
|
|
|
|
lines = append(lines, indent+indent+lastIndent+"Unbound:")
|
|
for _, line := range settings.Unbound.Lines() {
|
|
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")
|
|
}
|
|
|
|
if settings.UpdatePeriod > 0 {
|
|
lines = append(lines, indent+indent+lastIndent+"Update: every "+settings.UpdatePeriod.String())
|
|
}
|
|
|
|
return lines
|
|
}
|
|
|
|
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")
|
|
)
|
|
|
|
func (settings *DNS) read(r reader) (err error) {
|
|
settings.Enabled, err = r.env.OnOff("DOT", params.Default("on"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Plain DNS settings
|
|
if err := settings.readDNSPlaintext(r.env); err != nil {
|
|
return err
|
|
}
|
|
settings.KeepNameserver, err = r.env.OnOff("DNS_KEEP_NAMESERVER", params.Default("off"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 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
|
|
}
|
|
settings.UpdatePeriod, err = r.env.Duration("DNS_UPDATE_PERIOD", params.Default("24h"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
var (
|
|
ErrDNSAddressNotAnIP = errors.New("DNS plaintext address is not an IP address")
|
|
)
|
|
|
|
func (settings *DNS) readDNSPlaintext(env params.Env) error {
|
|
s, err := env.Get("DNS_PLAINTEXT_ADDRESS", params.Default("1.1.1.1"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
settings.PlaintextAddress = net.ParseIP(s)
|
|
if settings.PlaintextAddress == nil {
|
|
return fmt.Errorf("%w: %s", ErrDNSAddressNotAnIP, s)
|
|
}
|
|
|
|
return nil
|
|
}
|