/private-internet-access-docker

Private internet access openvpn client in a lightweight Docker container

Primary LanguageShellMIT LicenseMIT

Private Internet Access Client (OpenVPN+Iptables+DNS over TLS on Alpine Linux)

Lightweight VPN client to tunnel to private internet access servers

PIA Docker OpenVPN

Build Status Docker Build Status

GitHub last commit GitHub commit activity GitHub issues

Docker Pulls Docker Stars Docker Automated

Image size Image version

Donate PayPal

Image size RAM usage CPU usage
19.6MB 14MB to 80MB Low to Medium
Click to show base components

Features

  • Configure everything with environment variables

    • Destination region
    • Internet protocol
    • Level of encryption
    • Username and password
    • Malicious DNS blocking
    • Extra subnets allowed by firewall
    • Run openvpn without root (but will give reconnect problems)

  • Connect other containers to it (and thus computers, see this)

  • The iptables firewall allows traffic only with needed PIA servers (IP addresses, port, protocol) combinations

  • OpenVPN restarts on failure using another PIA IP address for the same region encryption combination

  • Docker healthcheck pings the DNS 1.1.1.1 to verify the connection is up

  • Openvpn and Unbound run without root

Setup

  1. Requirements

    • A Private Internet Access username and password - Sign up
    • Firewall requirements
      • Allow outbound TCP 853 to 1.1.1.1 to allow Unbound to resolve the PIA domain name at start. You can then block it once the container is started.
      • For UDP strong encryption, allow outbound UDP 1197
      • For UDP normal encryption, allow outbound UDP 1198
      • For TCP strong encryption, allow outbound TCP 501
      • For TCP normal encryption, allow outbound TCP 502

  2. Ensure /dev/net/tun is setup on your host with either:

    insmod /lib/modules/tun.ko
    # or...
    modprobe tun
  3. CLICK IF YOU HAVE AN ARM DEVICE

    • If you have a ARM 32 bit v6 architecture

      docker build -t qmcgaw/private-internet-access \
      --build-arg BASE_IMAGE=arm32v6/alpine \
      https://github.com/qdm12/private-internet-access-docker.git
    • If you have a ARM 32 bit v7 architecture

      docker build -t qmcgaw/private-internet-access \
      --build-arg BASE_IMAGE=arm32v7/alpine \
      https://github.com/qdm12/private-internet-access-docker.git
    • If you have a ARM 64 bit v8 architecture

      docker build -t qmcgaw/private-internet-access \
      --build-arg BASE_IMAGE=arm64v8/alpine \
      https://github.com/qdm12/private-internet-access-docker.git

  4. Launch the container with:

    docker run -d --name=pia --cap-add=NET_ADMIN --device=/dev/net/tun \
    -e REGION="CA Montreal" -e USER=js89ds7 -e PASSWORD=8fd9s239G \
    qmcgaw/private-internet-access

    or use docker-compose.yml with:

    docker-compose up -d

    Note that you can change all the environment variables

Testing

Check the PIA IP address matches your expectations

docker run --rm --network=container:pia alpine:3.9 wget -qO- https://ipinfo.io

Environment variables

Environment variable Default Description
REGION CA Montreal One of the PIA regions
PROTOCOL udp tcp or udp
ENCRYPTION strong normal or strong
USER Your PIA username
PASSWORD Your PIA password
NONROOT no Run OpenVPN without root, yes or no
EXTRA_SUBNETS comma separated subnets allowed in the container firewall (i.e. 192.168.1.0/24,192.168.10.121,10.0.0.5/28)
BLOCK_MALICIOUS off on or off, blocks malicious hostnames and IPs
BLOCK_NSA off on or off, blocks NSA hostnames
UNBLOCK comma separated string (i.e. web.com,web2.ca) to unblock hostnames

Connect to it

