Fix #81, new env variable OPENVPN_ROOT

This commit is contained in:
Quentin McGaw
2020-03-18 23:05:47 +00:00
parent 9d786bf338
commit d2b361b998
11 changed files with 56 additions and 8 deletions

View File

@@ -33,6 +33,7 @@ ENV VPNSP=pia \
USER= \ USER= \
PROTOCOL=udp \ PROTOCOL=udp \
OPENVPN_VERBOSITY=1 \ OPENVPN_VERBOSITY=1 \
OPENVPN_ROOT=no \
TZ= \ TZ= \
# PIA only # PIA only
PASSWORD= \ PASSWORD= \

View File

@@ -160,6 +160,7 @@ docker run --rm --network=container:pia alpine:3.11 wget -qO- https://ipinfo.io
| `SHADOWSOCKS_PASSWORD` | | Passsword to use to connect to the SOCKS5 proxy | | `SHADOWSOCKS_PASSWORD` | | Passsword to use to connect to the SOCKS5 proxy |
| `TZ` | | Specify a timezone to use i.e. `Europe/London` | | `TZ` | | Specify a timezone to use i.e. `Europe/London` |
| `OPENVPN_VERBOSITY` | `1` | Openvpn verbosity level from 0 to 6 | | `OPENVPN_VERBOSITY` | `1` | Openvpn verbosity level from 0 to 6 |
| `OPENVPN_ROOT` | `no` | Run OpenVPN as root, `yes` or `no` |
## Connect to it ## Connect to it
@@ -259,6 +260,33 @@ It can be useful to mount this file as a volume to read it from other containers
## FAQ ## FAQ
<details><summary>Openvpn disconnects because of a ping timeout</summary><p>
It happens especially on some PIA servers where they change their configuration or the server goes offline.
You will obtain an error similar to:
```s
openvpn: Wed Mar 18 22:13:00 2020 [3a51ae90324bcb0719cb399b650c64d4] Inactivity timeout (--ping-restart), restarting,
openvpn: Wed Mar 18 22:13:00 2020 SIGUSR1[soft,ping-restart] received, process restarting,
...
openvpn: Wed Mar 18 22:13:17 2020 Preserving previous TUN/TAP instance: tun0,
openvpn: Wed Mar 18 22:13:17 2020 NOTE: Pulled options changed on restart, will need to close and reopen TUN/TAP device.,
openvpn: Wed Mar 18 22:13:17 2020 ERROR: Linux route delete command failed: external program exited with error status: 2,
openvpn: Wed Mar 18 22:13:17 2020 ERROR: Linux route delete command failed: external program exited with error status: 2,
openvpn: Wed Mar 18 22:13:17 2020 ERROR: Linux route delete command failed: external program exited with error status: 2,
openvpn: Wed Mar 18 22:13:17 2020 ERROR: Linux route delete command failed: external program exited with error status: 2,
openvpn: Wed Mar 18 22:13:17 2020 /sbin/ip addr del dev tun0 local 10.6.11.6 peer 10.6.11.5,
openvpn: Wed Mar 18 22:13:17 2020 Linux ip addr del failed: external program exited with error status: 2,
openvpn: Wed Mar 18 22:13:18 2020 ERROR: Cannot ioctl TUNSETIFF tun: Operation not permitted (errno=1),
openvpn: Wed Mar 18 22:13:18 2020 Exiting due to fatal error,
exit status 1
```
To fix it, you would have to run openvpn with root, by setting the environment variable `OPENVPN_ROOT=yes`.
</p></details>
<details><summary>Private Internet Access: Why do I see openvpn warnings at start?</summary><p> <details><summary>Private Internet Access: Why do I see openvpn warnings at start?</summary><p>
You might see some warnings similar to: You might see some warnings similar to:

View File

@@ -132,12 +132,12 @@ func main() {
case "pia": case "pia":
connections, err = piaConf.GetOpenVPNConnections(allSettings.PIA.Region, allSettings.OpenVPN.NetworkProtocol, allSettings.PIA.Encryption) connections, err = piaConf.GetOpenVPNConnections(allSettings.PIA.Region, allSettings.OpenVPN.NetworkProtocol, allSettings.PIA.Encryption)
e.FatalOnError(err) e.FatalOnError(err)
err = piaConf.BuildConf(connections, allSettings.PIA.Encryption, allSettings.OpenVPN.Verbosity, uid, gid) err = piaConf.BuildConf(connections, allSettings.PIA.Encryption, allSettings.OpenVPN.Verbosity, uid, gid, allSettings.OpenVPN.Root)
e.FatalOnError(err) e.FatalOnError(err)
case "mullvad": case "mullvad":
connections, err = mullvadConf.GetOpenVPNConnections(allSettings.Mullvad.Country, allSettings.Mullvad.City, allSettings.Mullvad.ISP, allSettings.OpenVPN.NetworkProtocol, allSettings.Mullvad.Port) connections, err = mullvadConf.GetOpenVPNConnections(allSettings.Mullvad.Country, allSettings.Mullvad.City, allSettings.Mullvad.ISP, allSettings.OpenVPN.NetworkProtocol, allSettings.Mullvad.Port)
e.FatalOnError(err) e.FatalOnError(err)
err = mullvadConf.BuildConf(connections, allSettings.OpenVPN.Verbosity, uid, gid) err = mullvadConf.BuildConf(connections, allSettings.OpenVPN.Verbosity, uid, gid, allSettings.OpenVPN.Root)
e.FatalOnError(err) e.FatalOnError(err)
} }

