From 08d1afccfe21824acd266dae3564a639e169501a Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Mon, 29 Oct 2018 16:32:11 +0100 Subject: [PATCH] Reworked labels, readme and added License --- Dockerfile | 47 +++++++++++++++---------- LICENSE | 21 ++++++++++++ README.md | 99 +++++++++++++++++++++++++++-------------------------- hooks/build | 9 +++++ 4 files changed, 109 insertions(+), 67 deletions(-) create mode 100644 LICENSE create mode 100644 hooks/build diff --git a/Dockerfile b/Dockerfile index a521875d..9858ad7e 100644 --- a/Dockerfile +++ b/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 \ @@ -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 diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..dec71347 --- /dev/null +++ b/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. \ No newline at end of file diff --git a/README.md b/README.md index 3522c7f4..82e67709 100644 --- a/README.md +++ b/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. @@ -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 @@ -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 - ``` + or use [docker-compose.yml](https://github.com/qdm12/private-internet-access-docker/blob/master/docker-compose.yml) with: -1. Follow the [**Testing section**](#testing) - -### Option 2: Using Docker Compose - -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 ! @@ -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 @@ -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 -- Block malicious websites with Unbound -- Add checks when launching PIA $? \ No newline at end of file +- [ ] 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 + +This repository is under an [MIT license](https://github.com/qdm12/REPONAME_GITHUB/master/license) diff --git a/hooks/build b/hooks/build new file mode 100644 index 00000000..7af3d9ce --- /dev/null +++ b/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 .