PIA port forwarding final fixes (#259)
- Returns an error if the server does not support port forwarding - TLS verification using the server common name obtained through the API - Updated readme - Fixes #236
This commit is contained in:
@@ -113,4 +113,6 @@ RUN apk add -q --progress --no-cache --update openvpn ca-certificates iptables i
|
|||||||
deluser tinyproxy && \
|
deluser tinyproxy && \
|
||||||
deluser unbound && \
|
deluser unbound && \
|
||||||
mkdir /gluetun
|
mkdir /gluetun
|
||||||
|
# TODO remove once SAN is added to PIA servers certificates, see https://github.com/pia-foss/manual-connections/issues/10
|
||||||
|
ENV GODEBUG=x509ignoreCN=0
|
||||||
COPY --from=builder /tmp/gobuild/entrypoint /entrypoint
|
COPY --from=builder /tmp/gobuild/entrypoint /entrypoint
|
||||||
|
|||||||
@@ -352,11 +352,11 @@ There are various ways to achieve this, depending on your use case.
|
|||||||
|
|
||||||
## Private Internet Access port forwarding
|
## Private Internet Access port forwarding
|
||||||
|
|
||||||
Note that [not all regions support port forwarding](https://www.privateinternetaccess.com/helpdesk/kb/articles/how-do-i-enable-port-forwarding-on-my-vpn).
|
When `PORT_FORWARDING=on`, a port will be forwarded on the VPN server side and written to the file specified by `PORT_FORWARDING_STATUS_FILE=/tmp/gluetun/forwarded_port`.
|
||||||
|
|
||||||
When `PORT_FORWARDING=on`, a port will be forwarded on the VPN server side and written to the file specified by `PORT_FORWARDING_STATUS_FILE=/forwarded_port`.
|
|
||||||
It can be useful to mount this file as a volume to read it from other containers, for example to configure a torrenting client.
|
It can be useful to mount this file as a volume to read it from other containers, for example to configure a torrenting client.
|
||||||
|
|
||||||
|
For `VPNSP=private internet access` (default), you will keep the same forwarded port for 60 days as long as you bind mount the `/gluetun` directory.
|
||||||
|
|
||||||
You can also use the HTTP control server (see below) to get the port forwarded.
|
You can also use the HTTP control server (see below) to get the port forwarded.
|
||||||
|
|
||||||
## HTTP control server
|
## HTTP control server
|
||||||
|
|||||||
@@ -24,9 +24,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type piaV4 struct {
|
type piaV4 struct {
|
||||||
servers []models.PIAServer
|
servers []models.PIAServer
|
||||||
timeNow timeNowFunc
|
timeNow timeNowFunc
|
||||||
randSource rand.Source
|
randSource rand.Source
|
||||||
|
activeServer models.PIAServer
|
||||||
|
activeProtocol models.NetworkProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPrivateInternetAccessV4(servers []models.PIAServer, timeNow timeNowFunc) *piaV4 {
|
func newPrivateInternetAccessV4(servers []models.PIAServer, timeNow timeNowFunc) *piaV4 {
|
||||||
@@ -79,7 +81,29 @@ func (p *piaV4) GetOpenVPNConnection(selection models.ServerSelection) (connecti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pickRandomConnection(connections, p.randSource), nil
|
connection = pickRandomConnection(connections, p.randSource)
|
||||||
|
|
||||||
|
// Reverse lookup server from picked connection
|
||||||
|
found := false
|
||||||
|
for _, server := range servers {
|
||||||
|
IPs := server.OpenvpnUDP.IPs
|
||||||
|
if selection.Protocol == constants.TCP {
|
||||||
|
IPs = server.OpenvpnTCP.IPs
|
||||||
|
}
|
||||||
|
for _, IP := range IPs {
|
||||||
|
if connection.IP.Equal(IP) {
|
||||||
|
p.activeServer = server
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.activeProtocol = selection.Protocol
|
||||||
|
|
||||||
|
return connection, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *piaV4) BuildConf(connection models.OpenVPNConnection, verbosity, uid, gid int, root bool, cipher, auth string, extras models.ExtraConfigOptions) (lines []string) {
|
func (p *piaV4) BuildConf(connection models.OpenVPNConnection, verbosity, uid, gid int, root bool, cipher, auth string, extras models.ExtraConfigOptions) (lines []string) {
|
||||||
@@ -90,11 +114,19 @@ func (p *piaV4) BuildConf(connection models.OpenVPNConnection, verbosity, uid, g
|
|||||||
func (p *piaV4) PortForward(ctx context.Context, client *http.Client,
|
func (p *piaV4) PortForward(ctx context.Context, client *http.Client,
|
||||||
fileManager files.FileManager, pfLogger logging.Logger, gateway net.IP, fw firewall.Configurator,
|
fileManager files.FileManager, pfLogger logging.Logger, gateway net.IP, fw firewall.Configurator,
|
||||||
syncState func(port uint16) (pfFilepath models.Filepath)) {
|
syncState func(port uint16) (pfFilepath models.Filepath)) {
|
||||||
|
if !p.activeServer.PortForward {
|
||||||
|
pfLogger.Error("The server %s does not support port forwarding", p.activeServer.Region)
|
||||||
|
return
|
||||||
|
}
|
||||||
if gateway == nil {
|
if gateway == nil {
|
||||||
pfLogger.Error("aborting because: VPN gateway IP address was not found")
|
pfLogger.Error("aborting because: VPN gateway IP address was not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
client, err := newPIAv4HTTPClient()
|
commonName := p.activeServer.OpenvpnUDP.CN
|
||||||
|
if p.activeProtocol == constants.TCP {
|
||||||
|
commonName = p.activeServer.OpenvpnTCP.CN
|
||||||
|
}
|
||||||
|
client, err := newPIAv4HTTPClient(commonName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pfLogger.Error("aborting because: %s", err)
|
pfLogger.Error("aborting because: %s", err)
|
||||||
return
|
return
|
||||||
@@ -225,7 +257,7 @@ func filterPIAServers(servers []models.PIAServer, region string) (filtered []mod
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPIAv4HTTPClient() (client *http.Client, err error) {
|
func newPIAv4HTTPClient(serverName string) (client *http.Client, err error) {
|
||||||
certificateBytes, err := base64.StdEncoding.DecodeString(constants.PIACertificateStrong)
|
certificateBytes, err := base64.StdEncoding.DecodeString(constants.PIACertificateStrong)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot decode PIA root certificate: %w", err)
|
return nil, fmt.Errorf("cannot decode PIA root certificate: %w", err)
|
||||||
@@ -237,10 +269,10 @@ func newPIAv4HTTPClient() (client *http.Client, err error) {
|
|||||||
rootCAs := x509.NewCertPool()
|
rootCAs := x509.NewCertPool()
|
||||||
rootCAs.AddCert(certificate)
|
rootCAs.AddCert(certificate)
|
||||||
TLSClientConfig := &tls.Config{
|
TLSClientConfig := &tls.Config{
|
||||||
RootCAs: rootCAs,
|
RootCAs: rootCAs,
|
||||||
MinVersion: tls.VersionTLS12,
|
MinVersion: tls.VersionTLS12,
|
||||||
InsecureSkipVerify: true, //nolint:gosec
|
ServerName: serverName,
|
||||||
} // TODO fix and remove InsecureSkipVerify
|
}
|
||||||
transport := http.Transport{
|
transport := http.Transport{
|
||||||
TLSClientConfig: TLSClientConfig,
|
TLSClientConfig: TLSClientConfig,
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
@@ -267,9 +299,6 @@ func refreshPIAPortForwardData(client *http.Client, gateway net.IP, fileManager
|
|||||||
}
|
}
|
||||||
data.Port, data.Signature, data.Expiration, err = fetchPIAPortForwardData(client, gateway, data.Token)
|
data.Port, data.Signature, data.Expiration, err = fetchPIAPortForwardData(client, gateway, data.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.HasSuffix(err.Error(), "connection refused") {
|
|
||||||
return data, fmt.Errorf("cannot obtain port forwarding data: connection was refused, are you sure the region you are using supports port forwarding ;)")
|
|
||||||
}
|
|
||||||
return data, fmt.Errorf("cannot obtain port forwarding data: %w", err)
|
return data, fmt.Errorf("cannot obtain port forwarding data: %w", err)
|
||||||
}
|
}
|
||||||
if err := writePIAPortForwardData(fileManager, data); err != nil {
|
if err := writePIAPortForwardData(fileManager, data); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user