View File

@@ -18,6 +18,7 @@ services:
- USER=js89ds7 - USER=js89ds7
- PROTOCOL=udp - PROTOCOL=udp
- OPENVPN_VERBOSITY=1 - OPENVPN_VERBOSITY=1
- OPENVPN_ROOT=no
- TZ= - TZ=
# PIA only # PIA only

View File

@@ -25,7 +25,7 @@ func (c *configurator) GetOpenVPNConnections(country models.MullvadCountry, city
return connections, nil return connections, nil
} }
func (c *configurator) BuildConf(connections []models.OpenVPNConnection, verbosity, uid, gid int) (err error) { func (c *configurator) BuildConf(connections []models.OpenVPNConnection, verbosity, uid, gid int, root bool) (err error) {
if len(connections) == 0 { if len(connections) == 0 {
return fmt.Errorf("at least one connection string is expected") return fmt.Errorf("at least one connection string is expected")
} }
@@ -49,7 +49,6 @@ func (c *configurator) BuildConf(connections []models.OpenVPNConnection, verbosi
// Added constant values // Added constant values
"mute-replay-warnings", "mute-replay-warnings",
"auth-nocache", "auth-nocache",
"user nonrootuser",
"pull-filter ignore \"auth-token\"", // prevent auth failed loops "pull-filter ignore \"auth-token\"", // prevent auth failed loops
"auth-retry nointeract", "auth-retry nointeract",
"remote-random", "remote-random",
@@ -59,6 +58,9 @@ func (c *configurator) BuildConf(connections []models.OpenVPNConnection, verbosi
fmt.Sprintf("auth-user-pass %s", constants.OpenVPNAuthConf), fmt.Sprintf("auth-user-pass %s", constants.OpenVPNAuthConf),
fmt.Sprintf("proto %s", string(connections[0].Protocol)), fmt.Sprintf("proto %s", string(connections[0].Protocol)),
} }
if !root {
lines = append(lines, "user nonrootuser")
}
for _, connection := range connections { for _, connection := range connections {
lines = append(lines, fmt.Sprintf("remote %s %d", connection.IP.String(), connection.Port)) lines = append(lines, fmt.Sprintf("remote %s %d", connection.IP.String(), connection.Port))
} }

View File

@@ -12,7 +12,7 @@ const logPrefix = "Mullvad configurator"
// Configurator contains methods to download, read and modify the openvpn configuration to connect as a client // Configurator contains methods to download, read and modify the openvpn configuration to connect as a client
type Configurator interface { type Configurator interface {
GetOpenVPNConnections(country models.MullvadCountry, city models.MullvadCity, provider models.MullvadProvider, protocol models.NetworkProtocol, customPort uint16) (connections []models.OpenVPNConnection, err error) GetOpenVPNConnections(country models.MullvadCountry, city models.MullvadCity, provider models.MullvadProvider, protocol models.NetworkProtocol, customPort uint16) (connections []models.OpenVPNConnection, err error)
BuildConf(connections []models.OpenVPNConnection, verbosity, uid, gid int) (err error) BuildConf(connections []models.OpenVPNConnection, verbosity, uid, gid int, root bool) (err error)
} }
type configurator struct { type configurator struct {

View File

@@ -39,3 +39,9 @@ func (p *paramsReader) GetNetworkProtocol() (protocol models.NetworkProtocol, er
func (p *paramsReader) GetOpenVPNVerbosity() (verbosity int, err error) { func (p *paramsReader) GetOpenVPNVerbosity() (verbosity int, err error) {
return p.envParams.GetEnvIntRange("OPENVPN_VERBOSITY", 0, 6, libparams.Default("1")) 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"))
}

View File

@@ -36,6 +36,7 @@ type ParamsReader interface {
GetPassword() (s string, err error) GetPassword() (s string, err error)
GetNetworkProtocol() (protocol models.NetworkProtocol, err error) GetNetworkProtocol() (protocol models.NetworkProtocol, err error)
GetOpenVPNVerbosity() (verbosity int, err error) GetOpenVPNVerbosity() (verbosity int, err error)
GetOpenVPNRoot() (root bool, err error)
// PIA getters // PIA getters
GetPortForwarding() (activated bool, err error) GetPortForwarding() (activated bool, err error)

View File

@@ -54,7 +54,7 @@ func (c *configurator) GetOpenVPNConnections(region models.PIARegion, protocol m
return connections, nil return connections, nil
} }
func (c *configurator) BuildConf(connections []models.OpenVPNConnection, encryption models.PIAEncryption, verbosity, uid, gid int) (err error) { func (c *configurator) BuildConf(connections []models.OpenVPNConnection, encryption models.PIAEncryption, verbosity, uid, gid int, root bool) (err error) {
var X509CRL, certificate, cipherAlgo, authAlgo string var X509CRL, certificate, cipherAlgo, authAlgo string
if encryption == constants.PIAEncryptionNormal { if encryption == constants.PIAEncryptionNormal {
cipherAlgo = "aes-128-cbc" cipherAlgo = "aes-128-cbc"
@@ -84,7 +84,6 @@ func (c *configurator) BuildConf(connections []models.OpenVPNConnection, encrypt
// Added constant values // Added constant values
"auth-nocache", "auth-nocache",
"mute-replay-warnings", "mute-replay-warnings",
"user nonrootuser",
"pull-filter ignore \"auth-token\"", // prevent auth failed loops "pull-filter ignore \"auth-token\"", // prevent auth failed loops
"auth-retry nointeract", "auth-retry nointeract",
"remote-random", "remote-random",
@@ -96,6 +95,9 @@ func (c *configurator) BuildConf(connections []models.OpenVPNConnection, encrypt
fmt.Sprintf("cipher %s", cipherAlgo), fmt.Sprintf("cipher %s", cipherAlgo),
fmt.Sprintf("auth %s", authAlgo), fmt.Sprintf("auth %s", authAlgo),
} }
if !root {
lines = append(lines, "user nonrootuser")
}
for _, connection := range connections { for _, connection := range connections {
lines = append(lines, fmt.Sprintf("remote %s %d", connection.IP.String(), connection.Port)) lines = append(lines, fmt.Sprintf("remote %s %d", connection.IP.String(), connection.Port))
} }

View File

@@ -18,7 +18,7 @@ const logPrefix = "PIA configurator"
type Configurator interface { type Configurator interface {
GetOpenVPNConnections(region models.PIARegion, protocol models.NetworkProtocol, GetOpenVPNConnections(region models.PIARegion, protocol models.NetworkProtocol,
encryption models.PIAEncryption) (connections []models.OpenVPNConnection, err error) encryption models.PIAEncryption) (connections []models.OpenVPNConnection, err error)
BuildConf(connections []models.OpenVPNConnection, encryption models.PIAEncryption, verbosity, uid, gid int) (err error) BuildConf(connections []models.OpenVPNConnection, encryption models.PIAEncryption, verbosity, uid, gid int, root bool) (err error)
GetPortForward() (port uint16, err error) GetPortForward() (port uint16, err error)
WritePortForward(filepath models.Filepath, port uint16) (err error) WritePortForward(filepath models.Filepath, port uint16) (err error)
AllowPortForwardFirewall(device models.VPNDevice, port uint16) (err error) AllowPortForwardFirewall(device models.VPNDevice, port uint16) (err error)

View File

@@ -12,6 +12,7 @@ import (
type OpenVPN struct { type OpenVPN struct {
NetworkProtocol models.NetworkProtocol NetworkProtocol models.NetworkProtocol
Verbosity int Verbosity int
Root bool
} }
// GetOpenVPNSettings obtains the OpenVPN settings using the params functions // GetOpenVPNSettings obtains the OpenVPN settings using the params functions
@@ -24,14 +25,20 @@ func GetOpenVPNSettings(params params.ParamsReader) (settings OpenVPN, err error
if err != nil { if err != nil {
return settings, err return settings, err
} }
settings.Root, err = params.GetOpenVPNRoot()
return settings, nil return settings, nil
} }
func (o *OpenVPN) String() string { func (o *OpenVPN) String() string {
runAsRoot := "no"
if o.Root {
runAsRoot = "yes"
}
settingsList := []string{ settingsList := []string{
"OpenVPN settings:", "OpenVPN settings:",
"Network protocol: " + string(o.NetworkProtocol), "Network protocol: " + string(o.NetworkProtocol),
"Verbosity level: " + fmt.Sprintf("%d", o.Verbosity), "Verbosity level: " + fmt.Sprintf("%d", o.Verbosity),
"Run as root: " + runAsRoot,
} }
return strings.Join(settingsList, "\n|--") return strings.Join(settingsList, "\n|--")
} }