diff --git a/Dockerfile b/Dockerfile index 2475ab94..3e5a1c70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -70,6 +70,7 @@ ENV VPNSP="private internet access" \ BLOCK_SURVEILLANCE=off \ BLOCK_ADS=off \ UNBLOCK= \ + DNS_UPDATE_PERIOD=24h \ # Firewall EXTRA_SUBNETS= \ # Tinyproxy diff --git a/README.md b/README.md index 4a42e5fb..55b536b6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ *Lightweight swiss-knife-like VPN client to tunnel to Private Internet Access, Mullvad and Windscribe VPN servers, using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and Tinyproxy* -**ANNOUNCEMENT**: *Support for [Windscribe](https://windscribe.com/)* +**ANNOUNCEMENT**: *Auto-update of Unbound block lists and cryptographic files, see `DNS_UPDATE_PERIOD`* @@ -150,6 +150,7 @@ docker run --rm --network=container:pia alpine:3.11 wget -qO- https://ipinfo.io | `DOT_VERBOSITY` | `1` | | ✅ | ✅ | ✅ | DNS over TLS Unbound verbosity level | `0`, `1`, `2`, `3`, `4`, `5` | | `DOT_VERBOSITY_DETAILS` | `0` | | ✅ | ✅ | ✅ | Unbound details verbosity level | `0`, `1`, `2`, `3`, `4` | | `DOT_VALIDATION_LOGLEVEL` | `0` | | ✅ | ✅ | ✅ | Unbound validation log level | `0`, `1`, `2` | +| `DNS_UPDATE_PERIOD` | `24h` | | ✅ | ✅ | ✅ | Period to update block lists and cryptographic files and restart Unbound. Set to `0` to deactivate updates | Can be `30s`, `5m` or `10h` for example | | `BLOCK_MALICIOUS` | `on` | | ✅ | ✅ | ✅ | Block malicious hostnames and IPs with Unbound DNS over TLS | `on`, `off` | | `BLOCK_SURVEILLANCE` | `off` | | ✅ | ✅ | ✅ | Block surveillance hostnames and IPs with Unbound DNS over TLS | `on`, `off` | | `BLOCK_ADS` | `off` | | ✅ | ✅ | ✅ | Block ads hostnames and IPs with Unbound DNS over TLS | `on`, `off` | diff --git a/cmd/main.go b/cmd/main.go index 1af0b8a1..f23311d5 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -410,7 +410,11 @@ func unboundRun(ctx, unboundCtx context.Context, unboundCancel context.CancelFun return unboundCtx, unboundCancel, err } unboundCancel() - newCtx, newCancel = context.WithTimeout(ctx, 24*time.Hour) + if settings.UpdatePeriod > 0 { + newCtx, newCancel = context.WithTimeout(ctx, settings.UpdatePeriod) + } else { + newCtx, newCancel = context.WithCancel(ctx) + } stream, waitFn, err := dnsConf.Start(newCtx, settings.VerbosityDetailsLevel) if err != nil { newCancel() @@ -459,11 +463,7 @@ func unboundRunLoop(ctx context.Context, logger logging.Logger, dnsConf dns.Conf } unboundCtx, unboundCancel := context.WithCancel(ctx) defer unboundCancel() - for { - if ctx.Err() == context.Canceled { - logger.Info("shutting down") - break - } + for ctx.Err() == nil { var err error unboundCtx, unboundCancel, err = unboundRun(ctx, unboundCtx, unboundCancel, dnsConf, settings, uid, gid, streamMerger, waiter, httpServer) if err != nil { @@ -473,6 +473,7 @@ func unboundRunLoop(ctx context.Context, logger logging.Logger, dnsConf dns.Conf } logger.Info("attempting restart") } + logger.Info("shutting down") } func setupPortForwarding(logger logging.Logger, piaConf pia.Configurator, settings settings.PIA, uid, gid int) { diff --git a/docker-compose.yml b/docker-compose.yml index fd698ab7..cf7cf56b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -47,6 +47,7 @@ services: - BLOCK_SURVEILLANCE=off - BLOCK_ADS=off - UNBLOCK= + - DNS_UPDATE_PERIOD=24h # Firewall - EXTRA_SUBNETS= # Shadowsocks diff --git a/internal/params/dns.go b/internal/params/dns.go index dc17f210..1d68c831 100644 --- a/internal/params/dns.go +++ b/internal/params/dns.go @@ -4,6 +4,7 @@ import ( "fmt" "net" "strings" + "time" libparams "github.com/qdm12/golibs/params" "github.com/qdm12/private-internet-access-docker/internal/constants" @@ -132,3 +133,9 @@ func (p *reader) GetDNSOverTLSPrivateAddresses() (privateAddresses []string, err func (p *reader) GetDNSOverTLSIPv6() (ipv6 bool, err error) { return p.envParams.GetOnOff("DOT_IPV6", libparams.Default("off")) } + +// GetDNSUpdatePeriod obtains the period to use to update the block lists and cryptographic files +// and restart Unbound from the environment variable DNS_UPDATE_PERIOD +func (p *reader) GetDNSUpdatePeriod() (period time.Duration, err error) { + return p.envParams.GetDuration("DNS_UPDATE_PERIOD", libparams.Default("24h")) +} diff --git a/internal/params/params.go b/internal/params/params.go index 7fc0a603..4b21c9b4 100644 --- a/internal/params/params.go +++ b/internal/params/params.go @@ -3,6 +3,7 @@ package params import ( "net" "os" + "time" "github.com/qdm12/golibs/logging" libparams "github.com/qdm12/golibs/params" @@ -27,6 +28,7 @@ type Reader interface { GetDNSUnblockedHostnames() (hostnames []string, err error) GetDNSOverTLSPrivateAddresses() (privateAddresses []string, err error) GetDNSOverTLSIPv6() (ipv6 bool, err error) + GetDNSUpdatePeriod() (period time.Duration, err error) // System GetUID() (uid int, err error) diff --git a/internal/settings/dns.go b/internal/settings/dns.go index d92b89db..9d6901cb 100644 --- a/internal/settings/dns.go +++ b/internal/settings/dns.go @@ -3,6 +3,7 @@ package settings import ( "fmt" "strings" + "time" "github.com/qdm12/private-internet-access-docker/internal/constants" "github.com/qdm12/private-internet-access-docker/internal/models" @@ -23,6 +24,7 @@ type DNS struct { VerbosityDetailsLevel uint8 ValidationLogLevel uint8 IPv6 bool + UpdatePeriod time.Duration } func (d *DNS) String() string { @@ -66,6 +68,7 @@ func (d *DNS) String() string { "Verbosity details level: " + fmt.Sprintf("%d/4", d.VerbosityDetailsLevel), "Validation log level: " + fmt.Sprintf("%d/2", d.ValidationLogLevel), "IPv6 resolution: " + ipv6, + "Update period: " + d.UpdatePeriod.String(), } return strings.Join(settingsList, "\n |--") } @@ -120,6 +123,10 @@ func GetDNSSettings(paramsReader params.Reader) (settings DNS, err error) { if err != nil { return settings, err } + settings.UpdatePeriod, err = paramsReader.GetDNSUpdatePeriod() + if err != nil { + return settings, err + } // Consistency check IPv6Support := false