Files
gluetun/internal/configuration/unbound.go
2021-02-06 11:05:50 -05:00

134 lines
3.2 KiB
Go

package configuration
import (
"errors"
"fmt"
"net"
"strings"
unbound "github.com/qdm12/dns/pkg/unbound"
"github.com/qdm12/golibs/params"
)
func (settings *DNS) readUnbound(r reader) (err error) {
if err := settings.readUnboundProviders(r.env); err != nil {
return err
}
settings.Unbound.ListeningPort = 53
settings.Unbound.Caching, err = r.env.OnOff("DOT_CACHING", params.Default("on"))
if err != nil {
return err
}
settings.Unbound.IPv4 = true
settings.Unbound.IPv6, err = r.env.OnOff("DOT_IPV6", params.Default("off"))
if err != nil {
return err
}
verbosityLevel, err := r.env.IntRange("DOT_VERBOSITY", 0, 5, params.Default("1"))
if err != nil {
return err
}
settings.Unbound.VerbosityLevel = uint8(verbosityLevel)
verbosityDetailsLevel, err := r.env.IntRange("DOT_VERBOSITY_DETAILS", 0, 4, params.Default("0"))
if err != nil {
return err
}
settings.Unbound.VerbosityDetailsLevel = uint8(verbosityDetailsLevel)
validationLogLevel, err := r.env.IntRange("DOT_VALIDATION_LOGLEVEL", 0, 2, params.Default("0"))
if err != nil {
return err
}
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,
Mask: net.IPv4Mask(0, 0, 0, 0),
},
{
IP: net.IPv6zero,
Mask: net.IPMask{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
}
return nil
}
var (
ErrInvalidDNSOverTLSProvider = errors.New("invalid DNS over TLS provider")
)
func (settings *DNS) readUnboundProviders(env params.Env) (err error) {
s, err := env.Get("DOT_PROVIDERS", params.Default("cloudflare"))
if err != nil {
return err
}
for _, provider := range strings.Split(s, ",") {
_, ok := unbound.GetProviderData(provider)
if !ok {
return fmt.Errorf("%w: %s", ErrInvalidDNSOverTLSProvider, provider)
}
settings.Unbound.Providers = append(settings.Unbound.Providers, provider)
}
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
}