Skip to content
This repository was archived by the owner on Mar 16, 2024. It is now read-only.

Commit ee14898

Browse files
committed
Overhaul
1 parent ea0b4dd commit ee14898

18 files changed

+372
-425
lines changed

.dockerignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
*
2-
!data/
2+
!data/

.github/workflows/publish.yml

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Publish
33
on:
44
push:
55
tags:
6-
- 'v[0-9]+.[0-9]+.[0-9]+'
6+
- 'v[0-9]+.[0-9]+.[0-9]+'
77

88
env:
99
IMAGE_NAME: openvpn-client
@@ -13,47 +13,42 @@ jobs:
1313
runs-on: ubuntu-latest
1414

1515
steps:
16-
- name: Check out repository
17-
uses: actions/checkout@v2
18-
19-
- name: Set up QEMU
20-
uses: docker/setup-qemu-action@v1
21-
22-
- name: Set up Docker Buildx
23-
uses: docker/setup-buildx-action@v1
24-
25-
- name: Log in to registry
26-
uses: docker/login-action@v1
27-
with:
28-
registry: ghcr.io
29-
username: ${{ github.repository_owner }}
30-
password: ${{ secrets.GITHUB_TOKEN }}
31-
32-
- name: Create tags
33-
id: tags
34-
uses: docker/metadata-action@v3
35-
with:
36-
images: ghcr.io/wfg/openvpn-client
37-
tags: |
38-
type=semver,pattern={{version}}
39-
type=semver,pattern={{major}}.{{minor}}
40-
type=semver,pattern={{major}}
41-
42-
- name: Create build args
43-
id: build-args
44-
run: |
45-
ref=${{ github.ref }}
46-
vpatch=${ref##refs/*/}
47-
patch=${vpatch#v}
48-
echo "::set-output name=date::$(date --utc --iso-8601=seconds)"
49-
echo "::set-output name=version::$patch"
50-
51-
- name: Build and push
52-
uses: docker/build-push-action@v2
53-
with:
54-
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
55-
tags: ${{ steps.tags.outputs.tags }}
56-
build-args: |
57-
BUILD_DATE=${{ steps.build-args.outputs.date }}
58-
IMAGE_VERSION=${{ steps.build-args.outputs.version }}
59-
push: true
16+
- uses: actions/checkout@v3
17+
18+
- run: cat build-variables >> $GITHUB_ENV
19+
20+
- uses: docker/setup-qemu-action@v2
21+
22+
- uses: docker/setup-buildx-action@v2
23+
24+
- uses: docker/login-action@v2
25+
with:
26+
registry: ghcr.io
27+
username: ${{ github.repository_owner }}
28+
password: ${{ secrets.GITHUB_TOKEN }}
29+
30+
- id: tags
31+
uses: docker/metadata-action@v4
32+
with:
33+
images: ${{ env.IMAGE_NAME }}
34+
tags: |
35+
type=semver,pattern={{version}}
36+
type=semver,pattern={{major}}.{{minor}}
37+
type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }}
38+
39+
- id: build-args
40+
run: |
41+
ref=${{ github.ref }}
42+
vpatch=${ref##refs/*/}
43+
patch=${vpatch#v}
44+
echo "::set-output name=date::$(date --utc --iso-8601=seconds)"
45+
echo "::set-output name=version::$patch"
46+
47+
- uses: docker/build-push-action@v3
48+
with:
49+
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
50+
tags: ${{ steps.tags.outputs.tags }}
51+
build-args: |
52+
BUILD_DATE=${{ steps.build-args.outputs.date }}
53+
IMAGE_VERSION=${{ steps.build-args.outputs.version }}
54+
push: true

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
local/
1+
.local/

.pre-commit-config.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
repos:
2-
- repo: https://github.com/norwoodj/helm-docs
3-
rev: v1.6.0
4-
hooks:
5-
- id: helm-docs
6-
args:
7-
- --chart-search-root=chart
8-
- --template-files=./_templates.gotmpl
9-
- --template-files=README.md.gotmpl
2+
- repo: https://github.com/norwoodj/helm-docs
3+
rev: v1.6.0
4+
hooks:
5+
- id: helm-docs
6+
args:
7+
- --chart-search-root=chart
8+
- --template-files=./_templates.gotmpl
9+
- --template-files=README.md.gotmpl

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## Version 3.0.0 - 2022-06-14
4+
### Changed
5+
- Refactored scripts
6+
- Renamed a lot of variables ([PLEASE see docs](README.md#environment-variables))
7+
- Updated logic used to select the OpenVPN configuration file
8+
- Switched to `nftables`
9+
- Updated to Alpine 3.16
10+
- Fixed outdated proxy configuration files
11+
312
## Version 2.1.0 - 2022-03-06
413
### Added
514
- `VPN_CONFIG_PATTERN` environment variable.

Dockerfile

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
1-
FROM alpine:3.15
2-
3-
ARG IMAGE_VERSION
4-
ARG BUILD_DATE
5-
6-
LABEL org.opencontainers.image.created="$BUILD_DATE"
7-
LABEL org.opencontainers.image.source="github.com/wfg/docker-openvpn-client"
8-
LABEL org.opencontainers.image.version="$IMAGE_VERSION"
9-
10-
ENV KILL_SWITCH=on \
11-
VPN_LOG_LEVEL=3 \
12-
HTTP_PROXY=off \
13-
SOCKS_PROXY=off
1+
FROM alpine:3.16
142

153
RUN apk add --no-cache \
164
bash \
175
bind-tools \
186
dante-server \
7+
nftables \
198
openvpn \
209
tinyproxy
2110

22-
RUN mkdir -p /data/vpn
11+
COPY data/ /data/
2312

24-
COPY data/ /data
13+
ENV KILL_SWITCH=on
14+
ENV USE_VPN_DNS=on
15+
ENV VPN_LOG_LEVEL=3
16+
17+
ARG BUILD_DATE
18+
ARG IMAGE_VERSION
19+
20+
LABEL build-date=$BUILD_DATE
21+
LABEL image-version=$IMAGE_VERSION
2522

2623
HEALTHCHECK CMD ping -c 3 1.1.1.1 || exit 1
2724

28-
ENTRYPOINT ["/data/scripts/entry.sh"]
25+
WORKDIR /data
26+
27+
ENTRYPOINT [ "scripts/entry.sh" ]

README.md

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# OpenVPN Client for Docker
22
## What is this and what does it do?
33
[`ghcr.io/wfg/openvpn-client`](https://github.com/users/wfg/packages/container/package/openvpn-client) is a containerized OpenVPN client.
4-
It has a kill switch built with `iptables` that kills Internet connectivity to the container if the VPN tunnel goes down for any reason.
4+
It has a kill switch built with `nftables` that kills Internet connectivity to the container if the VPN tunnel goes down for any reason.
55
It also includes an HTTP proxy server ([Tinyproxy](https://tinyproxy.github.io/)) and a SOCKS proxy server ([Dante](https://www.inet.no/dante/index.html)).
66
This allows hosts and non-containerized applications to use the VPN without having to run VPN clients on those hosts.
77

@@ -14,10 +14,6 @@ If you find something that doesn't work or have an idea for a new feature, issue
1414
Having a containerized VPN client lets you use container networking to easily choose which applications you want using the VPN instead of having to set up split tunnelling.
1515
It also keeps you from having to install an OpenVPN client on the underlying host.
1616

17-
The idea for this image came from a similar project by [qdm12](https://github.com/qdm12) that has since evolved into something bigger and more complex than I wanted to use.
18-
I decided to dissect it and take it in my own direction.
19-
I plan to keep everything here well-documented so this is not only a learning experience for me, but also anyone else that uses it.
20-
2117
## How do I use it?
2218
### Getting the image
2319
You can either pull it from GitHub Container Registry or build it yourself.
@@ -62,22 +58,28 @@ services:
6258
restart: unless-stopped
6359
```
6460
65-
#### Environment variables (alphabetical)
61+
#### Environment variables
6662
| Variable | Default (blank is unset) | Description |
6763
| --- | --- | --- |
68-
| `HTTP_PROXY` | `off` | The on/off status of Tinyproxy, the built-in HTTP proxy server. To enable, set to `on`. Any other value (including unset) will cause the proxy server to not start. It listens on port 8080. |
69-
| `KEEP_DNS_UNCHANGED` | `off` | If `off`, the VPN server you connect to might override the DNS server used by the container. If `on`, the container will always use the DNS settings it had before connecting to the server. Usually, containers use the Docker internal DNS server by default. It allows to resolve IP addreses from container names, service names and Docker-specific names such as `host.docker.internal`. If DNS server is overriden, you won't be able to resolve such names. |
70-
| `KILL_SWITCH` | `on` | The on/off status of the network kill switch. |
71-
| `LISTEN_ON` | | Address the proxies will be listening on. Set to `0.0.0.0` to listen on all IP addresses. |
72-
| `PROXY_PASSWORD` | | Credentials for accessing the proxies. If `PROXY_PASSWORD` is specified, you must also specify `PROXY_USERNAME`. |
73-
| `PROXY_PASSWORD_SECRET` | | Docker secrets that contain the credentials for accessing the proxies. If `PROXY_PASSWORD_SECRET` is specified, you must also specify `PROXY_USERNAME_SECRET`. |
74-
| `PROXY_USERNAME` | | Credentials for accessing the proxies. If `PROXY_USERNAME` is specified, you must also specify `PROXY_PASSWORD`. |
75-
| `PROXY_USERNAME_SECRET` | | Docker secrets that contain the credentials for accessing the proxies. If `PROXY_USERNAME_SECRET` is specified, you must also specify `PROXY_PASSWORD_SECRET`. |
76-
| `SOCKS_PROXY` | `off` | The on/off status of Dante, the built-in SOCKS proxy server. To enable, set to `on`. Any other value (including unset) will cause the proxy server to not start. It listens on port 1080. |
77-
| `SUBNETS` | | A list of one or more comma-separated subnets (e.g. `192.168.0.0/24,192.168.1.0/24`) to allow outside of the VPN tunnel. |
64+
| `USE_VPN_DNS` | `on` | Whether or not to use the DNS servers pushed from the VPN server. It's best to leave this enabled unless you have a good reason to disable it. |
65+
| `VPN_CONFIG_FILE` | | The OpenVPN configuration file to use. If unset, the `VPN_CONFIG_PATTERN` is used. |
66+
| `VPN_CONFIG_PATTERN` | | The search pattern to use when looking for an OpenVPN configuration file. If unset, the search will include `*.conf` and `*.ovpn`. |
7867
| `VPN_AUTH_SECRET` | | Docker secret that contain the credentials for accessing the VPN. |
79-
| `VPN_CONFIG_FILE` | | The OpenVPN config file to use. If this is unset, the first file with the extension .conf will be used. |
80-
| `VPN_LOG_LEVEL` | `3` | OpenVPN verbosity (`1`-`11`) |
68+
| `VPN_LOG_LEVEL` | `3` | OpenVPN logging verbosity (`1`-`11`) |
69+
| `SUBNETS` | | A list of one or more comma-separated subnets (e.g. `192.168.0.0/24,192.168.1.0/24`) to allow outside of the VPN tunnel. |
70+
| `KILL_SWITCH` | `on` | Whether or not to enable the network kill switch. |
71+
| `HTTP_PROXY` | | Whether or not to enable the built-in HTTP proxy server. To enable, set to any "truthy" value (see below the table). Any other value (including unset) will cause the proxy server to not run. It listens on port 8080. |
72+
| `HTTP_PROXY_USERNAME` | | Credentials for accessing the HTTP proxy. If `HTTP_PROXY_USERNAME` is specified, you should also specify `HTTP_PROXY_PASSWORD`. |
73+
| `HTTP_PROXY_PASSWORD` | | Credentials for accessing the HTTP proxy. If `HTTP_PROXY_PASSWORD` is specified, you should also specify `HTTP_PROXY_USERNAME`. |
74+
| `HTTP_PROXY_USERNAME_SECRET` | | Docker secrets that contain the credentials for accessing the HTTP proxy. If `HTTP_PROXY_USERNAME_SECRET` is specified, you should also specify `HTTP_PROXY_PASSWORD_SECRET`. |
75+
| `HTTP_PROXY_PASSWORD_SECRET` | | Docker secrets that contain the credentials for accessing the HTTP proxy. If `HTTP_PROXY_PASSWORD_SECRET` is specified, you should also specify `HTTP_PROXY_USERNAME_SECRET`. |
76+
| `SOCKS_PROXY` | | Whether or not to enable the built-in SOCKS proxy server. To enable, set to any "truthy" value (see below the table). Any other value (including unset) will cause the proxy server to not run. It listens on port 1080. |
77+
| `SOCKS_LISTEN_ON` | | Address the proxies will be listening on. Set to `0.0.0.0` to listen on all IP addresses. |
78+
| `SOCKS_PROXY_USERNAME` | | Credentials for accessing the proxies. If `SOCKS_PROXY_USERNAME` is specified, you should also specify `SOCKS_PROXY_PASSWORD`. |
79+
| `SOCKS_PROXY_PASSWORD` | | Credentials for accessing the proxies. If `SOCKS_PROXY_PASSWORD` is specified, you should also specify `SOCKS_PROXY_USERNAME`. |
80+
| `SOCKS_PROXY_USERNAME_SECRET` | | Docker secrets that contain the credentials for accessing the proxies. If `SOCKS_PROXY_USERNAME_SECRET` is specified, you should also specify `SOCKS_PROXY_PASSWORD_SECRET`. |
81+
| `SOCKS_PROXY_PASSWORD_SECRET` | | Docker secrets that contain the credentials for accessing the proxies. If `SOCKS_PROXY_PASSWORD_SECRET` is specified, you should also specify `SOCKS_PROXY_USERNAME_SECRET`. |
82+
"Truthy" values are the following: `true`, `t`, `yes`, `y`, `1`, `on`, `enable`, or `enabled`.
8183

8284
##### Environment variable considerations
8385
###### `HTTP_PROXY` and `SOCKS_PROXY`
@@ -90,25 +92,10 @@ ports:
9092
- <host_port>:1080
9193
```
9294

93-
##### `PROXY_USERNAME_SECRET`, `PROXY_PASSWORD_SECRET`, and `VPN_AUTH_SECRET`
95+
##### `*_PROXY_USERNAME_SECRET`, `*_PROXY_PASSWORD_SECRET`, and `VPN_AUTH_SECRET`
9496
Compose has support for [Docker secrets](https://docs.docker.com/engine/swarm/secrets/#use-secrets-in-compose).
9597
See the [Compose file](docker-compose.yml) in this repository for example usage of passing proxy credentials as Docker secrets.
9698

97-
### VPN Authentication
98-
To provide the VPN user and password credentials, create a file called `passfile` in the config folder being mounted, right next to the vpn .conf (or .ovpn) file.
99-
100-
In the passfile, enter the username in the first line and password in the second line. For example:
101-
```
102-
gilbert
103-
p@sswd123
104-
```
105-
Now in the vpn configuration file, such as my_vpn.ovpn, create a new line and enter the following:
106-
```
107-
auth-user-pass passfile
108-
```
109-
That should be enough. You can refer to this link for more details: https://help.yeastar.com/en/s-series/topic/openvpn-username-password-authentication.html#openvpn-create-account-password-for-each-client__section_uyg_sps_33b
110-
111-
11299
### Using with other containers
113100
Once you have your `openvpn-client` container up and running, you can tell other containers to use `openvpn-client`'s network stack which gives them the ability to utilize the VPN tunnel.
114101
There are a few ways to accomplish this depending how how your container is created.
@@ -137,3 +124,21 @@ You should see an IP address owned by your VPN provider.
137124
```bash
138125
docker run --rm -it --network=container:openvpn-client alpine wget -qO - ifconfig.me
139126
```
127+
128+
### Troubleshooting
129+
#### VPN authentication
130+
Your OpenVPN configuration file may not come with authentication baked in.
131+
To provide OpenVPN the necessary credentials, create a file (any name will work, but this example will use `credentials.txt`) next to the OpenVPN configuration file with your username on the first line and your password on the second line.
132+
133+
For example:
134+
```
135+
vpn_username
136+
vpn_password
137+
```
138+
139+
In the OpenVPN configuration file, add the following line:
140+
```
141+
auth-user-pass credentials.txt
142+
```
143+
144+
This will tell OpenVPN to read `credentials.txt` whenever it needs credentials.

build-variables

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
IMAGE_NAME=ghcr.io/wfg/openvpn-client

build.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import datetime
5+
import subprocess
6+
7+
8+
parser = argparse.ArgumentParser()
9+
parser.add_argument('image_version', type=str)
10+
args = parser.parse_args()
11+
12+
docker_build_cmd = [
13+
'docker', 'build',
14+
'--build-arg', f'BUILD_DATE={str(datetime.datetime.now())}',
15+
'--build-arg', f'IMAGE_VERSION={args.image_version}',
16+
'--tag', f'ghcr.io/wfg/openvpn-client:{args.image_version}',
17+
'--tag', 'ghcr.io/wfg/openvpn-client:latest',
18+
'.',
19+
]
20+
subprocess.run(docker_build_cmd)

data/tinyproxy.conf renamed to data/config/http-proxy.conf

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,11 @@ Group tinyproxy
44
Port 8080
55
Listen
66
Bind
7-
87
Timeout 600
98

9+
LogLevel Info
10+
LogFile "/var/log/tinyproxy/tinyproxy.log"
1011
DefaultErrorFile "/usr/share/tinyproxy/default.html"
1112
StatFile "/usr/share/tinyproxy/stats.html"
12-
LogFile "/var/log/tinyproxy/tinyproxy.log"
13-
14-
LogLevel Info
1513

16-
MaxClients 100
17-
MinSpareServers 5
18-
MaxSpareServers 15
19-
StartServers 10
14+
DisableViaHeader yes

0 commit comments

Comments
 (0)