--- # Installs the OpenVPN virtual private network server. # ref: https://library.linode.com/networking/openvpn/debian-6-squeeze - name: Install OpenVPN and dependencies apt: name: "{{ packages }}" state: present vars: packages: - dnsmasq - openvpn - udev tags: - dependencies - name: Generate RSA keys for the CA and Server command: openssl genrsa -out {{ item }}.key {{ openvpn_key_size }} chdir={{ openvpn_path }} creates={{ item }}.key with_items: - ca - server - name: Create directories for clients file: path={{ openvpn_path}}/{{ item }} state=directory with_items: "{{ openvpn_clients }}" - name: Generate RSA keys for the clients command: openssl genrsa -out client.key {{ openvpn_key_size }} chdir={{ openvpn_path }}/{{ item }} creates=client.key with_items: "{{ openvpn_clients }}" - name: Set the proper permissions on all RSA keys file: path={{ openvpn_path }} recurse=yes state=directory owner=root group=root mode=0600 - name: Generate CA certificate command: openssl req -nodes -batch -new -x509 -key {{ openvpn_ca }}.key -out {{ openvpn_ca }}.crt -days {{ openvpn_days_valid }} -subj "{{ openssl_request_subject }}/CN=sovereign-ca-certificate" creates={{ openvpn_ca }}.crt # Properly sets the attributes that are described here: # openvpn.net/index.php/open-source/documentation/howto.html#mitm # # This is required in order for the 'ns-cert-type server' option to # work, which is enabled by default in most standard client.conf # files. - name: Generate the OpenSSL configuration that will be used for the Server certificate's req and ca commands template: src=openssl-server-certificate.cnf.j2 dest={{ openvpn_path }}/openssl-server-certificate.cnf - name: Seed a blank database file that will be used when generating the Server's certificate file: path={{ openvpn_path }}/index.txt state=touch - name: Seed a serial file that will be used when generating the Server's certificate copy: content="01" dest={{ openvpn_path }}/serial - name: Generate CSR for the Server command: openssl req -batch -extensions server -new -key server.key -out server.csr -config {{ openvpn_path }}/openssl-server-certificate.cnf chdir={{ openvpn_path }} creates=server.csr - name: Generate certificate for the Server command: openssl ca -batch -extensions server -in server.csr -out server.crt -config openssl-server-certificate.cnf chdir={{ openvpn_path }} creates=server.crt - name: Generate CSRs for the clients command: openssl req -new -key client.key -out client.csr -subj "{{ openssl_request_subject }}/CN={{ item }}" chdir={{ openvpn_path }}/{{ item }} creates=client.csr with_items: "{{ openvpn_clients }}" - name: Generate certificates for the clients command: openssl x509 -CA {{ openvpn_ca }}.crt -CAkey {{ openvpn_ca }}.key -CAcreateserial -req -days {{ openvpn_days_valid }} -in client.csr -out client.crt chdir={{ openvpn_path }}/{{ item }} creates=client.crt with_items: "{{ openvpn_clients }}" - name: Generate HMAC firewall key command: openvpn --genkey --secret {{ openvpn_hmac_firewall }} creates={{ openvpn_hmac_firewall }} - name: Register CA certificate contents command: cat ca.crt chdir={{ openvpn_path }} register: openvpn_ca_contents - name: Register client certificate contents command: cat client.crt chdir={{ openvpn_path }}/{{ item }} with_items: "{{ openvpn_clients }}" register: openvpn_client_certificates - name: Register client key contents command: cat client.key chdir={{ openvpn_path }}/{{ item }} with_items: "{{ openvpn_clients }}" register: openvpn_client_keys - name: Register HMAC firewall contents command: cat ta.key chdir={{ openvpn_path }} register: openvpn_hmac_firewall_contents - name: Create the client configs template: src=client.cnf.j2 dest={{ openvpn_path }}/{{ item[0] }}/{{ openvpn_server }}.ovpn with_together: - "{{ openvpn_clients }}" - "{{ openvpn_client_certificates.results }}" - "{{ openvpn_client_keys.results }}" - name: Generate Diffie-Hellman parameters (this will take a while) command: openssl dhparam -out {{ openvpn_dhparam }} {{ openvpn_key_size }} creates={{ openvpn_dhparam }} - name: Add empty rc.local if it doesn't exist copy: src=rc.local dest=/etc/rc.local mode=0700 owner=root group=root force=no - name: custom rc.local file with iptables rules template: src=rc.local_ansible_openvpn dest=/etc/rc.local_ansible_openvpn mode=0700 owner=root group=root - name: Ensure custom rc.local file is included in rc.local lineinfile: dest=/etc/rc.local line='bash /etc/rc.local_ansible_openvpn' insertbefore='exit 0' - name: Run custom rc file command: bash /etc/rc.local_ansible_openvpn changed_when: False - name: Enable IPv4 traffic forwarding sysctl: name=net.ipv4.ip_forward value=1 - name: Allow OpenVPN through ufw ufw: rule=allow port={{ openvpn_port }} proto={{ openvpn_protocol }} tags: ufw - name: Copy OpenVPN configuration file into place template: src=etc_openvpn_server.conf.j2 dest=/etc/openvpn/server.conf notify: restart openvpn - name: Enable OpenVPN server systemd service unit service: name=openvpn@server enabled=yes # OpenVPN must restart first so the VPN interface is available # to dnsmasq - meta: flush_handlers - name: Copy dnsmasq configuration file into place template: src=etc_dnsmasq.conf.j2 dest=/etc/dnsmasq.conf notify: restart dnsmasq - name: Copy the ca.crt and ta.key files that clients will need in order to connect to the OpenVPN server command: cp {{ openvpn_path }}/{{ item[1] }} {{ openvpn_path }}/{{ item[0] }} tags: - skip_ansible_lint with_nested: - "{{ openvpn_clients }}" - ["ca.crt", "ta.key"] - name: Retrieve the files that clients will need in order to connect to the OpenVPN server fetch: src={{ openvpn_path }}/{{ item[0] }}/{{ item[1] }} dest="{{ secret }}/sovereign-openvpn-files" fail_on_missing=yes with_nested: - "{{ openvpn_clients }}" - ["client.crt", "client.key", "ca.crt", "ta.key", "{{ openvpn_server }}.ovpn"] - name: Pause 5s seconds for OpenVPN ready pause: seconds=5 prompt="You are ready to set up your OpenVPN clients. The files that you need are in {{ secret }}/sovereign-openvpn-files. Make sure LZO compression is enabled and that you provide the ta.key file for the TLS-Auth option with a direction of '1'. Press any key to continue..."