You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Mar 16, 2024. It is now read-only.
- Added trap and cleanup function for cleaner and faster container stops.
- A copy of the OpenVPN config file is made to keep from modifying original.
- Slight reorganization and additional comments/logging
`yacht7/openvpn-client` is a containerized OpenVPN client. It has a kill switch built with `iptables` that kills Internet connectivity to the container if the VPN tunnel goes down for any reason. It also includes two types of proxy: HTTP (Tinyproxy) and SOCKS5 (Shadowsocks). These allow hosts and non-containerized applications to use the VPN without having to run VPN clients on every host.
4
+
5
+
This image requires the user to supply the necessary OpenVPN configuration file(s). Because of this, any VPN provider should work (however, if you find something that doesn't, please open an issue for it).
6
+
2
7
## Why?
3
-
Using this image will allow you establish a VPN connection usable by other containers (and hosts via the built-in proxies) without having to install a VPN client on the host. The image requires the user to supply the necessary OpenVPN configuration files, so (probably) any VPN provider will work.
8
+
Having a containerized VPN client lets you easy choose exactly what you want to use the VPN at the Docker level instead of having to set up split tunnelling at the VPN level. It also keeps you from having to install an OpenVPN client on the underlying host.
9
+
10
+
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. I decided to dissect it and take it in my own direction. I plan to keep everything here well-documented because I want this to be a learning experience for both me and hopefully anyone else that uses it.
4
11
5
-
It has a VPN kill switch enabled by default, so if the VPN connection is lost at any time, all internet connectivity to the container and connected clients is lost.
12
+
## How do I use it?
13
+
### Getting the image
14
+
You can either pull it from Docker Hub or build it yourself.
6
15
7
-
Please note that the kill switch does allow connections to the VPN server address/port combinations specified in the configuration file outside of the VPN tunnel in order to establish connection.
16
+
To pull from [Docker Hub](https://hub.docker.com/r/yacht7/openvpn-client), run `docker pull yacht7/openvpn-client`.
The image requires the container be created with the `NET_ADMIN` capability and `/dev/net/tun` accessible. Below are bare-bones examples for `docker run` and Compose; however, you'll probably want to do more than just run the VPN client. See the sections below to learn how to use the [proxies](#shadowsocks-and-tinyproxy) and have [other containers use `openvpn-client`'s network stack](#using-with-other-containers).
27
+
28
+
#### `docker run`
29
+
```bash
12
30
docker run -d \
13
31
--name=openvpn-client \
14
32
--cap-add=NET_ADMIN \
@@ -17,8 +35,8 @@ docker run -d \
17
35
yacht7/openvpn-client
18
36
```
19
37
20
-
### `docker-compose`
21
-
```
38
+
####`docker-compose`
39
+
```yaml
22
40
version: '2'
23
41
24
42
services:
@@ -33,58 +51,59 @@ services:
33
51
- <path/to/config>:/data/vpn
34
52
restart: unless-stopped
35
53
```
36
-
#### Considerations
37
-
##### Tinyproxy and Shadowsocks
38
-
If enabling Tinyproxy or Shadowsocks, you'll want to publish the proxy's port in order to access the proxy. To do that using `docker run`, add `-p <host_port>:<container_port>` where `<host_port>` and `<container_port>` are whatever port your proxy is using (8888 and 8388 by default for Tinyproxy and Shadowsocks). If you're using `docker-compose`, add the below snippet to the `openvpn-client` service definition in your Compose file.
39
-
```
40
-
ports:
41
-
- <host_port>:<container_port>
42
-
```
43
-
44
-
##### Handling ports intended for connected containers
45
-
If you plan on having [other containers use `openvpn-client`'s network stack](#using-with-other-containers) and those containers have web UIs, you'll want to publish the web UI ports on `openvpn-client` instead of the connected container. To do that, add `-p <host_port>:<container_port>` if you're using `docker run`, or add the below snippet to the `openvpn-client` service definition in your Compose file if using `docker-compose`.
46
-
```
47
-
ports:
48
-
- <host_port>:<container_port>
49
-
```
50
-
In both cases, replace `<host_port>` and `<container_port>` with the port used by your connected container.
51
-
52
-
### Environment variables
53
54
55
+
#### Environment variables
54
56
| Variable | Default (blank is unset) | Description |
55
57
| --- | --- | --- |
56
58
| `KILL_SWITCH` | `on` | The on/off status of VPN kill switch. To disable, set to any value besides `on`. |
57
-
|`SUBNETS`|| A comma-separated (no whitespaces) list of LAN subnets (e.g. `192.168.0.0/24,192.168.1.0/24`). |
59
+
| `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. See important note about this [below](#subnets). |
58
60
| `FORWARDED_PORTS` | | Port(s) forwarded by your VPN provider (e.g. `12345` or `9876,54321`) |
| `SHADOWSOCKS` | | The on/off status of Shadowsocks. To enable, set to `on`. Any other value, including leaving it unset, will cause the proxy to not start. |
61
-
|`SHADOWSOCKS_PORT`|`8388`| The port that Shadowsocks listens on. If manually specified, choose a port over 1024. |
62
-
|`SHADOWSOCKS_PASS`|`password`|Required to start Shadowsocks, so a default is specified. |
63
+
| `SHADOWSOCKS_PORT` | `8388` | The port on which Shadowsocks listens. If manually specified, choose a port over 1024. |
64
+
| `SHADOWSOCKS_PASS` | `password` | A password is required to start Shadowsocks, so a default is specified. I recommend you change this if Shadowsocks is enabled. |
63
65
| `TINYPROXY` | | The on/off status of Tinyproxy. To enable, set to `on`. Any other value, including leaving it unset, will cause the proxy to not start. |
64
-
|`TINYPROXY_PORT`|`8888`| The port that Tinyproxy listens on. If manually specified, choose a port over 1024. |
65
-
|`TINYPROXY_USER`||Setting `TINYPROXY_USER` and `TINYPROXY_PASS` will restrict access to the proxy server to only the specified username and password. |
66
-
|`TINYPROXY_PASS`||Setting `TINYPROXY_USER` and `TINYPROXY_PASS`will restrict access to the proxy server to only the specified username and password. |
66
+
| `TINYPROXY_PORT` | `8888` | The port on which Tinyproxy listens. If manually specified, choose a port over 1024. |
67
+
| `TINYPROXY_USER` | | Credentials for accessing Tinyproxy. If `TINYPROXY_USER` is specified, you must also specify `TINYPROXY_PASS`. |
68
+
| `TINYPROXY_PASS` | | Credentials for accessing Tinyproxy. If `TINYPROXY_PASS` is specified, you must also specify `TINYPROXY_USER`. |
67
69
68
-
#### `SUBNETS`
69
-
**Important note about this variable**: the DNS server used by this container prior to VPN connection must be included in the value specified. For example, if your underlying host is using 192.168.1.1 as a DNS server, then this address must be included in `SUBNETS` (`192.168.1.1` or `192.168.1.0/24` would be acceptable). This is necessary because the kill switch will block traffic outside of the VPN tunnel before it's actually established. If the DNS server is not whitelisted, the server addresses in the VPN configuration will not resolve.
70
+
##### Environment variable considerations
71
+
###### `KILL_SWITCH`
72
+
The kill switch allows connections outside of the VPN tunnel to the following two places: 1) the VPN server(s) specified in the configuration file and 2) all addresses specified in `SUBNETS`.
73
+
74
+
###### `SUBNETS`
75
+
**Important**: The DNS server used by this container prior to VPN connection must be included in the value specified. For example, if your container is using 192.168.1.1 as a DNS server, then this address or an appropriate CIDR block must be included in `SUBNETS`. This is necessary because the kill switch blocks traffic outside of the VPN tunnel before it's actually established. If the DNS server is not whitelisted, the server addresses in the VPN configuration will not resolve.
70
76
71
77
The subnets specified will have routes created and whitelists added in the firewall for them which allows for connectivity to and from hosts on the subnets.
72
78
73
-
##Running
74
-
### Verifying functionality
75
-
Once you have container running `yacht7/openvpn-client`, run the following command to spin up a temporary container using `openvpn-client` for networking. The `wget -qO - ifconfig.me` bit will return the public IP of the container (and anything else using `openvpn-client` for networking). You should see an IP address owned by your VPN provider.
76
-
```
77
-
docker run --rm -it --network=container:openvpn-client alpine wget -qO - ifconfig.me
79
+
###### `SHADOWSOCKS` and `TINYPROXY`
80
+
If enabling Shadowsocks or Tinyproxy, you'll want to publish the proxy's port in order to access the proxy. To do that using `docker run`, add `-p <host_port>:<container_port>` where `<host_port>` and `<container_port>` are whatever port your proxy is using (8388 and 8888 by default for Shadowsocks and Tinyproxy). If you're using `docker-compose`, add the below snippet to the `openvpn-client` service definition in your Compose file.
81
+
```yaml
82
+
ports:
83
+
- <host_port>:<container_port>
78
84
```
79
85
80
86
### Using with other containers
81
-
Once you have your OpenVPN client container up and running, you can tell other containers to use `openvpn-client`'s network stack which gives any container the ability to utilize the VPN tunnel. There are a few ways to accomplish this depending how how your container is created.
87
+
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. There are a few ways to accomplish this depending how how your container is created.
82
88
83
89
If your container is being created with
84
90
1. the same Compose YAML file as `openvpn-client`, add `network_mode: service:openvpn-client` to the container's service definition.
85
-
2. a different Compose YAML file as`openvpn-client`, add `network_mode: container:openvpn-client` to the container's service definition.
91
+
2. a different Compose YAML file than `openvpn-client`, add `network_mode: container:openvpn-client` to the container's service definition.
86
92
3. `docker run`, add `--network=container:openvpn-client` as an option to `docker run`.
87
93
88
94
Once running and provided your container has `wget` or `curl`, you can run `docker exec <container_name> wget -qO - ifconfig.me` or `docker exec <container_name> curl -s ifconfig.me` to get the public IP of the container and make sure everything is working as expected. This IP should match the one of `openvpn-client`.
89
95
90
-
If the connected container needs to publish ports, see [this](#handling-ports-intended-for-connected-containers) section.
96
+
#### Handling ports intended for connected containers
97
+
If you have a connected container and you need to access a port that container, you'll want to publish that port on the `openvpn-client` container instead of the connected container. To do that, add `-p <host_port>:<container_port>` if you're using `docker run`, or add the below snippet to the `openvpn-client` service definition in your Compose file if using `docker-compose`.
98
+
```yaml
99
+
ports:
100
+
- <host_port>:<container_port>
101
+
```
102
+
In both cases, replace `<host_port>` and `<container_port>` with the port used by your connected container.
103
+
104
+
### Verifying functionality
105
+
Once you have container running `yacht7/openvpn-client`, run the following command to spin up a temporary container using `openvpn-client` for networking. The `wget -qO - ifconfig.me` bit will return the public IP of the container (and anything else using `openvpn-client` for networking). You should see an IP address owned by your VPN provider.
106
+
```bash
107
+
docker run --rm -it --network=container:openvpn-client alpine wget -qO - ifconfig.me
0 commit comments