- Environment variables `UID` and `GID`, both defaulting to `1000` - All subprocesses (openvpn, tinyproxy, etc.) run using the UID and GID given - All files are written with an ownership for the UID and GID given - Port forwarded file has also ownership for UID, GID and read permission only
This commit is contained in:
12
Dockerfile
12
Dockerfile
@@ -36,6 +36,8 @@ ENV VPNSP=pia \
|
||||
OPENVPN_ROOT=no \
|
||||
OPENVPN_TARGET_IP= \
|
||||
TZ= \
|
||||
UID=1000 \
|
||||
GID=1000 \
|
||||
# PIA only
|
||||
PASSWORD= \
|
||||
REGION="Austria" \
|
||||
@@ -82,8 +84,8 @@ HEALTHCHECK --interval=3m --timeout=3s --start-period=20s --retries=1 CMD /entry
|
||||
RUN apk add -q --progress --no-cache --update openvpn ca-certificates iptables unbound tinyproxy tzdata && \
|
||||
echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
|
||||
apk add -q --progress --no-cache --update shadowsocks-libev && \
|
||||
rm -rf /*.zip /var/cache/apk/* /etc/unbound/* /usr/sbin/unbound-anchor /usr/sbin/unbound-checkconf /usr/sbin/unbound-control /usr/sbin/unbound-control-setup /usr/sbin/unbound-host /etc/tinyproxy/tinyproxy.conf && \
|
||||
adduser nonrootuser -D -H --uid 1000 && \
|
||||
chown nonrootuser -R /etc/unbound /etc/tinyproxy && \
|
||||
chmod 700 /etc/unbound /etc/tinyproxy
|
||||
COPY --from=builder --chown=1000:1000 /tmp/gobuild/entrypoint /entrypoint
|
||||
rm -rf /var/cache/apk/* /etc/unbound/* /usr/sbin/unbound-* /etc/tinyproxy/tinyproxy.conf && \
|
||||
deluser openvpn && \
|
||||
deluser tinyproxy && \
|
||||
deluser unbound
|
||||
COPY --from=builder /tmp/gobuild/entrypoint /entrypoint
|
||||
|
||||
@@ -170,6 +170,8 @@ docker run --rm --network=container:pia alpine:3.11 wget -qO- https://ipinfo.io
|
||||
| `OPENVPN_TARGET_IP` | | (Optional) Specify a target VPN server IP address to use, valid for Mullvad and Private Internet Access |
|
||||
| `OPENVPN_CIPHER` | | Specify a custom cipher to use, use at your own risk. It will also set `ncp-disable` if using AES GCM for PIA |
|
||||
| `OPENVPN_AUTH` | | Specify a custom auth algorithm to use (i.e. `sha256`) *for pia only* |
|
||||
| `UID` | `1000` | User ID to run as non root and for ownership of files written |
|
||||
| `GID` | `1000` | Group ID to run as non root and for ownership of files written |
|
||||
|
||||
## Connect to it
|
||||
|
||||
|
||||
88
cmd/main.go
88
cmd/main.go
@@ -13,6 +13,7 @@ import (
|
||||
"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"
|
||||
@@ -30,10 +31,6 @@ import (
|
||||
"github.com/qdm12/private-internet-access-docker/internal/windscribe"
|
||||
)
|
||||
|
||||
const (
|
||||
uid, gid = 1000, 1000
|
||||
)
|
||||
|
||||
func main() {
|
||||
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel, -1)
|
||||
if err != nil {
|
||||
@@ -52,6 +49,7 @@ func main() {
|
||||
client := network.NewClient(15 * time.Second)
|
||||
// Create configurators
|
||||
fileManager := files.NewFileManager()
|
||||
alpineConf := alpine.NewConfigurator(logger, fileManager)
|
||||
ovpnConf := openvpn.NewConfigurator(logger, fileManager)
|
||||
dnsConf := dns.NewConfigurator(logger, client, fileManager)
|
||||
firewallConf := firewall.NewConfigurator(logger, fileManager)
|
||||
@@ -74,6 +72,13 @@ func main() {
|
||||
e.FatalOnError(err)
|
||||
logger.Info(allSettings.String())
|
||||
|
||||
err = alpineConf.CreateUser("nonrootuser", allSettings.UID)
|
||||
e.FatalOnError(err)
|
||||
err = fileManager.SetOwnership("/etc/unbound", allSettings.UID, allSettings.GID)
|
||||
e.FatalOnError(err)
|
||||
err = fileManager.SetOwnership("/etc/tinyproxy", allSettings.UID, allSettings.GID)
|
||||
e.FatalOnError(err)
|
||||
|
||||
if err := ovpnConf.CheckTUN(); err != nil {
|
||||
logger.Warn(err)
|
||||
err = ovpnConf.CreateTUN()
|
||||
@@ -92,7 +97,7 @@ func main() {
|
||||
openVPNUser = allSettings.Windscribe.User
|
||||
openVPNPassword = allSettings.Windscribe.Password
|
||||
}
|
||||
err = ovpnConf.WriteAuthFile(openVPNUser, openVPNPassword, uid, gid)
|
||||
err = ovpnConf.WriteAuthFile(openVPNUser, openVPNPassword, allSettings.UID, allSettings.GID)
|
||||
e.FatalOnError(err)
|
||||
|
||||
// Temporarily reset chain policies allowing Kubernetes sidecar to
|
||||
@@ -113,11 +118,11 @@ func main() {
|
||||
if allSettings.DNS.Enabled {
|
||||
initialDNSToUse := constants.DNSProviderMapping()[allSettings.DNS.Providers[0]]
|
||||
dnsConf.UseDNSInternally(initialDNSToUse.IPs[0])
|
||||
err = dnsConf.DownloadRootHints(uid, gid)
|
||||
err = dnsConf.DownloadRootHints(allSettings.UID, allSettings.GID)
|
||||
e.FatalOnError(err)
|
||||
err = dnsConf.DownloadRootKey(uid, gid)
|
||||
err = dnsConf.DownloadRootKey(allSettings.UID, allSettings.GID)
|
||||
e.FatalOnError(err)
|
||||
err = dnsConf.MakeUnboundConf(allSettings.DNS, uid, gid)
|
||||
err = dnsConf.MakeUnboundConf(allSettings.DNS, allSettings.UID, allSettings.GID)
|
||||
e.FatalOnError(err)
|
||||
stream, waitFn, err := dnsConf.Start(allSettings.DNS.VerbosityDetailsLevel)
|
||||
e.FatalOnError(err)
|
||||
@@ -135,19 +140,54 @@ func main() {
|
||||
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)
|
||||
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, uid, gid, allSettings.OpenVPN.Root, allSettings.OpenVPN.Cipher, allSettings.OpenVPN.Auth)
|
||||
err = piaConf.BuildConf(
|
||||
connections,
|
||||
allSettings.PIA.Encryption,
|
||||
allSettings.OpenVPN.Verbosity,
|
||||
allSettings.UID,
|
||||
allSettings.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)
|
||||
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, uid, gid, allSettings.OpenVPN.Root, allSettings.OpenVPN.Cipher)
|
||||
err = mullvadConf.BuildConf(
|
||||
connections,
|
||||
allSettings.OpenVPN.Verbosity,
|
||||
allSettings.UID,
|
||||
allSettings.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)
|
||||
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, uid, gid, allSettings.OpenVPN.Root, allSettings.OpenVPN.Cipher, allSettings.OpenVPN.Auth)
|
||||
err = windscribeConf.BuildConf(
|
||||
connections,
|
||||
allSettings.OpenVPN.Verbosity,
|
||||
allSettings.UID,
|
||||
allSettings.GID,
|
||||
allSettings.OpenVPN.Root,
|
||||
allSettings.OpenVPN.Cipher,
|
||||
allSettings.OpenVPN.Auth)
|
||||
e.FatalOnError(err)
|
||||
}
|
||||
|
||||
@@ -167,7 +207,13 @@ func main() {
|
||||
e.FatalOnError(err)
|
||||
|
||||
if allSettings.TinyProxy.Enabled {
|
||||
err = tinyProxyConf.MakeConf(allSettings.TinyProxy.LogLevel, allSettings.TinyProxy.Port, allSettings.TinyProxy.User, allSettings.TinyProxy.Password, uid, gid)
|
||||
err = tinyProxyConf.MakeConf(
|
||||
allSettings.TinyProxy.LogLevel,
|
||||
allSettings.TinyProxy.Port,
|
||||
allSettings.TinyProxy.User,
|
||||
allSettings.TinyProxy.Password,
|
||||
allSettings.UID,
|
||||
allSettings.GID)
|
||||
e.FatalOnError(err)
|
||||
err = firewallConf.AllowAnyIncomingOnPort(allSettings.TinyProxy.Port)
|
||||
e.FatalOnError(err)
|
||||
@@ -182,7 +228,11 @@ func main() {
|
||||
}
|
||||
|
||||
if allSettings.ShadowSocks.Enabled {
|
||||
err = shadowsocksConf.MakeConf(allSettings.ShadowSocks.Port, allSettings.ShadowSocks.Password, uid, gid)
|
||||
err = shadowsocksConf.MakeConf(
|
||||
allSettings.ShadowSocks.Port,
|
||||
allSettings.ShadowSocks.Password,
|
||||
allSettings.UID,
|
||||
allSettings.GID)
|
||||
e.FatalOnError(err)
|
||||
err = firewallConf.AllowAnyIncomingOnPort(allSettings.ShadowSocks.Port)
|
||||
e.FatalOnError(err)
|
||||
@@ -202,7 +252,11 @@ func main() {
|
||||
if err != nil {
|
||||
logger.Error("port forwarding:", err)
|
||||
}
|
||||
if err := piaConf.WritePortForward(allSettings.PIA.PortForwarding.Filepath, port); err != nil {
|
||||
if err := piaConf.WritePortForward(
|
||||
allSettings.PIA.PortForwarding.Filepath,
|
||||
port,
|
||||
allSettings.UID,
|
||||
allSettings.GID); err != nil {
|
||||
logger.Error("port forwarding:", err)
|
||||
}
|
||||
if err := piaConf.AllowPortForwardFirewall(constants.TUN, port); err != nil {
|
||||
|
||||
6
go.mod
6
go.mod
@@ -4,7 +4,7 @@ go 1.13
|
||||
|
||||
require (
|
||||
github.com/kyokomi/emoji v2.1.0+incompatible
|
||||
github.com/qdm12/golibs v0.0.0-20200224235252-bc16caae82ea
|
||||
github.com/stretchr/testify v1.4.0
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d
|
||||
github.com/qdm12/golibs v0.0.0-20200329231626-f55b47cd4e96
|
||||
github.com/stretchr/testify v1.5.1
|
||||
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775
|
||||
)
|
||||
|
||||
8
go.sum
8
go.sum
@@ -61,8 +61,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/qdm12/golibs v0.0.0-20200224235252-bc16caae82ea h1:ILUt8UU795dKZ2r7p3G44w1/vcGM/FUFXCcePYXYfS8=
|
||||
github.com/qdm12/golibs v0.0.0-20200224235252-bc16caae82ea/go.mod h1:YULaFjj6VGmhjak6f35sUWwEleHUmngN5IQ3kdvd6XE=
|
||||
github.com/qdm12/golibs v0.0.0-20200329231626-f55b47cd4e96 h1:vGvPItljtw8Z0xVJSyE80Z+6zzRZqrHoXr5vx5iB+rI=
|
||||
github.com/qdm12/golibs v0.0.0-20200329231626-f55b47cd4e96/go.mod h1:YULaFjj6VGmhjak6f35sUWwEleHUmngN5IQ3kdvd6XE=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -70,6 +70,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
|
||||
@@ -93,6 +95,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE=
|
||||
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
|
||||
28
internal/alpine/alpine.go
Normal file
28
internal/alpine/alpine.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package alpine
|
||||
|
||||
import (
|
||||
"os/user"
|
||||
|
||||
"github.com/qdm12/golibs/files"
|
||||
"github.com/qdm12/golibs/logging"
|
||||
)
|
||||
|
||||
const logPrefix = "alpine configurator"
|
||||
|
||||
type Configurator interface {
|
||||
CreateUser(username string, uid int) error
|
||||
}
|
||||
|
||||
type configurator struct {
|
||||
fileManager files.FileManager
|
||||
lookupUID func(uid string) (*user.User, error)
|
||||
lookupUser func(username string) (*user.User, error)
|
||||
}
|
||||
|
||||
func NewConfigurator(logger logging.Logger, fileManager files.FileManager) Configurator {
|
||||
return &configurator{
|
||||
fileManager: fileManager,
|
||||
lookupUID: user.LookupId,
|
||||
lookupUser: user.Lookup,
|
||||
}
|
||||
}
|
||||
38
internal/alpine/users.go
Normal file
38
internal/alpine/users.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package alpine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/user"
|
||||
)
|
||||
|
||||
// CreateUser creates a user in Alpine with the given UID
|
||||
func (c *configurator) CreateUser(username string, uid int) error {
|
||||
UIDStr := fmt.Sprintf("%d", uid)
|
||||
u, err := c.lookupUID(UIDStr)
|
||||
_, unknownUID := err.(user.UnknownUserIdError)
|
||||
if err != nil && !unknownUID {
|
||||
return fmt.Errorf("cannot create user: %w", err)
|
||||
} else if u != nil {
|
||||
if u.Username == username {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("user with ID %d exists with username %q instead of %q", uid, u.Username, username)
|
||||
}
|
||||
u, err = c.lookupUser(username)
|
||||
_, unknownUsername := err.(user.UnknownUserError)
|
||||
if err != nil && !unknownUsername {
|
||||
return fmt.Errorf("cannot create user: %w", err)
|
||||
} else if u != nil {
|
||||
return fmt.Errorf("cannot create user: user with name %s already exists for ID %s instead of %d", username, u.Uid, uid)
|
||||
}
|
||||
passwd, err := c.fileManager.ReadFile("/etc/passwd")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create user: %w", err)
|
||||
}
|
||||
passwd = append(passwd, []byte(fmt.Sprintf("%s:x:%d:::/dev/null:/sbin/nologin\n", username, uid))...)
|
||||
|
||||
if err := c.fileManager.WriteToFile("/etc/passwd", passwd); err != nil {
|
||||
return fmt.Errorf("cannot create user: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
15
internal/params/ids.go
Normal file
15
internal/params/ids.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package params
|
||||
|
||||
import (
|
||||
libparams "github.com/qdm12/golibs/params"
|
||||
)
|
||||
|
||||
// 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"))
|
||||
}
|
||||
@@ -28,6 +28,10 @@ type ParamsReader interface {
|
||||
GetDNSOverTLSPrivateAddresses() (privateAddresses []string)
|
||||
GetDNSOverTLSIPv6() (ipv6 bool, err error)
|
||||
|
||||
// IDs
|
||||
GetUID() (uid int, err error)
|
||||
GetGID() (gid int, err error)
|
||||
|
||||
// Firewall getters
|
||||
GetExtraSubnets() (extraSubnets []net.IPNet, err error)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ type Configurator interface {
|
||||
encryption models.PIAEncryption, targetIP net.IP) (connections []models.OpenVPNConnection, err error)
|
||||
BuildConf(connections []models.OpenVPNConnection, encryption models.PIAEncryption, verbosity, uid, gid int, root bool, cipher, auth string) (err error)
|
||||
GetPortForward() (port uint16, err error)
|
||||
WritePortForward(filepath models.Filepath, port uint16) (err error)
|
||||
WritePortForward(filepath models.Filepath, port uint16, uid, gid int) (err error)
|
||||
AllowPortForwardFirewall(device models.VPNDevice, port uint16) (err error)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/qdm12/golibs/files"
|
||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
||||
)
|
||||
@@ -35,9 +36,13 @@ func (c *configurator) GetPortForward() (port uint16, err error) {
|
||||
return body.Port, nil
|
||||
}
|
||||
|
||||
func (c *configurator) WritePortForward(filepath models.Filepath, port uint16) (err error) {
|
||||
func (c *configurator) WritePortForward(filepath models.Filepath, port uint16, uid, gid int) (err error) {
|
||||
c.logger.Info("%s: Writing forwarded port to %s", logPrefix, filepath)
|
||||
return c.fileManager.WriteLinesToFile(string(filepath), []string{fmt.Sprintf("%d", port)})
|
||||
return c.fileManager.WriteLinesToFile(
|
||||
string(filepath),
|
||||
[]string{fmt.Sprintf("%d", port)},
|
||||
files.Ownership(uid, gid),
|
||||
files.Permissions(400))
|
||||
}
|
||||
|
||||
func (c *configurator) AllowPortForwardFirewall(device models.VPNDevice, port uint16) (err error) {
|
||||
|
||||
@@ -18,6 +18,8 @@ type Settings struct {
|
||||
Firewall Firewall
|
||||
TinyProxy TinyProxy
|
||||
ShadowSocks ShadowSocks
|
||||
UID int
|
||||
GID int
|
||||
}
|
||||
|
||||
func (s *Settings) String() string {
|
||||
@@ -32,6 +34,7 @@ func (s *Settings) String() string {
|
||||
}
|
||||
return strings.Join([]string{
|
||||
"Settings summary below:",
|
||||
fmt.Sprintf("|-- Using UID %d and GID %d", s.UID, s.GID),
|
||||
s.OpenVPN.String(),
|
||||
vpnServiceProvider,
|
||||
s.DNS.String(),
|
||||
@@ -115,5 +118,13 @@ func GetAllSettings(params params.ParamsReader) (settings Settings, err error) {
|
||||
if err != nil {
|
||||
return settings, err
|
||||
}
|
||||
settings.UID, err = params.GetUID()
|
||||
if err != nil {
|
||||
return settings, err
|
||||
}
|
||||
settings.GID, err = params.GetGID()
|
||||
if err != nil {
|
||||
return settings, err
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user