diff --git a/playbooks/deploy.yml b/playbooks/deploy.yml new file mode 100644 index 0000000..9e4e451 --- /dev/null +++ b/playbooks/deploy.yml @@ -0,0 +1,5 @@ +--- +- name: 'Deploy openvpn server role to host group' + hosts: 'openvpn_server' + roles: + - 'enbewe.openvpn.server' diff --git a/roles/server/defaults/main.yml b/roles/server/defaults/main.yml new file mode 100644 index 0000000..dc483f8 --- /dev/null +++ b/roles/server/defaults/main.yml @@ -0,0 +1,15 @@ +--- +openvpn_server_port: '1194' +openvpn_server_config_name: 'server' +openvpn_server_directory: 'server' +openvpn_server_routes: [] +openvpn_server_client_configs: {} +openvpn_sysctl_settings: {} + +openvpn_server_ca: '{{ openvpn_server_directory }}/ca.crt' +openvpn_server_cert: '{{ openvpn_server_directory }}/cert.crt' +openvpn_server_key: '{{ openvpn_server_directory }}/cert.key' +openvpn_server_passfile: '{{ openvpn_server_directory }}/cert.pwd' +openvpn_server_crl: '{{ openvpn_server_directory }}/crl.pem' +openvpn_server_dhfile: '{{ openvpn_server_directory }}/dh2048.pem' +openvpn_server_tlsauth: '{{ openvpn_server_directory }}/tls-auth.key' diff --git a/roles/server/handlers/main.yml b/roles/server/handlers/main.yml new file mode 100644 index 0000000..96b8542 --- /dev/null +++ b/roles/server/handlers/main.yml @@ -0,0 +1,11 @@ +--- +- name: 'Reload openvpn services' + become: true + ansible.builtin.service: + daemon_reload: true + +- name: 'Restart openvpn server' + become: true + ansible.builtin.service: + name: 'openvpn@{{ openvpn_server_config_name }}' + state: 'restarted' diff --git a/roles/server/tasks/main.yml b/roles/server/tasks/main.yml new file mode 100644 index 0000000..fbf6b58 --- /dev/null +++ b/roles/server/tasks/main.yml @@ -0,0 +1,99 @@ +--- +- name: 'Install the official package repository for OpenVPN' + block: + - name: 'Add the signing key' + become: true + ansible.builtin.get_url: + url: 'https://swupdate.openvpn.net/repos/repo-public.gpg' + dest: '/etc/apt/keyrings/openvpn-repo-public.asc' + + - name: 'Add the actual repo' + become: true + ansible.builtin.apt_repository: + repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/openvpn-repo-public.asc] https://build.openvpn.net/debian/openvpn/stable {{ ansible_distribution_release }} main" + state: present + +- name: 'Install server software and kernel module' + become: true + ansible.builtin.apt: + name: '{{ item }}' + update_cache: true + state: 'present' + loop: + - 'openvpn' + - 'openvpn-dco-dkms' + +- name: 'Prepare the folder for vpn server files' + become: true + ansible.builtin.file: + path: '{{ item }}' + state: 'directory' + owner: 'root' + group: 'root' + mode: 'u=rwx,g=rx,o=rx' + loop: + - '/etc/openvpn/{{ openvpn_server_directory }}' + - '/etc/openvpn/{{ openvpn_server_directory }}/ccd' + +- name: 'Deploy config files' + become: true + ansible.builtin.template: + src: '{{ item.src }}' + dest: '{{ item.dest }}' + owner: 'root' + group: 'root' + mode: '{{ item.mode }}' + loop: + - src: 'ca.crt.j2' + dest: '/etc/openvpn/{{ openvpn_server_ca }}' + mode: 'u=rw,g=r,o=r' + - src: 'cert.crt.j2' + dest: '/etc/openvpn/{{ openvpn_server_cert }}' + mode: 'u=rw,g=r,o=r' + - src: 'cert.key.j2' + dest: '/etc/openvpn/{{ openvpn_server_key }}' + mode: 'u=rw,g=,o=' + - src: 'cert.pwd.j2' + dest: '/etc/openvpn/{{ openvpn_server_passfile }}' + mode: 'u=rw,g=,o=' + - src: 'crl.pem.j2' + dest: '/etc/openvpn/{{ openvpn_server_crl }}' + mode: 'u=rw,g=r,o=r' + - src: 'tls-auth.key.j2' + dest: '/etc/openvpn/{{ openvpn_server_tlsauth }}' + mode: 'u=rw,g=,o=' + - src: 'dh2048.pem.j2' + dest: '/etc/openvpn/{{ openvpn_server_dhfile }}' + mode: 'u=rw,g=r,o=r' + notify: 'Restart openvpn server' + +- name: 'Deploy client specific config' + become: true + ansible.builtin.template: + src: 'ccd.j2' + dest: '/etc/openvpn/{{ openvpn_server_directory }}/ccd/{{ item.key }}' + owner: 'root' + group: 'root' + mode: 'u=rw,g=r,o=r' + loop: '{{ openvpn_server_client_configs | dict2items }}' + notify: 'Restart openvpn server' + +- name: 'Deploy server config' + become: true + ansible.builtin.template: + src: 'openvpn_server.conf.j2' + dest: '/etc/openvpn/{{ openvpn_server_config_name }}.conf' + owner: 'root' + group: 'root' + mode: 'u=rw,g=r,o=r' + notify: + - 'Reload openvpn services' + - 'Restart openvpn server' + +- name: 'Configure ip forwarding to allow external communication throught the vpn' + become: true + ansible.posix.sysctl: + name: '{{ item.key }}' + value: '{{ item.value }}' + loop: '{{ openvpn_sysctl_settings | dict2items }}' + notify: 'Restart openvpn server' diff --git a/roles/server/templates/ca.crt.j2 b/roles/server/templates/ca.crt.j2 new file mode 100644 index 0000000..0850aad --- /dev/null +++ b/roles/server/templates/ca.crt.j2 @@ -0,0 +1 @@ +{{ openvpn_server_ca_content }} diff --git a/roles/server/templates/ccd.j2 b/roles/server/templates/ccd.j2 new file mode 100644 index 0000000..6b1a02a --- /dev/null +++ b/roles/server/templates/ccd.j2 @@ -0,0 +1 @@ +{{ item.value }} diff --git a/roles/server/templates/cert.crt.j2 b/roles/server/templates/cert.crt.j2 new file mode 100644 index 0000000..c5d8917 --- /dev/null +++ b/roles/server/templates/cert.crt.j2 @@ -0,0 +1 @@ +{{ openvpn_server_cert_content }} diff --git a/roles/server/templates/cert.key.j2 b/roles/server/templates/cert.key.j2 new file mode 100644 index 0000000..10e9f95 --- /dev/null +++ b/roles/server/templates/cert.key.j2 @@ -0,0 +1 @@ +{{ openvpn_server_key_content }} diff --git a/roles/server/templates/cert.pwd.j2 b/roles/server/templates/cert.pwd.j2 new file mode 100644 index 0000000..8a39604 --- /dev/null +++ b/roles/server/templates/cert.pwd.j2 @@ -0,0 +1 @@ +{{ openvpn_server_askpass_content }} diff --git a/roles/server/templates/crl.pem.j2 b/roles/server/templates/crl.pem.j2 new file mode 100644 index 0000000..07e06de --- /dev/null +++ b/roles/server/templates/crl.pem.j2 @@ -0,0 +1 @@ +{{ openvpn_server_crl_content }} diff --git a/roles/server/templates/dh2048.pem.j2 b/roles/server/templates/dh2048.pem.j2 new file mode 100644 index 0000000..cc6e520 --- /dev/null +++ b/roles/server/templates/dh2048.pem.j2 @@ -0,0 +1 @@ +{{ openvpn_server_dh_content }} diff --git a/roles/server/templates/openvpn_server.conf.j2 b/roles/server/templates/openvpn_server.conf.j2 new file mode 100644 index 0000000..6ddfb02 --- /dev/null +++ b/roles/server/templates/openvpn_server.conf.j2 @@ -0,0 +1,111 @@ + ###### ######## ## ## ######## ######## ### ## +## ## ## ### ## ## ## ## ## ## ## +## ## #### ## ## ## ## ## ## ## +## #### ###### ## ## ## ###### ######## ## ## ## +## ## ## ## #### ## ## ## ######### ## +## ## ## ## ### ## ## ## ## ## ## + ###### ######## ## ## ######## ## ## ## ## ######## + +# Reduce the OpenVPN daemon's privileges after initialization +user nobody +group nogroup + +# TCP or UDP server? +proto udp +proto udp6 + +# Subnet mode instead of p2p +topology subnet + +# Which TCP/UDP port should OpenVPN listen on? +port {{ openvpn_server_port }} + +# "dev tun" will create a routed IP tunnel, "dev tap" will create an +# ethernet tunnel +dev tun + +# Enable compression on the VPN link +comp-lzo + +# Maintain a record of client virtual IP address associations in this file. +ifconfig-pool-persist {{ openvpn_server_directory }}/ipp.txt + +# Output a short status file showing current connections, truncated +# and rewritten every minute. +status {{ openvpn_server_directory }}/openvpn-status.log + +# Configure server mode and supply a VPN subnet for OpenVPN to draw client +# addresses from. The server will take subnet ip .1 for itself, the rest will +# be made available to clients. +server {{ openvpn_server_ipv4_pool }} {{ openvpn_server_ipv4_subnet }} +server-ipv6 {{ openvpn_server_ipv6 }} + +{% for route in openvpn_server_routes %} +route {{route.network }} {{ route.subnet }} +{% endfor %} + +# Uncomment this directive to allow different clients to be able +# to "see" each other. +client-to-client + +# Ping every 10 seconds, assume that remote peer is down if no ping received +# during a 120 second time period. +keepalive 10 120 + +# The persist options will try to avoid accessing certain resources on restart +# that may no longer be accessible because of the privilege downgrade. +persist-key +persist-tun + +# Allow client specific configurations +client-config-dir {{ openvpn_server_directory }}/ccd + +# Set the appropriate level of log +# file verbosity. +# +# 0 is silent, except for fatal errors +# 4 is reasonable for general usage +# 5 and 6 can help to debug connection problems +# 9 is extremely verbose +verb 4 + + + ###### ######## ###### ## ## ######## #### ######## ## ## +## ## ## ## ## ## ## ## ## ## ## ## ## +## ## ## ## ## ## ## ## ## #### + ###### ###### ## ## ## ######## ## ## ## + ## ## ## ## ## ## ## ## ## ## +## ## ## ## ## ## ## ## ## ## ## ## + ###### ######## ###### ####### ## ## #### ## ## +# SSL/TLS root certificate (ca), certificate (cert), and private key (key) +ca {{ openvpn_server_ca }} +cert {{ openvpn_server_cert }} +key {{ openvpn_server_key }} + +# Password for certificate provided in separate file +askpass {{ openvpn_server_passfile }} +auth-nocache + +# Verify against revoked certificates +crl-verify {{ openvpn_server_crl }} + +# Diffie hellman parameters +dh {{ openvpn_server_dhfile }} + +# For extra security beyond that provided by SSL/TLS, create an "HMAC firewall" +# to help block DoS attacks and UDP port flooding. +# The server and each client must have a copy of this key. +# The second parameter should be '0' on the server and '1' on the clients. +tls-auth {{ openvpn_server_tlsauth }} 0 + +# Select a cryptographic cipher +cipher AES-256-CBC + +# Improve message authentication +auth SHA256 + +# Enforce TLSv1.2 +tls-version-min 1.2 + +# Limit the available cipersuites to reasonably safe choices +tls-cipher TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 diff --git a/roles/server/templates/tls-auth.key.j2 b/roles/server/templates/tls-auth.key.j2 new file mode 100644 index 0000000..f7d7c02 --- /dev/null +++ b/roles/server/templates/tls-auth.key.j2 @@ -0,0 +1 @@ +{{ openvpn_server_tlsauth_content }}