Golangcilint in build pipeline and fix lint errors

- Fix bad permissions bits for files
- VPNSP is 'private internet access' instead of 'pia' (retro compatible)
- Check errors of deferred unsetEnv functions in params package
-  Other lint errors fixing and code simplifications
This commit is contained in:
Quentin McGaw
2020-04-12 20:05:28 +00:00
parent 8f6b6306d6
commit 768147095f
43 changed files with 2742 additions and 2598 deletions

View File

@@ -1,10 +1,14 @@
{
"name": "pia-dev",
"dockerComposeFile": ["docker-compose.yml"],
"dockerComposeFile": [
"docker-compose.yml"
],
"service": "vscode",
"runServices": ["vscode"],
"runServices": [
"vscode"
],
"shutdownAction": "stopCompose",
// "postCreateCommand": "go mod download",
"postCreateCommand": "go mod download",
"workspaceFolder": "/workspace",
"extensions": [
"ms-vscode.go",
@@ -38,10 +42,54 @@
"deepCompletion": true,
"usePlaceholders": false
},
"go.lintTool": "golangci-lint",
"go.lintFlags": [
"--fast",
"--enable",
"staticcheck",
"--enable",
"bodyclose",
"--enable",
"dogsled",
"--enable",
"gochecknoglobals",
"--enable",
"gochecknoinits",
"--enable",
"gocognit",
"--enable",
"goconst",
"--enable",
"gocritic",
"--enable",
"gocyclo",
"--enable",
"golint",
"--enable",
"gosec",
"--enable",
"interfacer",
"--enable",
"maligned",
"--enable",
"misspell",
"--enable",
"nakedret",
"--enable",
"prealloc",
"--enable",
"scopelint",
"--enable",
"unconvert",
"--enable",
"unparam",
"--enable",
"whitespace"
],
// Golang on save
"go.buildOnSave": "package",
"go.lintOnSave": "package",
"go.vetOnSave": "package",
"go.buildOnSave": "workspace",
"go.lintOnSave": "workspace",
"go.vetOnSave": "workspace",
"editor.formatOnSave": true,
"[go]": {
"editor.codeActionsOnSave": {
@@ -56,7 +104,10 @@
"GOFLAGS": "-tags=integration"
},
"go.testEnvVars": {},
"go.testFlags": ["-v"],
"go.testFlags": [
"-v",
// "-race"
],
"go.testTimeout": "600s"
}
}

50
.golangci.yml Normal file
View File

@@ -0,0 +1,50 @@
linters-settings:
maligned:
suggest-new: true
misspell:
locale: US
linters:
disable-all: true
enable:
- bodyclose
- deadcode
- dogsled
- dupl
- errcheck
- gochecknoglobals
- gochecknoinits
- gocognit
- goconst
- gocritic
- gocyclo
- goimports
- golint
- gosec
- gosimple
- govet
- ineffassign
- interfacer
- maligned
- misspell
- nakedret
- prealloc
- rowserrcheck
- scopelint
- staticcheck
- structcheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
- whitespace
run:
skip-dirs:
- .devcontainer
- .github
- postgres
service:
golangci-lint-version: 1.24.x # use the fixed version to not introduce new linters unexpectedly

View File

@@ -3,13 +3,17 @@ ARG GO_VERSION=1.14
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS builder
RUN apk --update add git
WORKDIR /tmp/gobuild
ENV CGO_ENABLED=0
ARG GOLANGCI_LINT_VERSION=v1.24.0
RUN wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s ${GOLANGCI_LINT_VERSION}
WORKDIR /tmp/gobuild
COPY .golangci.yml .
COPY go.mod go.sum ./
RUN go mod download 2>&1
COPY cmd/main.go .
COPY internal/ ./internal/
RUN go test ./...
RUN golangci-lint run --timeout=10m
RUN go build -ldflags="-s -w" -o entrypoint main.go
FROM alpine:${ALPINE_VERSION}
@@ -29,7 +33,7 @@ LABEL \
org.opencontainers.image.source="https://github.com/qdm12/private-internet-access-docker" \
org.opencontainers.image.title="PIA client" \
org.opencontainers.image.description="VPN client to tunnel to private internet access servers using OpenVPN, IPtables, DNS over TLS and Alpine Linux"
ENV VPNSP=pia \
ENV VPNSP="private internet access" \
USER= \
PROTOCOL=udp \
OPENVPN_VERBOSITY=1 \

View File

