Ansible role to install and configure openvpn server.
Further development of this Ansible role has been moved to Collection bodsch.core. This repository will therefore no longer be actively maintained.
The ipv4 filter requires python's netaddr
be installed on the ansible controller.
Ansible Collections
ansible-galaxy collection install bodsch.core
or
ansible-galaxy collection install --requirements-file collections.yml
Tested on
- Arch Linux
- Artix Linux
- Debian based
- Debian 11
openvpn_directory: /etc/openvpn
openvpn_diffie_hellman_keysize: 2048
openvpn_mtu: 1500
openvpn_mssfix: 1360
openvpn_keepalive:
interval: 10
timeout: 120
# server or client
openvpn_type: ""
openvpn_service:
state: started
enabled: true
openvpn_systemd: {}
openvpn_logging: {}
openvpn_easyrsa: {}
openvpn_certificate: {}
openvpn_server: {}
openvpn_persistent_pool: []
openvpn_mobile_clients: []
openvpn_config_save_dir: ""
openvpn_subnet:
ip: 10.8.3.0
mask: 255.255.255.0
openvpn_iptables:
enabled: false
openvpn_push:
routes: []
route_gateway: ""
dhcp_options:
domains: []
dns: []
sndbuf: 393216
rcvbuf: 393216
If OpenVPN has a dependency on another service (e.g. on sshd), then it should be possible
here to force the service into a corresponding dependency.
(Assuming that I have understood the systemd documentation correctly!)
openvpn_systemd:
requires_services:
- sshd.service
verbose
Set the appropriate level of log file verbosity.
0
is silent, except for fatal errors4
is reasonable for general usage5
and6
can help to debug connection problems9
is extremely verbose
mute
Silence repeating messages.
At most 20 sequential messages of the same message category will be output to the log.
example
openvpn_logging:
directory: /var/log/openvpn
file: openvpn.log
status: status.log
verbosity: 3
mute: 10
append: true
The best way to create a PKI for OpenVPN is to separate your CA duty from each server & client.
The CA should ideally be on a secure environment (whatever that means to you.)
Loss/theft of the CA key destroys the security of the entire PKI.
The crl file has a runtime of 180 days (default).
After these 180 days have expired, the VPN clients will no longer establish a connection to the server!
For this reason I have integrated crl_warn
.
If expired
is configured with true
, each time the role is run, it checks whether the crl file is still valid.
If the runtime is less than expire_in_days
, the crl file is automatically renewed.
example
openvpn_easyrsa:
directory: /etc/easy-rsa
openssl_config: ""
key_size: 4096
ca_expire: 3650
cert_expire: 3650
crl_days: 180
crl_warn:
expired: true
expire_in_days: 20
x509_dn_mode: cn_only
# Choices for crypto alg are: (each in lower-case)
# * rsa
# * ec
# * ed
crypto_mode: ec
rsa_curve: secp384r1
# sha256, sha224, sha384, sha512
digest: sha512
example
openvpn_certificate:
req_country: DE
req_province: Hamburg
req_city: Hamburg
req_org: ACME Inc.
req_email: openvpn@acme.inc
req_ou: Special Forces
req_cn_ca: 'Open VPN'
req_cn_server: '{{ ansible_fqdn }}'
user
/ group
It's a good idea to reduce the OpenVPN daemon's privileges after initialization.
tls_auth
For extra security beyond that provided by SSL/TLS, create an
"HMAC firewall" to help block DoS attacks and UDP port flooding.
example
openvpn_server:
# network interface connected to internal net
interface: eth0
# external IP of VPN server (EIP)
external_ip: '' # {{ ansible_default_ipv4.address }}'
# Which local IP address should OpenVPN
# listen on? (optional)
listen_ip: ''
# valid: 'udp' or 'tcp'
proto: udp
# Which TCP/UDP port should OpenVPN listen on?
port: 1194
# valid: 'tun' or 'tap'
# "tun" will create a routed IP tunnel,
# "tap" will create an ethernet tunnel.
device: tun
max_clients: 10
tls_auth:
enabled: true
cipher: AES-256-GCM
user: nobody
group: nogroup
The generated OVPN files for mobile clients are stored on the VPN server under /root/vpn-configs
.
You can also transfer them to the Ansible controller.
To do this, openvpn_config_save_dir
must be configured accordingly.
tls_auth
is recommended when is activated in openvpn_server
!
variable | default | description |
---|---|---|
name |
- |
|
state |
present |
|
roadrunner |
false |
|
remote |
- |
|
port |
1194 |
|
proto |
udp |
|
device |
tun |
|
ping |
20 |
|
ping_restart |
45 |
|
cert |
${name}.crt |
|
key |
${name}.key |
example
openvpn_mobile_clients:
- name: molecule_static
state: present
remote: server
port: 1194
proto: udp
device: tun
ping: 20
ping_restart: 45
cert: molecule_static.crt
key: molecule_static.key
- name: roadrunner_one
state: present
roadrunner: true
remote: server
port: 1194
proto: udp
device: tun
ping: 20
ping_restart: 45
cert: roadrunner_one.crt
key: roadrunner_one.key
example
openvpn_persistent_pool:
- name: molecule_mobile
state: present
static_ip: 10.8.3.10
Configure server mode and supply a VPN subnet for OpenVPN to draw client addresses from. The server will take 10.8.0.1 for itself, the rest will be made available to clients. Each client will be able to reach the server on 10.8.0.1.
Use distinct subnets for every VPN server, if client IPs are persisted!
(ifconfig-pool-persist
in openvpn server.conf
)
example
openvpn_subnet:
ip: 10.8.3.0
mask: 255.255.255.0
Configuration options that can be pushed to the VPN client.
openvpn_push:
routes: []
dhcp_options:
domains: []
dns: []
sndbuf: 393216
rcvbuf: 393216
Push routes to the client to allow it to reach other private subnets behind the server.
Remember that these private subnets will also need to know to route the OpenVPN client address pool
(10.8.0.0/255.255.255.0) back to the OpenVPN server.
List of routes which are propagated to client. Try to keep these nets small!
example
openvpn_push:
routes:
- net: 10.8.3.0
netmask: 255.255.255.0
example
openvpn_push:
dhcp_options:
dns:
- 10.15.0.2
- 10.15.0.5
example
openvpn_push:
dhcp_options:
domains:
- matrix.vpn
- customer.vpn
example
openvpn_iptables:
enabled: false
openvpn_type: server
openvpn_persistent_pool:
- name: client1.example.com
state: present
static_ip: 172.25.0.10
- name: client2.example.com
state: present
static_ip: 172.25.0.11
openvpn_subnet:
ip: 172.25.0.0
netmask: 255.255.255.0
openvpn_push:
routes:
- net: 172.25.0.0
netmask: 255.255.255.0
openvpn_type: client
openvpn_mobile_clients:
- name: client1.example.com
remote: vpn.example.com
port: 1194
proto: udp
device: tun
ping: 20
ping_restart: 45
cert: client1.example.com.crt
key: client1.example.com.key
tls_auth:
enabled: true
openvpn_type: server
openvpn_mobile_clients:
- name: client2.example.com
remote: vpn.example.com
roadrunner: true
port: 1194
proto: udp
device: tun
ping: 20
ping_restart: 45
cert: client2.example.com.crt
key: client2.example.com.key
tls_auth:
enabled: true
Please read Contribution
The master
Branch is my Working Horse includes the "latest, hot shit" and can be complete broken!
If you want to use something stable, please use a Tagged Version!
- Bodo Schulz
FREE SOFTWARE, HELL YEAH!