Skip to content

Commit

Permalink
Reworked labels, readme and added License
Browse files Browse the repository at this point in the history
  • Loading branch information
qdm12 committed Oct 29, 2018
1 parent 4bcaec6 commit 08d1afc
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 67 deletions.
47 changes: 29 additions & 18 deletions Dockerfile
@@ -1,23 +1,32 @@
FROM alpine:3.8
LABEL maintainer="quentin.mcgaw@gmail.com" \
description="VPN client to private internet access servers using OpenVPN, IPtables firewall, DNS over TLS with Unbound and Alpine Linux" \
download="6.6MB" \
size="15.7MB" \
ram="13MB" \
cpu_usage="Low" \
github="https://github.com/qdm12/private-internet-access-docker"
ARG ALPINE_VERSION=3.8

FROM alpine:${ALPINE_VERSION}
ARG BUILD_DATE
ARG VCS_REF
LABEL org.label-schema.schema-version="1.0.0-rc1" \
maintainer="quentin.mcgaw@gmail.com" \
org.label-schema.build-date=$BUILD_DATE \
org.label-schema.vcs-ref=$VCS_REF \
org.label-schema.vcs-url="https://github.com/qdm12/private-internet-access-docker" \
org.label-schema.url="https://github.com/qdm12/private-internet-access-docker" \
org.label-schema.vcs-description="VPN client to tunnel to private internet access servers using OpenVPN, IPtables, DNS over TLS and Alpine Linux" \
org.label-schema.vcs-usage="https://github.com/qdm12/private-internet-access-docker/blob/master/README.md#setup" \
org.label-schema.docker.cmd="docker run -d -v ./auth.conf:/auth.conf:ro --cap-add=NET_ADMIN --device=/dev/net/tun qmcgaw/private-internet-access" \
org.label-schema.docker.cmd.devel="docker run -it --rm -v ./auth.conf:/auth.conf:ro --cap-add=NET_ADMIN --device=/dev/net/tun qmcgaw/private-internet-access" \
org.label-schema.docker.params="" \
org.label-schema.version="" \
image-size="17.1MB" \
ram-usage="13MB to 80MB" \
cpu-usage="Low"
ENV ENCRYPTION=strong \
PROTOCOL=tcp \
REGION="CA Montreal" \
BLOCK_MALICIOUS=off
HEALTHCHECK --interval=5m --timeout=15s --start-period=10s --retries=2 \
CMD if [[ "$(wget -qqO- 'https://duckduckgo.com/?q=what+is+my+ip' | grep -ow 'Your IP address is [0-9.]*[0-9]' | grep -ow '[0-9][0-9.]*')" == "$INITIAL_IP" ]]; then echo "IP address is the same as the non VPN IP address"; exit 1; fi
COPY --from=qmcgaw/dns-trustanchor /named.root /etc/unbound/root.hints
COPY --from=qmcgaw/dns-trustanchor /root.key /etc/unbound/root.key
RUN echo https://dl-3.alpinelinux.org/alpine/v3.8/main > /etc/apk/repositories && \
apk add -q --progress --no-cache --update openvpn wget ca-certificates iptables unbound && \
apk add -q --progress --no-cache --update --virtual=build-dependencies unzip && \
mkdir /openvpn-udp-normal /openvpn-udp-strong /openvpn-tcp-normal /openvpn-tcp-strong && \
RUN V_ALPINE="v$(cat /etc/alpine-release | grep -oE '[0-9]+\.[0-9]+')" && \
echo https://dl-3.alpinelinux.org/alpine/$V_ALPINE/main > /etc/apk/repositories && \
apk add -q --progress --no-cache --update openvpn wget ca-certificates iptables unbound unzip && \
wget -q https://www.privateinternetaccess.com/openvpn/openvpn.zip \
https://www.privateinternetaccess.com/openvpn/openvpn-strong.zip \
https://www.privateinternetaccess.com/openvpn/openvpn-tcp.zip \
Expand All @@ -26,13 +35,15 @@ RUN echo https://dl-3.alpinelinux.org/alpine/v3.8/main > /etc/apk/repositories &
unzip -q openvpn-strong.zip -d /openvpn-udp-strong && \
unzip -q openvpn-tcp.zip -d /openvpn-tcp-normal && \
unzip -q openvpn-strong-tcp.zip -d /openvpn-tcp-strong && \
apk del -q --progress --purge build-dependencies && \
apk del -q --progress --purge unzip && \
rm -rf /*.zip /var/cache/apk/* /etc/unbound/unbound.conf && \
chown unbound /etc/unbound/root.key && \
adduser -S nonrootuser
COPY unbound.conf /etc/unbound/unbound.conf
COPY --from=qmcgaw/dns-trustanchor /named.root /etc/unbound/root.hints
COPY --from=qmcgaw/dns-trustanchor /root.key /etc/unbound/root.key
COPY --from=qmcgaw/malicious-hostnames /malicious-hostnames.bz2 /etc/unbound/malicious-hostnames.bz2
COPY --from=qmcgaw/malicious-ips /malicious-ips.bz2 /etc/unbound/malicious-ips.bz2
COPY unbound.conf /etc/unbound/unbound.conf
COPY entrypoint.sh /entrypoint.sh
RUN chmod 700 /entrypoint.sh
RUN chown unbound /etc/unbound/root.key && \
chmod 700 /entrypoint.sh
ENTRYPOINT /entrypoint.sh
21 changes: 21 additions & 0 deletions LICENSE
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018 Quentin McGaw

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
99 changes: 50 additions & 49 deletions README.md
@@ -1,6 +1,6 @@
# Private Internet Access Client (OpenVPN+Iptables+DNS over TLS on Alpine Linux)

Docker VPN client to private internet access servers using [OpenVPN](https://openvpn.net/), Iptables and Unbound (Cloudflare DNS over TLS) on Alpine Linux.
*VPN client to tunnel to private internet access servers using OpenVPN, IPtables, DNS over TLS and Alpine Linux*

Optionally set the protocol (TCP, UDP) and the level of encryption using Docker environment variables.

Expand All @@ -19,31 +19,36 @@ A killswitch is implemented with the *iptables* firewall, only allowing traffic
[![Docker Stars](https://img.shields.io/docker/stars/qmcgaw/private-internet-access.svg)](https://hub.docker.com/r/qmcgaw/private-internet-access)
[![Docker Automated](https://img.shields.io/docker/automated/qmcgaw/private-internet-access.svg)](https://hub.docker.com/r/qmcgaw/private-internet-access)

[![?](https://images.microbadger.com/badges/image/qmcgaw/private-internet-access.svg)](https://microbadger.com/images/qmcgaw/private-internet-access)
[![?](https://images.microbadger.com/badges/version/qmcgaw/private-internet-access.svg)](https://microbadger.com/images/qmcgaw/private-internet-access)
[![Image size](https://images.microbadger.com/badges/image/qmcgaw/private-internet-access.svg)](https://microbadger.com/images/qmcgaw/private-internet-access)
[![Image version](https://images.microbadger.com/badges/version/qmcgaw/private-internet-access.svg)](https://microbadger.com/images/qmcgaw/private-internet-access)

| Download size | Image size | RAM usage | CPU usage |
| --- | --- | --- | --- |
| 6.6MB | 15.7MB | 14MB | Low |
| Image size | RAM usage | CPU usage |
| --- | --- | --- |
| 15.7MB | 14MB | Low |

## Features
It is based on:

- [Alpine 3.8](https://alpinelinux.org) for a tiny image
- [OpenVPN 2.4.6-r3](https://pkgs.alpinelinux.org/package/v3.8/main/x86_64/openvpn) to tunnel to PIA servers
- [IPtables 1.6.2-r0](https://pkgs.alpinelinux.org/package/v3.8/main/x86_64/iptables) enforces the container to communicate only through the VPN or with other containers in its virtual network (killswitch)
- [Unbound 1.7.3-r0](https://pkgs.alpinelinux.org/package/v3.8/main/x86_64/unbound) configured with Cloudflare's [1.1.1.1](https://1.1.1.1) DNS over TLS
- [Malicious hostnames list](https://github.com/qdm12/malicious-hostnames-docker) used with Unbound (see `BLOCK_MALICIOUS` environment variable)
- [Malicious IPs list](https://github.com/qdm12/malicious-ips-docker) used with Unbound (see `BLOCK_MALICIOUS`)

## Extra features

- Uses [OpenVPN 2.4.6-r3](https://pkgs.alpinelinux.org/package/v3.8/main/x86_64/openvpn) to connect to PIA servers
- The firewall [IPtables 1.6.2-r0](https://pkgs.alpinelinux.org/package/v3.8/main/x86_64/iptables) enforces the container to communicate only through the VPN or with other containers in its virtual network
- Your DNS queries are encrypted using [Unbound 1.7.3-r0](https://pkgs.alpinelinux.org/package/v3.8/main/x86_64/unbound) configure with Cloudflare's 1.1.1.1 DNS over TLS
- Malicious domain names resolution is blocked with [Unbound 1.7.3-r0](https://pkgs.alpinelinux.org/package/v3.8/main/x86_64/unbound)
- Lightweight, based on [Alpine 3.8](https://alpinelinux.org)
- Restarts OpenVPN on failure using another IP address corresponding to the PIA server domain name (usually 10 IPs per subdomain name)
- Regular Docker healthchecks using wget on duckduckgo.com
- Connect other containers to it
- Restarts OpenVPN on failure using another IP address corresponding to the PIA server domain name (usually 10 IPs per subdomain name)
- Regular Docker healthchecks using [duckduckgo.com](https://duckduckgo.com) to obtain your current public IP address and compare it with your initial non-VPN IP address
- Openvpn and Unbound do not run as root

## Requirements

- A Private Internet Access **username** and **password** - [Sign up](https://www.privateinternetaccess.com/pages/buy-vpn/)
- [Docker](https://docs.docker.com/install/) installed on the host
- If you use an advanced firewall:
- If you use a firewall on the host:
- Allow outgoing TCP port 853 for Cloudflare DNS over TLS initial resolution of PIA server domain name.
- Allow outgoing TCP port 443 for querying duckduckgo to obtain the initial IP address for the healthcheck.
- Allow outgoing TCP port 443 for querying duckduckgo.com to obtain the initial IP address for the healthcheck.
- Allow outgoing TCP port 501 for TCP strong encryption
- Allow outgoing TCP port 502 for TCP normal encryption
- Allow outgoing UDP port 1197 for UDP strong encryption
Expand All @@ -57,78 +62,67 @@ A killswitch is implemented with the *iptables* firewall, only allowing traffic
insmod /lib/modules/tun.ko
```


Or

```bash
sudo modprobe tun
```


1. Create a network to be used by this container and other containers connecting to it with:

```bash
docker network create pianet
```

1. Create a file *auth.conf* in `/yourhostpath` (for example), with:

1. Create a file *auth.conf* in `./`, with:
- On the first line: your PIA username (i.e. `js89ds7`)
- On the second line: your PIA password (i.e. `8fd9s239G`)

### Option 1: Using Docker only

1. Run the container with (at least change `/yourhostpath` to your actual path):
1. Launch the container with:

```bash
docker run -d --name=pia \
docker run -d --name=pia -v ./auth.conf:/auth.conf:ro \
--cap-add=NET_ADMIN --device=/dev/net/tun --network=pianet \
-v /yourhostpath/auth.conf:/auth.conf:ro \
-e REGION="CA Montreal" -e PROTOCOL=udp -e ENCRYPTION=normal \
-e REGION="CA Montreal" -e PROTOCOL=udp -e ENCRYPTION=strong \
qmcgaw/private-internet-access
```

Note that you can change `REGION`, `PROTOCOL` and `ENCRYPTION`, see the [Environment variables section](#environment-variables) for more.
1. Wait about 5 seconds for it to connect to the PIA server. You can check with:

```bash
docker logs pia
```

1. Follow the [**Testing section**](#testing)

### Option 2: Using Docker Compose
or use [docker-compose.yml](https://github.com/qdm12/private-internet-access-docker/blob/master/docker-compose.yml) with:

1. Download [**docker-compose.yml**](https://github.com/qdm12/private-internet-access-docker/blob/master/docker-compose.yml)
1. Edit it and change at least `yourpath`
1. Run the container as a daemon in the background with:

```bash
docker-compose up -d
```

Note that you can change `REGION`, `PROTOCOL` and `ENCRYPTION`, see the [Environment variables section](#environment-variables) for more.

Note that you can change `REGION`, `PROTOCOL` and `ENCRYPTION`, see the [Environment variables section](#environment-variables)

1. Wait about 5 seconds for it to connect to the PIA server. You can check with:

```bash
docker logs -f pia
```


1. Follow the [**Testing section**](#testing)

## Testing

1. Note that you can simply use the HEALTCHECK provided. The container will stop by itself if the VPN IP is the same as your initial public IP address.

Otherwise you can follow these instructions:
You can simply use the Docker healthcheck. The container will mark itself as **unhealthy** if the public IP address is the same as your initial public IP address. Otherwise you can follow these instructions:

1. Check your host IP address with:

```bash
curl -s ifconfig.co
wget -qO- https://ipinfo.io/ip
```

1. Run the **curl** Docker container using your *pia* container with:

```bash
docker run --rm --network=container:pia byrnedo/alpine-curl -s ifconfig.co
docker run --rm --network=container:pia alpine:3.8 wget -qO- https://ipinfo.io/ip
```

If the displayed IP address appears and is different that your host IP address, the PIA client works !
Expand All @@ -137,11 +131,12 @@ Otherwise you can follow these instructions:

| Environment variable | Default | Description |
| --- | --- | --- |
| `REGION` | `Switzerland` | Any one of the [regions supported by private internet access](https://www.privateinternetaccess.com/pages/network/) |
| `PROTOCOL` | `tcp` | `tcp` or `udp` |
| `REGION` | `CA Montreal` | Any one of the [regions supported by private internet access](https://www.privateinternetaccess.com/pages/network/) |
| `PROTOCOL` | `udp` | `tcp` or `udp` |
| `ENCRYPTION` | `strong` | `normal` or `strong` |
| `BLOCK_MALICIOUS` | `off` | `on` or `off` |

If you know what you're doing, you can change the container name (`pia`), the hostname (`piaclient`) and the network name (`pianet`) as well.
If you know what you're doing, you can change the container name (`pia`) and the network name (`pianet`)

## Connect other containers to it

Expand Down Expand Up @@ -220,12 +215,18 @@ For more containers, add more `--link pia:xxx` and modify *nginx.conf* according
## EXTRA: For the paranoids

- You might want to build the Docker image yourself
- The download and unziping is done at build for the ones not able to download the zip files with their ISPs.
- The download and unziping is done at build for the ones not able to download the zip files through their ISP
- Checksums for PIA openvpn zip files are not used as these files change often
- You should use strong encryption for the environment variable `ENCRYPTION`
- Let me know if you have any extra idea :) !

### TODOs
## TODOs

- [ ] Iptables should change after initial ip address is obtained
- More checks for environment variables provided
- Add checks when launching PIA $?
- VPN server for other devices to go through the tunnel

## License

- Block malicious websites with Unbound
- Add checks when launching PIA $?
This repository is under an [MIT license](https://github.com/qdm12/REPONAME_GITHUB/master/license)
9 changes: 9 additions & 0 deletions hooks/build
@@ -0,0 +1,9 @@
#!/bin/bash

# see http://label-schema.org/rc1
# https://docs.docker.com/docker-cloud/builds/advanced/#override-build-test-or-push-commands
# https://docs.docker.com/docker-cloud/builds/advanced/#custom-build-phase-hooks

docker build --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
--build-arg VCS_REF=`git rev-parse --short HEAD` \
-t $IMAGE_NAME .

0 comments on commit 08d1afc

Please sign in to comment.