Skip to content

Instantly share code, notes, and snippets.

@gravcat
Last active January 10, 2019 16:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gravcat/218ab3487f9e14b3b68c0c6c9b006f90 to your computer and use it in GitHub Desktop.
Save gravcat/218ab3487f9e14b3b68c0c6c9b006f90 to your computer and use it in GitHub Desktop.
create a docker-based openvpn server, accepting a list of users to create configs and certs for
[Unit]
Description=OpenVPN connection to %i
PartOf=openvpn.service
ReloadPropagatedFrom=openvpn.service
Before=systemd-user-sessions.service
After=network-online.target
Wants=network-online.target
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
[Service]
Type=notify
PrivateTmp=true
WorkingDirectory=/etc/openvpn
ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/%i.conf --writepid /run/openvpn/%i.pid
PIDFile=/run/openvpn/%i.pid
KillMode=process
ExecReload=/bin/kill -HUP $MAINPID
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
LimitNPROC=10
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw
ProtectSystem=true
ProtectHome=true
RestartSec=5s
Restart=on-failure
[Install]
WantedBy=multi-user.target
import argparse
import os
# set up arguments to accept list of users
parser = argparse.ArgumentParser(description='List your VPN usernames.')
parser.add_argument('-u','--users', nargs='+', help='<Required> Username or usernames, space delimited.', required=True)
args = parser.parse_args()
users = args.users
hostname = os.uname()[1]
ovpn_data_volume = 'ovpn_data'
os.system('docker volume create {0}'.format(ovpn_data_volume))
os.system('docker run -v {0}:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_genconfig -u udp://{1}'.format(ovpn_data_volume,hostname))
os.system('docker run -v {0}:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn ovpn_initpki'.format(ovpn_data_volume))
os.system('docker run -v {0}:/etc/openvpn -d -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn'.format(ovpn_data_volume))
for user in users:
os.system('docker run -v {0}:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn easyrsa build-client-full {1} nopass'.format(ovpn_data_volume, user))
os.system('docker run -v {0}:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_getclient {1} > {1}.ovpn'.format(ovpn_data_volume,user))
@gravcat
Copy link
Author

gravcat commented Nov 27, 2018

example script usage

# one user
python3 ovpn_server_docker.py -u gravcat
# many users
python3 ovpn_server_docker.py -u gravcat yourusername yourcat yourmom

@gravcat
Copy link
Author

gravcat commented Dec 12, 2018

quick start:

  1. docker host: run the python script on the host that will be your openvpn server/gateway
  2. docker host -> vpn client system: bring .ovpn configs for your user[s] back to client system which will use them, store in ~/openvpn/youruser.ovpn
  3. vpn client system: apt install openvpn -y or equivalent
  4. vpn client system: install the service file in this gist to /etc/systemd/system/multi-user.target.wants/openvpn@client.service
  5. vpn client system: reboot, start the openvpn@client service, or invoke openvpn manually for this session sudo openvpn --config ~/openvpn/youruser.ovpn

tips:

  1. If you'd like to tunnel all traffic through the vpn tunnel rather than only routes you establish; add the following line to your client's openvpn config, in ~/openvpn/youruser.ovpn
redirect-gateway def1
  1. If you'd like the client VPN connection to be established every time the client system boots, follow quick-start and then:
sudo systemctl enable openvpn@client.service
  1. If you'd like the server VPN to be available on every boot, modify the .py script on L16 to also add --restart always

todo:

  • server vpn restarting automatically on each system boot should be a default(=yes) argument in the .py script
  • consider end to end setup? could also include a client setup script, inputting a config file via an argument!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment