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 unbound && \
|
||||
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
|
||||
|
||||
@@ -352,11 +352,11 @@ There are various ways to achieve this, depending on your use case.
|
||||
|
||||
## 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=/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=/tmp/gluetun/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.
|
||||
|
||||
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.
|
||||
|
||||
## HTTP control server
|
||||
|
||||
@@ -24,9 +24,11 @@ import (
|
||||
)
|
||||
|
||||
type piaV4 struct {
|
||||
servers []models.PIAServer
|
||||
timeNow timeNowFunc
|
||||
randSource rand.Source
|
||||
servers []models.PIAServer
|
||||
timeNow timeNowFunc
|
||||
randSource rand.Source
|
||||
activeServer models.PIAServer
|
||||
activeProtocol models.NetworkProtocol
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -90,11 +114,19 @@ func (p *piaV4) BuildConf(connection models.OpenVPNConnection, verbosity, uid, g
|
||||
func (p *piaV4) PortForward(ctx context.Context, client *http.Client,
|
||||
fileManager files.FileManager, pfLogger logging.Logger, gateway net.IP, fw firewall.Configurator,
|
||||
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 {
|
||||
pfLogger.Error("aborting because: VPN gateway IP address was not found")
|
||||
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 {
|
||||
pfLogger.Error("aborting because: %s", err)
|
||||
return
|
||||
@@ -225,7 +257,7 @@ func filterPIAServers(servers []models.PIAServer, region string) (filtered []mod
|
||||
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)
|
||||
if err != nil {
|
||||
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.AddCert(certificate)
|
||||
TLSClientConfig := &tls.Config{
|
||||
RootCAs: rootCAs,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: true, //nolint:gosec
|
||||
} // TODO fix and remove InsecureSkipVerify
|
||||
RootCAs: rootCAs,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
ServerName: serverName,
|
||||
}
|
||||
transport := http.Transport{
|
||||
TLSClientConfig: TLSClientConfig,
|
||||
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)
|
||||
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)
|
||||
}
|
||||
if err := writePIAPortForwardData(fileManager, data); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user