There are various ways to achieve this, depending on your use case.

  • Connect other containers to PIA

    Add --network=container:pia when launching the container

  • Connect containers from another docker-compose.yml

    Add network_mode: "container:pia" to your docker-compose.yml

  • Connect containers in the same docker-compose.yml as PIA

    Add network_mode: "service:pia" to your docker-compose.yml (no need for depends_on)

  • Access ports of containers connected to PIA

    To access port 8000 of container xyz and 9000 of container abc connected to PIA, you will need a reverse proxy such as qmcgaw/caddy-scratch (you can build it for ARM, see its readme)

    1. Create the file Caddyfile

      touch Caddyfile
      chown 1000 Caddyfile
      # chown 1000 because caddy-scratch runs as user ID 1000 by default
      chmod 600 Caddyfile

      with this content:

      :8000 {
          proxy / xyz:8000
      }
      :9000 {
          proxy / abc:9000
      }

      You can of course make more complicated Caddyfile (such as proxying /xyz to xyz:8000 and /abc to abc:9000, just ask me!)

    2. Run Caddy with

      docker run -d -p 8000:8000/tcp -p 9000:9000/tcp \
      --link pia:xyz --link pia:abc \
      -v $(pwd)/Caddyfile:/Caddyfile:ro \
      qmcgaw/caddy-scratch

      WARNING: Make sure the Docker network in which Caddy runs is the same as the one of PIA. It can be the default bridge network.

    3. You can now access xyz:8000 at localhost:8000 and abc:9000 at localhost:9000

    For more containers, add more --link pia:xxx and modify the Caddyfile accordingly

    If you want to user a docker-compose.yml, you can use this example - make sure PIA is launched and connected first:

    version: '3'
    services:
      piaproxy:
        image: qmcgaw/caddy-scratch
        container_name: piaproxy
        ports:
          - 8000:8000/tcp
          - 9000:9000/tcp
        external_links:
          - pia:xyz
          - pia:abc
        volumes:
          - ./Caddyfile:/Caddyfile:ro
      abc:
        image: abc
        container_name: abc
        network_mode: "container:pia"
      xyz:
        image: xyz
        container_name: xyz
        network_mode: "container:pia"

  • Access ports of containers connected to PIA, all in the same docker-compose.yml

    To access port 8000 of container xyz and 9000 of container abc connected to PIA, you could use:

    version: '3'
    services:
      pia:
        image: qmcgaw/private-internet-access
        container_name: pia
        cap_add:
          - NET_ADMIN
        devices:
          - /dev/net/tun
        environment:
          - USER=js89ds7
          - PASSWORD=8fd9s239G
        ports:
          - 8000:8000/tcp
          - 9000:9000/tcp
      abc:
        image: abc
        container_name: abc
        network_mode: "service:pia"
      xyz:
        image: xyz
        container_name: xyz
        network_mode: "service:pia"

  • Access ports of containers connected to PIA, all in the same docker-compose.yml, using a reverse proxy

    To access port 8000 of container xyz and 9000 of container abc connected to PIA, you will need a reverse proxy such as qmcgaw/caddy-scratch (you can build it for ARM, see its readme)

    1. Create the file Caddyfile

      touch Caddyfile
      chown 1000 Caddyfile
      # chown 1000 because caddy-scratch runs as user ID 1000 by default
      chmod 600 Caddyfile

      with this content:

      :8000 {
          proxy / xyz:8000
      }
      :9000 {
          proxy / abc:9000
      }

      You can of course make more complicated Caddyfile (such as proxying /xyz to xyz:8000 and /abc to abc:9000, just ask me!)

    2. Use this example:

      version: '3'
      services:
        pia:
          image: qmcgaw/private-internet-access
          container_name: pia
          cap_add:
            - NET_ADMIN
          devices:
            - /dev/net/tun
          environment:
            - USER=js89ds7
            - PASSWORD=8fd9s239G
        piaproxy:
          image: qmcgaw/caddy-scratch
          container_name: piaproxy
          ports:
            - 8000:8000/tcp
            - 9000:9000/tcp
          external_links:
            - pia:xyz
            - pia:abc
          volumes:
            - ./Caddyfile:/Caddyfile:ro
        abc:
          image: abc
          container_name: abc
          network_mode: "service:pia"
        xyz:
          image: xyz
          container_name: xyz
          network_mode: "service:pia"

  • Connect to the PIA through an HTTP proxy (i.e. with Firefox)

    This is in progress, using Tiny Proxy, thanks for waiting !

For the paranoids

  • You can review the code which essential consists in the Dockerfile and entrypoint.sh

  • Build the images yourself:

    docker build -t qmcgaw/private-internet-access https://github.com/qdm12/private-internet-access-docker.git
  • The download and unziping of PIA openvpn files is done at build for the ones not able to download the zip files

  • Checksums for PIA openvpn zip files are not used as these files change often (but HTTPS is used)

  • Use -e ENCRYPTION=strong -e BLOCK_MALICIOUS=on

  • DNS Leaks tests might not work because of this (TLDR: DNS server is a local caching intermediary)

TODOs

  • Tiny proxy for LAN devices to use the container
  • Port forwarding

License

This repository is under an MIT license