diff --git a/Dockerfile b/Dockerfile index 053cfe07..254e0f19 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,11 +34,17 @@ ENV USER= \ TINYPROXY_LOG=Critical \ TINYPROXY_PORT=8888 \ TINYPROXY_USER= \ - TINYPROXY_PASSWORD= + TINYPROXY_PASSWORD= \ + SHADOWSOCKS=on \ + SHADOWSOCKS_LOG=on \ + SHADOWSOCKS_PORT=8388 \ + SHADOWSOCKS_PASSWORD= ENTRYPOINT /entrypoint.sh -EXPOSE 8888 +EXPOSE 8888/tcp 8388/tcp 8388/udp HEALTHCHECK --interval=3m --timeout=3s --start-period=20s --retries=1 CMD /healthcheck.sh RUN apk add -q --progress --no-cache --update openvpn wget ca-certificates iptables unbound unzip tinyproxy jq && \ + echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \ + apk add -q --progress --no-cache --update shadowsocks-libev && \ 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 \ @@ -65,9 +71,10 @@ RUN apk add -q --progress --no-cache --update openvpn wget ca-certificates iptab rm -f /tmp/* COPY unbound.conf /etc/unbound/unbound.conf COPY tinyproxy.conf /etc/tinyproxy/tinyproxy.conf +COPY shadowsocks.json /etc/shadowsocks.json COPY entrypoint.sh healthcheck.sh portforward.sh / RUN chown nonrootuser -R /etc/unbound /etc/tinyproxy && \ chmod 700 /etc/unbound /etc/tinyproxy && \ - chmod 600 /etc/unbound/unbound.conf /etc/tinyproxy/tinyproxy.conf && \ + chmod 600 /etc/unbound/unbound.conf /etc/tinyproxy/tinyproxy.conf /etc/shadowsocks.json && \ chmod 500 /entrypoint.sh /healthcheck.sh /portforward.sh && \ chmod 400 /etc/unbound/root.hints /etc/unbound/root.key /etc/unbound/*.bz2 diff --git a/README.md b/README.md index 3e151acf..30b5a696 100644 --- a/README.md +++ b/README.md @@ -53,12 +53,14 @@ - Connect other containers to it, [see this](https://github.com/qdm12/private-internet-access-docker#connect-to-it) - **ARM** compatible - Port forwarding -- HTTP proxy for LAN devices - The *iptables* firewall allows traffic only with needed PIA servers (IP addresses, port, protocol) combinations - OpenVPN reconnects automatically on failure - Docker healthcheck pings the DNS 1.1.1.1 to verify the connection is up - Unbound DNS runs *without root* - OpenVPN can run *without root* but this disallows OpenVPN reconnecting, it can be set with `NONROOT=yes` +- Connect your LAN devices + - HTTP Web proxy *tinyproxy* + - SOCKS5 proxy *shadowsocks* ## Setup @@ -72,6 +74,7 @@ - For TCP strong encryption, allow outbound TCP 501 - For TCP normal encryption, allow outbound TCP 502 - For the built-in web HTTP proxy, allow inbound TCP 8888 + - For the built-in SOCKS5 proxy, allow inbound TCP 8388 and UDP 8388 - Docker API 1.25 to support `init` - If you use Docker Compose, docker-compose >= 1.22.0, to support `init: true` @@ -130,6 +133,7 @@ Note that you can: - Change the many [environment variables](#environment-variables) available - Use `-p 8888:8888/tcp` to access the HTTP web proxy (and put your LAN in `EXTRA_SUBNETS` environment variable) + - Use `-p 8388:8388/tcp -p 8388:8388/udp` to access the SOCKS5 proxy (and put your LAN in `EXTRA_SUBNETS` environment variable) - Pass additional arguments to *openvpn* using Docker's command function (commands after the image name) ## Testing @@ -162,6 +166,10 @@ docker run --rm --network=container:pia alpine:3.10 wget -qO- https://ipinfo.io | `TINYPROXY_PORT` | `8888` | `1024` to `65535` internal port for HTTP proxy | | `TINYPROXY_USER` | | Username to use to connect to the HTTP proxy | | `TINYPROXY_PASSWORD` | | Passsword to use to connect to the HTTP proxy | +| `SHADOWSOCKS` | `on` | `on` or `off`, to enable the internal SOCKS5 proxy Shadowsocks | +| `SHADOWSOCKS_LOG` | `on` | `on` or `off` to enable logging for Shadowsocks | +| `SHADOWSOCKS_PORT` | `8388` | `1024` to `65535` internal port for SOCKS5 proxy | +| `SHADOWSOCKS_PASSWORD` | | Passsword to use to connect to the SOCKS5 proxy | ## Connect to it @@ -182,15 +190,25 @@ There are various ways to achieve this, depending on your use case. Add `network_mode: "container:pia"` to your *docker-compose.yml*, provided PIA is already running
--
+-
1. Setup a HTTP proxy client, such as [SwitchyOmega for Chrome](https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif?hl=en)
1. Ensure the PIA container is launched with:
- - port 8888 published `-p 8888:8888/tcp`
- - your LAN subnet, i.e. 192.168.1.0/24, set as `-e EXTRA_SUBNETS=192.168.1.0/24`
- 1. With your HTTP proxy client, connect to the Docker host (i.e. `192.168.1.10`) on port `8888`. You might need to enter your credentials if you set them with the environment variables `PROXY_USER` and `PROXY_PASSWORD`.
+ - port `8888` published `-p 8888:8888/tcp`
+ - your LAN subnet, i.e. `192.168.1.0/24`, set as `-e EXTRA_SUBNETS=192.168.1.0/24`
+ 1. With your HTTP proxy client, connect to the Docker host (i.e. `192.168.1.10`) on port `8888`. You need to enter your credentials if you set them with `TINYPROXY_USER` and `TINYPROXY_PASSWORD`.
+ 1. If you set `PROXY_LOG_LEVEL` to `Info`, more information will be logged in the Docker logs, merged with the OpenVPN logs.
+ `TINYPROXY_LOG` defaults to `Critical` to avoid logging everything, for privacy purposes.
+
+
+
+ 1. Setup a SOCKS5 proxy client, there is a list of [ShadowSocks clients for **all platforms**](https://shadowsocks.org/en/download/clients.html)
+ 1. Ensure the PIA container is launched with:
+ - port `8388` published `-p 8388:8388/tcp -p 8388:8388/udp`
+ - your LAN subnet, i.e. `192.168.1.0/24`, set as `-e EXTRA_SUBNETS=192.168.1.0/24`
+ 1. With your SOCKS5 proxy client, connect to the Docker host (i.e. `192.168.1.10`) on port `8388`, using the password you have set with `SHADOWSOCKS_PASSWORD`.
1. If you set `PROXY_LOG_LEVEL` to `Info`, more information will be logged in the Docker logs, merged with the OpenVPN logs.
- `PROXY_LOG_LEVEL` defaults to `Critical` to avoid logging everything, for privacy purposes.
@@ -264,7 +282,10 @@ Note that not all regions support port forwarding.
## TODOs
-- Mix logs from unbound, tinyproxy and openvpn in Docker logs
+- Shadowsocks
+ - Test DNS queries
+ - Get logs from file and merge with docker stdout
+- Mix Logs of Unbound
- Maybe use `--inactive 3600 --ping 10 --ping-exit 60` as default behavior
- Try without tun
diff --git a/docker-compose.yml b/docker-compose.yml
index 811a4f87..ef176fae 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '3.7'
+version: "3.7"
services:
pia:
build: https://github.com/qdm12/private-internet-access-docker.git
@@ -12,7 +12,9 @@ services:
init: true
ports:
- 8888:8888/tcp
- # command:
+ - 8388:8388/tcp
+ - 8388:8388/udp
+ # command:
environment:
- USER=js89ds7
- PASSWORD=8fd9s239G
@@ -26,9 +28,11 @@ services:
- UNBLOCK=
- FIREWALL=on
- EXTRA_SUBNETS=
- - PROXY=on
- - PROXY_LOG_LEVEL=Critical
- - PROXY_USER=
- - PROXY_PASSWORD=
+ - TINYPROXY=on
+ - TINYPROXY_LOG=Critical
+ - TINYPROXY_USER=
+ - TINYPROXY_PASSWORD=
+ - SHADOWSOCKS=on
+ - SHADOWSOCKS_LOG=on
+ - SHADOWSOCKS_PASSWORD=
restart: always
-
\ No newline at end of file
diff --git a/entrypoint.sh b/entrypoint.sh
index f86a576f..e14073e5 100644
--- a/entrypoint.sh
+++ b/entrypoint.sh
@@ -50,6 +50,7 @@ printf "OpenVPN version: $(openvpn --version | head -n 1 | grep -oE "OpenVPN [0-
printf "Unbound version: $(unbound -h | grep "Version" | cut -d" " -f2)\n"
printf "Iptables version: $(iptables --version | cut -d" " -f2)\n"
printf "TinyProxy version: $(tinyproxy -v | cut -d" " -f2)\n"
+printf "ShadowSocks version: $(ss-server --help | head -n 2 | tail -n 1 | cut -d" " -f 2)\n"
############################################
# BACKWARD COMPATIBILITY PARAMETERS
@@ -127,6 +128,25 @@ elif [ -z "$TINYPROXY_USER" ] && [ ! -z "$TINYPROXY_PASSWORD" ]; then
printf "TINYPROXY_USER is not set but TINYPROXY_PASSWORD is set\n"
exit 1
fi
+exitIfNotIn SHADOWSOCKS "on,off"
+exitIfNotIn SHADOWSOCKS_LOG "on,off"
+if [ -z $SHADOWSOCKS_PORT ]; then
+ SHADOWSOCKS_PORT=8388
+fi
+if [ `echo $SHADOWSOCKS_PORT | grep -E "^[0-9]+$"` != $SHADOWSOCKS_PORT ]; then
+ printf "SHADOWSOCKS_PORT is not a valid number\n"
+ exit 1
+elif [ $SHADOWSOCKS_PORT -lt 1024 ]; then
+ printf "SHADOWSOCKS_PORT cannot be a privileged port under port 1024\n"
+ exit 1
+elif [ $SHADOWSOCKS_PORT -gt 65535 ]; then
+ printf "SHADOWSOCKS_PORT cannot be a port higher than the maximum port 65535\n"
+ exit 1
+fi
+if [ -z $SHADOWSOCKS_PASSWORD ]; then
+ printf "SHADOWSOCKS_PASSWORD is not set\n"
+ exit 1
+fi
############################################
# SHOW PARAMETERS
@@ -156,6 +176,7 @@ if [ "$TINYPROXY" == "on" ]; then
printf " * Tinyproxy has authentication: $tinyproxy_auth\n"
unset -v tinyproxy_auth
fi
+printf " * ShadowSocks SOCKS5 proxy: $SHADOWSOCKS\n"
printf "PIA parameters:\n"
printf " * Remote port forwarding: $PORT_FORWARDING\n"
[ "$PORT_FORWARDING" == "on" ] && printf " * Remote port forwarding status file: $PORT_FORWARDING_STATUS_FILE\n"
@@ -421,6 +442,33 @@ if [ "$TINYPROXY" == "on" ]; then
tinyproxy -d &
fi
+############################################
+# SHADOWSOCKS
+############################################
+if [ "$SHADOWSOCKS" == "on" ]; then
+ ARGS="-c /etc/shadowsocks.json"
+ # add -d 127.0.0.1 for DNS?
+ if [ "$SHADOWSOCKS_LOG" == " on" ]; then
+ printf "[INFO] Setting ShadowSocks logging..."
+ ARGS="$ARGS -v"
+ printf "DONE\n"
+ fi
+ printf "[INFO] Setting ShadowSocks port to $SHADOWSOCKS_PORT..."
+ jq ".port_password = {\"$SHADOWSOCKS_PORT\":\"\"}" /etc/shadowsocks.json > /tmp/shadowsocks.json && mv /tmp/shadowsocks.json /etc/shadowsocks.json
+ exitOnError $?
+ printf "DONE\n"
+ printf "[INFO] Setting ShadowSocks password..."
+ jq ".port_password[\"$SHADOWSOCKS_PORT\"] = \"$SHADOWSOCKS_PASSWORD\"" /etc/shadowsocks.json > /tmp/shadowsocks.json && mv /tmp/shadowsocks.json /etc/shadowsocks.json
+ exitOnError $?
+ printf "DONE\n"
+ ARGS="$ARGS -s `jq --raw-output '.server' /etc/shadowsocks.json`"
+ unset -v SERVER
+ ARGS="$ARGS -p $SHADOWSOCKS_PORT"
+ ARGS="$ARGS -k $SHADOWSOCKS_PASSWORD"
+ ss-server $ARGS &
+ unset -v ARGS
+fi
+
############################################
# READ FORWARDED PORT
############################################
diff --git a/shadowsocks.json b/shadowsocks.json
new file mode 100644
index 00000000..7293bf8d
--- /dev/null
+++ b/shadowsocks.json
@@ -0,0 +1,14 @@
+{
+ "server": "0.0.0.0",
+ "user": "nonrootuser",
+ "method": "chacha20-ietf-poly1305",
+ "timeout": 30,
+ "fast_open": false,
+ "mode": "tcp_and_udp",
+ "port_password": {
+ "8388": ""
+ },
+ "workers": 2,
+ "interface": "tun",
+ "nameserver": "127.0.0.1"
+}
\ No newline at end of file
Connect LAN devices through the built-in HTTP proxy *Tinyproxy* (i.e. with Chrome, Kodi, etc.)
Connect LAN devices through the built-in SOCKS5 proxy *Shadowsocks* (per app, system wide, etc.)
Access ports of containers connected to PIA