@@ -113,7 +113,7 @@ docker run --rm --network=container:pia alpine:3.11 wget -qO- https://ipinfo.io
| Environment variable | Default | Properties | PIA | Mullvad | Windscribe | Description | Choices |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `VPNSP` | `pia` | | ✅ | ✅ | ✅ | VPN Service Provider | `pia`, `mullvad`, `windscribe` |
| `VPNSP` | `private internet access` | | ✅ | ✅ | ✅ | VPN Service Provider | `private internet access`, `mullvad`, `windscribe` |
| `REGION` | `Austria` | | ✅ | ❌ | ✅ | VPN server region | One of the [PIA regions](https://www.privateinternetaccess.com/pages/network/) or of the [Windscribe regions](https://windscribe.com/status) |
| `COUNTRY` | `Sweden` | Optional | ❌ | ✅ | ❌ | VPN server country | One of the [Mullvad countries](https://mullvad.net/en/servers/#openvpn) |
| `CITY` | | Optional | ❌ | ✅ | ❌ | VPN server city | One of the [Mullvad cities](https://mullvad.net/en/servers/#openvpn) |

View File

@@ -1,325 +1,325 @@
package main
import (
"context"
"fmt"
"net"
"os"
"strings"
"time"
"github.com/qdm12/golibs/command"
"github.com/qdm12/golibs/files"
libhealthcheck "github.com/qdm12/golibs/healthcheck"
"github.com/qdm12/golibs/logging"
"github.com/qdm12/golibs/network"
"github.com/qdm12/golibs/signals"
"github.com/qdm12/private-internet-access-docker/internal/alpine"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/dns"
"github.com/qdm12/private-internet-access-docker/internal/env"
"github.com/qdm12/private-internet-access-docker/internal/firewall"
"github.com/qdm12/private-internet-access-docker/internal/healthcheck"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/mullvad"
"github.com/qdm12/private-internet-access-docker/internal/openvpn"
"github.com/qdm12/private-internet-access-docker/internal/params"
"github.com/qdm12/private-internet-access-docker/internal/pia"
"github.com/qdm12/private-internet-access-docker/internal/routing"
"github.com/qdm12/private-internet-access-docker/internal/settings"
"github.com/qdm12/private-internet-access-docker/internal/shadowsocks"
"github.com/qdm12/private-internet-access-docker/internal/splash"
"github.com/qdm12/private-internet-access-docker/internal/tinyproxy"
"github.com/qdm12/private-internet-access-docker/internal/windscribe"
)
func main() {
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel, -1)
if err != nil {
panic(err)
}
if libhealthcheck.Mode(os.Args) {
if err := healthcheck.HealthCheck(); err != nil {
fmt.Println(err)
os.Exit(1)
}
os.Exit(0)
}
paramsReader := params.NewParamsReader(logger)
fmt.Println(splash.Splash(paramsReader))
e := env.New(logger)
client := network.NewClient(15 * time.Second)
// Create configurators
fileManager := files.NewFileManager()
alpineConf := alpine.NewConfigurator(fileManager)
ovpnConf := openvpn.NewConfigurator(logger, fileManager)
dnsConf := dns.NewConfigurator(logger, client, fileManager)
firewallConf := firewall.NewConfigurator(logger)
routingConf := routing.NewRouting(logger, fileManager)
piaConf := pia.NewConfigurator(client, fileManager, firewallConf, logger)
mullvadConf := mullvad.NewConfigurator(fileManager, logger)
windscribeConf := windscribe.NewConfigurator(fileManager)
tinyProxyConf := tinyproxy.NewConfigurator(fileManager, logger)
shadowsocksConf := shadowsocks.NewConfigurator(fileManager, logger)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
streamMerger := command.NewStreamMerger(ctx)
e.PrintVersion("OpenVPN", ovpnConf.Version)
e.PrintVersion("Unbound", dnsConf.Version)
e.PrintVersion("IPtables", firewallConf.Version)
e.PrintVersion("TinyProxy", tinyProxyConf.Version)
e.PrintVersion("ShadowSocks", shadowsocksConf.Version)
allSettings, err := settings.GetAllSettings(paramsReader)
e.FatalOnError(err)
logger.Info(allSettings.String())
err = alpineConf.CreateUser("nonrootuser", allSettings.System.UID)
e.FatalOnError(err)
err = fileManager.SetOwnership("/etc/unbound", allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
err = fileManager.SetOwnership("/etc/tinyproxy", allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
if err := ovpnConf.CheckTUN(); err != nil {
logger.Warn(err)
err = ovpnConf.CreateTUN()
e.FatalOnError(err)
}
var openVPNUser, openVPNPassword string
switch allSettings.VPNSP {
case "pia":
openVPNUser = allSettings.PIA.User
openVPNPassword = allSettings.PIA.Password
case "mullvad":
openVPNUser = allSettings.Mullvad.User
openVPNPassword = "m"
case "windscribe":
openVPNUser = allSettings.Windscribe.User
openVPNPassword = allSettings.Windscribe.Password
}
err = ovpnConf.WriteAuthFile(openVPNUser, openVPNPassword, allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
defaultInterface, defaultGateway, defaultSubnet, err := routingConf.DefaultRoute()
e.FatalOnError(err)
// Temporarily reset chain policies allowing Kubernetes sidecar to
// successfully restart the container. Without this, the existing rules will
// pre-exist, preventing the nslookup of the PIA region address. These will
// simply be redundant at Docker runtime as they will already be set this way
// Thanks to @npawelek https://github.com/npawelek
err = firewallConf.AcceptAll()
e.FatalOnError(err)
go func() {
// Blocking line merging reader for all programs: openvpn, tinyproxy, unbound and shadowsocks
logger.Info("Launching standard output merger")
err = streamMerger.CollectLines(func(line string) {
logger.Info(line)
if strings.Contains(line, "Initialization Sequence Completed") {
onConnected(logger, routingConf, fileManager, piaConf,
defaultInterface,
allSettings.VPNSP,
allSettings.PIA.PortForwarding.Enabled,
allSettings.PIA.PortForwarding.Filepath,
allSettings.System.IPStatusFilepath,
allSettings.System.UID,
allSettings.System.GID)
}
})
e.FatalOnError(err)
}()
if allSettings.DNS.Enabled {
initialDNSToUse := constants.DNSProviderMapping()[allSettings.DNS.Providers[0]]
dnsConf.UseDNSInternally(initialDNSToUse.IPs[0])
err = dnsConf.DownloadRootHints(allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
err = dnsConf.DownloadRootKey(allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
err = dnsConf.MakeUnboundConf(allSettings.DNS, allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
stream, waitFn, err := dnsConf.Start(allSettings.DNS.VerbosityDetailsLevel)
e.FatalOnError(err)
go func() {
e.FatalOnError(waitFn())
}()
go streamMerger.Merge("unbound", stream)
dnsConf.UseDNSInternally(net.IP{127, 0, 0, 1}) // use Unbound
err = dnsConf.UseDNSSystemWide(net.IP{127, 0, 0, 1}) // use Unbound
e.FatalOnError(err)
err = dnsConf.WaitForUnbound()
e.FatalOnError(err)
}
var connections []models.OpenVPNConnection
switch allSettings.VPNSP {
case "pia":
connections, err = piaConf.GetOpenVPNConnections(
allSettings.PIA.Region,
allSettings.OpenVPN.NetworkProtocol,
allSettings.PIA.Encryption,
allSettings.OpenVPN.TargetIP)
e.FatalOnError(err)
err = piaConf.BuildConf(
connections,
allSettings.PIA.Encryption,
allSettings.OpenVPN.Verbosity,
allSettings.System.UID,
allSettings.System.GID,
allSettings.OpenVPN.Root,
allSettings.OpenVPN.Cipher,
allSettings.OpenVPN.Auth)
e.FatalOnError(err)
case "mullvad":
connections, err = mullvadConf.GetOpenVPNConnections(
allSettings.Mullvad.Country,
allSettings.Mullvad.City,
allSettings.Mullvad.ISP,
allSettings.OpenVPN.NetworkProtocol,
allSettings.Mullvad.Port,
allSettings.OpenVPN.TargetIP)
e.FatalOnError(err)
err = mullvadConf.BuildConf(
connections,
allSettings.OpenVPN.Verbosity,
allSettings.System.UID,
allSettings.System.GID,
allSettings.OpenVPN.Root,
allSettings.OpenVPN.Cipher)
e.FatalOnError(err)
case "windscribe":
connections, err = windscribeConf.GetOpenVPNConnections(
allSettings.Windscribe.Region,
allSettings.OpenVPN.NetworkProtocol,
allSettings.Windscribe.Port,
allSettings.OpenVPN.TargetIP)
e.FatalOnError(err)
err = windscribeConf.BuildConf(
connections,
allSettings.OpenVPN.Verbosity,
allSettings.System.UID,
allSettings.System.GID,
allSettings.OpenVPN.Root,
allSettings.OpenVPN.Cipher,
allSettings.OpenVPN.Auth)
e.FatalOnError(err)
}
err = routingConf.AddRoutesVia(allSettings.Firewall.AllowedSubnets, defaultGateway, defaultInterface)
e.FatalOnError(err)
err = firewallConf.Clear()
e.FatalOnError(err)
err = firewallConf.BlockAll()
e.FatalOnError(err)
err = firewallConf.CreateGeneralRules()
e.FatalOnError(err)
err = firewallConf.CreateVPNRules(constants.TUN, defaultInterface, connections)
e.FatalOnError(err)
err = firewallConf.CreateLocalSubnetsRules(defaultSubnet, allSettings.Firewall.AllowedSubnets, defaultInterface)
e.FatalOnError(err)
if allSettings.TinyProxy.Enabled {
err = tinyProxyConf.MakeConf(
allSettings.TinyProxy.LogLevel,
allSettings.TinyProxy.Port,
allSettings.TinyProxy.User,
allSettings.TinyProxy.Password,
allSettings.System.UID,
allSettings.System.GID)
e.FatalOnError(err)
err = firewallConf.AllowAnyIncomingOnPort(allSettings.TinyProxy.Port)
e.FatalOnError(err)
stream, waitFn, err := tinyProxyConf.Start()
e.FatalOnError(err)
go func() {
if err := waitFn(); err != nil {
logger.Error(err)
}
}()
go streamMerger.Merge("tinyproxy", stream)
}
if allSettings.ShadowSocks.Enabled {
err = shadowsocksConf.MakeConf(
allSettings.ShadowSocks.Port,
allSettings.ShadowSocks.Password,
allSettings.ShadowSocks.Method,
allSettings.System.UID,
allSettings.System.GID)
e.FatalOnError(err)
err = firewallConf.AllowAnyIncomingOnPort(allSettings.ShadowSocks.Port)
e.FatalOnError(err)
stream, waitFn, err := shadowsocksConf.Start("0.0.0.0", allSettings.ShadowSocks.Port, allSettings.ShadowSocks.Password, allSettings.ShadowSocks.Log)
e.FatalOnError(err)
go func() {
if err := waitFn(); err != nil {
logger.Error(err)
}
}()
go streamMerger.Merge("shadowsocks", stream)
}
stream, waitFn, err := ovpnConf.Start()
e.FatalOnError(err)
go streamMerger.Merge("openvpn", stream)
go signals.WaitForExit(func(signal string) int {
logger.Warn("Caught OS signal %s, shutting down", signal)
if allSettings.VPNSP == "pia" && allSettings.PIA.PortForwarding.Enabled {
if err := piaConf.ClearPortForward(allSettings.PIA.PortForwarding.Filepath, allSettings.System.UID, allSettings.System.GID); err != nil {
logger.Error(err)
}
}
time.Sleep(100 * time.Millisecond) // wait for other processes to exit
return 0
})
e.FatalOnError(waitFn())
}
func onConnected(
logger logging.Logger,
routingConf routing.Routing,
fileManager files.FileManager,
piaConf pia.Configurator,
defaultInterface string,
VPNSP string,
portForwarding bool,
portForwardingFilepath models.Filepath,
ipStatusFilepath models.Filepath,
uid, gid int,
) {
ip, err := routingConf.CurrentPublicIP(defaultInterface)
if err != nil {
logger.Error(err)
} else {
logger.Info("Tunnel IP is %s, see more information at https://ipinfo.io/%s", ip, ip)
err := fileManager.WriteLinesToFile(
string(ipStatusFilepath),
[]string{ip.String()},
files.Ownership(uid, gid),
files.Permissions(400))
if err != nil {
logger.Error(err)
}
}
if VPNSP != "pia" || !portForwarding {
return
}
port, err := piaConf.GetPortForward()
if err != nil {
logger.Error("port forwarding:", err)
return
}
logger.Info("port forwarding: Port %d", port)
if err := piaConf.WritePortForward(portForwardingFilepath, port, uid, gid); err != nil {
logger.Error("port forwarding:", err)
return
}
if err := piaConf.AllowPortForwardFirewall(constants.TUN, port); err != nil {
logger.Error("port forwarding:", err)
return
}
}
package main
import (
"context"
"fmt"
"net"
"os"
"strings"
"time"
"github.com/qdm12/golibs/command"
"github.com/qdm12/golibs/files"
libhealthcheck "github.com/qdm12/golibs/healthcheck"
"github.com/qdm12/golibs/logging"
"github.com/qdm12/golibs/network"
"github.com/qdm12/golibs/signals"
"github.com/qdm12/private-internet-access-docker/internal/alpine"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/dns"
"github.com/qdm12/private-internet-access-docker/internal/env"
"github.com/qdm12/private-internet-access-docker/internal/firewall"
"github.com/qdm12/private-internet-access-docker/internal/healthcheck"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/mullvad"
"github.com/qdm12/private-internet-access-docker/internal/openvpn"
"github.com/qdm12/private-internet-access-docker/internal/params"
"github.com/qdm12/private-internet-access-docker/internal/pia"
"github.com/qdm12/private-internet-access-docker/internal/routing"
"github.com/qdm12/private-internet-access-docker/internal/settings"
"github.com/qdm12/private-internet-access-docker/internal/shadowsocks"
"github.com/qdm12/private-internet-access-docker/internal/splash"
"github.com/qdm12/private-internet-access-docker/internal/tinyproxy"
"github.com/qdm12/private-internet-access-docker/internal/windscribe"
)
func main() {
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel, -1)
if err != nil {
panic(err)
}
if libhealthcheck.Mode(os.Args) {
if err := healthcheck.HealthCheck(); err != nil {
fmt.Println(err)
os.Exit(1)
}
os.Exit(0)
}
paramsReader := params.NewReader(logger)
fmt.Println(splash.Splash(paramsReader))
e := env.New(logger)
client := network.NewClient(15 * time.Second)
// Create configurators
fileManager := files.NewFileManager()
alpineConf := alpine.NewConfigurator(fileManager)
ovpnConf := openvpn.NewConfigurator(logger, fileManager)
dnsConf := dns.NewConfigurator(logger, client, fileManager)
firewallConf := firewall.NewConfigurator(logger)
routingConf := routing.NewRouting(logger, fileManager)
piaConf := pia.NewConfigurator(client, fileManager, firewallConf, logger)
mullvadConf := mullvad.NewConfigurator(fileManager, logger)
windscribeConf := windscribe.NewConfigurator(fileManager)
tinyProxyConf := tinyproxy.NewConfigurator(fileManager, logger)
shadowsocksConf := shadowsocks.NewConfigurator(fileManager, logger)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
streamMerger := command.NewStreamMerger(ctx)
e.PrintVersion("OpenVPN", ovpnConf.Version)
e.PrintVersion("Unbound", dnsConf.Version)
e.PrintVersion("IPtables", firewallConf.Version)
e.PrintVersion("TinyProxy", tinyProxyConf.Version)
e.PrintVersion("ShadowSocks", shadowsocksConf.Version)
allSettings, err := settings.GetAllSettings(paramsReader)
e.FatalOnError(err)
logger.Info(allSettings.String())
err = alpineConf.CreateUser("nonrootuser", allSettings.System.UID)
e.FatalOnError(err)
err = fileManager.SetOwnership("/etc/unbound", allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
err = fileManager.SetOwnership("/etc/tinyproxy", allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
if err := ovpnConf.CheckTUN(); err != nil {
logger.Warn(err)
err = ovpnConf.CreateTUN()
e.FatalOnError(err)
}
var openVPNUser, openVPNPassword string
switch allSettings.VPNSP {
case constants.PrivateInternetAccess:
openVPNUser = allSettings.PIA.User
openVPNPassword = allSettings.PIA.Password
case constants.Mullvad:
openVPNUser = allSettings.Mullvad.User
openVPNPassword = "m"
case constants.Windscribe:
openVPNUser = allSettings.Windscribe.User
openVPNPassword = allSettings.Windscribe.Password
}
err = ovpnConf.WriteAuthFile(openVPNUser, openVPNPassword, allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
defaultInterface, defaultGateway, defaultSubnet, err := routingConf.DefaultRoute()
e.FatalOnError(err)
// Temporarily reset chain policies allowing Kubernetes sidecar to
// successfully restart the container. Without this, the existing rules will
// pre-exist, preventing the nslookup of the PIA region address. These will
// simply be redundant at Docker runtime as they will already be set this way
// Thanks to @npawelek https://github.com/npawelek
err = firewallConf.AcceptAll()
e.FatalOnError(err)
go func() {
// Blocking line merging paramsReader for all programs: openvpn, tinyproxy, unbound and shadowsocks
logger.Info("Launching standard output merger")
err = streamMerger.CollectLines(func(line string) {
logger.Info(line)
if strings.Contains(line, "Initialization Sequence Completed") {
onConnected(logger, routingConf, fileManager, piaConf,
defaultInterface,
allSettings.VPNSP,
allSettings.PIA.PortForwarding.Enabled,
allSettings.PIA.PortForwarding.Filepath,
allSettings.System.IPStatusFilepath,
allSettings.System.UID,
allSettings.System.GID)
}
})
e.FatalOnError(err)
}()
if allSettings.DNS.Enabled {
initialDNSToUse := constants.DNSProviderMapping()[allSettings.DNS.Providers[0]]
dnsConf.UseDNSInternally(initialDNSToUse.IPs[0])
err = dnsConf.DownloadRootHints(allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
err = dnsConf.DownloadRootKey(allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
err = dnsConf.MakeUnboundConf(allSettings.DNS, allSettings.System.UID, allSettings.System.GID)
e.FatalOnError(err)
stream, waitFn, err := dnsConf.Start(allSettings.DNS.VerbosityDetailsLevel)
e.FatalOnError(err)
go func() {
e.FatalOnError(waitFn())
}()
go streamMerger.Merge("unbound", stream)
dnsConf.UseDNSInternally(net.IP{127, 0, 0, 1}) // use Unbound
err = dnsConf.UseDNSSystemWide(net.IP{127, 0, 0, 1}) // use Unbound
e.FatalOnError(err)
err = dnsConf.WaitForUnbound()
e.FatalOnError(err)
}
var connections []models.OpenVPNConnection
switch allSettings.VPNSP {
case constants.PrivateInternetAccess:
connections, err = piaConf.GetOpenVPNConnections(
allSettings.PIA.Region,
allSettings.OpenVPN.NetworkProtocol,
allSettings.PIA.Encryption,
allSettings.OpenVPN.TargetIP)
e.FatalOnError(err)
err = piaConf.BuildConf(
connections,
allSettings.PIA.Encryption,
allSettings.OpenVPN.Verbosity,
allSettings.System.UID,
allSettings.System.GID,
allSettings.OpenVPN.Root,
allSettings.OpenVPN.Cipher,
allSettings.OpenVPN.Auth)
e.FatalOnError(err)
case constants.Mullvad:
connections, err = mullvadConf.GetOpenVPNConnections(
allSettings.Mullvad.Country,
allSettings.Mullvad.City,
allSettings.Mullvad.ISP,
allSettings.OpenVPN.NetworkProtocol,
allSettings.Mullvad.Port,
allSettings.OpenVPN.TargetIP)
e.FatalOnError(err)
err = mullvadConf.BuildConf(
connections,
allSettings.OpenVPN.Verbosity,
allSettings.System.UID,
allSettings.System.GID,
allSettings.OpenVPN.Root,
allSettings.OpenVPN.Cipher)
e.FatalOnError(err)
case constants.Windscribe:
connections, err = windscribeConf.GetOpenVPNConnections(
allSettings.Windscribe.Region,
allSettings.OpenVPN.NetworkProtocol,
allSettings.Windscribe.Port,
allSettings.OpenVPN.TargetIP)
e.FatalOnError(err)
err = windscribeConf.BuildConf(
connections,
allSettings.OpenVPN.Verbosity,
allSettings.System.UID,
allSettings.System.GID,
allSettings.OpenVPN.Root,
allSettings.OpenVPN.Cipher,
allSettings.OpenVPN.Auth)
e.FatalOnError(err)
}
err = routingConf.AddRoutesVia(allSettings.Firewall.AllowedSubnets, defaultGateway, defaultInterface)
e.FatalOnError(err)
err = firewallConf.Clear()
e.FatalOnError(err)
err = firewallConf.BlockAll()
e.FatalOnError(err)
err = firewallConf.CreateGeneralRules()
e.FatalOnError(err)
err = firewallConf.CreateVPNRules(constants.TUN, defaultInterface, connections)
e.FatalOnError(err)
err = firewallConf.CreateLocalSubnetsRules(defaultSubnet, allSettings.Firewall.AllowedSubnets, defaultInterface)
e.FatalOnError(err)
if allSettings.TinyProxy.Enabled {
err = tinyProxyConf.MakeConf(
allSettings.TinyProxy.LogLevel,
allSettings.TinyProxy.Port,
allSettings.TinyProxy.User,
allSettings.TinyProxy.Password,
allSettings.System.UID,
allSettings.System.GID)
e.FatalOnError(err)
err = firewallConf.AllowAnyIncomingOnPort(allSettings.TinyProxy.Port)
e.FatalOnError(err)
stream, waitFn, err := tinyProxyConf.Start()
e.FatalOnError(err)
go func() {
if err := waitFn(); err != nil {
logger.Error(err)
}
}()
go streamMerger.Merge("tinyproxy", stream)
}
if allSettings.ShadowSocks.Enabled {
err = shadowsocksConf.MakeConf(
allSettings.ShadowSocks.Port,
allSettings.ShadowSocks.Password,
allSettings.ShadowSocks.Method,
allSettings.System.UID,
allSettings.System.GID)
e.FatalOnError(err)
err = firewallConf.AllowAnyIncomingOnPort(allSettings.ShadowSocks.Port)
e.FatalOnError(err)
stream, waitFn, err := shadowsocksConf.Start("0.0.0.0", allSettings.ShadowSocks.Port, allSettings.ShadowSocks.Password, allSettings.ShadowSocks.Log)
e.FatalOnError(err)
go func() {
if err := waitFn(); err != nil {
logger.Error(err)
}
}()
go streamMerger.Merge("shadowsocks", stream)
}
stream, waitFn, err := ovpnConf.Start()
e.FatalOnError(err)
go streamMerger.Merge("openvpn", stream)
go signals.WaitForExit(func(signal string) int {
logger.Warn("Caught OS signal %s, shutting down", signal)
if allSettings.VPNSP == "pia" && allSettings.PIA.PortForwarding.Enabled {
if err := piaConf.ClearPortForward(allSettings.PIA.PortForwarding.Filepath, allSettings.System.UID, allSettings.System.GID); err != nil {
logger.Error(err)
}
}
time.Sleep(100 * time.Millisecond) // wait for other processes to exit
return 0
})
e.FatalOnError(waitFn())
}
func onConnected(
logger logging.Logger,
routingConf routing.Routing,
fileManager files.FileManager,
piaConf pia.Configurator,
defaultInterface string,
vpnsp models.VPNProvider,
portForwarding bool,
portForwardingFilepath models.Filepath,
ipStatusFilepath models.Filepath,
uid, gid int,
) {
ip, err := routingConf.CurrentPublicIP(defaultInterface)
if err != nil {
logger.Error(err)
} else {
logger.Info("Tunnel IP is %s, see more information at https://ipinfo.io/%s", ip, ip)
err := fileManager.WriteLinesToFile(
string(ipStatusFilepath),
[]string{ip.String()},
files.Ownership(uid, gid),
files.Permissions(0400))
if err != nil {
logger.Error(err)
}
}
if vpnsp != constants.PrivateInternetAccess || !portForwarding {
return
}
port, err := piaConf.GetPortForward()
if err != nil {
logger.Error("port forwarding:", err)
return
}
logger.Info("port forwarding: Port %d", port)
if err := piaConf.WritePortForward(portForwardingFilepath, port, uid, gid); err != nil {
logger.Error("port forwarding:", err)
return
}
if err := piaConf.AllowPortForwardFirewall(constants.TUN, port); err != nil {
logger.Error("port forwarding:", err)
return
}
}

View File

@@ -14,7 +14,7 @@ services:
# command:
environment:
# More variables are available, see the readme table
- VPNSP=pia
- VPNSP=private internet access
- USER=js89ds7
- PROTOCOL=udp
- OPENVPN_VERBOSITY=1

View File

@@ -1,89 +1,89 @@
package constants
import (
"net"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
const (
// Cloudflare is a DNS over TLS provider
Cloudflare models.DNSProvider = "cloudflare"
// Google is a DNS over TLS provider
Google models.DNSProvider = "google"
// Quad9 is a DNS over TLS provider
Quad9 models.DNSProvider = "quad9"
// Quadrant is a DNS over TLS provider
Quadrant models.DNSProvider = "quadrant"
// CleanBrowsing is a DNS over TLS provider
CleanBrowsing models.DNSProvider = "cleanbrowsing"
// SecureDNS is a DNS over TLS provider
SecureDNS models.DNSProvider = "securedns"
// LibreDNS is a DNS over TLS provider
LibreDNS models.DNSProvider = "libredns"
)
// DNSProviderMapping returns a constant mapping of dns provider name
// to their data such as IP addresses or TLS host name.
func DNSProviderMapping() map[models.DNSProvider]models.DNSProviderData {
return map[models.DNSProvider]models.DNSProviderData{
Cloudflare: models.DNSProviderData{
IPs: []net.IP{{1, 1, 1, 1}, {1, 0, 0, 1}, {0x26, 0x6, 0x47, 0x0, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11}, {0x26, 0x6, 0x47, 0x0, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x01}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("cloudflare-dns.com"),
},
Google: models.DNSProviderData{
IPs: []net.IP{{8, 8, 8, 8}, {8, 8, 4, 4}, {0x20, 0x1, 0x48, 0x60, 0x48, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x88, 0x88}, {0x20, 0x1, 0x48, 0x60, 0x48, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x88, 0x44}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("dns.google"),
},
Quad9: models.DNSProviderData{
IPs: []net.IP{{9, 9, 9, 9}, {149, 112, 112, 112}, {0x26, 0x20, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe}, {0x26, 0x20, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("dns.quad9.net"),
},
Quadrant: models.DNSProviderData{
IPs: []net.IP{{12, 159, 2, 159}, {0x20, 0x1, 0x18, 0x90, 0x14, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x59}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("dns-tls.qis.io"),
},
CleanBrowsing: models.DNSProviderData{
IPs: []net.IP{{185, 228, 168, 9}, {185, 228, 169, 9}, {0x2a, 0xd, 0x2a, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}, {0x2a, 0xd, 0x2a, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("security-filter-dns.cleanbrowsing.org"),
},
SecureDNS: models.DNSProviderData{
IPs: []net.IP{{146, 185, 167, 43}, {0x2a, 0x3, 0xb0, 0xc0, 0x0, 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0xe, 0x9a, 0x30, 0x1}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("dot.securedns.eu"),
},
LibreDNS: models.DNSProviderData{
IPs: []net.IP{{116, 203, 115, 192}},
SupportsTLS: true,
Host: models.DNSHost("dot.libredns.gr"),
},
}
}
// Block lists URLs
const (
AdsBlockListHostnamesURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/ads-hostnames.updated"
AdsBlockListIPsURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/ads-ips.updated"
MaliciousBlockListHostnamesURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/malicious-hostnames.updated"
MaliciousBlockListIPsURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/malicious-ips.updated"
SurveillanceBlockListHostnamesURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/surveillance-hostnames.updated"
SurveillanceBlockListIPsURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/surveillance-ips.updated"
)
// DNS certificates to fetch
// TODO obtain from source directly, see qdm12/updated)
const (
NamedRootURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/named.root.updated"
RootKeyURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/root.key.updated"
)
package constants
import (
"net"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
const (
// Cloudflare is a DNS over TLS provider
Cloudflare models.DNSProvider = "cloudflare"
// Google is a DNS over TLS provider
Google models.DNSProvider = "google"
// Quad9 is a DNS over TLS provider
Quad9 models.DNSProvider = "quad9"
// Quadrant is a DNS over TLS provider
Quadrant models.DNSProvider = "quadrant"
// CleanBrowsing is a DNS over TLS provider
CleanBrowsing models.DNSProvider = "cleanbrowsing"
// SecureDNS is a DNS over TLS provider
SecureDNS models.DNSProvider = "securedns"
// LibreDNS is a DNS over TLS provider
LibreDNS models.DNSProvider = "libredns"
)
// DNSProviderMapping returns a constant mapping of dns provider name
// to their data such as IP addresses or TLS host name.
func DNSProviderMapping() map[models.DNSProvider]models.DNSProviderData {
return map[models.DNSProvider]models.DNSProviderData{
Cloudflare: {
IPs: []net.IP{{1, 1, 1, 1}, {1, 0, 0, 1}, {0x26, 0x6, 0x47, 0x0, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11}, {0x26, 0x6, 0x47, 0x0, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x01}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("cloudflare-dns.com"),
},
Google: {
IPs: []net.IP{{8, 8, 8, 8}, {8, 8, 4, 4}, {0x20, 0x1, 0x48, 0x60, 0x48, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x88, 0x88}, {0x20, 0x1, 0x48, 0x60, 0x48, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x88, 0x44}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("dns.google"),
},
Quad9: {
IPs: []net.IP{{9, 9, 9, 9}, {149, 112, 112, 112}, {0x26, 0x20, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe}, {0x26, 0x20, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("dns.quad9.net"),
},
Quadrant: {
IPs: []net.IP{{12, 159, 2, 159}, {0x20, 0x1, 0x18, 0x90, 0x14, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x59}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("dns-tls.qis.io"),
},
CleanBrowsing: {
IPs: []net.IP{{185, 228, 168, 9}, {185, 228, 169, 9}, {0x2a, 0xd, 0x2a, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}, {0x2a, 0xd, 0x2a, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("security-filter-dns.cleanbrowsing.org"),
},
SecureDNS: {
IPs: []net.IP{{146, 185, 167, 43}, {0x2a, 0x3, 0xb0, 0xc0, 0x0, 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0xe, 0x9a, 0x30, 0x1}},
SupportsTLS: true,
SupportsIPv6: true,
Host: models.DNSHost("dot.securedns.eu"),
},
LibreDNS: {
IPs: []net.IP{{116, 203, 115, 192}},
SupportsTLS: true,
Host: models.DNSHost("dot.libredns.gr"),
},
}
}
// Block lists URLs
const (
AdsBlockListHostnamesURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/ads-hostnames.updated"
AdsBlockListIPsURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/ads-ips.updated"
MaliciousBlockListHostnamesURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/malicious-hostnames.updated"
MaliciousBlockListIPsURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/malicious-ips.updated"
SurveillanceBlockListHostnamesURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/surveillance-hostnames.updated"
SurveillanceBlockListIPsURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/surveillance-ips.updated"
)
// DNS certificates to fetch
// TODO obtain from source directly, see qdm12/updated)
const (
NamedRootURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/named.root.updated"
RootKeyURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/root.key.updated"
)

View File

@@ -1,85 +1,85 @@
package constants
import (
"github.com/qdm12/private-internet-access-docker/internal/models"
)
const (
// PIAEncryptionNormal is the normal level of encryption for communication with PIA servers
PIAEncryptionNormal models.PIAEncryption = "normal"
// PIAEncryptionStrong is the strong level of encryption for communication with PIA servers
PIAEncryptionStrong models.PIAEncryption = "strong"
)
const (
PIAX509CRL_NORMAL = "MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EWB4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Reze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqyMR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A=="
PIAX509CRL_STRONG = "MIIDWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAgEAppFfEpGsasjB1QgJcosGpzbf2kfRhM84o2TlqY1ua+Gi5TMdKydA3LJcNTjlI9a0TYAJfeRX5IkpoglSUuHuJgXhP3nEvX10mjXDpcu/YvM8TdE5JV2+EGqZ80kFtBeOq94WcpiVKFTR4fO+VkOK9zwspFfb1cNs9rHvgJ1QMkRUF8PpLN6AkntHY0+6DnigtSaKqldqjKTDTv2OeH3nPoh80SGrt0oCOmYKfWTJGpggMGKvIdvU3vH9+EuILZKKIskt+1dwdfA5Bkz1GLmiQG7+9ZZBQUjBG9Dos4hfX/rwJ3eU8oUIm4WoTz9rb71SOEuUUjP5NPy9HNx2vx+cVvLsTF4ZDZaUztW9o9JmIURDtbeyqxuHN3prlPWB6aj73IIm2dsDQvs3XXwRIxs8NwLbJ6CyEuvEOVCskdM8rdADWx1J0lRNlOJ0Z8ieLLEmYAA834VN1SboB6wJIAPxQU3rcBhXqO9y8aa2oRMg8NxZ5gr+PnKVMqag1x0IxbIgLxtkXQvxXxQHEMSODzvcOfK/nBRBsqTj30P+R87sU8titOoxNeRnBDRNhdEy/QGAqGh62ShPpQUCJdnKRiRTjnil9hMQHevoSuFKeEMO30FQL7BZyo37GFU+q1WPCplVZgCP9hC8Rn5K2+f6KLFo5bhtowSmu+GY1yZtg+RTtsA="
PIACertificate_NORMAL = "MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXDL1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzXlH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWpcdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RCOfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tLy8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZOsqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpMb3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2VzczEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5jb22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAna5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xUryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK37pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyCGohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUtYDQ8z9v+DMO6iwyIDRiU"
PIACertificate_STRONG = "MIIHqzCCBZOgAwIBAgIJAJ0u+vODZJntMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzQwMzNaFw0zNDA0MTIxNzQwMzNaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVkhjumaqBbL8aSgj6xbX1QPTfTd1qHsAZd2B97m8Vw31c/2yQgZNf5qZY0+jOIHULNDe4R9TIvyBEbvnAg/OkPw8n/+ScgYOeH876VUXzjLDBnDb8DLr/+w9oVsuDeFJ9KV2UFM1OYX0SnkHnrYAN2QLF98ESK4NCSU01h5zkcgmQ+qKSfA9Ny0/UpsKPBFqsQ25NvjDWFhCpeqCHKUJ4Be27CDbSl7lAkBuHMPHJs8f8xPgAbHRXZOxVCpayZ2SNDfCwsnGWpWFoMGvdMbygngCn6jA/W1VSFOlRlfLuuGe7QFfDwA0jaLCxuWt/BgZylp7tAzYKR8lnWmtUCPm4+BtjyVDYtDCiGBD9Z4P13RFWvJHw5aapx/5W/CuvVyI7pKwvc2IT+KPxCUhH1XI8ca5RN3C9NoPJJf6qpg4g0rJH3aaWkoMRrYvQ+5PXXYUzjtRHImghRGd/ydERYoAZXuGSbPkm9Y/p2X8unLcW+F0xpJD98+ZI+tzSsI99Zs5wijSUGYr9/j18KHFTMQ8n+1jauc5bCCegN27dPeKXNSZ5riXFL2XX6BkY68y58UaNzmeGMiUL9BOV1iV+PMb7B7PYs7oFLjAhh0EdyvfHkrh/ZV9BEhtFa7yXp8XR0J6vz1YV9R6DYJmLjOEbhU8N0gc3tZm4Qz39lIIG6w3FDAgMBAAGjggFUMIIBUDAdBgNVHQ4EFgQUrsRtyWJftjpdRM0+925Y6Cl08SUwggEfBgNVHSMEggEWMIIBEoAUrsRtyWJftjpdRM0+925Y6Cl08SWhge6kgeswgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tggkAnS7684Nkme0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOCAgEAJsfhsPk3r8kLXLxY+v+vHzbr4ufNtqnL9/1Uuf8NrsCtpXAoyZ0YqfbkWx3NHTZ7OE9ZRhdMP/RqHQE1p4N4Sa1nZKhTKasV6KhHDqSCt/dvEm89xWm2MVA7nyzQxVlHa9AkcBaemcXEiyT19XdpiXOP4Vhs+J1R5m8zQOxZlV1GtF9vsXmJqWZpOVPmZ8f35BCsYPvv4yMewnrtAC8PFEK/bOPeYcKN50bol22QYaZuLfpkHfNiFTnfMh8sl/ablPyNY7DUNiP5DRcMdIwmfGQxR5WEQoHL3yPJ42LkB5zs6jIm26DGNXfwura/mi105+ENH1CaROtRYwkiHb08U6qLXXJz80mWJkT90nr8Asj35xN2cUppg74nG3YVav/38P48T56hG1NHbYF5uOCske19F6wi9maUoto/3vEr0rnXJUp2KODmKdvBI7co245lHBABWikk8VfejQSlCtDBXn644ZMtAdoxKNfR2WTFVEwJiyd1Fzx0yujuiXDROLhISLQDRjVVAvawrAtLZWYK31bY7KlezPlQnl/D9Asxe85l8jO5+0LdJ6VyOs/Hd4w52alDW/MFySDZSfQHMTIc30hLBJ8OnCEIvluVQQ2UQvoW+no177N9L2Y+M9TcTA62ZyMXShHQGeh20rb4kK8f+iFX8NxtdHVSkxMEFSfDDyQ="
)
func PIAGeoChoices() (regions []string) {
for region := range PIAGeoToSubdomainMapping() {
regions = append(regions, string(region))
}
return regions
}
func PIAGeoToSubdomainMapping() map[models.PIARegion]string {
return map[models.PIARegion]string{
models.PIARegion("AU Melbourne"): "au-melbourne",
models.PIARegion("AU Perth"): "au-perth",
models.PIARegion("AU Sydney"): "au-sydney",
models.PIARegion("Austria"): "austria",
models.PIARegion("Belgium"): "belgium",
models.PIARegion("CA Montreal"): "ca-montreal",
models.PIARegion("CA Toronto"): "ca-toronto",
models.PIARegion("CA Vancouver"): "ca-vancouver",
models.PIARegion("Czech Republic"): "czech",
models.PIARegion("DE Berlin"): "de-berlin",
models.PIARegion("DE Frankfurt"): "de-frankfurt",
models.PIARegion("Denmark"): "denmark",
models.PIARegion("Finland"): "fi",
models.PIARegion("France"): "france",
models.PIARegion("Hong Kong"): "hk",
models.PIARegion("Hungary"): "hungary",
models.PIARegion("India"): "in",
models.PIARegion("Ireland"): "ireland",
models.PIARegion("Israel"): "israel",
models.PIARegion("Italy"): "italy",
models.PIARegion("Japan"): "japan",
models.PIARegion("Luxembourg"): "lu",
models.PIARegion("Mexico"): "mexico",
models.PIARegion("Netherlands"): "nl",
models.PIARegion("New Zealand"): "nz",
models.PIARegion("Norway"): "no",
models.PIARegion("Poland"): "poland",
models.PIARegion("Romania"): "ro",
models.PIARegion("Singapore"): "sg",
models.PIARegion("Spain"): "spain",
models.PIARegion("Sweden"): "sweden",
models.PIARegion("Switzerland"): "swiss",
models.PIARegion("UAE"): "ae",
models.PIARegion("UK London"): "uk-london",
models.PIARegion("UK Manchester"): "uk-manchester",
models.PIARegion("UK Southampton"): "uk-southampton",
models.PIARegion("US Atlanta"): "us-atlanta",
models.PIARegion("US California"): "us-california",
models.PIARegion("US Chicago"): "us-chicago",
models.PIARegion("US Denver"): "us-denver",
models.PIARegion("US East"): "us-east",
models.PIARegion("US Florida"): "us-florida",
models.PIARegion("US Houston"): "us-houston",
models.PIARegion("US Las Vegas"): "us-lasvegas",
models.PIARegion("US New York City"): "us-newyorkcity",
models.PIARegion("US Seattle"): "us-seattle",
models.PIARegion("US Silicon Valley"): "us-siliconvalley",
models.PIARegion("US Texas"): "us-texas",
models.PIARegion("US Washington DC"): "us-washingtondc",
models.PIARegion("US West"): "us-west",
}
}
const (
PIAPortForwardURL models.URL = "http://209.222.18.222:2000"
)
package constants
import (
"github.com/qdm12/private-internet-access-docker/internal/models"
)
const (
// PIAEncryptionNormal is the normal level of encryption for communication with PIA servers
PIAEncryptionNormal models.PIAEncryption = "normal"
// PIAEncryptionStrong is the strong level of encryption for communication with PIA servers
PIAEncryptionStrong models.PIAEncryption = "strong"
)
const (
PiaX509CRLNormal = "MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EWB4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Reze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqyMR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A=="
PiaX509CRLStrong = "MIIDWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAgEAppFfEpGsasjB1QgJcosGpzbf2kfRhM84o2TlqY1ua+Gi5TMdKydA3LJcNTjlI9a0TYAJfeRX5IkpoglSUuHuJgXhP3nEvX10mjXDpcu/YvM8TdE5JV2+EGqZ80kFtBeOq94WcpiVKFTR4fO+VkOK9zwspFfb1cNs9rHvgJ1QMkRUF8PpLN6AkntHY0+6DnigtSaKqldqjKTDTv2OeH3nPoh80SGrt0oCOmYKfWTJGpggMGKvIdvU3vH9+EuILZKKIskt+1dwdfA5Bkz1GLmiQG7+9ZZBQUjBG9Dos4hfX/rwJ3eU8oUIm4WoTz9rb71SOEuUUjP5NPy9HNx2vx+cVvLsTF4ZDZaUztW9o9JmIURDtbeyqxuHN3prlPWB6aj73IIm2dsDQvs3XXwRIxs8NwLbJ6CyEuvEOVCskdM8rdADWx1J0lRNlOJ0Z8ieLLEmYAA834VN1SboB6wJIAPxQU3rcBhXqO9y8aa2oRMg8NxZ5gr+PnKVMqag1x0IxbIgLxtkXQvxXxQHEMSODzvcOfK/nBRBsqTj30P+R87sU8titOoxNeRnBDRNhdEy/QGAqGh62ShPpQUCJdnKRiRTjnil9hMQHevoSuFKeEMO30FQL7BZyo37GFU+q1WPCplVZgCP9hC8Rn5K2+f6KLFo5bhtowSmu+GY1yZtg+RTtsA="
PIACertificateNormal = "MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXDL1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzXlH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWpcdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RCOfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tLy8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZOsqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpMb3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2VzczEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5jb22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAna5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xUryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK37pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyCGohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUtYDQ8z9v+DMO6iwyIDRiU"
PIACertificateStrong = "MIIHqzCCBZOgAwIBAgIJAJ0u+vODZJntMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzQwMzNaFw0zNDA0MTIxNzQwMzNaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVkhjumaqBbL8aSgj6xbX1QPTfTd1qHsAZd2B97m8Vw31c/2yQgZNf5qZY0+jOIHULNDe4R9TIvyBEbvnAg/OkPw8n/+ScgYOeH876VUXzjLDBnDb8DLr/+w9oVsuDeFJ9KV2UFM1OYX0SnkHnrYAN2QLF98ESK4NCSU01h5zkcgmQ+qKSfA9Ny0/UpsKPBFqsQ25NvjDWFhCpeqCHKUJ4Be27CDbSl7lAkBuHMPHJs8f8xPgAbHRXZOxVCpayZ2SNDfCwsnGWpWFoMGvdMbygngCn6jA/W1VSFOlRlfLuuGe7QFfDwA0jaLCxuWt/BgZylp7tAzYKR8lnWmtUCPm4+BtjyVDYtDCiGBD9Z4P13RFWvJHw5aapx/5W/CuvVyI7pKwvc2IT+KPxCUhH1XI8ca5RN3C9NoPJJf6qpg4g0rJH3aaWkoMRrYvQ+5PXXYUzjtRHImghRGd/ydERYoAZXuGSbPkm9Y/p2X8unLcW+F0xpJD98+ZI+tzSsI99Zs5wijSUGYr9/j18KHFTMQ8n+1jauc5bCCegN27dPeKXNSZ5riXFL2XX6BkY68y58UaNzmeGMiUL9BOV1iV+PMb7B7PYs7oFLjAhh0EdyvfHkrh/ZV9BEhtFa7yXp8XR0J6vz1YV9R6DYJmLjOEbhU8N0gc3tZm4Qz39lIIG6w3FDAgMBAAGjggFUMIIBUDAdBgNVHQ4EFgQUrsRtyWJftjpdRM0+925Y6Cl08SUwggEfBgNVHSMEggEWMIIBEoAUrsRtyWJftjpdRM0+925Y6Cl08SWhge6kgeswgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tggkAnS7684Nkme0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOCAgEAJsfhsPk3r8kLXLxY+v+vHzbr4ufNtqnL9/1Uuf8NrsCtpXAoyZ0YqfbkWx3NHTZ7OE9ZRhdMP/RqHQE1p4N4Sa1nZKhTKasV6KhHDqSCt/dvEm89xWm2MVA7nyzQxVlHa9AkcBaemcXEiyT19XdpiXOP4Vhs+J1R5m8zQOxZlV1GtF9vsXmJqWZpOVPmZ8f35BCsYPvv4yMewnrtAC8PFEK/bOPeYcKN50bol22QYaZuLfpkHfNiFTnfMh8sl/ablPyNY7DUNiP5DRcMdIwmfGQxR5WEQoHL3yPJ42LkB5zs6jIm26DGNXfwura/mi105+ENH1CaROtRYwkiHb08U6qLXXJz80mWJkT90nr8Asj35xN2cUppg74nG3YVav/38P48T56hG1NHbYF5uOCske19F6wi9maUoto/3vEr0rnXJUp2KODmKdvBI7co245lHBABWikk8VfejQSlCtDBXn644ZMtAdoxKNfR2WTFVEwJiyd1Fzx0yujuiXDROLhISLQDRjVVAvawrAtLZWYK31bY7KlezPlQnl/D9Asxe85l8jO5+0LdJ6VyOs/Hd4w52alDW/MFySDZSfQHMTIc30hLBJ8OnCEIvluVQQ2UQvoW+no177N9L2Y+M9TcTA62ZyMXShHQGeh20rb4kK8f+iFX8NxtdHVSkxMEFSfDDyQ="
)
func PIAGeoChoices() (regions []string) {
for region := range PIAGeoToSubdomainMapping() {
regions = append(regions, string(region))
}
return regions
}
func PIAGeoToSubdomainMapping() map[models.PIARegion]string {
return map[models.PIARegion]string{
models.PIARegion("AU Melbourne"): "au-melbourne",
models.PIARegion("AU Perth"): "au-perth",
models.PIARegion("AU Sydney"): "au-sydney",
models.PIARegion("Austria"): "austria",
models.PIARegion("Belgium"): "belgium",
models.PIARegion("CA Montreal"): "ca-montreal",
models.PIARegion("CA Toronto"): "ca-toronto",
models.PIARegion("CA Vancouver"): "ca-vancouver",
models.PIARegion("Czech Republic"): "czech",
models.PIARegion("DE Berlin"): "de-berlin",
models.PIARegion("DE Frankfurt"): "de-frankfurt",
models.PIARegion("Denmark"): "denmark",
models.PIARegion("Finland"): "fi",
models.PIARegion("France"): "france",
models.PIARegion("Hong Kong"): "hk",
models.PIARegion("Hungary"): "hungary",
models.PIARegion("India"): "in",
models.PIARegion("Ireland"): "ireland",
models.PIARegion("Israel"): "israel",
models.PIARegion("Italy"): "italy",
models.PIARegion("Japan"): "japan",
models.PIARegion("Luxembourg"): "lu",
models.PIARegion("Mexico"): "mexico",
models.PIARegion("Netherlands"): "nl",
models.PIARegion("New Zealand"): "nz",
models.PIARegion("Norway"): "no",
models.PIARegion("Poland"): "poland",
models.PIARegion("Romania"): "ro",
models.PIARegion("Singapore"): "sg",
models.PIARegion("Spain"): "spain",
models.PIARegion("Sweden"): "sweden",
models.PIARegion("Switzerland"): "swiss",
models.PIARegion("UAE"): "ae",
models.PIARegion("UK London"): "uk-london",
models.PIARegion("UK Manchester"): "uk-manchester",
models.PIARegion("UK Southampton"): "uk-southampton",
models.PIARegion("US Atlanta"): "us-atlanta",
models.PIARegion("US California"): "us-california",
models.PIARegion("US Chicago"): "us-chicago",
models.PIARegion("US Denver"): "us-denver",
models.PIARegion("US East"): "us-east",
models.PIARegion("US Florida"): "us-florida",
models.PIARegion("US Houston"): "us-houston",
models.PIARegion("US Las Vegas"): "us-lasvegas",
models.PIARegion("US New York City"): "us-newyorkcity",
models.PIARegion("US Seattle"): "us-seattle",
models.PIARegion("US Silicon Valley"): "us-siliconvalley",
models.PIARegion("US Texas"): "us-texas",
models.PIARegion("US Washington DC"): "us-washingtondc",
models.PIARegion("US West"): "us-west",
}
}
const (
PIAPortForwardURL models.URL = "http://209.222.18.222:2000"
)

View File

@@ -1,287 +1,289 @@
package dns
import (
"fmt"
"sort"
"strings"
"github.com/qdm12/golibs/files"
"github.com/qdm12/golibs/logging"
"github.com/qdm12/golibs/network"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/settings"
)
func (c *configurator) MakeUnboundConf(settings settings.DNS, uid, gid int) (err error) {
c.logger.Info("generating Unbound configuration")
lines, warnings, err := generateUnboundConf(settings, c.client, c.logger)
for _, warning := range warnings {
c.logger.Warn(warning)
}
if err != nil {
return err
}
return c.fileManager.WriteLinesToFile(
string(constants.UnboundConf),
lines,
files.Ownership(uid, gid),
files.Permissions(0400))
}
// MakeUnboundConf generates an Unbound configuration from the user provided settings
func generateUnboundConf(settings settings.DNS, client network.Client, logger logging.Logger) (lines []string, warnings []error, err error) {
doIPv6 := "no"
if settings.IPv6 {
doIPv6 = "yes"
}
serverSection := map[string]string{
// Logging
"verbosity": fmt.Sprintf("%d", settings.VerbosityLevel),
"val-log-level": fmt.Sprintf("%d", settings.ValidationLogLevel),
"use-syslog": "no",
// Performance
"num-threads": "1",
"prefetch": "yes",
"prefetch-key": "yes",
"key-cache-size": "16m",
"key-cache-slabs": "4",
"msg-cache-size": "4m",
"msg-cache-slabs": "4",
"rrset-cache-size": "4m",
"rrset-cache-slabs": "4",
"cache-min-ttl": "3600",
"cache-max-ttl": "9000",
// Privacy
"rrset-roundrobin": "yes",
"hide-identity": "yes",
"hide-version": "yes",
// Security
"tls-cert-bundle": fmt.Sprintf("%q", constants.CACertificates),
"root-hints": fmt.Sprintf("%q", constants.RootHints),
"trust-anchor-file": fmt.Sprintf("%q", constants.RootKey),
"harden-below-nxdomain": "yes",
"harden-referral-path": "yes",
"harden-algo-downgrade": "yes",
// Network
"do-ip4": "yes",
"do-ip6": doIPv6,
"interface": "127.0.0.1",
"port": "53",
// Other
"username": "\"nonrootuser\"",
}
// Block lists
hostnamesLines, ipsLines, warnings := buildBlocked(client,
settings.BlockMalicious, settings.BlockAds, settings.BlockSurveillance,
settings.AllowedHostnames, settings.PrivateAddresses,
)
logger.Info("%d hostnames blocked overall", len(hostnamesLines))
logger.Info("%d IP addresses blocked overall", len(ipsLines))
sort.Slice(hostnamesLines, func(i, j int) bool { // for unit tests really
return hostnamesLines[i] < hostnamesLines[j]
})
sort.Slice(ipsLines, func(i, j int) bool { // for unit tests really
return ipsLines[i] < ipsLines[j]
})
// Server
lines = append(lines, "server:")
var serverLines []string
for k, v := range serverSection {
serverLines = append(serverLines, " "+k+": "+v)
}
sort.Slice(serverLines, func(i, j int) bool {
return serverLines[i] < serverLines[j]
})
lines = append(lines, serverLines...)
lines = append(lines, hostnamesLines...)
lines = append(lines, ipsLines...)
// Forward zone
lines = append(lines, "forward-zone:")
forwardZoneSection := map[string]string{
"name": "\".\"",
"forward-tls-upstream": "yes",
}
if settings.Caching {
forwardZoneSection["forward-no-cache"] = "no"
} else {
forwardZoneSection["forward-no-cache"] = "yes"
}
var forwardZoneLines []string
for k, v := range forwardZoneSection {
forwardZoneLines = append(forwardZoneLines, " "+k+": "+v)
}
sort.Slice(forwardZoneLines, func(i, j int) bool {
return forwardZoneLines[i] < forwardZoneLines[j]
})
for _, provider := range settings.Providers {
providerData := constants.DNSProviderMapping()[provider]
for _, IP := range providerData.IPs {
forwardZoneLines = append(forwardZoneLines,
fmt.Sprintf(" forward-addr: %s@853#%s", IP.String(), providerData.Host))
}
}
lines = append(lines, forwardZoneLines...)
return lines, warnings, nil
}
func buildBlocked(client network.Client, blockMalicious, blockAds, blockSurveillance bool,
allowedHostnames, privateAddresses []string) (hostnamesLines, ipsLines []string, errs []error) {
chHostnames := make(chan []string)
chIPs := make(chan []string)
chErrors := make(chan []error)
go func() {
lines, errs := buildBlockedHostnames(client, blockMalicious, blockAds, blockSurveillance, allowedHostnames)
chHostnames <- lines
chErrors <- errs
}()
go func() {
lines, errs := buildBlockedIPs(client, blockMalicious, blockAds, blockSurveillance, privateAddresses)
chIPs <- lines
chErrors <- errs
}()
n := 2
for n > 0 {
select {
case lines := <-chHostnames:
hostnamesLines = append(hostnamesLines, lines...)
case lines := <-chIPs:
ipsLines = append(ipsLines, lines...)
case routineErrs := <-chErrors:
errs = append(errs, routineErrs...)
n--
}
}
return hostnamesLines, ipsLines, errs
}
func getList(client network.Client, URL string) (results []string, err error) {
content, status, err := client.GetContent(URL)
if err != nil {
return nil, err
} else if status != 200 {
return nil, fmt.Errorf("HTTP status code is %d and not 200", status)
}
results = strings.Split(string(content), "\n")
// remove empty lines
last := len(results) - 1
for i := range results {
if len(results[i]) == 0 {
results[i] = results[last]
last--
}
}
results = results[:last+1]
if len(results) == 0 {
return nil, nil
}
return results, nil
}
func buildBlockedHostnames(client network.Client, blockMalicious, blockAds, blockSurveillance bool,
allowedHostnames []string) (lines []string, errs []error) {
chResults := make(chan []string)
chError := make(chan error)
listsLeftToFetch := 0
if blockMalicious {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.MaliciousBlockListHostnamesURL))
chResults <- results
chError <- err
}()
}
if blockAds {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.AdsBlockListHostnamesURL))
chResults <- results
chError <- err
}()
}
if blockSurveillance {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.SurveillanceBlockListHostnamesURL))
chResults <- results
chError <- err
}()
}
uniqueResults := make(map[string]struct{})
for listsLeftToFetch > 0 {
select {
case results := <-chResults:
for _, result := range results {
uniqueResults[result] = struct{}{}
}
case err := <-chError:
listsLeftToFetch--
if err != nil {
errs = append(errs, err)
}
}
}
for _, allowedHostname := range allowedHostnames {
delete(uniqueResults, allowedHostname)
}
for result := range uniqueResults {
lines = append(lines, " local-zone: \""+result+"\" static")
}
return lines, errs
}
func buildBlockedIPs(client network.Client, blockMalicious, blockAds, blockSurveillance bool,
privateAddresses []string) (lines []string, errs []error) {
chResults := make(chan []string)
chError := make(chan error)
listsLeftToFetch := 0
if blockMalicious {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.MaliciousBlockListIPsURL))
chResults <- results
chError <- err
}()
}
if blockAds {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.AdsBlockListIPsURL))
chResults <- results
chError <- err
}()
}
if blockSurveillance {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.SurveillanceBlockListIPsURL))
chResults <- results
chError <- err
}()
}
uniqueResults := make(map[string]struct{})
for listsLeftToFetch > 0 {
select {
case results := <-chResults:
for _, result := range results {
uniqueResults[result] = struct{}{}
}
case err := <-chError:
listsLeftToFetch--
if err != nil {
errs = append(errs, err)
}
}
}
for _, privateAddress := range privateAddresses {
uniqueResults[privateAddress] = struct{}{}
}
for result := range uniqueResults {
lines = append(lines, " private-address: "+result)
}
return lines, errs
}
package dns
import (
"fmt"
"net/http"
"sort"
"strings"
"github.com/qdm12/golibs/files"
"github.com/qdm12/golibs/logging"
"github.com/qdm12/golibs/network"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/settings"
)
func (c *configurator) MakeUnboundConf(settings settings.DNS, uid, gid int) (err error) {
c.logger.Info("generating Unbound configuration")
lines, warnings := generateUnboundConf(settings, c.client, c.logger)
for _, warning := range warnings {
c.logger.Warn(warning)
}
return c.fileManager.WriteLinesToFile(
string(constants.UnboundConf),
lines,
files.Ownership(uid, gid),
files.Permissions(0400))
}
// MakeUnboundConf generates an Unbound configuration from the user provided settings
func generateUnboundConf(settings settings.DNS, client network.Client, logger logging.Logger) (lines []string, warnings []error) {
doIPv6 := "no"
if settings.IPv6 {
doIPv6 = "yes"
}
serverSection := map[string]string{
// Logging
"verbosity": fmt.Sprintf("%d", settings.VerbosityLevel),
"val-log-level": fmt.Sprintf("%d", settings.ValidationLogLevel),
"use-syslog": "no",
// Performance
"num-threads": "1",
"prefetch": "yes",
"prefetch-key": "yes",
"key-cache-size": "16m",
"key-cache-slabs": "4",
"msg-cache-size": "4m",
"msg-cache-slabs": "4",
"rrset-cache-size": "4m",
"rrset-cache-slabs": "4",
"cache-min-ttl": "3600",
"cache-max-ttl": "9000",
// Privacy
"rrset-roundrobin": "yes",
"hide-identity": "yes",
"hide-version": "yes",
// Security
"tls-cert-bundle": fmt.Sprintf("%q", constants.CACertificates),
"root-hints": fmt.Sprintf("%q", constants.RootHints),
"trust-anchor-file": fmt.Sprintf("%q", constants.RootKey),
"harden-below-nxdomain": "yes",
"harden-referral-path": "yes",
"harden-algo-downgrade": "yes",
// Network
"do-ip4": "yes",
"do-ip6": doIPv6,
"interface": "127.0.0.1",
"port": "53",
// Other
"username": "\"nonrootuser\"",
}
// Block lists
hostnamesLines, ipsLines, warnings := buildBlocked(client,
settings.BlockMalicious, settings.BlockAds, settings.BlockSurveillance,
settings.AllowedHostnames, settings.PrivateAddresses,
)
logger.Info("%d hostnames blocked overall", len(hostnamesLines))
logger.Info("%d IP addresses blocked overall", len(ipsLines))
sort.Slice(hostnamesLines, func(i, j int) bool { // for unit tests really
return hostnamesLines[i] < hostnamesLines[j]
})
sort.Slice(ipsLines, func(i, j int) bool { // for unit tests really
return ipsLines[i] < ipsLines[j]
})
// Server
lines = append(lines, "server:")
serverLines := make([]string, len(serverSection))
i := 0
for k, v := range serverSection {
serverLines[i] = " " + k + ": " + v
i++
}
sort.Slice(serverLines, func(i, j int) bool {
return serverLines[i] < serverLines[j]
})
lines = append(lines, serverLines...)
lines = append(lines, hostnamesLines...)
lines = append(lines, ipsLines...)
// Forward zone
lines = append(lines, "forward-zone:")
forwardZoneSection := map[string]string{
"name": "\".\"",
"forward-tls-upstream": "yes",
}
if settings.Caching {
forwardZoneSection["forward-no-cache"] = "no"
} else {
forwardZoneSection["forward-no-cache"] = "yes"
}
forwardZoneLines := make([]string, len(forwardZoneSection))
i = 0
for k, v := range forwardZoneSection {
forwardZoneLines[i] = " " + k + ": " + v
i++
}
sort.Slice(forwardZoneLines, func(i, j int) bool {
return forwardZoneLines[i] < forwardZoneLines[j]
})
for _, provider := range settings.Providers {
providerData := constants.DNSProviderMapping()[provider]
for _, IP := range providerData.IPs {
forwardZoneLines = append(forwardZoneLines,
fmt.Sprintf(" forward-addr: %s@853#%s", IP.String(), providerData.Host))
}
}
lines = append(lines, forwardZoneLines...)
return lines, warnings
}
func buildBlocked(client network.Client, blockMalicious, blockAds, blockSurveillance bool,
allowedHostnames, privateAddresses []string) (hostnamesLines, ipsLines []string, errs []error) {
chHostnames := make(chan []string)
chIPs := make(chan []string)
chErrors := make(chan []error)
go func() {
lines, errs := buildBlockedHostnames(client, blockMalicious, blockAds, blockSurveillance, allowedHostnames)
chHostnames <- lines
chErrors <- errs
}()
go func() {
lines, errs := buildBlockedIPs(client, blockMalicious, blockAds, blockSurveillance, privateAddresses)
chIPs <- lines
chErrors <- errs
}()
n := 2
for n > 0 {
select {
case lines := <-chHostnames:
hostnamesLines = append(hostnamesLines, lines...)
case lines := <-chIPs:
ipsLines = append(ipsLines, lines...)
case routineErrs := <-chErrors:
errs = append(errs, routineErrs...)
n--
}
}
return hostnamesLines, ipsLines, errs
}
func getList(client network.Client, url string) (results []string, err error) {
content, status, err := client.GetContent(url)
if err != nil {
return nil, err
} else if status != http.StatusOK {
return nil, fmt.Errorf("HTTP status code is %d and not 200", status)
}
results = strings.Split(string(content), "\n")
// remove empty lines
last := len(results) - 1
for i := range results {
if len(results[i]) == 0 {
results[i] = results[last]
last--
}
}
results = results[:last+1]
if len(results) == 0 {
return nil, nil
}
return results, nil
}
func buildBlockedHostnames(client network.Client, blockMalicious, blockAds, blockSurveillance bool,
allowedHostnames []string) (lines []string, errs []error) {
chResults := make(chan []string)
chError := make(chan error)
listsLeftToFetch := 0
if blockMalicious {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.MaliciousBlockListHostnamesURL))
chResults <- results
chError <- err
}()
}
if blockAds {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.AdsBlockListHostnamesURL))
chResults <- results
chError <- err
}()
}
if blockSurveillance {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.SurveillanceBlockListHostnamesURL))
chResults <- results
chError <- err
}()
}
uniqueResults := make(map[string]struct{})
for listsLeftToFetch > 0 {
select {
case results := <-chResults:
for _, result := range results {
uniqueResults[result] = struct{}{}
}
case err := <-chError:
listsLeftToFetch--
if err != nil {
errs = append(errs, err)
}
}
}
for _, allowedHostname := range allowedHostnames {
delete(uniqueResults, allowedHostname)
}
for result := range uniqueResults {
lines = append(lines, " local-zone: \""+result+"\" static")
}
return lines, errs
}
func buildBlockedIPs(client network.Client, blockMalicious, blockAds, blockSurveillance bool,
privateAddresses []string) (lines []string, errs []error) {
chResults := make(chan []string)
chError := make(chan error)
listsLeftToFetch := 0
if blockMalicious {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.MaliciousBlockListIPsURL))
chResults <- results
chError <- err
}()
}
if blockAds {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.AdsBlockListIPsURL))
chResults <- results
chError <- err
}()
}
if blockSurveillance {
listsLeftToFetch++
go func() {
results, err := getList(client, string(constants.SurveillanceBlockListIPsURL))
chResults <- results
chError <- err
}()
}
uniqueResults := make(map[string]struct{})
for listsLeftToFetch > 0 {
select {
case results := <-chResults:
for _, result := range results {
uniqueResults[result] = struct{}{}
}
case err := <-chError:
listsLeftToFetch--
if err != nil {
errs = append(errs, err)
}
}
}
for _, privateAddress := range privateAddresses {
uniqueResults[privateAddress] = struct{}{}
}
for result := range uniqueResults {
lines = append(lines, " private-address: "+result)
}
return lines, errs
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,20 +9,20 @@ import (
)
// UseDNSInternally is to change the Go program DNS only
func (c *configurator) UseDNSInternally(IP net.IP) {
c.logger.Info("using DNS address %s internally", IP.String())
func (c *configurator) UseDNSInternally(ip net.IP) {
c.logger.Info("using DNS address %s internally", ip.String())
net.DefaultResolver = &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{}
return d.DialContext(ctx, "udp", net.JoinHostPort(IP.String(), "53"))
return d.DialContext(ctx, "udp", net.JoinHostPort(ip.String(), "53"))
},
}
}
// UseDNSSystemWide changes the nameserver to use for DNS system wide
func (c *configurator) UseDNSSystemWide(IP net.IP) error {
c.logger.Info("using DNS address %s system wide", IP.String())
func (c *configurator) UseDNSSystemWide(ip net.IP) error {
c.logger.Info("using DNS address %s system wide", ip.String())
data, err := c.fileManager.ReadFile(string(constants.ResolvConf))
if err != nil {
return err
@@ -35,12 +35,12 @@ func (c *configurator) UseDNSSystemWide(IP net.IP) error {
found := false
for i := range lines {
if strings.HasPrefix(lines[i], "nameserver ") {
lines[i] = "nameserver " + IP.String()
lines[i] = "nameserver " + ip.String()
found = true
}
}
if !found {
lines = append(lines, "nameserver "+IP.String())
lines = append(lines, "nameserver "+ip.String())
}
data = []byte(strings.Join(lines, "\n"))
return c.fileManager.WriteToFile(string(constants.ResolvConf), data)

View File

@@ -2,6 +2,7 @@ package dns
import (
"fmt"
"net/http"
"github.com/qdm12/golibs/files"
"github.com/qdm12/private-internet-access-docker/internal/constants"
@@ -12,7 +13,7 @@ func (c *configurator) DownloadRootHints(uid, gid int) error {
content, status, err := c.client.GetContent(string(constants.NamedRootURL))
if err != nil {
return err
} else if status != 200 {
} else if status != http.StatusOK {
return fmt.Errorf("HTTP status code is %d for %s", status, constants.NamedRootURL)
}
return c.fileManager.WriteToFile(
@@ -27,7 +28,7 @@ func (c *configurator) DownloadRootKey(uid, gid int) error {
content, status, err := c.client.GetContent(string(constants.RootKeyURL))
if err != nil {
return err
} else if status != 200 {
} else if status != http.StatusOK {
return fmt.Errorf("HTTP status code is %d for %s", status, constants.RootKeyURL)
}
return c.fileManager.WriteToFile(

View File

@@ -16,7 +16,7 @@ import (
"github.com/qdm12/private-internet-access-docker/internal/constants"
)
func Test_DownloadRootHints(t *testing.T) {
func Test_DownloadRootHints(t *testing.T) { //nolint:dupl
t.Parallel()
tests := map[string]struct {
content []byte
@@ -78,7 +78,7 @@ func Test_DownloadRootHints(t *testing.T) {
}
}
func Test_DownloadRootKey(t *testing.T) {
func Test_DownloadRootKey(t *testing.T) { //nolint:dupl
t.Parallel()
tests := map[string]struct {
content []byte

View File

@@ -14,7 +14,7 @@ func (c *configurator) WaitForUnbound() (err error) {
return nil
}
c.logger.Warn("could not resolve %s (try %d of %d): %s", hostToResolve, try, maxTries, err)
time.Sleep(time.Duration(maxTries * 50 * time.Millisecond))
time.Sleep(maxTries * 50 * time.Millisecond)
}
return fmt.Errorf("Unbound does not seem to be working after %d tries", maxTries)
}

View File

@@ -68,7 +68,6 @@ func Test_PrintVersion(t *testing.T) {
logger.EXPECT().Error(tc.commandErr).Do(func(err error) {
logged = err.Error()
}).Times(1)
} else {
logger.EXPECT().Info("%s version: %s", tc.program, tc.commandVersion).
Do(func(format, program, version string) {

View File

@@ -10,8 +10,8 @@ import (
func HealthCheck() error {
// DNS, HTTP and HTTPs check on github.com
connectivty := connectivity.NewConnectivity(3 * time.Second)
errs := connectivty.Checks("github.com")
connectivity := connectivity.NewConnectivity(3 * time.Second)
errs := connectivity.Checks("github.com")
if len(errs) > 0 {
var errsStr []string
for _, err := range errs {

View File

@@ -3,10 +3,10 @@ package models
import "net"
type MullvadServer struct {
IPs []net.IP
Country MullvadCountry
City MullvadCity
Provider MullvadProvider
Owned bool
IPs []net.IP
DefaultPort uint16
}

View File

@@ -30,7 +30,7 @@ func (c *configurator) CreateTUN() error {
if err := c.mkNod(string(constants.TunnelDevice), unix.S_IFCHR, int(dev)); err != nil {
return err
}
if err := c.fileManager.SetUserPermissions(string(constants.TunnelDevice), 666); err != nil {
if err := c.fileManager.SetUserPermissions(string(constants.TunnelDevice), 0666); err != nil {
return err
}
return nil

View File

@@ -1,124 +1,122 @@
package params
import (
"fmt"
"strings"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetDNSOverTLS obtains if the DNS over TLS should be enabled
// from the environment variable DOT
func (p *paramsReader) GetDNSOverTLS() (DNSOverTLS bool, err error) {
return p.envParams.GetOnOff("DOT", libparams.Default("on"))
}
// GetDNSOverTLSProviders obtains the DNS over TLS providers to use
// from the environment variable DOT_PROVIDERS
func (p *paramsReader) GetDNSOverTLSProviders() (providers []models.DNSProvider, err error) {
s, err := p.envParams.GetEnv("DOT_PROVIDERS", libparams.Default("cloudflare"))
if err != nil {
return nil, err
}
for _, word := range strings.Split(s, ",") {
provider := models.DNSProvider(word)
switch provider {
case constants.Cloudflare, constants.Google, constants.Quad9, constants.Quadrant, constants.CleanBrowsing, constants.SecureDNS, constants.LibreDNS:
providers = append(providers, provider)
default:
return nil, fmt.Errorf("DNS over TLS provider %q is not valid", provider)
}
}
return providers, nil
}
// GetDNSOverTLSVerbosity obtains the verbosity level to use for Unbound
// from the environment variable DOT_VERBOSITY
func (p *paramsReader) GetDNSOverTLSVerbosity() (verbosityLevel uint8, err error) {
n, err := p.envParams.GetEnvIntRange("DOT_VERBOSITY", 0, 5, libparams.Default("1"))
return uint8(n), err
}
// GetDNSOverTLSVerbosityDetails obtains the log level to use for Unbound
// from the environment variable DOT_VERBOSITY_DETAILS
func (p *paramsReader) GetDNSOverTLSVerbosityDetails() (verbosityDetailsLevel uint8, err error) {
n, err := p.envParams.GetEnvIntRange("DOT_VERBOSITY_DETAILS", 0, 4, libparams.Default("0"))
return uint8(n), err
}
// GetDNSOverTLSValidationLogLevel obtains the log level to use for Unbound DOT validation
// from the environment variable DOT_VALIDATION_LOGLEVEL
func (p *paramsReader) GetDNSOverTLSValidationLogLevel() (validationLogLevel uint8, err error) {
n, err := p.envParams.GetEnvIntRange("DOT_VALIDATION_LOGLEVEL", 0, 2, libparams.Default("0"))
return uint8(n), err
}
// GetDNSMaliciousBlocking obtains if malicious hostnames/IPs should be blocked
// from being resolved by Unbound, using the environment variable BLOCK_MALICIOUS
func (p *paramsReader) GetDNSMaliciousBlocking() (blocking bool, err error) {
return p.envParams.GetOnOff("BLOCK_MALICIOUS", libparams.Default("on"))
}
// GetDNSSurveillanceBlocking obtains if surveillance hostnames/IPs should be blocked
// from being resolved by Unbound, using the environment variable BLOCK_SURVEILLANCE
// and BLOCK_NSA for retrocompatibility
func (p *paramsReader) GetDNSSurveillanceBlocking() (blocking bool, err error) {
// Retro-compatibility
s, err := p.envParams.GetEnv("BLOCK_NSA")
if err != nil {
return false, err
} else if len(s) != 0 {
p.logger.Warn("You are using the old environment variable BLOCK_NSA, please consider changing it to BLOCK_SURVEILLANCE")
return p.envParams.GetOnOff("BLOCK_NSA", libparams.Compulsory())
}
return p.envParams.GetOnOff("BLOCK_SURVEILLANCE", libparams.Default("off"))
}
// GetDNSAdsBlocking obtains if ads hostnames/IPs should be blocked
// from being resolved by Unbound, using the environment variable BLOCK_ADS
func (p *paramsReader) GetDNSAdsBlocking() (blocking bool, err error) {
return p.envParams.GetOnOff("BLOCK_ADS", libparams.Default("off"))
}
// GetDNSUnblockedHostnames obtains a list of hostnames to unblock from block lists
// from the comma separated list for the environment variable UNBLOCK
func (p *paramsReader) GetDNSUnblockedHostnames() (hostnames []string, err error) {
s, err := p.envParams.GetEnv("UNBLOCK")
if err != nil {
return nil, err
}
if len(s) == 0 {
return nil, nil
}
hostnames = strings.Split(s, ",")
for _, hostname := range hostnames {
if !p.verifier.MatchHostname(hostname) {
return nil, fmt.Errorf("hostname %q does not seem valid", hostname)
}
}
return hostnames, nil
}
// GetDNSOverTLSCaching obtains if Unbound caching should be enable or not
// from the environment variable DOT_CACHING
func (p *paramsReader) GetDNSOverTLSCaching() (caching bool, err error) {
return p.envParams.GetOnOff("DOT_CACHING")
}
// GetDNSOverTLSPrivateAddresses obtains if Unbound caching should be enable or not
// from the environment variable DOT_PRIVATE_ADDRESS
func (p *paramsReader) GetDNSOverTLSPrivateAddresses() (privateAddresses []string) {
s, _ := p.envParams.GetEnv("DOT_PRIVATE_ADDRESS")
for _, s := range strings.Split(s, ",") {
privateAddresses = append(privateAddresses, s)
}
return privateAddresses
}
// GetDNSOverTLSIPv6 obtains if Unbound should resolve ipv6 addresses using ipv6 DNS over TLS
// servers from the environment variable DOT_IPV6
func (p *paramsReader) GetDNSOverTLSIPv6() (ipv6 bool, err error) {
return p.envParams.GetOnOff("DOT_IPV6")
}
package params
import (
"fmt"
"strings"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetDNSOverTLS obtains if the DNS over TLS should be enabled
// from the environment variable DOT
func (p *reader) GetDNSOverTLS() (DNSOverTLS bool, err error) { //nolint:gocritic
return p.envParams.GetOnOff("DOT", libparams.Default("on"))
}
// GetDNSOverTLSProviders obtains the DNS over TLS providers to use
// from the environment variable DOT_PROVIDERS
func (p *reader) GetDNSOverTLSProviders() (providers []models.DNSProvider, err error) {
s, err := p.envParams.GetEnv("DOT_PROVIDERS", libparams.Default("cloudflare"))
if err != nil {
return nil, err
}
for _, word := range strings.Split(s, ",") {
provider := models.DNSProvider(word)
switch provider {
case constants.Cloudflare, constants.Google, constants.Quad9, constants.Quadrant, constants.CleanBrowsing, constants.SecureDNS, constants.LibreDNS:
providers = append(providers, provider)
default:
return nil, fmt.Errorf("DNS over TLS provider %q is not valid", provider)
}
}
return providers, nil
}
// GetDNSOverTLSVerbosity obtains the verbosity level to use for Unbound
// from the environment variable DOT_VERBOSITY
func (p *reader) GetDNSOverTLSVerbosity() (verbosityLevel uint8, err error) {
n, err := p.envParams.GetEnvIntRange("DOT_VERBOSITY", 0, 5, libparams.Default("1"))
return uint8(n), err
}
// GetDNSOverTLSVerbosityDetails obtains the log level to use for Unbound
// from the environment variable DOT_VERBOSITY_DETAILS
func (p *reader) GetDNSOverTLSVerbosityDetails() (verbosityDetailsLevel uint8, err error) {
n, err := p.envParams.GetEnvIntRange("DOT_VERBOSITY_DETAILS", 0, 4, libparams.Default("0"))
return uint8(n), err
}
// GetDNSOverTLSValidationLogLevel obtains the log level to use for Unbound DOT validation
// from the environment variable DOT_VALIDATION_LOGLEVEL
func (p *reader) GetDNSOverTLSValidationLogLevel() (validationLogLevel uint8, err error) {
n, err := p.envParams.GetEnvIntRange("DOT_VALIDATION_LOGLEVEL", 0, 2, libparams.Default("0"))
return uint8(n), err
}
// GetDNSMaliciousBlocking obtains if malicious hostnames/IPs should be blocked
// from being resolved by Unbound, using the environment variable BLOCK_MALICIOUS
func (p *reader) GetDNSMaliciousBlocking() (blocking bool, err error) {
return p.envParams.GetOnOff("BLOCK_MALICIOUS", libparams.Default("on"))
}
// GetDNSSurveillanceBlocking obtains if surveillance hostnames/IPs should be blocked
// from being resolved by Unbound, using the environment variable BLOCK_SURVEILLANCE
// and BLOCK_NSA for retrocompatibility
func (p *reader) GetDNSSurveillanceBlocking() (blocking bool, err error) {
// Retro-compatibility
s, err := p.envParams.GetEnv("BLOCK_NSA")
if err != nil {
return false, err
} else if len(s) != 0 {
p.logger.Warn("You are using the old environment variable BLOCK_NSA, please consider changing it to BLOCK_SURVEILLANCE")
return p.envParams.GetOnOff("BLOCK_NSA", libparams.Compulsory())
}
return p.envParams.GetOnOff("BLOCK_SURVEILLANCE", libparams.Default("off"))
}
// GetDNSAdsBlocking obtains if ads hostnames/IPs should be blocked
// from being resolved by Unbound, using the environment variable BLOCK_ADS
func (p *reader) GetDNSAdsBlocking() (blocking bool, err error) {
return p.envParams.GetOnOff("BLOCK_ADS", libparams.Default("off"))
}
// GetDNSUnblockedHostnames obtains a list of hostnames to unblock from block lists
// from the comma separated list for the environment variable UNBLOCK
func (p *reader) GetDNSUnblockedHostnames() (hostnames []string, err error) {
s, err := p.envParams.GetEnv("UNBLOCK")
if err != nil {
return nil, err
}
if len(s) == 0 {
return nil, nil
}
hostnames = strings.Split(s, ",")
for _, hostname := range hostnames {
if !p.verifier.MatchHostname(hostname) {
return nil, fmt.Errorf("hostname %q does not seem valid", hostname)
}
}
return hostnames, nil
}
// GetDNSOverTLSCaching obtains if Unbound caching should be enable or not
// from the environment variable DOT_CACHING
func (p *reader) GetDNSOverTLSCaching() (caching bool, err error) {
return p.envParams.GetOnOff("DOT_CACHING")
}
// GetDNSOverTLSPrivateAddresses obtains if Unbound caching should be enable or not
// from the environment variable DOT_PRIVATE_ADDRESS
func (p *reader) GetDNSOverTLSPrivateAddresses() (privateAddresses []string) {
s, _ := p.envParams.GetEnv("DOT_PRIVATE_ADDRESS")
privateAddresses = append(privateAddresses, strings.Split(s, ",")...)
return privateAddresses
}
// GetDNSOverTLSIPv6 obtains if Unbound should resolve ipv6 addresses using ipv6 DNS over TLS
// servers from the environment variable DOT_IPV6
func (p *reader) GetDNSOverTLSIPv6() (ipv6 bool, err error) {
return p.envParams.GetOnOff("DOT_IPV6")
}

View File

@@ -1,29 +1,29 @@
package params
import (
"fmt"
"net"
"strings"
)
// GetExtraSubnets obtains the CIDR subnets from the comma separated list of the
// environment variable EXTRA_SUBNETS
func (p *paramsReader) GetExtraSubnets() (extraSubnets []net.IPNet, err error) {
s, err := p.envParams.GetEnv("EXTRA_SUBNETS")
if err != nil {
return nil, err
} else if s == "" {
return nil, nil
}
subnets := strings.Split(s, ",")
for _, subnet := range subnets {
_, cidr, err := net.ParseCIDR(subnet)
if err != nil {
return nil, fmt.Errorf("could not parse subnet %q from environment variable with key EXTRA_SUBNETS: %w", subnet, err)
} else if cidr == nil {
return nil, fmt.Errorf("parsing subnet %q resulted in a nil CIDR", subnet)
}
extraSubnets = append(extraSubnets, *cidr)
}
return extraSubnets, nil
}
package params
import (
"fmt"
"net"
"strings"
)
// GetExtraSubnets obtains the CIDR subnets from the comma separated list of the
// environment variable EXTRA_SUBNETS
func (p *reader) GetExtraSubnets() (extraSubnets []net.IPNet, err error) {
s, err := p.envParams.GetEnv("EXTRA_SUBNETS")
if err != nil {
return nil, err
} else if s == "" {
return nil, nil
}
subnets := strings.Split(s, ",")
for _, subnet := range subnets {
_, cidr, err := net.ParseCIDR(subnet)
if err != nil {
return nil, fmt.Errorf("could not parse subnet %q from environment variable with key EXTRA_SUBNETS: %w", subnet, err)
} else if cidr == nil {
return nil, fmt.Errorf("parsing subnet %q resulted in a nil CIDR", subnet)
}
extraSubnets = append(extraSubnets, *cidr)
}
return extraSubnets, nil
}

View File

@@ -10,7 +10,7 @@ import (
// GetMullvadCountry obtains the country for the Mullvad server from the
// environment variable COUNTRY
func (p *paramsReader) GetMullvadCountry() (country models.MullvadCountry, err error) {
func (p *reader) GetMullvadCountry() (country models.MullvadCountry, err error) {
choices := append(constants.MullvadCountryChoices(), "")
s, err := p.envParams.GetValueIfInside("COUNTRY", choices)
return models.MullvadCountry(strings.ToLower(s)), err
@@ -18,7 +18,7 @@ func (p *paramsReader) GetMullvadCountry() (country models.MullvadCountry, err e
// GetMullvadCity obtains the city for the Mullvad server from the
// environment variable CITY
func (p *paramsReader) GetMullvadCity() (country models.MullvadCity, err error) {
func (p *reader) GetMullvadCity() (country models.MullvadCity, err error) {
choices := append(constants.MullvadCityChoices(), "")
s, err := p.envParams.GetValueIfInside("CITY", choices)
return models.MullvadCity(strings.ToLower(s)), err
@@ -26,7 +26,7 @@ func (p *paramsReader) GetMullvadCity() (country models.MullvadCity, err error)
// GetMullvadISP obtains the ISP for the Mullvad server from the
// environment variable ISP
func (p *paramsReader) GetMullvadISP() (country models.MullvadProvider, err error) {
func (p *reader) GetMullvadISP() (country models.MullvadProvider, err error) {
choices := append(constants.MullvadProviderChoices(), "")
s, err := p.envParams.GetValueIfInside("ISP", choices)
return models.MullvadProvider(strings.ToLower(s)), err
@@ -34,7 +34,7 @@ func (p *paramsReader) GetMullvadISP() (country models.MullvadProvider, err erro
// GetMullvadPort obtains the port to reach the Mullvad server on from the
// environment variable PORT
func (p *paramsReader) GetMullvadPort() (port uint16, err error) {
func (p *reader) GetMullvadPort() (port uint16, err error) {
n, err := p.envParams.GetEnvIntRange("PORT", 0, 65535, libparams.Default("0"))
return uint16(n), err
}

View File

@@ -1,80 +1,82 @@
package params
import (
"fmt"
"net"
"strings"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetUser obtains the user to use to connect to the VPN servers
func (p *paramsReader) GetUser() (s string, err error) {
defer func() {
unsetenvErr := p.unsetEnv("USER")
if err == nil {
err = unsetenvErr
}
}()
return p.envParams.GetEnv("USER", libparams.CaseSensitiveValue(), libparams.Compulsory())
}
// GetPassword obtains the password to use to connect to the VPN servers
func (p *paramsReader) GetPassword() (s string, err error) {
defer func() {
unsetenvErr := p.unsetEnv("PASSWORD")
if err == nil {
err = unsetenvErr
}
}()
return p.envParams.GetEnv("PASSWORD", libparams.CaseSensitiveValue(), libparams.Compulsory())
}
// GetNetworkProtocol obtains the network protocol to use to connect to the
// VPN servers from the environment variable PROTOCOL
func (p *paramsReader) GetNetworkProtocol() (protocol models.NetworkProtocol, err error) {
s, err := p.envParams.GetValueIfInside("PROTOCOL", []string{"tcp", "udp"}, libparams.Default("udp"))
return models.NetworkProtocol(s), err
}
// GetOpenVPNVerbosity obtains the verbosity level for verbosity between 0 and 6
// from the environment variable OPENVPN_VERBOSITY
func (p *paramsReader) GetOpenVPNVerbosity() (verbosity int, err error) {
return p.envParams.GetEnvIntRange("OPENVPN_VERBOSITY", 0, 6, libparams.Default("1"))
}
// GetOpenVPNRoot obtains if openvpn should be run as root
// from the environment variable OPENVPN_ROOT
func (p *paramsReader) GetOpenVPNRoot() (root bool, err error) {
return p.envParams.GetYesNo("OPENVPN_ROOT", libparams.Default("no"))
}
// GetTargetIP obtains the IP address to choose from the list of IP addresses
// available for a particular region, from the environment variable
// OPENVPN_TARGET_IP
func (p *paramsReader) GetTargetIP() (ip net.IP, err error) {
s, err := p.envParams.GetEnv("OPENVPN_TARGET_IP")
if len(s) == 0 {
return nil, nil
}
ip = net.ParseIP(s)
if ip == nil {
return nil, fmt.Errorf("target IP address %q is not valid", s)
}
return ip, nil
}
// GetOpenVPNCipher obtains a custom cipher to use with OpenVPN
// from the environment variable OPENVPN_CIPHER
func (p *paramsReader) GetOpenVPNCipher() (cipher string, err error) {
cipher, err = p.envParams.GetEnv("OPENVPN_CIPHER")
return strings.ToLower(cipher), err
}
// GetOpenVPNAuth obtains a custom auth algorithm to use with OpenVPN
// from the environment variable OPENVPN_AUTH
func (p *paramsReader) GetOpenVPNAuth() (auth string, err error) {
auth, err = p.envParams.GetEnv("OPENVPN_AUTH")
return strings.ToLower(auth), err
}
package params
import (
"fmt"
"net"
"strings"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetUser obtains the user to use to connect to the VPN servers
func (p *reader) GetUser() (s string, err error) {
defer func() {
unsetenvErr := p.unsetEnv("USER")
if err == nil {
err = unsetenvErr
}
}()
return p.envParams.GetEnv("USER", libparams.CaseSensitiveValue(), libparams.Compulsory())
}
// GetPassword obtains the password to use to connect to the VPN servers
func (p *reader) GetPassword() (s string, err error) {
defer func() {
unsetenvErr := p.unsetEnv("PASSWORD")
if err == nil {
err = unsetenvErr
}
}()
return p.envParams.GetEnv("PASSWORD", libparams.CaseSensitiveValue(), libparams.Compulsory())
}
// GetNetworkProtocol obtains the network protocol to use to connect to the
// VPN servers from the environment variable PROTOCOL
func (p *reader) GetNetworkProtocol() (protocol models.NetworkProtocol, err error) {
s, err := p.envParams.GetValueIfInside("PROTOCOL", []string{"tcp", "udp"}, libparams.Default("udp"))
return models.NetworkProtocol(s), err
}
// GetOpenVPNVerbosity obtains the verbosity level for verbosity between 0 and 6
// from the environment variable OPENVPN_VERBOSITY
func (p *reader) GetOpenVPNVerbosity() (verbosity int, err error) {
return p.envParams.GetEnvIntRange("OPENVPN_VERBOSITY", 0, 6, libparams.Default("1"))
}
// GetOpenVPNRoot obtains if openvpn should be run as root
// from the environment variable OPENVPN_ROOT
func (p *reader) GetOpenVPNRoot() (root bool, err error) {
return p.envParams.GetYesNo("OPENVPN_ROOT", libparams.Default("no"))
}
// GetTargetIP obtains the IP address to choose from the list of IP addresses
// available for a particular region, from the environment variable
// OPENVPN_TARGET_IP
func (p *reader) GetTargetIP() (ip net.IP, err error) {
s, err := p.envParams.GetEnv("OPENVPN_TARGET_IP")
if len(s) == 0 {
return nil, nil
} else if err != nil {
return nil, err
}
ip = net.ParseIP(s)
if ip == nil {
return nil, fmt.Errorf("target IP address %q is not valid", s)
}
return ip, nil
}
// GetOpenVPNCipher obtains a custom cipher to use with OpenVPN
// from the environment variable OPENVPN_CIPHER
func (p *reader) GetOpenVPNCipher() (cipher string, err error) {
cipher, err = p.envParams.GetEnv("OPENVPN_CIPHER")
return strings.ToLower(cipher), err
}
// GetOpenVPNAuth obtains a custom auth algorithm to use with OpenVPN
// from the environment variable OPENVPN_AUTH
func (p *reader) GetOpenVPNAuth() (auth string, err error) {
auth, err = p.envParams.GetEnv("OPENVPN_AUTH")
return strings.ToLower(auth), err
}

View File

@@ -1,108 +1,111 @@
package params
import (
"net"
"os"
"github.com/qdm12/golibs/logging"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/golibs/verification"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// ParamsReader contains methods to obtain parameters
type ParamsReader interface {
GetVPNSP() (vpnServiceProvider string, err error)
// DNS over TLS getters
GetDNSOverTLS() (DNSOverTLS bool, err error)
GetDNSOverTLSProviders() (providers []models.DNSProvider, err error)
GetDNSOverTLSCaching() (caching bool, err error)
GetDNSOverTLSVerbosity() (verbosityLevel uint8, err error)
GetDNSOverTLSVerbosityDetails() (verbosityDetailsLevel uint8, err error)
GetDNSOverTLSValidationLogLevel() (validationLogLevel uint8, err error)
GetDNSMaliciousBlocking() (blocking bool, err error)
GetDNSSurveillanceBlocking() (blocking bool, err error)
GetDNSAdsBlocking() (blocking bool, err error)
GetDNSUnblockedHostnames() (hostnames []string, err error)
GetDNSOverTLSPrivateAddresses() (privateAddresses []string)
GetDNSOverTLSIPv6() (ipv6 bool, err error)
// System
GetUID() (uid int, err error)
GetGID() (gid int, err error)
GetTimezone() (timezone string, err error)
GetIPStatusFilepath() (filepath models.Filepath, err error)
// Firewall getters
GetExtraSubnets() (extraSubnets []net.IPNet, err error)
// VPN getters
GetUser() (s string, err error)
GetPassword() (s string, err error)
GetNetworkProtocol() (protocol models.NetworkProtocol, err error)
GetOpenVPNVerbosity() (verbosity int, err error)
GetOpenVPNRoot() (root bool, err error)
GetTargetIP() (ip net.IP, err error)
GetOpenVPNCipher() (cipher string, err error)
GetOpenVPNAuth() (auth string, err error)
// PIA getters
GetPortForwarding() (activated bool, err error)
GetPortForwardingStatusFilepath() (filepath models.Filepath, err error)
GetPIAEncryption() (models.PIAEncryption, error)
GetPIARegion() (models.PIARegion, error)
// Mullvad getters
GetMullvadCountry() (country models.MullvadCountry, err error)
GetMullvadCity() (country models.MullvadCity, err error)
GetMullvadISP() (country models.MullvadProvider, err error)
GetMullvadPort() (port uint16, err error)
// Windscribe getters
GetWindscribeRegion() (country models.WindscribeRegion, err error)
GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error)
// Shadowsocks getters
GetShadowSocks() (activated bool, err error)
GetShadowSocksLog() (activated bool, err error)
GetShadowSocksPort() (port uint16, err error)
GetShadowSocksPassword() (password string, err error)
GetShadowSocksMethod() (method string, err error)
// Tinyproxy getters
GetTinyProxy() (activated bool, err error)
GetTinyProxyLog() (models.TinyProxyLogLevel, error)
GetTinyProxyPort() (port uint16, err error)
GetTinyProxyUser() (user string, err error)
GetTinyProxyPassword() (password string, err error)
// Version getters
GetVersion() string
GetBuildDate() string
GetVcsRef() string
}
type paramsReader struct {
envParams libparams.EnvParams
logger logging.Logger
verifier verification.Verifier
unsetEnv func(key string) error
}
// NewParamsReader returns a paramsReadeer object to read parameters from
// environment variables
func NewParamsReader(logger logging.Logger) ParamsReader {
return &paramsReader{
envParams: libparams.NewEnvParams(),
logger: logger,
verifier: verification.NewVerifier(),
unsetEnv: os.Unsetenv,
}
}
// GetVPNSP obtains the VPN service provider to use from the environment variable VPNSP
func (p *paramsReader) GetVPNSP() (vpnServiceProvider string, err error) {
s, err := p.envParams.GetValueIfInside("VPNSP", []string{"pia", "mullvad", "windscribe"})
return s, err
}
package params
import (
"net"
"os"
"github.com/qdm12/golibs/logging"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/golibs/verification"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// Reader contains methods to obtain parameters
type Reader interface {
GetVPNSP() (vpnServiceProvider models.VPNProvider, err error)
// DNS over TLS getters
GetDNSOverTLS() (DNSOverTLS bool, err error)
GetDNSOverTLSProviders() (providers []models.DNSProvider, err error)
GetDNSOverTLSCaching() (caching bool, err error)
GetDNSOverTLSVerbosity() (verbosityLevel uint8, err error)
GetDNSOverTLSVerbosityDetails() (verbosityDetailsLevel uint8, err error)
GetDNSOverTLSValidationLogLevel() (validationLogLevel uint8, err error)
GetDNSMaliciousBlocking() (blocking bool, err error)
GetDNSSurveillanceBlocking() (blocking bool, err error)
GetDNSAdsBlocking() (blocking bool, err error)
GetDNSUnblockedHostnames() (hostnames []string, err error)
GetDNSOverTLSPrivateAddresses() (privateAddresses []string)
GetDNSOverTLSIPv6() (ipv6 bool, err error)
// System
GetUID() (uid int, err error)
GetGID() (gid int, err error)
GetTimezone() (timezone string, err error)
GetIPStatusFilepath() (filepath models.Filepath, err error)
// Firewall getters
GetExtraSubnets() (extraSubnets []net.IPNet, err error)
// VPN getters
GetUser() (s string, err error)
GetPassword() (s string, err error)
GetNetworkProtocol() (protocol models.NetworkProtocol, err error)
GetOpenVPNVerbosity() (verbosity int, err error)
GetOpenVPNRoot() (root bool, err error)
GetTargetIP() (ip net.IP, err error)
GetOpenVPNCipher() (cipher string, err error)
GetOpenVPNAuth() (auth string, err error)
// PIA getters
GetPortForwarding() (activated bool, err error)
GetPortForwardingStatusFilepath() (filepath models.Filepath, err error)
GetPIAEncryption() (models.PIAEncryption, error)
GetPIARegion() (models.PIARegion, error)
// Mullvad getters
GetMullvadCountry() (country models.MullvadCountry, err error)
GetMullvadCity() (country models.MullvadCity, err error)
GetMullvadISP() (country models.MullvadProvider, err error)
GetMullvadPort() (port uint16, err error)
// Windscribe getters
GetWindscribeRegion() (country models.WindscribeRegion, err error)
GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error)
// Shadowsocks getters
GetShadowSocks() (activated bool, err error)
GetShadowSocksLog() (activated bool, err error)
GetShadowSocksPort() (port uint16, err error)
GetShadowSocksPassword() (password string, err error)
GetShadowSocksMethod() (method string, err error)
// Tinyproxy getters
GetTinyProxy() (activated bool, err error)
GetTinyProxyLog() (models.TinyProxyLogLevel, error)
GetTinyProxyPort() (port uint16, err error)
GetTinyProxyUser() (user string, err error)
GetTinyProxyPassword() (password string, err error)
// Version getters
GetVersion() string
GetBuildDate() string
GetVcsRef() string
}
type reader struct {
envParams libparams.EnvParams
logger logging.Logger
verifier verification.Verifier
unsetEnv func(key string) error
}
// Newreader returns a paramsReadeer object to read parameters from
// environment variables
func NewReader(logger logging.Logger) Reader {
return &reader{
envParams: libparams.NewEnvParams(),
logger: logger,
verifier: verification.NewVerifier(),
unsetEnv: os.Unsetenv,
}
}
// GetVPNSP obtains the VPN service provider to use from the environment variable VPNSP
func (p *reader) GetVPNSP() (vpnServiceProvider models.VPNProvider, err error) {
s, err := p.envParams.GetValueIfInside("VPNSP", []string{"pia", "private internet access", "mullvad", "windscribe"})
if s == "pia" {
s = "private internet access"
}
return models.VPNProvider(s), err
}

View File

@@ -1,60 +1,60 @@
package params
import (
"fmt"
"math/rand"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetPortForwarding obtains if port forwarding on the VPN provider server
// side is enabled or not from the environment variable PORT_FORWARDING
func (p *paramsReader) GetPortForwarding() (activated bool, err error) {
s, err := p.envParams.GetEnv("PORT_FORWARDING", libparams.Default("off"))
if err != nil {
return false, err
}
// Custom for retro-compatibility
if s == "false" || s == "off" {
return false, nil
} else if s == "true" || s == "on" {
return true, nil
}
return false, fmt.Errorf("PORT_FORWARDING can only be \"on\" or \"off\"")
}
// GetPortForwardingStatusFilepath obtains the port forwarding status file path
// from the environment variable PORT_FORWARDING_STATUS_FILE
func (p *paramsReader) GetPortForwardingStatusFilepath() (filepath models.Filepath, err error) {
filepathStr, err := p.envParams.GetPath("PORT_FORWARDING_STATUS_FILE", libparams.Default("/forwarded_port"), libparams.CaseSensitiveValue())
return models.Filepath(filepathStr), err
}
// GetPIAEncryption obtains the encryption level for the PIA connection
// from the environment variable PIA_ENCRYPTION, and using ENCRYPTION for
// retro compatibility
func (p *paramsReader) GetPIAEncryption() (models.PIAEncryption, error) {
// Retro-compatibility
s, err := p.envParams.GetValueIfInside("ENCRYPTION", []string{"normal", "strong", ""})
if err != nil {
return "", err
} else if len(s) != 0 {
p.logger.Warn("You are using the old environment variable ENCRYPTION, please consider changing it to PIA_ENCRYPTION")
return models.PIAEncryption(s), nil
}
s, err = p.envParams.GetValueIfInside("PIA_ENCRYPTION", []string{"normal", "strong"}, libparams.Default("strong"))
return models.PIAEncryption(s), err
}
// GetPIARegion obtains the region for the PIA server from the
// environment variable REGION
func (p *paramsReader) GetPIARegion() (region models.PIARegion, err error) {
choices := append(constants.PIAGeoChoices(), "")
s, err := p.envParams.GetValueIfInside("REGION", choices)
if len(s) == 0 { // Suggestion by @rorph https://github.com/rorph
s = choices[rand.Int()%len(choices)]
}
return models.PIARegion(s), err
}
package params
import (
"fmt"
"math/rand"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetPortForwarding obtains if port forwarding on the VPN provider server
// side is enabled or not from the environment variable PORT_FORWARDING
func (p *reader) GetPortForwarding() (activated bool, err error) {
s, err := p.envParams.GetEnv("PORT_FORWARDING", libparams.Default("off"))
if err != nil {
return false, err
}
// Custom for retro-compatibility
if s == "false" || s == "off" {
return false, nil
} else if s == "true" || s == "on" {
return true, nil
}
return false, fmt.Errorf("PORT_FORWARDING can only be \"on\" or \"off\"")
}
// GetPortForwardingStatusFilepath obtains the port forwarding status file path
// from the environment variable PORT_FORWARDING_STATUS_FILE
func (p *reader) GetPortForwardingStatusFilepath() (filepath models.Filepath, err error) {
filepathStr, err := p.envParams.GetPath("PORT_FORWARDING_STATUS_FILE", libparams.Default("/forwarded_port"), libparams.CaseSensitiveValue())
return models.Filepath(filepathStr), err
}
// GetPIAEncryption obtains the encryption level for the PIA connection
// from the environment variable PIA_ENCRYPTION, and using ENCRYPTION for
// retro compatibility
func (p *reader) GetPIAEncryption() (models.PIAEncryption, error) {
// Retro-compatibility
s, err := p.envParams.GetValueIfInside("ENCRYPTION", []string{"normal", "strong", ""})
if err != nil {
return "", err
} else if len(s) != 0 {
p.logger.Warn("You are using the old environment variable ENCRYPTION, please consider changing it to PIA_ENCRYPTION")
return models.PIAEncryption(s), nil
}
s, err = p.envParams.GetValueIfInside("PIA_ENCRYPTION", []string{"normal", "strong"}, libparams.Default("strong"))
return models.PIAEncryption(s), err
}
// GetPIARegion obtains the region for the PIA server from the
// environment variable REGION
func (p *reader) GetPIARegion() (region models.PIARegion, err error) {
choices := append(constants.PIAGeoChoices(), "")
s, err := p.envParams.GetValueIfInside("REGION", choices)
if len(s) == 0 { // Suggestion by @rorph https://github.com/rorph
s = choices[rand.Int()%len(choices)] //nolint:gosec
}
return models.PIARegion(s), err
}

View File

@@ -1,46 +1,51 @@
package params
import (
"strconv"
libparams "github.com/qdm12/golibs/params"
)
// GetShadowSocks obtains if ShadowSocks is on from the environment variable
// SHADOWSOCKS
func (p *paramsReader) GetShadowSocks() (activated bool, err error) {
return p.envParams.GetOnOff("SHADOWSOCKS", libparams.Default("off"))
}
// GetShadowSocksLog obtains the ShadowSocks log level from the environment variable
// SHADOWSOCKS_LOG
func (p *paramsReader) GetShadowSocksLog() (activated bool, err error) {
return p.envParams.GetOnOff("SHADOWSOCKS_LOG", libparams.Default("off"))
}
// GetShadowSocksPort obtains the ShadowSocks listening port from the environment variable
// SHADOWSOCKS_PORT
func (p *paramsReader) GetShadowSocksPort() (port uint16, err error) {
portStr, err := p.envParams.GetEnv("SHADOWSOCKS_PORT", libparams.Default("8388"))
if err != nil {
return 0, err
}
if err := p.verifier.VerifyPort(portStr); err != nil {
return 0, err
}
portUint64, err := strconv.ParseUint(portStr, 10, 16)
return uint16(portUint64), err
}
// GetShadowSocksPassword obtains the ShadowSocks server password from the environment variable
// SHADOWSOCKS_PASSWORD
func (p *paramsReader) GetShadowSocksPassword() (password string, err error) {
defer p.unsetEnv("SHADOWSOCKS_PASSWORD")
return p.envParams.GetEnv("SHADOWSOCKS_PASSWORD", libparams.CaseSensitiveValue())
}
// GetShadowSocksMethod obtains the ShadowSocks method to use from the environment variable
// SHADOWSOCKS_METHOD
func (p *paramsReader) GetShadowSocksMethod() (method string, err error) {
return p.envParams.GetEnv("SHADOWSOCKS_METHOD", libparams.Default("chacha20-ietf-poly1305"))
}
package params
import (
"strconv"
libparams "github.com/qdm12/golibs/params"
)
// GetShadowSocks obtains if ShadowSocks is on from the environment variable
// SHADOWSOCKS
func (p *reader) GetShadowSocks() (activated bool, err error) {
return p.envParams.GetOnOff("SHADOWSOCKS", libparams.Default("off"))
}
// GetShadowSocksLog obtains the ShadowSocks log level from the environment variable
// SHADOWSOCKS_LOG
func (p *reader) GetShadowSocksLog() (activated bool, err error) {
return p.envParams.GetOnOff("SHADOWSOCKS_LOG", libparams.Default("off"))
}
// GetShadowSocksPort obtains the ShadowSocks listening port from the environment variable
// SHADOWSOCKS_PORT
func (p *reader) GetShadowSocksPort() (port uint16, err error) {
portStr, err := p.envParams.GetEnv("SHADOWSOCKS_PORT", libparams.Default("8388"))
if err != nil {
return 0, err
}
if err := p.verifier.VerifyPort(portStr); err != nil {
return 0, err
}
portUint64, err := strconv.ParseUint(portStr, 10, 16)
return uint16(portUint64), err
}
// GetShadowSocksPassword obtains the ShadowSocks server password from the environment variable
// SHADOWSOCKS_PASSWORD
func (p *reader) GetShadowSocksPassword() (password string, err error) {
defer func() {
unsetErr := p.unsetEnv("SHADOWSOCKS_PASSWORD")
if err == nil {
err = unsetErr
}
}()
return p.envParams.GetEnv("SHADOWSOCKS_PASSWORD", libparams.CaseSensitiveValue())
}
// GetShadowSocksMethod obtains the ShadowSocks method to use from the environment variable
// SHADOWSOCKS_METHOD
func (p *reader) GetShadowSocksMethod() (method string, err error) {
return p.envParams.GetEnv("SHADOWSOCKS_METHOD", libparams.Default("chacha20-ietf-poly1305"))
}

View File

@@ -1,28 +1,28 @@
package params
import (
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetUID obtains the user ID to use from the environment variable UID
func (p *paramsReader) GetUID() (uid int, err error) {
return p.envParams.GetEnvIntRange("UID", 0, 65535, libparams.Default("1000"))
}
// GetGID obtains the group ID to use from the environment variable GID
func (p *paramsReader) GetGID() (gid int, err error) {
return p.envParams.GetEnvIntRange("GID", 0, 65535, libparams.Default("1000"))
}
// GetTZ obtains the timezone from the environment variable TZ
func (p *paramsReader) GetTimezone() (timezone string, err error) {
return p.envParams.GetEnv("TZ")
}
// GetIPStatusFilepath obtains the IP status file path
// from the environment variable IP_STATUS_FILE
func (p *paramsReader) GetIPStatusFilepath() (filepath models.Filepath, err error) {
filepathStr, err := p.envParams.GetPath("IP_STATUS_FILE", libparams.Default("/ip"), libparams.CaseSensitiveValue())
return models.Filepath(filepathStr), err
}
package params
import (
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetUID obtains the user ID to use from the environment variable UID
func (p *reader) GetUID() (uid int, err error) {
return p.envParams.GetEnvIntRange("UID", 0, 65535, libparams.Default("1000"))
}
// GetGID obtains the group ID to use from the environment variable GID
func (p *reader) GetGID() (gid int, err error) {
return p.envParams.GetEnvIntRange("GID", 0, 65535, libparams.Default("1000"))
}
// GetTZ obtains the timezone from the environment variable TZ
func (p *reader) GetTimezone() (timezone string, err error) {
return p.envParams.GetEnv("TZ")
}
// GetIPStatusFilepath obtains the IP status file path
// from the environment variable IP_STATUS_FILE
func (p *reader) GetIPStatusFilepath() (filepath models.Filepath, err error) {
filepathStr, err := p.envParams.GetPath("IP_STATUS_FILE", libparams.Default("/ip"), libparams.CaseSensitiveValue())
return models.Filepath(filepathStr), err
}

View File

@@ -1,94 +1,116 @@
package params
import (
"strconv"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetTinyProxy obtains if TinyProxy is on from the environment variable
// TINYPROXY, and using PROXY as a retro-compatibility name
func (p *paramsReader) GetTinyProxy() (activated bool, err error) {
// Retro-compatibility
s, err := p.envParams.GetEnv("PROXY")
if err != nil {
return false, err
} else if len(s) != 0 {
p.logger.Warn("You are using the old environment variable PROXY, please consider changing it to TINYPROXY")
return p.envParams.GetOnOff("PROXY", libparams.Compulsory())
}
return p.envParams.GetOnOff("TINYPROXY", libparams.Default("off"))
}
// GetTinyProxyLog obtains the TinyProxy log level from the environment variable
// TINYPROXY_LOG, and using PROXY_LOG_LEVEL as a retro-compatibility name
func (p *paramsReader) GetTinyProxyLog() (models.TinyProxyLogLevel, error) {
// Retro-compatibility
s, err := p.envParams.GetEnv("PROXY_LOG_LEVEL")
if err != nil {
return models.TinyProxyLogLevel(s), err
} else if len(s) != 0 {
p.logger.Warn("You are using the old environment variable PROXY_LOG_LEVEL, please consider changing it to TINYPROXY_LOG")
s, err = p.envParams.GetValueIfInside("PROXY_LOG_LEVEL", []string{"Info", "Connect", "Notice", "Warning", "Error", "Critical"}, libparams.Compulsory())
return models.TinyProxyLogLevel(s), err
}
s, err = p.envParams.GetValueIfInside("TINYPROXY_LOG", []string{"Info", "Connect", "Notice", "Warning", "Error", "Critical"}, libparams.Default("Connect"))
return models.TinyProxyLogLevel(s), err
}
// GetTinyProxyPort obtains the TinyProxy listening port from the environment variable
// TINYPROXY_PORT, and using PROXY_PORT as a retro-compatibility name
func (p *paramsReader) GetTinyProxyPort() (port uint16, err error) {
// Retro-compatibility
portStr, err := p.envParams.GetEnv("PROXY_PORT")
if err != nil {
return 0, err
} else if len(portStr) != 0 {
p.logger.Warn("You are using the old environment variable PROXY_PORT, please consider changing it to TINYPROXY_PORT")
} else {
portStr, err = p.envParams.GetEnv("TINYPROXY_PORT", libparams.Default("8888"))
if err != nil {
return 0, err
}
}
if err := p.verifier.VerifyPort(portStr); err != nil {
return 0, err
}
portUint64, err := strconv.ParseUint(portStr, 10, 16)
return uint16(portUint64), err
}
// GetTinyProxyUser obtains the TinyProxy server user from the environment variable
// TINYPROXY_USER, and using PROXY_USER as a retro-compatibility name
func (p *paramsReader) GetTinyProxyUser() (user string, err error) {
defer p.unsetEnv("PROXY_USER")
defer p.unsetEnv("TINYPROXY_USER")
// Retro-compatibility
user, err = p.envParams.GetEnv("PROXY_USER", libparams.CaseSensitiveValue())
if err != nil {
return user, err
}
if len(user) != 0 {
p.logger.Warn("You are using the old environment variable PROXY_USER, please consider changing it to TINYPROXY_USER")
return user, nil
}
return p.envParams.GetEnv("TINYPROXY_USER", libparams.CaseSensitiveValue())
}
// GetTinyProxyPassword obtains the TinyProxy server password from the environment variable
// TINYPROXY_PASSWORD, and using PROXY_PASSWORD as a retro-compatibility name
func (p *paramsReader) GetTinyProxyPassword() (password string, err error) {
defer p.unsetEnv("PROXY_PASSWORD")
defer p.unsetEnv("TINYPROXY_PASSWORD")
// Retro-compatibility
password, err = p.envParams.GetEnv("PROXY_PASSWORD", libparams.CaseSensitiveValue())
if err != nil {
return password, err
}
if len(password) != 0 {
p.logger.Warn("You are using the old environment variable PROXY_PASSWORD, please consider changing it to TINYPROXY_PASSWORD")
return password, nil
}
return p.envParams.GetEnv("TINYPROXY_PASSWORD", libparams.CaseSensitiveValue())
}
package params
import (
"strconv"
libparams "github.com/qdm12/golibs/params"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
// GetTinyProxy obtains if TinyProxy is on from the environment variable
// TINYPROXY, and using PROXY as a retro-compatibility name
func (p *reader) GetTinyProxy() (activated bool, err error) {
// Retro-compatibility
s, err := p.envParams.GetEnv("PROXY")
if err != nil {
return false, err
} else if len(s) != 0 {
p.logger.Warn("You are using the old environment variable PROXY, please consider changing it to TINYPROXY")
return p.envParams.GetOnOff("PROXY", libparams.Compulsory())
}
return p.envParams.GetOnOff("TINYPROXY", libparams.Default("off"))
}
// GetTinyProxyLog obtains the TinyProxy log level from the environment variable
// TINYPROXY_LOG, and using PROXY_LOG_LEVEL as a retro-compatibility name
func (p *reader) GetTinyProxyLog() (models.TinyProxyLogLevel, error) {
// Retro-compatibility
s, err := p.envParams.GetEnv("PROXY_LOG_LEVEL")
if err != nil {
return models.TinyProxyLogLevel(s), err
} else if len(s) != 0 {
p.logger.Warn("You are using the old environment variable PROXY_LOG_LEVEL, please consider changing it to TINYPROXY_LOG")
s, err = p.envParams.GetValueIfInside("PROXY_LOG_LEVEL", []string{"Info", "Connect", "Notice", "Warning", "Error", "Critical"}, libparams.Compulsory())
return models.TinyProxyLogLevel(s), err
}
s, err = p.envParams.GetValueIfInside("TINYPROXY_LOG", []string{"Info", "Connect", "Notice", "Warning", "Error", "Critical"}, libparams.Default("Connect"))
return models.TinyProxyLogLevel(s), err
}
// GetTinyProxyPort obtains the TinyProxy listening port from the environment variable
// TINYPROXY_PORT, and using PROXY_PORT as a retro-compatibility name
func (p *reader) GetTinyProxyPort() (port uint16, err error) {
// Retro-compatibility
portStr, err := p.envParams.GetEnv("PROXY_PORT")
switch {
case err != nil:
return 0, err
case len(portStr) != 0:
p.logger.Warn("You are using the old environment variable PROXY_PORT, please consider changing it to TINYPROXY_PORT")
default:
portStr, err = p.envParams.GetEnv("TINYPROXY_PORT", libparams.Default("8888"))
if err != nil {
return 0, err
}
}
if err := p.verifier.VerifyPort(portStr); err != nil {
return 0, err
}
portUint64, err := strconv.ParseUint(portStr, 10, 16)
return uint16(portUint64), err
}
// GetTinyProxyUser obtains the TinyProxy server user from the environment variable
// TINYPROXY_USER, and using PROXY_USER as a retro-compatibility name
func (p *reader) GetTinyProxyUser() (user string, err error) {
defer func() {
unsetErr := p.unsetEnv("PROXY_USER")
if err == nil {
err = unsetErr
}
}()
defer func() {
unsetErr := p.unsetEnv("TINYPROXY_USER")
if err == nil {
err = unsetErr
}
}()
// Retro-compatibility
user, err = p.envParams.GetEnv("PROXY_USER", libparams.CaseSensitiveValue())
if err != nil {
return user, err
}
if len(user) != 0 {
p.logger.Warn("You are using the old environment variable PROXY_USER, please consider changing it to TINYPROXY_USER")
return user, nil
}
return p.envParams.GetEnv("TINYPROXY_USER", libparams.CaseSensitiveValue())
}
// GetTinyProxyPassword obtains the TinyProxy server password from the environment variable
// TINYPROXY_PASSWORD, and using PROXY_PASSWORD as a retro-compatibility name
func (p *reader) GetTinyProxyPassword() (password string, err error) {
defer func() {
unsetErr := p.unsetEnv("PROXY_PASSWORD")
if err == nil {
err = unsetErr
}
}()
defer func() {
unsetErr := p.unsetEnv("TINYPROXY_PASSWORD")
if err == nil {
err = unsetErr
}
}()
// Retro-compatibility
password, err = p.envParams.GetEnv("PROXY_PASSWORD", libparams.CaseSensitiveValue())
if err != nil {
return password, err
}
if len(password) != 0 {
p.logger.Warn("You are using the old environment variable PROXY_PASSWORD, please consider changing it to TINYPROXY_PASSWORD")
return password, nil
}
return p.envParams.GetEnv("TINYPROXY_PASSWORD", libparams.CaseSensitiveValue())
}

View File

@@ -4,17 +4,17 @@ import (
libparams "github.com/qdm12/golibs/params"
)
func (p *paramsReader) GetVersion() string {
func (p *reader) GetVersion() string {
version, _ := p.envParams.GetEnv("VERSION", libparams.Default("?"), libparams.CaseSensitiveValue())
return version
}
func (p *paramsReader) GetBuildDate() string {
func (p *reader) GetBuildDate() string {
buildDate, _ := p.envParams.GetEnv("BUILD_DATE", libparams.Default("?"), libparams.CaseSensitiveValue())
return buildDate
}
func (p *paramsReader) GetVcsRef() string {
func (p *reader) GetVcsRef() string {
buildDate, _ := p.envParams.GetEnv("VCS_REF", libparams.Default("?"), libparams.CaseSensitiveValue())
return buildDate
}

View File

@@ -11,15 +11,14 @@ import (
// GetWindscribeRegion obtains the region for the Windscribe server from the
// environment variable REGION
func (p *paramsReader) GetWindscribeRegion() (country models.WindscribeRegion, err error) {
choices := append(constants.WindscribeRegionChoices())
s, err := p.envParams.GetValueIfInside("REGION", choices)
func (p *reader) GetWindscribeRegion() (country models.WindscribeRegion, err error) {
s, err := p.envParams.GetValueIfInside("REGION", constants.WindscribeRegionChoices())
return models.WindscribeRegion(strings.ToLower(s)), err
}
// GetMullvadPort obtains the port to reach the Mullvad server on from the
// environment variable PORT
func (p *paramsReader) GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error) {
func (p *reader) GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error) {
n, err := p.envParams.GetEnvIntRange("PORT", 0, 65535, libparams.Default("0"))
if err != nil {
return 0, err

View File

@@ -14,7 +14,7 @@ func (c *configurator) GetOpenVPNConnections(region models.PIARegion, protocol m
geoMapping := constants.PIAGeoToSubdomainMapping()
var subdomain string
for r, s := range geoMapping {
if strings.ToLower(string(region)) == strings.ToLower(string(r)) {
if strings.EqualFold(string(region), string(r)) {
subdomain = s
break
}
@@ -75,8 +75,8 @@ func (c *configurator) BuildConf(connections []models.OpenVPNConnection, encrypt
if len(auth) == 0 {
auth = "sha1"
}
X509CRL = constants.PIAX509CRL_NORMAL
certificate = constants.PIACertificate_NORMAL
X509CRL = constants.PiaX509CRLNormal
certificate = constants.PIACertificateNormal
} else { // strong encryption
if len(cipher) == 0 {
cipher = "aes-256-cbc"
@@ -84,8 +84,8 @@ func (c *configurator) BuildConf(connections []models.OpenVPNConnection, encrypt
if len(auth) == 0 {
auth = "sha256"
}
X509CRL = constants.PIAX509CRL_STRONG
certificate = constants.PIACertificate_STRONG
X509CRL = constants.PiaX509CRLStrong
certificate = constants.PIACertificateStrong
}
lines := []string{
"client",

View File

@@ -4,6 +4,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"github.com/qdm12/golibs/files"
"github.com/qdm12/private-internet-access-docker/internal/constants"
@@ -19,11 +20,12 @@ func (c *configurator) GetPortForward() (port uint16, err error) {
clientID := hex.EncodeToString(b)
url := fmt.Sprintf("%s/?client_id=%s", constants.PIAPortForwardURL, clientID)
content, status, err := c.client.GetContent(url)
if err != nil {
switch {
case err != nil:
return 0, err
} else if status != 200 {
case status != http.StatusOK:
return 0, fmt.Errorf("status is %d for %s; does your PIA server support port forwarding?", status, url)
} else if len(content) == 0 {
case len(content) == 0:
return 0, fmt.Errorf("port forwarding is already activated on this connection, has expired, or you are not connected to a PIA region that supports port forwarding")
}
body := struct {
@@ -42,7 +44,7 @@ func (c *configurator) WritePortForward(filepath models.Filepath, port uint16, u
string(filepath),
[]string{fmt.Sprintf("%d", port)},
files.Ownership(uid, gid),
files.Permissions(400))
files.Permissions(0400))
}
func (c *configurator) AllowPortForwardFirewall(device models.VPNDevice, port uint16) (err error) {
@@ -52,5 +54,5 @@ func (c *configurator) AllowPortForwardFirewall(device models.VPNDevice, port ui
func (c *configurator) ClearPortForward(filepath models.Filepath, uid, gid int) (err error) {
c.logger.Info("Clearing forwarded port status file %s", filepath)
return c.fileManager.WriteToFile(string(filepath), nil, files.Ownership(uid, gid), files.Permissions(400))
return c.fileManager.WriteToFile(string(filepath), nil, files.Ownership(uid, gid), files.Permissions(0400))
}

View File

@@ -72,7 +72,7 @@ func parseRoutingEntry(s string) (r routingEntry, err error) {
return r, nil
}
func reversedHexToIPv4(reversedHex string) (IP net.IP, err error) {
func reversedHexToIPv4(reversedHex string) (ip net.IP, err error) {
bytes, err := hex.DecodeString(reversedHex)
if err != nil {
return nil, fmt.Errorf("cannot parse reversed IP hex %q: %s", reversedHex, err)

View File

@@ -1,133 +1,138 @@
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// DNS contains settings to configure Unbound for DNS over TLS operation
type DNS struct {
Enabled bool
Providers []models.DNSProvider
AllowedHostnames []string
PrivateAddresses []string
Caching bool
BlockMalicious bool
BlockSurveillance bool
BlockAds bool
VerbosityLevel uint8
VerbosityDetailsLevel uint8
ValidationLogLevel uint8
IPv6 bool
}
func (d *DNS) String() string {
if !d.Enabled {
return "DNS over TLS settings: disabled"
}
caching, blockMalicious, blockSurveillance, blockAds, ipv6 := "disabled", "disabed", "disabed", "disabed", "disabed"
if d.Caching {
caching = "enabled"
}
if d.BlockMalicious {
blockMalicious = "enabled"
}
if d.BlockSurveillance {
blockSurveillance = "enabled"
}
if d.BlockAds {
blockAds = "enabled"
}
if d.IPv6 {
ipv6 = "enabled"
}
var providersStr []string
for _, provider := range d.Providers {
providersStr = append(providersStr, string(provider))
}
settingsList := []string{
"DNS over TLS settings:",
"DNS over TLS provider:\n |--" + strings.Join(providersStr, "\n |--"),
"Caching: " + caching,
"Block malicious: " + blockMalicious,
"Block surveillance: " + blockSurveillance,
"Block ads: " + blockAds,
"Allowed hostnames:\n |--" + strings.Join(d.AllowedHostnames, "\n |--"),
"Private addresses:\n |--" + strings.Join(d.PrivateAddresses, "\n |--"),
"Verbosity level: " + fmt.Sprintf("%d/5", d.VerbosityLevel),
"Verbosity details level: " + fmt.Sprintf("%d/4", d.VerbosityDetailsLevel),
"Validation log level: " + fmt.Sprintf("%d/2", d.ValidationLogLevel),
"IPv6 resolution: " + ipv6,
}
return strings.Join(settingsList, "\n |--")
}
// GetDNSSettings obtains DNS over TLS settings from environment variables using the params package.
func GetDNSSettings(params params.ParamsReader) (settings DNS, err error) {
settings.Enabled, err = params.GetDNSOverTLS()
if err != nil || !settings.Enabled {
return settings, err
}
settings.Providers, err = params.GetDNSOverTLSProviders()
if err != nil {
return settings, err
}
settings.AllowedHostnames, err = params.GetDNSUnblockedHostnames()
if err != nil {
return settings, err
}
settings.Caching, err = params.GetDNSOverTLSCaching()
if err != nil {
return settings, err
}
settings.BlockMalicious, err = params.GetDNSMaliciousBlocking()
if err != nil {
return settings, err
}
settings.BlockSurveillance, err = params.GetDNSSurveillanceBlocking()
if err != nil {
return settings, err
}
settings.BlockAds, err = params.GetDNSAdsBlocking()
if err != nil {
return settings, err
}
settings.VerbosityLevel, err = params.GetDNSOverTLSVerbosity()
if err != nil {
return settings, err
}
settings.VerbosityDetailsLevel, err = params.GetDNSOverTLSVerbosityDetails()
if err != nil {
return settings, err
}
settings.ValidationLogLevel, err = params.GetDNSOverTLSValidationLogLevel()
if err != nil {
return settings, err
}
settings.PrivateAddresses = params.GetDNSOverTLSPrivateAddresses()
settings.IPv6, err = params.GetDNSOverTLSIPv6()
if err != nil {
return settings, err
}
// Consistency check
IPv6Support := false
for _, provider := range settings.Providers {
providerData, ok := constants.DNSProviderMapping()[provider]
if !ok {
return settings, fmt.Errorf("DNS provider %q does not have associated data", provider)
} else if !providerData.SupportsTLS {
return settings, fmt.Errorf("DNS provider %q does not support DNS over TLS", provider)
} else if providerData.SupportsIPv6 {
IPv6Support = true
}
}
if settings.IPv6 && !IPv6Support {
return settings, fmt.Errorf("None of the DNS over TLS provider(s) set support IPv6")
}
return settings, nil
}
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// DNS contains settings to configure Unbound for DNS over TLS operation
type DNS struct {
Enabled bool
Providers []models.DNSProvider
AllowedHostnames []string
PrivateAddresses []string
Caching bool
BlockMalicious bool
BlockSurveillance bool
BlockAds bool
VerbosityLevel uint8
VerbosityDetailsLevel uint8
ValidationLogLevel uint8
IPv6 bool
}
func (d *DNS) String() string {
if !d.Enabled {
return "DNS over TLS settings: disabled"
}
const (
enabled = "enabled"
disabled = "disabled"
)
caching, blockMalicious, blockSurveillance, blockAds, ipv6 := disabled, disabled, disabled, disabled, disabled
if d.Caching {
caching = enabled
}
if d.BlockMalicious {
blockMalicious = enabled
}
if d.BlockSurveillance {
blockSurveillance = enabled
}
if d.BlockAds {
blockAds = enabled
}
if d.IPv6 {
ipv6 = enabled
}
providersStr := make([]string, len(d.Providers))
for i := range d.Providers {
providersStr[i] = string(d.Providers[i])
}
settingsList := []string{
"DNS over TLS settings:",
"DNS over TLS provider:\n |--" + strings.Join(providersStr, "\n |--"),
"Caching: " + caching,
"Block malicious: " + blockMalicious,
"Block surveillance: " + blockSurveillance,
"Block ads: " + blockAds,
"Allowed hostnames:\n |--" + strings.Join(d.AllowedHostnames, "\n |--"),
"Private addresses:\n |--" + strings.Join(d.PrivateAddresses, "\n |--"),
"Verbosity level: " + fmt.Sprintf("%d/5", d.VerbosityLevel),
"Verbosity details level: " + fmt.Sprintf("%d/4", d.VerbosityDetailsLevel),
"Validation log level: " + fmt.Sprintf("%d/2", d.ValidationLogLevel),
"IPv6 resolution: " + ipv6,
}
return strings.Join(settingsList, "\n |--")
}
// GetDNSSettings obtains DNS over TLS settings from environment variables using the params package.
func GetDNSSettings(paramsReader params.Reader) (settings DNS, err error) {
settings.Enabled, err = paramsReader.GetDNSOverTLS()
if err != nil || !settings.Enabled {
return settings, err
}
settings.Providers, err = paramsReader.GetDNSOverTLSProviders()
if err != nil {
return settings, err
}
settings.AllowedHostnames, err = paramsReader.GetDNSUnblockedHostnames()
if err != nil {
return settings, err
}
settings.Caching, err = paramsReader.GetDNSOverTLSCaching()
if err != nil {
return settings, err
}
settings.BlockMalicious, err = paramsReader.GetDNSMaliciousBlocking()
if err != nil {
return settings, err
}
settings.BlockSurveillance, err = paramsReader.GetDNSSurveillanceBlocking()
if err != nil {
return settings, err
}
settings.BlockAds, err = paramsReader.GetDNSAdsBlocking()
if err != nil {
return settings, err
}
settings.VerbosityLevel, err = paramsReader.GetDNSOverTLSVerbosity()
if err != nil {
return settings, err
}
settings.VerbosityDetailsLevel, err = paramsReader.GetDNSOverTLSVerbosityDetails()
if err != nil {
return settings, err
}
settings.ValidationLogLevel, err = paramsReader.GetDNSOverTLSValidationLogLevel()
if err != nil {
return settings, err
}
settings.PrivateAddresses = paramsReader.GetDNSOverTLSPrivateAddresses()
settings.IPv6, err = paramsReader.GetDNSOverTLSIPv6()
if err != nil {
return settings, err
}
// Consistency check
IPv6Support := false
for _, provider := range settings.Providers {
providerData, ok := constants.DNSProviderMapping()[provider]
switch {
case !ok:
return settings, fmt.Errorf("DNS provider %q does not have associated data", provider)
case !providerData.SupportsTLS:
return settings, fmt.Errorf("DNS provider %q does not support DNS over TLS", provider)
case providerData.SupportsIPv6:
IPv6Support = true
}
}
if settings.IPv6 && !IPv6Support {
return settings, fmt.Errorf("None of the DNS over TLS provider(s) set support IPv6")
}
return settings, nil
}

View File

@@ -1,34 +1,34 @@
package settings
import (
"net"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// Firewall contains settings to customize the firewall operation
type Firewall struct {
AllowedSubnets []net.IPNet
}
func (f *Firewall) String() string {
var allowedSubnets []string
for _, net := range f.AllowedSubnets {
allowedSubnets = append(allowedSubnets, net.String())
}
settingsList := []string{
"Firewall settings:",
"Allowed subnets: " + strings.Join(allowedSubnets, ", "),
}
return strings.Join(settingsList, "\n |--")
}
// GetFirewallSettings obtains firewall settings from environment variables using the params package.
func GetFirewallSettings(params params.ParamsReader) (settings Firewall, err error) {
settings.AllowedSubnets, err = params.GetExtraSubnets()
if err != nil {
return settings, err
}
return settings, nil
}
package settings
import (
"net"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// Firewall contains settings to customize the firewall operation
type Firewall struct {
AllowedSubnets []net.IPNet
}
func (f *Firewall) String() string {
allowedSubnets := make([]string, len(f.AllowedSubnets))
for i := range f.AllowedSubnets {
allowedSubnets[i] = f.AllowedSubnets[i].String()
}
settingsList := []string{
"Firewall settings:",
"Allowed subnets: " + strings.Join(allowedSubnets, ", "),
}
return strings.Join(settingsList, "\n |--")
}
// GetFirewallSettings obtains firewall settings from environment variables using the params package.
func GetFirewallSettings(paramsReader params.Reader) (settings Firewall, err error) {
settings.AllowedSubnets, err = paramsReader.GetExtraSubnets()
if err != nil {
return settings, err
}
return settings, nil
}

View File

@@ -1,56 +1,56 @@
package settings
import (
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// Mullvad contains the settings to connect to a Mullvad server
type Mullvad struct {
User string
Country models.MullvadCountry
City models.MullvadCity
ISP models.MullvadProvider
Port uint16
}
func (m *Mullvad) String() string {
settingsList := []string{
"Mullvad settings:",
"User: [redacted]",
"Country: " + string(m.Country),
"City: " + string(m.City),
"ISP: " + string(m.ISP),
"Port: " + string(m.Port),
}
return strings.Join(settingsList, "\n |--")
}
// GetMullvadSettings obtains Mullvad settings from environment variables using the params package.
func GetMullvadSettings(params params.ParamsReader) (settings Mullvad, err error) {
settings.User, err = params.GetUser()
if err != nil {
return settings, err
}
// Remove spaces in user ID to simplify user's life, thanks @JeordyR
settings.User = strings.ReplaceAll(settings.User, " ", "")
settings.Country, err = params.GetMullvadCountry()
if err != nil {
return settings, err
}
settings.City, err = params.GetMullvadCity()
if err != nil {
return settings, err
}
settings.ISP, err = params.GetMullvadISP()
if err != nil {
return settings, err
}
settings.Port, err = params.GetMullvadPort()
if err != nil {
return settings, err
}
return settings, nil
}
package settings
import (
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// Mullvad contains the settings to connect to a Mullvad server
type Mullvad struct {
User string
Country models.MullvadCountry
City models.MullvadCity
ISP models.MullvadProvider
Port uint16
}
func (m *Mullvad) String() string {
settingsList := []string{
"Mullvad settings:",
"User: [redacted]",
"Country: " + string(m.Country),
"City: " + string(m.City),
"ISP: " + string(m.ISP),
"Port: " + string(m.Port),
}
return strings.Join(settingsList, "\n |--")
}
// GetMullvadSettings obtains Mullvad settings from environment variables using the params package.
func GetMullvadSettings(paramsReader params.Reader) (settings Mullvad, err error) {
settings.User, err = paramsReader.GetUser()
if err != nil {
return settings, err
}
// Remove spaces in user ID to simplify user's life, thanks @JeordyR
settings.User = strings.ReplaceAll(settings.User, " ", "")
settings.Country, err = paramsReader.GetMullvadCountry()
if err != nil {
return settings, err
}
settings.City, err = paramsReader.GetMullvadCity()
if err != nil {
return settings, err
}
settings.ISP, err = paramsReader.GetMullvadISP()
if err != nil {
return settings, err
}
settings.Port, err = paramsReader.GetMullvadPort()
if err != nil {
return settings, err
}
return settings, nil
}

View File

@@ -1,66 +1,66 @@
package settings
import (
"fmt"
"net"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// OpenVPN contains settings to configure the OpenVPN client
type OpenVPN struct {
NetworkProtocol models.NetworkProtocol
Verbosity int
Root bool
TargetIP net.IP
Cipher string
Auth string
}
// GetOpenVPNSettings obtains the OpenVPN settings using the params functions
func GetOpenVPNSettings(params params.ParamsReader) (settings OpenVPN, err error) {
settings.NetworkProtocol, err = params.GetNetworkProtocol()
if err != nil {
return settings, err
}
settings.Verbosity, err = params.GetOpenVPNVerbosity()
if err != nil {
return settings, err
}
settings.Root, err = params.GetOpenVPNRoot()
if err != nil {
return settings, err
}
settings.TargetIP, err = params.GetTargetIP()
if err != nil {
return settings, err
}
settings.Cipher, err = params.GetOpenVPNCipher()
if err != nil {
return settings, err
}
settings.Auth, err = params.GetOpenVPNAuth()
if err != nil {
return settings, err
}
return settings, nil
}
func (o *OpenVPN) String() string {
runAsRoot := "no"
if o.Root {
runAsRoot = "yes"
}
settingsList := []string{
"OpenVPN settings:",
"Network protocol: " + string(o.NetworkProtocol),
"Verbosity level: " + fmt.Sprintf("%d", o.Verbosity),
"Run as root: " + runAsRoot,
"Target IP address: " + o.TargetIP.String(),
"Custom cipher: " + o.Cipher,
"Custom auth algorithm: " + o.Auth,
}
return strings.Join(settingsList, "\n|--")
}
package settings
import (
"fmt"
"net"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// OpenVPN contains settings to configure the OpenVPN client
type OpenVPN struct {
NetworkProtocol models.NetworkProtocol
Verbosity int
Root bool
TargetIP net.IP
Cipher string
Auth string
}
// GetOpenVPNSettings obtains the OpenVPN settings using the params functions
func GetOpenVPNSettings(paramsReader params.Reader) (settings OpenVPN, err error) {
settings.NetworkProtocol, err = paramsReader.GetNetworkProtocol()
if err != nil {
return settings, err
}
settings.Verbosity, err = paramsReader.GetOpenVPNVerbosity()
if err != nil {
return settings, err
}
settings.Root, err = paramsReader.GetOpenVPNRoot()
if err != nil {
return settings, err
}
settings.TargetIP, err = paramsReader.GetTargetIP()
if err != nil {
return settings, err
}
settings.Cipher, err = paramsReader.GetOpenVPNCipher()
if err != nil {
return settings, err
}
settings.Auth, err = paramsReader.GetOpenVPNAuth()
if err != nil {
return settings, err
}
return settings, nil
}
func (o *OpenVPN) String() string {
runAsRoot := "no"
if o.Root {
runAsRoot = "yes"
}
settingsList := []string{
"OpenVPN settings:",
"Network protocol: " + string(o.NetworkProtocol),
"Verbosity level: " + fmt.Sprintf("%d", o.Verbosity),
"Run as root: " + runAsRoot,
"Target IP address: " + o.TargetIP.String(),
"Custom cipher: " + o.Cipher,
"Custom auth algorithm: " + o.Auth,
}
return strings.Join(settingsList, "\n|--")
}

View File

@@ -1,74 +1,74 @@
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// PIA contains the settings to connect to a PIA server
type PIA struct {
User string
Password string
Encryption models.PIAEncryption
Region models.PIARegion
PortForwarding PortForwarding
}
// PortForwarding contains settings for port forwarding
type PortForwarding struct {
Enabled bool
Filepath models.Filepath
}
func (p *PortForwarding) String() string {
if p.Enabled {
return fmt.Sprintf("on, saved in %s", p.Filepath)
}
return "off"
}
func (p *PIA) String() string {
settingsList := []string{
"PIA settings:",
"User: [redacted]",
"Password: [redacted]",
"Region: " + string(p.Region),
"Encryption: " + string(p.Encryption),
"Port forwarding: " + p.PortForwarding.String(),
}
return strings.Join(settingsList, "\n |--")
}
// GetPIASettings obtains PIA settings from environment variables using the params package.
func GetPIASettings(params params.ParamsReader) (settings PIA, err error) {
settings.User, err = params.GetUser()
if err != nil {
return settings, err
}
settings.Password, err = params.GetPassword()
if err != nil {
return settings, err
}
settings.Encryption, err = params.GetPIAEncryption()
if err != nil {
return settings, err
}
settings.Region, err = params.GetPIARegion()
if err != nil {
return settings, err
}
settings.PortForwarding.Enabled, err = params.GetPortForwarding()
if err != nil {
return settings, err
}
if settings.PortForwarding.Enabled {
settings.PortForwarding.Filepath, err = params.GetPortForwardingStatusFilepath()
if err != nil {
return settings, err
}
}
return settings, nil
}
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// PIA contains the settings to connect to a PIA server
type PIA struct {
User string
Password string
Encryption models.PIAEncryption
Region models.PIARegion
PortForwarding PortForwarding
}
// PortForwarding contains settings for port forwarding
type PortForwarding struct {
Enabled bool
Filepath models.Filepath
}
func (p *PortForwarding) String() string {
if p.Enabled {
return fmt.Sprintf("on, saved in %s", p.Filepath)
}
return "off"
}
func (p *PIA) String() string {
settingsList := []string{
"PIA settings:",
"User: [redacted]",
"Password: [redacted]",
"Region: " + string(p.Region),
"Encryption: " + string(p.Encryption),
"Port forwarding: " + p.PortForwarding.String(),
}
return strings.Join(settingsList, "\n |--")
}
// GetPIASettings obtains PIA settings from environment variables using the params package.
func GetPIASettings(paramsReader params.Reader) (settings PIA, err error) {
settings.User, err = paramsReader.GetUser()
if err != nil {
return settings, err
}
settings.Password, err = paramsReader.GetPassword()
if err != nil {
return settings, err
}
settings.Encryption, err = paramsReader.GetPIAEncryption()
if err != nil {
return settings, err
}
settings.Region, err = paramsReader.GetPIARegion()
if err != nil {
return settings, err
}
settings.PortForwarding.Enabled, err = paramsReader.GetPortForwarding()
if err != nil {
return settings, err
}
if settings.PortForwarding.Enabled {
settings.PortForwarding.Filepath, err = paramsReader.GetPortForwardingStatusFilepath()
if err != nil {
return settings, err
}
}
return settings, nil
}

View File

@@ -1,125 +1,127 @@
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// Settings contains all settings for the program to run
type Settings struct {
VPNSP string
OpenVPN OpenVPN
PIA PIA
Mullvad Mullvad
Windscribe Windscribe
System System
DNS DNS
Firewall Firewall
TinyProxy TinyProxy
ShadowSocks ShadowSocks
}
func (s *Settings) String() string {
var vpnServiceProvider string
switch s.VPNSP {
case "pia":
vpnServiceProvider = s.PIA.String()
case "mullvad":
vpnServiceProvider = s.Mullvad.String()
case "windscribe":
vpnServiceProvider = s.Windscribe.String()
}
return strings.Join([]string{
"Settings summary below:",
s.OpenVPN.String(),
vpnServiceProvider,
s.System.String(),
s.DNS.String(),
s.Firewall.String(),
s.TinyProxy.String(),
s.ShadowSocks.String(),
"", // new line at the end
}, "\n")
}
// GetAllSettings obtains all settings for the program and returns an error as soon
// as an error is encountered reading them.
func GetAllSettings(params params.ParamsReader) (settings Settings, err error) {
settings.VPNSP, err = params.GetVPNSP()
if err != nil {
return settings, err
}
settings.OpenVPN, err = GetOpenVPNSettings(params)
if err != nil {
return settings, err
}
switch settings.VPNSP {
case "pia":
switch settings.OpenVPN.Cipher {
case "", "aes-128-cbc", "aes-256-cbc", "aes-128-gcm", "aes-256-gcm":
default:
return settings, fmt.Errorf("cipher %q is not supported by Private Internet Access", settings.OpenVPN.Cipher)
}
switch settings.OpenVPN.Auth {
case "", "sha1", "sha256":
default:
return settings, fmt.Errorf("auth algorithm %q is not supported by Private Internet Access", settings.OpenVPN.Auth)
}
settings.PIA, err = GetPIASettings(params)
case "mullvad":
switch settings.OpenVPN.Cipher {
case "":
default:
return settings, fmt.Errorf("cipher %q is not supported by Mullvad", settings.OpenVPN.Cipher)
}
switch settings.OpenVPN.Auth {
case "":
default:
return settings, fmt.Errorf("auth algorithm %q is not supported by Mullvad (not using auth at all)", settings.OpenVPN.Auth)
}
settings.Mullvad, err = GetMullvadSettings(params)
case "windscribe":
switch settings.OpenVPN.Cipher {
case "", "aes-256-cbc", "aes-256-gcm": // TODO check inside params getters
default:
return settings, fmt.Errorf("cipher %q is not supported by Windscribe", settings.OpenVPN.Cipher)
}
switch settings.OpenVPN.Auth {
case "", "sha512":
default:
return settings, fmt.Errorf("auth algorithm %q is not supported by Windscribe", settings.OpenVPN.Auth)
}
settings.Windscribe, err = GetWindscribeSettings(params, settings.OpenVPN.NetworkProtocol)
default:
err = fmt.Errorf("VPN service provider %q is not valid", settings.VPNSP)
}
if err != nil {
return settings, err
}
if err != nil {
return settings, err
}
settings.DNS, err = GetDNSSettings(params)
if err != nil {
return settings, err
}
settings.Firewall, err = GetFirewallSettings(params)
if err != nil {
return settings, err
}
settings.TinyProxy, err = GetTinyProxySettings(params)
if err != nil {
return settings, err
}
settings.ShadowSocks, err = GetShadowSocksSettings(params)
if err != nil {
return settings, err
}
settings.System, err = GetSystemSettings(params)
if err != nil {
return settings, err
}
return settings, nil
}
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// Settings contains all settings for the program to run
type Settings struct {
VPNSP models.VPNProvider
OpenVPN OpenVPN
PIA PIA
Mullvad Mullvad
Windscribe Windscribe
System System
DNS DNS
Firewall Firewall
TinyProxy TinyProxy
ShadowSocks ShadowSocks
}
func (s *Settings) String() string {
var vpnServiceProviderSettings string
switch s.VPNSP {
case constants.PrivateInternetAccess:
vpnServiceProviderSettings = s.PIA.String()
case constants.Mullvad:
vpnServiceProviderSettings = s.Mullvad.String()
case constants.Windscribe:
vpnServiceProviderSettings = s.Windscribe.String()
}
return strings.Join([]string{
"Settings summary below:",
s.OpenVPN.String(),
vpnServiceProviderSettings,
s.System.String(),
s.DNS.String(),
s.Firewall.String(),
s.TinyProxy.String(),
s.ShadowSocks.String(),
"", // new line at the end
}, "\n")
}
// GetAllSettings obtains all settings for the program and returns an error as soon
// as an error is encountered reading them.
func GetAllSettings(paramsReader params.Reader) (settings Settings, err error) {
settings.VPNSP, err = paramsReader.GetVPNSP()
if err != nil {
return settings, err
}
settings.OpenVPN, err = GetOpenVPNSettings(paramsReader)
if err != nil {
return settings, err
}
switch settings.VPNSP {
case constants.PrivateInternetAccess:
switch settings.OpenVPN.Cipher {
case "", "aes-128-cbc", "aes-256-cbc", "aes-128-gcm", "aes-256-gcm":
default:
return settings, fmt.Errorf("cipher %q is not supported by Private Internet Access", settings.OpenVPN.Cipher)
}
switch settings.OpenVPN.Auth {
case "", "sha1", "sha256":
default:
return settings, fmt.Errorf("auth algorithm %q is not supported by Private Internet Access", settings.OpenVPN.Auth)
}
settings.PIA, err = GetPIASettings(paramsReader)
case constants.Mullvad:
switch settings.OpenVPN.Cipher {
case "":
default:
return settings, fmt.Errorf("cipher %q is not supported by Mullvad", settings.OpenVPN.Cipher)
}
switch settings.OpenVPN.Auth {
case "":
default:
return settings, fmt.Errorf("auth algorithm %q is not supported by Mullvad (not using auth at all)", settings.OpenVPN.Auth)
}
settings.Mullvad, err = GetMullvadSettings(paramsReader)
case constants.Windscribe:
switch settings.OpenVPN.Cipher {
case "", "aes-256-cbc", "aes-256-gcm": // TODO check inside params getters
default:
return settings, fmt.Errorf("cipher %q is not supported by Windscribe", settings.OpenVPN.Cipher)
}
switch settings.OpenVPN.Auth {
case "", "sha512":
default:
return settings, fmt.Errorf("auth algorithm %q is not supported by Windscribe", settings.OpenVPN.Auth)
}
settings.Windscribe, err = GetWindscribeSettings(paramsReader, settings.OpenVPN.NetworkProtocol)
default:
err = fmt.Errorf("VPN service provider %q is not valid", settings.VPNSP)
}
if err != nil {
return settings, err
}
if err != nil {
return settings, err
}
settings.DNS, err = GetDNSSettings(paramsReader)
if err != nil {
return settings, err
}
settings.Firewall, err = GetFirewallSettings(paramsReader)
if err != nil {
return settings, err
}
settings.TinyProxy, err = GetTinyProxySettings(paramsReader)
if err != nil {
return settings, err
}
settings.ShadowSocks, err = GetShadowSocksSettings(paramsReader)
if err != nil {
return settings, err
}
settings.System, err = GetSystemSettings(paramsReader)
if err != nil {
return settings, err
}
return settings, nil
}

View File

@@ -1,60 +1,60 @@
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// ShadowSocks contains settings to configure the Shadowsocks server
type ShadowSocks struct {
Enabled bool
Password string
Log bool
Port uint16
Method string
}
func (s *ShadowSocks) String() string {
if !s.Enabled {
return "ShadowSocks settings: disabled"
}
log := "disabled"
if s.Log {
log = "enabled"
}
settingsList := []string{
"ShadowSocks settings:",
"Password: [redacted]",
"Log: " + log,
fmt.Sprintf("Port: %d", s.Port),
"Method: " + s.Method,
}
return strings.Join(settingsList, "\n |--")
}
// GetShadowSocksSettings obtains ShadowSocks settings from environment variables using the params package.
func GetShadowSocksSettings(params params.ParamsReader) (settings ShadowSocks, err error) {
settings.Enabled, err = params.GetShadowSocks()
if err != nil || !settings.Enabled {
return settings, err
}
settings.Port, err = params.GetShadowSocksPort()
if err != nil {
return settings, err
}
settings.Password, err = params.GetShadowSocksPassword()
if err != nil {
return settings, err
}
settings.Log, err = params.GetShadowSocksLog()
if err != nil {
return settings, err
}
settings.Method, err = params.GetShadowSocksMethod()
if err != nil {
return settings, err
}
return settings, nil
}
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// ShadowSocks contains settings to configure the Shadowsocks server
type ShadowSocks struct {
Method string
Password string
Port uint16
Enabled bool
Log bool
}
func (s *ShadowSocks) String() string {
if !s.Enabled {
return "ShadowSocks settings: disabled"
}
log := "disabled"
if s.Log {
log = "enabled"
}
settingsList := []string{
"ShadowSocks settings:",
"Password: [redacted]",
"Log: " + log,
fmt.Sprintf("Port: %d", s.Port),
"Method: " + s.Method,
}
return strings.Join(settingsList, "\n |--")
}
// GetShadowSocksSettings obtains ShadowSocks settings from environment variables using the params package.
func GetShadowSocksSettings(paramsReader params.Reader) (settings ShadowSocks, err error) {
settings.Enabled, err = paramsReader.GetShadowSocks()
if err != nil || !settings.Enabled {
return settings, err
}
settings.Port, err = paramsReader.GetShadowSocksPort()
if err != nil {
return settings, err
}
settings.Password, err = paramsReader.GetShadowSocksPassword()
if err != nil {
return settings, err
}
settings.Log, err = paramsReader.GetShadowSocksLog()
if err != nil {
return settings, err
}
settings.Method, err = paramsReader.GetShadowSocksMethod()
if err != nil {
return settings, err
}
return settings, nil
}

View File

@@ -17,20 +17,20 @@ type System struct {
}
// GetSystemSettings obtains the System settings using the params functions
func GetSystemSettings(params params.ParamsReader) (settings System, err error) {
settings.UID, err = params.GetUID()
func GetSystemSettings(paramsReader params.Reader) (settings System, err error) {
settings.UID, err = paramsReader.GetUID()
if err != nil {
return settings, err
}
settings.GID, err = params.GetGID()
settings.GID, err = paramsReader.GetGID()
if err != nil {
return settings, err
}
settings.Timezone, err = params.GetTimezone()
settings.Timezone, err = paramsReader.GetTimezone()
if err != nil {
return settings, err
}
settings.IPStatusFilepath, err = params.GetIPStatusFilepath()
settings.IPStatusFilepath, err = paramsReader.GetIPStatusFilepath()
if err != nil {
return settings, err
}

View File

@@ -1,59 +1,59 @@
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// TinyProxy contains settings to configure TinyProxy
type TinyProxy struct {
Enabled bool
User string
Password string
Port uint16
LogLevel models.TinyProxyLogLevel
}
func (t *TinyProxy) String() string {
if !t.Enabled {
return "TinyProxy settings: disabled"
}
auth := "disabled"
if t.User != "" {
auth = "enabled"
}
settingsList := []string{
fmt.Sprintf("Port: %d", t.Port),
"Authentication: " + auth,
"Log level: " + string(t.LogLevel),
}
return "TinyProxy settings:\n" + strings.Join(settingsList, "\n |--")
}
// GetTinyProxySettings obtains TinyProxy settings from environment variables using the params package.
func GetTinyProxySettings(params params.ParamsReader) (settings TinyProxy, err error) {
settings.Enabled, err = params.GetTinyProxy()
if err != nil || !settings.Enabled {
return settings, err
}
settings.User, err = params.GetTinyProxyUser()
if err != nil {
return settings, err
}
settings.Password, err = params.GetTinyProxyPassword()
if err != nil {
return settings, err
}
settings.Port, err = params.GetTinyProxyPort()
if err != nil {
return settings, err
}
settings.LogLevel, err = params.GetTinyProxyLog()
if err != nil {
return settings, err
}
return settings, nil
}
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// TinyProxy contains settings to configure TinyProxy
type TinyProxy struct {
User string
Password string
LogLevel models.TinyProxyLogLevel
Port uint16
Enabled bool
}
func (t *TinyProxy) String() string {
if !t.Enabled {
return "TinyProxy settings: disabled"
}
auth := "disabled"
if t.User != "" {
auth = "enabled"
}
settingsList := []string{
fmt.Sprintf("Port: %d", t.Port),
"Authentication: " + auth,
"Log level: " + string(t.LogLevel),
}
return "TinyProxy settings:\n" + strings.Join(settingsList, "\n |--")
}
// GetTinyProxySettings obtains TinyProxy settings from environment variables using the params package.
func GetTinyProxySettings(paramsReader params.Reader) (settings TinyProxy, err error) {
settings.Enabled, err = paramsReader.GetTinyProxy()
if err != nil || !settings.Enabled {
return settings, err
}
settings.User, err = paramsReader.GetTinyProxyUser()
if err != nil {
return settings, err
}
settings.Password, err = paramsReader.GetTinyProxyPassword()
if err != nil {
return settings, err
}
settings.Port, err = paramsReader.GetTinyProxyPort()
if err != nil {
return settings, err
}
settings.LogLevel, err = paramsReader.GetTinyProxyLog()
if err != nil {
return settings, err
}
return settings, nil
}

View File

@@ -1,49 +1,49 @@
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// Windscribe contains the settings to connect to a Windscribe server
type Windscribe struct {
User string
Password string
Region models.WindscribeRegion
Port uint16
}
func (w *Windscribe) String() string {
settingsList := []string{
"Windscribe settings:",
"User: [redacted]",
"Password: [redacted]",
"Region: " + string(w.Region),
"Custom port: " + fmt.Sprintf("%d", w.Port),
}
return strings.Join(settingsList, "\n |--")
}
// GetWindscribeSettings obtains Windscribe settings from environment variables using the params package.
func GetWindscribeSettings(params params.ParamsReader, protocol models.NetworkProtocol) (settings Windscribe, err error) {
settings.User, err = params.GetUser()
if err != nil {
return settings, err
}
settings.Password, err = params.GetPassword()
if err != nil {
return settings, err
}
settings.Region, err = params.GetWindscribeRegion()
if err != nil {
return settings, err
}
settings.Port, err = params.GetWindscribePort(protocol)
if err != nil {
return settings, err
}
return settings, nil
}
package settings
import (
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/models"
"github.com/qdm12/private-internet-access-docker/internal/params"
)
// Windscribe contains the settings to connect to a Windscribe server
type Windscribe struct {
User string
Password string
Region models.WindscribeRegion
Port uint16
}
func (w *Windscribe) String() string {
settingsList := []string{
"Windscribe settings:",
"User: [redacted]",
"Password: [redacted]",
"Region: " + string(w.Region),
"Custom port: " + fmt.Sprintf("%d", w.Port),
}
return strings.Join(settingsList, "\n |--")
}
// GetWindscribeSettings obtains Windscribe settings from environment variables using the params package.
func GetWindscribeSettings(paramsReader params.Reader, protocol models.NetworkProtocol) (settings Windscribe, err error) {
settings.User, err = paramsReader.GetUser()
if err != nil {
return settings, err
}
settings.Password, err = paramsReader.GetPassword()
if err != nil {
return settings, err
}
settings.Region, err = paramsReader.GetWindscribeRegion()
if err != nil {
return settings, err
}
settings.Port, err = paramsReader.GetWindscribePort(protocol)
if err != nil {
return settings, err
}
return settings, nil
}

View File

@@ -11,7 +11,7 @@ import (
)
// Splash returns the welcome spash message
func Splash(paramsReader params.ParamsReader) string {
func Splash(paramsReader params.Reader) string {
version := paramsReader.GetVersion()
vcsRef := paramsReader.GetVcsRef()
buildDate := paramsReader.GetBuildDate()