Refactoring (#1334)

<!--- Provide a general summary of your changes in the Title above -->

## Description
Renames the vpn role to strongswan, and split up the variables to support 2 separate VPNs. Closes #1330 and closes #1162
Configures Ansible to use python3 on the server side. Closes #1024 
Removes unneeded playbooks, reorganises a lot of variables
Reorganises the `config` folder. Closes #1330
<details><summary>Here is how the config directory looks like now</summary>
<p>

```
configs/X.X.X.X/
|-- ipsec
|   |-- apple
|   |   |-- desktop.mobileconfig
|   |   |-- laptop.mobileconfig
|   |   `-- phone.mobileconfig
|   |-- manual
|   |   |-- cacert.pem
|   |   |-- desktop.p12
|   |   |-- desktop.ssh.pem
|   |   |-- ipsec_desktop.conf
|   |   |-- ipsec_desktop.secrets
|   |   |-- ipsec_laptop.conf
|   |   |-- ipsec_laptop.secrets
|   |   |-- ipsec_phone.conf
|   |   |-- ipsec_phone.secrets
|   |   |-- laptop.p12
|   |   |-- laptop.ssh.pem
|   |   |-- phone.p12
|   |   `-- phone.ssh.pem
|   `-- windows
|       |-- desktop.ps1
|       |-- laptop.ps1
|       `-- phone.ps1
|-- ssh-tunnel
|   |-- desktop.pem
|   |-- desktop.pub
|   |-- laptop.pem
|   |-- laptop.pub
|   |-- phone.pem
|   |-- phone.pub
|   `-- ssh_config
`-- wireguard
    |-- desktop.conf
    |-- desktop.png
    |-- laptop.conf
    |-- laptop.png
    |-- phone.conf
    `-- phone.png
```

![finder](https://i.imgur.com/FtOmKO0.png)

</p>
</details>

## Motivation and Context
This refactoring is focused to aim to the 1.0 release

## How Has This Been Tested?
Deployed to several cloud providers with various options enabled and disabled

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [x] Refactoring

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [x] I have read the **CONTRIBUTING** document.
- [x] My code follows the code style of this project.
- [x] My change requires a change to the documentation.
- [x] I have updated the documentation accordingly.
- [x] All new and existing tests passed.
pull/1348/head
Jack Ivanov 5 years ago committed by Dan Guido
parent 7e7476ec6b
commit 273c7665d3

@ -123,9 +123,9 @@ Install strongSwan, then copy the included ipsec_user.conf, ipsec_user.secrets,
#### Ubuntu Server 18.04 example #### Ubuntu Server 18.04 example
1. `sudo apt-get install strongswan libstrongswan-standard-plugins`: install strongSwan 1. `sudo apt-get install strongswan libstrongswan-standard-plugins`: install strongSwan
2. `/etc/ipsec.d/certs`: copy `<name>.crt` from `algo-master/configs/<server_ip>/pki/certs/<name>.crt` 2. `/etc/ipsec.d/certs`: copy `<name>.crt` from `algo-master/configs/<server_ip>/ipsec/manual/<name>.crt`
3. `/etc/ipsec.d/private`: copy `<name>.key` from `algo-master/configs/<server_ip>/pki/private/<name>.key` 3. `/etc/ipsec.d/private`: copy `<name>.key` from `algo-master/configs/<server_ip>/ipsec/manual/<name>.key`
4. `/etc/ipsec.d/cacerts`: copy `cacert.pem` from `algo-master/configs/<server_ip>/pki/cacert.pem` 4. `/etc/ipsec.d/cacerts`: copy `cacert.pem` from `algo-master/configs/<server_ip>/ipsec/manual/cacert.pem`
5. `/etc/ipsec.secrets`: add your `user.key` to the list, e.g. `<server_ip> : ECDSA <name>.key` 5. `/etc/ipsec.secrets`: add your `user.key` to the list, e.g. `<server_ip> : ECDSA <name>.key`
6. `/etc/ipsec.conf`: add the connection from `ipsec_user.conf` and ensure `leftcert` matches the `<name>.crt` filename 6. `/etc/ipsec.conf`: add the connection from `ipsec_user.conf` and ensure `leftcert` matches the `<name>.crt` filename
7. `sudo ipsec restart`: pick up config changes 7. `sudo ipsec restart`: pick up config changes
@ -160,7 +160,7 @@ If you turned on the optional SSH tunneling role, then local user accounts will
Use the example command below to start an SSH tunnel by replacing `user` and `ip` with your own. Once the tunnel is setup, you can configure a browser or other application to use 127.0.0.1:1080 as a SOCKS proxy to route traffic through the Algo server. Use the example command below to start an SSH tunnel by replacing `user` and `ip` with your own. Once the tunnel is setup, you can configure a browser or other application to use 127.0.0.1:1080 as a SOCKS proxy to route traffic through the Algo server.
`ssh -D 127.0.0.1:1080 -f -q -C -N user@ip -i configs/ip_user.ssh.pem` `ssh -D 127.0.0.1:1080 -f -q -C -N user@ip -i configs/<server_ip>/ssh-tunnel/<user>.pem`
## SSH into Algo Server ## SSH into Algo Server

@ -18,8 +18,14 @@ keys_clean_all: False
# Clean up cloud python environments # Clean up cloud python environments
clean_environment: false clean_environment: false
vpn_network: 10.19.48.0/24 # Deploy StrongSwan to enable IPsec support
vpn_network_ipv6: 'fd9d:bc11:4020::/48' ipsec_enabled: true
# StrongSwan log level
# https://wiki.strongswan.org/projects/strongswan/wiki/LoggerConfiguration
strongswan_log_level: 2
# Deploy WireGuard
wireguard_enabled: true wireguard_enabled: true
wireguard_port: 51820 wireguard_port: 51820
# If you're behind NAT or a firewall and you want to receive incoming connections long after network traffic has gone silent. # If you're behind NAT or a firewall and you want to receive incoming connections long after network traffic has gone silent.
@ -36,10 +42,6 @@ wireguard_PersistentKeepalive: 0
# See: https://github.com/trailofbits/algo/blob/master/docs/troubleshooting.md#various-websites-appear-to-be-offline-through-the-vpn # See: https://github.com/trailofbits/algo/blob/master/docs/troubleshooting.md#various-websites-appear-to-be-offline-through-the-vpn
reduce_mtu: 0 reduce_mtu: 0
# StrongSwan log level
# https://wiki.strongswan.org/projects/strongswan/wiki/LoggerConfiguration
strongswan_log_level: 2
# Algo will use the following lists to block ads. You can add new block lists # Algo will use the following lists to block ads. You can add new block lists
# after deployment by modifying the line starting "BLOCKLIST_URLS=" at: # after deployment by modifying the line starting "BLOCKLIST_URLS=" at:
# /usr/local/sbin/adblock.sh # /usr/local/sbin/adblock.sh
@ -90,10 +92,6 @@ unattended_reboot:
enabled: false enabled: false
time: 06:00 time: 06:00
pkcs12_PayloadCertificateUUID: "{{ 900000 | random | to_uuid | upper }}"
VPN_PayloadIdentifier: "{{ 800000 | random | to_uuid | upper }}"
CA_PayloadIdentifier: "{{ 700000 | random | to_uuid | upper }}"
# Block traffic between connected clients # Block traffic between connected clients
BetweenClients_DROP: true BetweenClients_DROP: true

@ -48,30 +48,45 @@
when: when:
- server_name is undefined - server_name is undefined
- algo_provider != "local" - algo_provider != "local"
- block:
- pause:
prompt: |
Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to cellular networks?
[y/N]
register: _ondemand_cellular
when: ondemand_cellular is undefined
- pause: - pause:
prompt: | prompt: |
Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to cellular networks? Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to Wi-Fi?
[y/N] [y/N]
register: _ondemand_cellular register: _ondemand_wifi
when: ondemand_cellular is undefined when: ondemand_wifi is undefined
- pause: - pause:
prompt: | prompt: |
Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to Wi-Fi? List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand"
[y/N] (e.g., your home network. Comma-separated value, e.g., HomeNet,OfficeWifi,AlgoWiFi)
register: _ondemand_wifi register: _ondemand_wifi_exclude
when: ondemand_wifi is undefined when:
- ondemand_wifi_exclude is undefined
- (ondemand_wifi|default(false)|bool) or
(booleans_map[_ondemand_wifi.user_input|default(omit)]|default(false))
- pause: - pause:
prompt: | prompt: |
List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand" Do you want the VPN to support Windows 10 or Linux Desktop clients? (enables compatible ciphers and key exchange, less secure)
(e.g., your home network. Comma-separated value, e.g., HomeNet,OfficeWifi,AlgoWiFi) [y/N]
register: _ondemand_wifi_exclude register: _windows
when: when: windows is undefined
- ondemand_wifi_exclude is undefined
- (ondemand_wifi|default(false)|bool) or - pause:
(booleans_map[_ondemand_wifi.user_input|default(omit)]|default(false)) prompt: |
Do you want to retain the CA key? (required to add users in the future, but less secure)
[y/N]
register: _store_cakey
when: store_cakey is undefined
when: ipsec_enabled
- pause: - pause:
prompt: | prompt: |
@ -87,20 +102,6 @@
register: _ssh_tunneling register: _ssh_tunneling
when: ssh_tunneling is undefined when: ssh_tunneling is undefined
- pause:
prompt: |
Do you want the VPN to support Windows 10 or Linux Desktop clients? (enables compatible ciphers and key exchange, less secure)
[y/N]
register: _windows
when: windows is undefined
- pause:
prompt: |
Do you want to retain the CA key? (required to add users in the future, but less secure)
[y/N]
register: _store_cakey
when: store_cakey is undefined
- name: Set facts based on the input - name: Set facts based on the input
set_fact: set_fact:
algo_server_name: >- algo_server_name: >-

@ -9,7 +9,7 @@
groups: vpn-host groups: vpn-host
ansible_connection: "{% if cloud_instance_ip == 'localhost' %}local{% else %}ssh{% endif %}" ansible_connection: "{% if cloud_instance_ip == 'localhost' %}local{% else %}ssh{% endif %}"
ansible_ssh_user: "{{ ansible_ssh_user }}" ansible_ssh_user: "{{ ansible_ssh_user }}"
ansible_python_interpreter: "/usr/bin/python2.7" ansible_python_interpreter: "/usr/bin/python3"
algo_provider: "{{ algo_provider }}" algo_provider: "{{ algo_provider }}"
algo_server_name: "{{ algo_server_name }}" algo_server_name: "{{ algo_server_name }}"
algo_ondemand_cellular: "{{ algo_ondemand_cellular }}" algo_ondemand_cellular: "{{ algo_ondemand_cellular }}"

@ -1,67 +0,0 @@
---
# This playbook is designed to help when modifying the Windows script template
# in roles/vpn/templates/client_windows.ps1.j2
# It rebuilds the client_USER.ps1 scripts for each user defined in config.cfg,
# without redeploying users or opening an SSH connection to the Algo server at
# all.
#
# This playbook is _not_ part of a normal Algo deployment.
# It is only intended to speed up development of the client_USER.ps1 Windows
# Algo install scripts.
#
# REQUIREMENTS
# - Algo must have been deployed once
# - Windows users must have been enabled at deployment time
# - All users defined in config.cfg must not have changed
# - Only one Algo deployment exists in the configs/ directory
# - There must be exactly one subfolder in the configs/ directory:
# the folder named after the IP of the algo server
- hosts: localhost
gather_facts: False
tags: always
vars_files:
- ../config.cfg
tasks:
- name: Get config subdir
shell: find ../configs/* -maxdepth 0 -type d | sed 's/.*\///'
register: config_subdir_result
- fail:
msg:
- "Found wrong number of config subdirs... stdout:"
- "{{ config_subdir_result.split('\n') }}"
when: config_subdir_result.stdout.split('\n') | length != 1
- set_fact:
IP_subject_alt_name: "{{ config_subdir_result.stdout }}"
- debug:
var: IP_subject_alt_name
- name: Register p12 PayloadContent
shell: cat private/{{ item }}.p12 | base64
register: PayloadContent
args:
chdir: "../configs/{{ IP_subject_alt_name }}/pki/"
with_items: "{{ users }}"
- name: Set facts for mobileconfigs
set_fact:
proxy_enabled: false
PayloadContentCA: "{{ lookup('file' , '../configs/{{ IP_subject_alt_name }}/pki/cacert.pem')|b64encode }}"
- name: Build the windows client powershell script
template:
src: ../roles/vpn/templates/client_windows.ps1.j2
dest: ../configs/{{ IP_subject_alt_name }}/windows_{{ item.0 }}.ps1
mode: 0600
with_together:
- "{{ users }}"
- "{{ PayloadContent.results }}"
- name: List windows client powershell scripts
debug:
msg: "configs/{{ IP_subject_alt_name }}/windows_{{ item }}.ps1"
with_items:
- "{{ users }}"

@ -50,11 +50,11 @@
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ item.dest }}" dest: "{{ item.dest }}"
with_items: with_items:
- src: "configs/{{ IP_subject_alt_name }}/pki/certs/{{ vpn_user }}.crt" - src: "configs/{{ IP_subject_alt_name }}/ipsec/.pki/certs/{{ vpn_user }}.crt"
dest: "{{ configs_prefix }}/ipsec.d/certs/{{ vpn_user }}.crt" dest: "{{ configs_prefix }}/ipsec.d/certs/{{ vpn_user }}.crt"
- src: "configs/{{ IP_subject_alt_name }}/pki/cacert.pem" - src: "configs/{{ IP_subject_alt_name }}/ipsec/.pki/cacert.pem"
dest: "{{ configs_prefix }}/ipsec.d/cacerts/{{ IP_subject_alt_name }}.pem" dest: "{{ configs_prefix }}/ipsec.d/cacerts/{{ IP_subject_alt_name }}.pem"
- src: "configs/{{ IP_subject_alt_name }}/pki/private/{{ vpn_user }}.key" - src: "configs/{{ IP_subject_alt_name }}/ipsec/.pki/private/{{ vpn_user }}.key"
dest: "{{ configs_prefix }}/ipsec.d/private/{{ vpn_user }}.key" dest: "{{ configs_prefix }}/ipsec.d/private/{{ vpn_user }}.key"
notify: notify:
- restart strongswan - restart strongswan

@ -19,3 +19,9 @@
ifconfig lo100 create && ifconfig lo100 create &&
ifconfig lo100 inet {{ local_service_ip }} netmask 255.255.255.255 && ifconfig lo100 inet {{ local_service_ip }} netmask 255.255.255.255 &&
ifconfig lo100 inet6 FCAA::1/64; echo $? ifconfig lo100 inet6 FCAA::1/64; echo $?
- name: save iptables
shell: service netfilter-persistent save
- name: restart iptables
service: name=netfilter-persistent state=restarted

@ -1,4 +1,16 @@
--- ---
- name: FreeBSD | Install prerequisites
package:
name:
- python3
- sudo
vars:
ansible_python_interpreter: /usr/local/bin/python2.7
- name: Set python3 as the interpreter to use
set_fact:
ansible_python_interpreter: /usr/local/bin/python3
- name: Gather facts - name: Gather facts
setup: setup:
@ -15,7 +27,6 @@
strongswan_additional_plugins: strongswan_additional_plugins:
- kernel-pfroute - kernel-pfroute
- kernel-pfkey - kernel-pfkey
ansible_python_interpreter: /usr/local/bin/python2.7
tools: tools:
- git - git
- subversion - subversion

@ -1,24 +1,4 @@
--- ---
- block:
- name: Ubuntu | Install prerequisites
apt:
name: "{{ item }}"
update_cache: true
with_items:
- python2.7
- sudo
- name: Ubuntu | Configure defaults
alternatives:
name: python
link: /usr/bin/python
path: /usr/bin/python2.7
priority: 1
tags:
- update-alternatives
vars:
ansible_python_interpreter: /usr/bin/python3
- name: Gather facts - name: Gather facts
setup: setup:
@ -115,15 +95,20 @@
value: 1 value: 1
- name: Install tools - name: Install tools
package: name="{{ item }}" state=present apt:
name: "{{ item }}"
state: present
update_cache: true
with_items: with_items:
- "{{ tools|default([]) }}" - "{{ tools|default([]) }}"
- name: Install headers - name: Install headers
apt: apt:
name: "{{ item }}" name:
- linux-headers-generic
- "linux-headers-{{ ansible_kernel }}"
state: present state: present
when: install_headers when: install_headers
with_items:
- linux-headers-generic - include_tasks: iptables.yml
- "linux-headers-{{ ansible_kernel }}" tags: iptables

@ -1,3 +1,6 @@
{% set subnets = ([strongswan_network] if ipsec_enabled else []) + ([wireguard_network_ipv4] if wireguard_enabled else []) %}
{% set ports = (['500', '4500'] if ipsec_enabled else []) + ([wireguard_port] if wireguard_enabled else []) %}
#### The mangle table #### The mangle table
# This table allows us to modify packet headers # This table allows us to modify packet headers
# Packets enter this table first # Packets enter this table first
@ -10,8 +13,8 @@
:OUTPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0] :POSTROUTING ACCEPT [0:0]
{% if reduce_mtu|int > 0 %} {% if reduce_mtu|int > 0 and ipsec_enabled %}
-A FORWARD -s {{ vpn_network }} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss {{ 1360 - reduce_mtu|int }} -A FORWARD -s {{ strongswan_network }} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss {{ 1360 - reduce_mtu|int }}
{% endif %} {% endif %}
COMMIT COMMIT
@ -27,7 +30,7 @@ COMMIT
:POSTROUTING ACCEPT [0:0] :POSTROUTING ACCEPT [0:0]
# Allow traffic from the VPN network to the outside world, and replies # Allow traffic from the VPN network to the outside world, and replies
-A POSTROUTING -s {{ vpn_network }}{% if wireguard_enabled %},{{ wireguard_vpn_network }}{% endif %} -m policy --pol none --dir out -j MASQUERADE -A POSTROUTING -s {{ subnets|join(',') }} -m policy --pol none --dir out -j MASQUERADE
COMMIT COMMIT
@ -54,12 +57,15 @@ COMMIT
-A INPUT -p ah -j ACCEPT -A INPUT -p ah -j ACCEPT
# rate limit ICMP traffic per source # rate limit ICMP traffic per source
-A INPUT -p icmp --icmp-type echo-request -m hashlimit --hashlimit-upto 5/s --hashlimit-mode srcip --hashlimit-srcmask 32 --hashlimit-name icmp-echo-drop -j ACCEPT -A INPUT -p icmp --icmp-type echo-request -m hashlimit --hashlimit-upto 5/s --hashlimit-mode srcip --hashlimit-srcmask 32 --hashlimit-name icmp-echo-drop -j ACCEPT
# Accept IPSEC traffic to ports 500 (IPSEC) and 4500 (MOBIKE aka IKE + NAT traversal) # Accept IPSEC/WireGuard traffic to ports {{ subnets|join(',') }}
-A INPUT -p udp -m multiport --dports 500,4500{% if wireguard_enabled %},{{ wireguard_port}}{% endif %} -j ACCEPT -A INPUT -p udp -m multiport --dports {{ ports|join(',') }} -j ACCEPT
# Allow new traffic to port 22 (SSH) # Allow new traffic to port 22 (SSH)
-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# Allow any traffic from the VPN
{% if ipsec_enabled %}
# Allow any traffic from the IPsec VPN
-A INPUT -p ipencap -m policy --dir in --pol ipsec --proto esp -j ACCEPT -A INPUT -p ipencap -m policy --dir in --pol ipsec --proto esp -j ACCEPT
{% endif %}
# TODO: # TODO:
# The IP of the resolver should be bound to a DUMMY interface. # The IP of the resolver should be bound to a DUMMY interface.
@ -70,10 +76,7 @@ COMMIT
-A INPUT -d {{ local_service_ip }} -p udp --dport 53 -j ACCEPT -A INPUT -d {{ local_service_ip }} -p udp --dport 53 -j ACCEPT
# Drop traffic between VPN clients # Drop traffic between VPN clients
{% if BetweenClients_DROP %} -A FORWARD -s {{ subnets|join(',') }} -d {{ subnets|join(',') }} -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
{% set BetweenClientsPolicy = "DROP" %}
{% endif %}
-A FORWARD -s {{ vpn_network }}{% if wireguard_enabled %},{{ wireguard_vpn_network }}{% endif %} -d {{ vpn_network }}{% if wireguard_enabled %},{{ wireguard_vpn_network }}{% endif %} -j {{ BetweenClientsPolicy | default("ACCEPT") }}
# Forward any packet that's part of an established connection # Forward any packet that's part of an established connection
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
@ -83,12 +86,14 @@ COMMIT
-A FORWARD -p udp -m multiport --ports 137,138 -j DROP -A FORWARD -p udp -m multiport --ports 137,138 -j DROP
-A FORWARD -p tcp -m multiport --ports 137,139 -j DROP -A FORWARD -p tcp -m multiport --ports 137,139 -j DROP
{% if ipsec_enabled %}
# Forward any IPSEC traffic from the VPN network # Forward any IPSEC traffic from the VPN network
-A FORWARD -m conntrack --ctstate NEW -s {{ vpn_network }} -m policy --pol ipsec --dir in -j ACCEPT -A FORWARD -m conntrack --ctstate NEW -s {{ strongswan_network }} -m policy --pol ipsec --dir in -j ACCEPT
{% endif %}
# Forward any traffic from the WireGuard VPN network
{% if wireguard_enabled %} {% if wireguard_enabled %}
-A FORWARD -m conntrack --ctstate NEW -s {{ wireguard_vpn_network }} -m policy --pol none --dir in -j ACCEPT # Forward any traffic from the WireGuard VPN network
-A FORWARD -m conntrack --ctstate NEW -s {{ wireguard_network_ipv4 }} -m policy --pol none --dir in -j ACCEPT
{% endif %} {% endif %}
COMMIT COMMIT

@ -1,3 +1,6 @@
{% set subnets = ([strongswan_network_ipv6] if ipsec_enabled else []) + ([wireguard_network_ipv6] if wireguard_enabled else []) %}
{% set ports = (['500', '4500'] if ipsec_enabled else []) + ([wireguard_port] if wireguard_enabled else []) %}
#### The mangle table #### The mangle table
# This table allows us to modify packet headers # This table allows us to modify packet headers
# Packets enter this table first # Packets enter this table first
@ -10,8 +13,8 @@
:OUTPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0] :POSTROUTING ACCEPT [0:0]
{% if reduce_mtu|int > 0 %} {% if reduce_mtu|int > 0 and ipsec_enabled %}
-A FORWARD -s {{ vpn_network_ipv6 }} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss {{ 1340 - reduce_mtu|int }} -A FORWARD -s {{ strongswan_network_ipv6 }} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss {{ 1340 - reduce_mtu|int }}
{% endif %} {% endif %}
COMMIT COMMIT
@ -26,7 +29,7 @@ COMMIT
:POSTROUTING ACCEPT [0:0] :POSTROUTING ACCEPT [0:0]
# Allow traffic from the VPN network to the outside world, and replies # Allow traffic from the VPN network to the outside world, and replies
-A POSTROUTING -s {{ vpn_network_ipv6 }}{% if wireguard_enabled %},{{ wireguard_vpn_network_ipv6 }}{% endif %} -m policy --pol none --dir out -j MASQUERADE -A POSTROUTING -s {{ subnets|join(',') }} -m policy --pol none --dir out -j MASQUERADE
COMMIT COMMIT
@ -60,8 +63,8 @@ COMMIT
-A INPUT -m ah -j ACCEPT -A INPUT -m ah -j ACCEPT
# rate limit ICMP traffic per source # rate limit ICMP traffic per source
-A INPUT -p icmpv6 --icmpv6-type echo-request -m hashlimit --hashlimit-upto 5/s --hashlimit-mode srcip --hashlimit-srcmask 32 --hashlimit-name icmp-echo-drop -j ACCEPT -A INPUT -p icmpv6 --icmpv6-type echo-request -m hashlimit --hashlimit-upto 5/s --hashlimit-mode srcip --hashlimit-srcmask 32 --hashlimit-name icmp-echo-drop -j ACCEPT
# Accept IPSEC traffic to ports 500 (IPSEC) and 4500 (MOBIKE aka IKE + NAT traversal) # Accept IPSEC/WireGuard traffic to ports {{ subnets|join(',') }}
-A INPUT -p udp -m multiport --dports 500,4500{% if wireguard_enabled %},{{ wireguard_port}}{% endif %} -j ACCEPT -A INPUT -p udp -m multiport --dports {{ ports|join(',') }} -j ACCEPT
# Allow new traffic to port 22 (SSH) # Allow new traffic to port 22 (SSH)
-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
@ -83,19 +86,18 @@ COMMIT
-A INPUT -d fcaa::1 -p udp --dport 53 -j ACCEPT -A INPUT -d fcaa::1 -p udp --dport 53 -j ACCEPT
# Drop traffic between VPN clients # Drop traffic between VPN clients
{% if BetweenClients_DROP %} -A FORWARD -s {{ subnets|join(',') }} -d {{ subnets|join(',') }} -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
{% set BetweenClientsPolicy = "DROP" %}
{% endif %}
-A FORWARD -s {{ vpn_network_ipv6 }}{% if wireguard_enabled %},{{ wireguard_vpn_network_ipv6 }}{% endif %} -d {{ vpn_network_ipv6 }}{% if wireguard_enabled %},{{ wireguard_vpn_network_ipv6 }}{% endif %} -j {{ BetweenClientsPolicy | default("ACCEPT") }}
-A FORWARD -j ICMPV6-CHECK -A FORWARD -j ICMPV6-CHECK
-A FORWARD -p tcp --dport 445 -j DROP -A FORWARD -p tcp --dport 445 -j DROP
-A FORWARD -p udp -m multiport --ports 137,138 -j DROP -A FORWARD -p udp -m multiport --ports 137,138 -j DROP
-A FORWARD -p tcp -m multiport --ports 137,139 -j DROP -A FORWARD -p tcp -m multiport --ports 137,139 -j DROP
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -m conntrack --ctstate NEW -s {{ vpn_network_ipv6 }} -m policy --pol ipsec --dir in -j ACCEPT {% if ipsec_enabled %}
-A FORWARD -m conntrack --ctstate NEW -s {{ strongswan_network_ipv6 }} -m policy --pol ipsec --dir in -j ACCEPT
{% endif %}
{% if wireguard_enabled %} {% if wireguard_enabled %}
-A FORWARD -m conntrack --ctstate NEW -s {{ wireguard_vpn_network_ipv6 }} -m policy --pol none --dir in -j ACCEPT -A FORWARD -m conntrack --ctstate NEW -s {{ wireguard_network_ipv6 }} -m policy --pol none --dir in -j ACCEPT
{% endif %} {% endif %}
# Use the ICMPV6-CHECK chain, described above # Use the ICMPV6-CHECK chain, described above

@ -0,0 +1,2 @@
---
ssh_tunnels_config_path: "configs/{{ IP_subject_alt_name }}/ssh-tunnel/"

@ -25,65 +25,93 @@
owner: root owner: root
group: "{{ root_group|default('root') }}" group: "{{ root_group|default('root') }}"
- name: Ensure that the SSH users exist - block:
user: - name: Ensure that the SSH users exist
name: "{{ item }}" user:
groups: algo name: "{{ item }}"
home: '/var/jail/{{ item }}' groups: algo
createhome: yes home: '/var/jail/{{ item }}'
generate_ssh_key: false createhome: yes
shell: /bin/false generate_ssh_key: false
state: present shell: /bin/false
append: yes state: present
with_items: "{{ users }}" append: yes
tags: update-users with_items: "{{ users }}"
- name: The authorized keys file created - block:
authorized_key: - name: Clean up the ssh-tunnel directory
user: "{{ item }}" file:
key: "{{ lookup('file', 'configs/' + IP_subject_alt_name + '/pki/public/' + item + '.pub') }}" dest: "{{ ssh_tunnels_config_path }}"
state: present state: absent
manage_dir: true when: keys_clean_all|bool == True
exclusive: true
with_items: "{{ users }}"
tags: update-users
- name: Generate SSH fingerprints - name: Ensure the config directories exist
shell: ssh-keyscan {{ IP_subject_alt_name }} 2>/dev/null file:
register: ssh_fingerprints dest: "{{ ssh_tunnels_config_path }}"
state: directory
recurse: yes
mode: '0700'
- name: Fetch the known_hosts file - name: Check if the private keys exist
local_action: stat:
module: template path: "{{ ssh_tunnels_config_path }}/{{ item }}.pem"
src: known_hosts.j2 register: privatekey
dest: configs/{{ IP_subject_alt_name }}/known_hosts with_items: "{{ users }}"
become: no
- name: Build the client ssh config - name: Build ssh private keys
local_action: openssl_privatekey:
module: template path: "{{ ssh_tunnels_config_path }}/{{ item.item }}.pem"
src: ssh_config.j2 passphrase: "{{ p12_export_password }}"
dest: configs/{{ IP_subject_alt_name }}/{{ item }}.ssh_config cipher: aes256
mode: 0600 force: false
become: false no_log: true
tags: update-users when: not item.stat.exists
with_items: "{{ users }}" with_items: "{{ privatekey.results }}"
register: openssl_privatekey
- name: Get active users - name: Build ssh public keys
getent: openssl_publickey:
database: group path: "{{ ssh_tunnels_config_path }}/{{ item.item.item }}.pub"
key: algo privatekey_path: "{{ ssh_tunnels_config_path }}/{{ item.item.item }}.pem"
split: ':' privatekey_passphrase: "{{ p12_export_password }}"
tags: update-users format: OpenSSH
force: true
no_log: true
when: item.changed
with_items: "{{ openssl_privatekey.results }}"
- name: Build the client ssh config
template:
src: ssh_config.j2
dest: "{{ ssh_tunnels_config_path }}/{{ item }}.ssh_config"
mode: 0700
with_items: "{{ users }}"
delegate_to: localhost
become: false
- name: The authorized keys file created
authorized_key:
user: "{{ item }}"
key: "{{ lookup('file', ssh_tunnels_config_path + '/' + item + '.pub') }}"
state: present
manage_dir: true
exclusive: true
with_items: "{{ users }}"
- name: Get active users
getent:
database: group
key: algo
split: ':'
- name: Delete non-existing users - name: Delete non-existing users
user: user:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent
remove: yes remove: yes
force: yes force: yes
when: item not in users when: item not in users
with_items: "{{ getent_group['algo'][2].split(',') }}" with_items: "{{ getent_group['algo'][2].split(',') }}"
tags: update-users tags: update-users
rescue: rescue:
- debug: var=fail_hint - debug: var=fail_hint

@ -1,3 +0,0 @@
{% for item in ssh_fingerprints.stdout_lines %}
{{ item }}
{% endfor %}

@ -1,31 +1,11 @@
--- ---
ipsec_config_path: "configs/{{ IP_subject_alt_name }}/ipsec/"
ipsec_pki_path: "{{ ipsec_config_path }}/.pki/"
strongswan_network: 10.19.48.0/24
strongswan_network_ipv6: 'fd9d:bc11:4020::/48'
strongswan_shell: /usr/sbin/nologin strongswan_shell: /usr/sbin/nologin
strongswan_home: /var/lib/strongswan strongswan_home: /var/lib/strongswan
BetweenClients_DROP: true BetweenClients_DROP: true
wireguard_config_path: "configs/{{ IP_subject_alt_name }}/wireguard/"
wireguard_interface: wg0
wireguard_network_ipv4:
subnet: 10.19.49.0
prefix: 24
gateway: 10.19.49.1
clients_range: 10.19.49
clients_start: 2
wireguard_network_ipv6:
subnet: 'fd9d:bc11:4021::'
prefix: 48
gateway: 'fd9d:bc11:4021::1'
clients_range: 'fd9d:bc11:4021::'
clients_start: 2
wireguard_vpn_network: "{{ wireguard_network_ipv4['subnet'] }}/{{ wireguard_network_ipv4['prefix'] }}"
wireguard_vpn_network_ipv6: "{{ wireguard_network_ipv6['subnet'] }}/{{ wireguard_network_ipv6['prefix'] }}"
keys_clean_all: false
wireguard_dns_servers: >-
{% if local_dns|default(false)|bool or dns_encryption|default(false)|bool == true %}
{{ local_service_ip }}
{% else %}
{% for host in dns_servers.ipv4 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% if ipv6_support %},{% for host in dns_servers.ipv6 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% endif %}
{% endif %}
algo_ondemand_cellular: false algo_ondemand_cellular: false
algo_ondemand_wifi: false algo_ondemand_wifi: false
algo_ondemand_wifi_exclude: '_null' algo_ondemand_wifi_exclude: '_null'
@ -65,3 +45,7 @@ ciphers:
compat: compat:
ike: aes256gcm16-prfsha512-ecp384,aes256-sha2_512-prfsha512-ecp384,aes256-sha2_384-prfsha384-ecp384! ike: aes256gcm16-prfsha512-ecp384,aes256-sha2_512-prfsha512-ecp384,aes256-sha2_384-prfsha384-ecp384!
esp: aes256gcm16-ecp384,aes256-sha2_512-prfsha512-ecp384! esp: aes256gcm16-ecp384,aes256-sha2_512-prfsha512-ecp384!
pkcs12_PayloadCertificateUUID: "{{ 900000 | random | to_uuid | upper }}"
VPN_PayloadIdentifier: "{{ 800000 | random | to_uuid | upper }}"
CA_PayloadIdentifier: "{{ 700000 | random | to_uuid | upper }}"

@ -7,11 +7,5 @@
- name: restart apparmor - name: restart apparmor
service: name=apparmor state=restarted service: name=apparmor state=restarted
- name: save iptables
shell: service netfilter-persistent save
- name: restart iptables
service: name=netfilter-persistent state=restarted
- name: rereadcrls - name: rereadcrls
shell: ipsec rereadcrls; ipsec purgecrls shell: ipsec rereadcrls; ipsec purgecrls

@ -1,20 +1,19 @@
--- ---
- name: Register p12 PayloadContent - name: Register p12 PayloadContent
shell: cat private/{{ item }}.p12 | base64 shell: cat private/{{ item }}.p12 | base64
register: PayloadContent register: PayloadContent
args: args:
chdir: "configs/{{ IP_subject_alt_name }}/pki/" chdir: "{{ ipsec_pki_path }}"
with_items: "{{ users }}" with_items: "{{ users }}"
- name: Set facts for mobileconfigs - name: Set facts for mobileconfigs
set_fact: set_fact:
PayloadContentCA: "{{ lookup('file' , 'configs/{{ IP_subject_alt_name }}/pki/cacert.pem')|b64encode }}" PayloadContentCA: "{{ lookup('file' , '{{ ipsec_pki_path }}/cacert.pem')|b64encode }}"
- name: Build the mobileconfigs - name: Build the mobileconfigs
template: template:
src: mobileconfig.j2 src: mobileconfig.j2
dest: configs/{{ IP_subject_alt_name }}/{{ item.0 }}.mobileconfig dest: "{{ ipsec_config_path }}/apple/{{ item.0 }}.mobileconfig"
mode: 0600 mode: 0600
with_together: with_together:
- "{{ users }}" - "{{ users }}"
@ -24,7 +23,7 @@
- name: Build the client ipsec config file - name: Build the client ipsec config file
template: template:
src: client_ipsec.conf.j2 src: client_ipsec.conf.j2
dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.conf dest: "{{ ipsec_config_path }}/manual/{{ item }}.conf"
mode: 0600 mode: 0600
with_items: with_items:
- "{{ users }}" - "{{ users }}"
@ -32,7 +31,7 @@
- name: Build the client ipsec secret file - name: Build the client ipsec secret file
template: template:
src: client_ipsec.secrets.j2 src: client_ipsec.secrets.j2
dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.secrets dest: "{{ ipsec_config_path }}/manual/{{ item }}.secrets"
mode: 0600 mode: 0600
with_items: with_items:
- "{{ users }}" - "{{ users }}"
@ -40,7 +39,7 @@
- name: Build the windows client powershell script - name: Build the windows client powershell script
template: template:
src: client_windows.ps1.j2 src: client_windows.ps1.j2
dest: configs/{{ IP_subject_alt_name }}/windows_{{ item.0 }}.ps1 dest: "{{ ipsec_config_path }}/windows/{{ item.0 }}.ps1"
mode: 0600 mode: 0600
when: algo_windows when: algo_windows
with_together: with_together:
@ -49,8 +48,6 @@
- name: Restrict permissions for the local private directories - name: Restrict permissions for the local private directories
file: file:
path: "{{ item }}" path: "{{ ipsec_config_path }}"
state: directory state: directory
mode: 0700 mode: 0700
with_items:
- configs/{{ IP_subject_alt_name }}

@ -0,0 +1,27 @@
---
- name: Copy the keys to the strongswan directory
copy:
src: "{{ ipsec_pki_path }}/{{ item.src }}"
dest: "{{ config_prefix|default('/') }}etc/ipsec.d/{{ item.dest }}"
owner: "{{ item.owner }}"
group: "{{ item.group }}"
mode: "{{ item.mode }}"
with_items:
- src: "cacert.pem"
dest: "cacerts/ca.crt"
owner: strongswan
group: "{{ root_group|default('root') }}"
mode: "0600"
- src: "certs/{{ IP_subject_alt_name }}.crt"
dest: "certs/{{ IP_subject_alt_name }}.crt"
owner: strongswan
group: "{{ root_group|default('root') }}"
mode: "0600"
- src: "private/{{ IP_subject_alt_name }}.key"
dest: "private/{{ IP_subject_alt_name }}.key"
owner: strongswan
group: "{{ root_group|default('root') }}"
mode: "0600"
notify:
- restart strongswan

@ -3,23 +3,23 @@
- name: Setup the config files from our templates - name: Setup the config files from our templates
template: template:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ item.dest }}" dest: "{{ config_prefix|default('/') }}etc/{{ item.dest }}"
owner: "{{ item.owner }}" owner: "{{ item.owner }}"
group: "{{ item.group }}" group: "{{ item.group }}"
mode: "{{ item.mode }}" mode: "{{ item.mode }}"
with_items: with_items:
- src: strongswan.conf.j2 - src: strongswan.conf.j2
dest: "{{ config_prefix|default('/') }}etc/strongswan.conf" dest: "strongswan.conf"
owner: root owner: root
group: "{{ root_group|default('root') }}" group: "{{ root_group|default('root') }}"
mode: "0644" mode: "0644"
- src: ipsec.conf.j2 - src: ipsec.conf.j2
dest: "{{ config_prefix|default('/') }}etc/ipsec.conf" dest: "ipsec.conf"
owner: root owner: root
group: "{{ root_group|default('root') }}" group: "{{ root_group|default('root') }}"
mode: "0644" mode: "0644"
- src: ipsec.secrets.j2 - src: ipsec.secrets.j2
dest: "{{ config_prefix|default('/') }}etc/ipsec.secrets" dest: "ipsec.secrets"
owner: strongswan owner: strongswan
group: "{{ root_group|default('root') }}" group: "{{ root_group|default('root') }}"
mode: "0600" mode: "0600"

@ -1,11 +1,5 @@
--- ---
- block: - block:
- name: Include WireGuard role
include_role:
name: wireguard
tags: wireguard
when: wireguard_enabled and ansible_distribution == 'Ubuntu'
- include_tasks: ubuntu.yml - include_tasks: ubuntu.yml
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu' when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'

@ -7,13 +7,13 @@
- name: Ensure the pki directory does not exist - name: Ensure the pki directory does not exist
file: file:
dest: configs/{{ IP_subject_alt_name }}/pki dest: "{{ ipsec_pki_path }}"
state: absent state: absent
when: keys_clean_all|bool == True when: keys_clean_all|bool == True
- name: Ensure the pki directories exist - name: Ensure the pki directories exist
file: file:
dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}" dest: "{{ ipsec_pki_path }}/{{ item }}"
state: directory state: directory
recurse: yes recurse: yes
mode: '0700' mode: '0700'
@ -26,9 +26,20 @@
- public - public
- reqs - reqs
- name: Ensure the config directories exist
file:
dest: "{{ ipsec_config_path }}/{{ item }}"
state: directory
recurse: yes
mode: '0700'
with_items:
- apple
- windows
- manual
- name: Ensure the files exist - name: Ensure the files exist
file: file:
dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}" dest: "{{ ipsec_pki_path }}/{{ item }}"
state: touch state: touch
with_items: with_items:
- ".rnd" - ".rnd"
@ -40,7 +51,7 @@
- name: Generate the openssl server configs - name: Generate the openssl server configs
template: template:
src: openssl.cnf.j2 src: openssl.cnf.j2
dest: "configs/{{ IP_subject_alt_name }}/pki/openssl.cnf" dest: "{{ ipsec_pki_path }}/openssl.cnf"
- name: Build the CA pair - name: Build the CA pair
shell: > shell: >
@ -55,20 +66,19 @@
-passout pass:"{{ CA_password }}" && -passout pass:"{{ CA_password }}" &&
touch {{ IP_subject_alt_name }}_ca_generated touch {{ IP_subject_alt_name }}_ca_generated
args: args:
chdir: "configs/{{ IP_subject_alt_name }}/pki/" chdir: "{{ ipsec_pki_path }}"
creates: "{{ IP_subject_alt_name }}_ca_generated" creates: "{{ IP_subject_alt_name }}_ca_generated"
executable: bash executable: bash
- name: Copy the CA certificate - name: Copy the CA certificate
copy: copy:
src: "configs/{{ IP_subject_alt_name }}/pki/cacert.pem" src: "{{ ipsec_pki_path }}/cacert.pem"
dest: "configs/{{ IP_subject_alt_name }}/cacert.pem" dest: "{{ ipsec_config_path }}/manual/cacert.pem"
mode: 0600
- name: Generate the serial number - name: Generate the serial number
shell: echo 01 > serial && touch serial_generated shell: echo 01 > serial && touch serial_generated
args: args:
chdir: "configs/{{ IP_subject_alt_name }}/pki/" chdir: "{{ ipsec_pki_path }}"
creates: serial_generated creates: serial_generated
- name: Build the server pair - name: Build the server pair
@ -90,7 +100,7 @@
-subj "/CN={{ IP_subject_alt_name }}" && -subj "/CN={{ IP_subject_alt_name }}" &&
touch certs/{{ IP_subject_alt_name }}_crt_generated touch certs/{{ IP_subject_alt_name }}_crt_generated
args: args:
chdir: "configs/{{ IP_subject_alt_name }}/pki/" chdir: "{{ ipsec_pki_path }}"
creates: certs/{{ IP_subject_alt_name }}_crt_generated creates: certs/{{ IP_subject_alt_name }}_crt_generated
executable: bash executable: bash
@ -113,23 +123,15 @@
-subj "/CN={{ item }}" && -subj "/CN={{ item }}" &&
touch certs/{{ item }}_crt_generated touch certs/{{ item }}_crt_generated
args: args:
chdir: "configs/{{ IP_subject_alt_name }}/pki/" chdir: "{{ ipsec_pki_path }}"
creates: certs/{{ item }}_crt_generated creates: certs/{{ item }}_crt_generated
executable: bash executable: bash
with_items: "{{ users }}" with_items: "{{ users }}"
- name: Create links for the private keys
file:
src: "pki/private/{{ item }}.key"
dest: "configs/{{ IP_subject_alt_name }}/{{ item }}.ssh.pem"
state: link
force: true
with_items: "{{ users }}"
- name: Build openssh public keys - name: Build openssh public keys
openssl_publickey: openssl_publickey:
path: "configs/{{ IP_subject_alt_name }}/pki/public/{{ item }}.pub" path: "{{ ipsec_pki_path }}/public/{{ item }}.pub"
privatekey_path: "configs/{{ IP_subject_alt_name }}/pki/private/{{ item }}.key" privatekey_path: "{{ ipsec_pki_path }}/private/{{ item }}.key"
format: OpenSSH format: OpenSSH
with_items: "{{ users }}" with_items: "{{ users }}"
@ -144,16 +146,15 @@
-out private/{{ item }}.p12 -out private/{{ item }}.p12
-passout pass:"{{ p12_export_password }}" -passout pass:"{{ p12_export_password }}"
args: args:
chdir: "configs/{{ IP_subject_alt_name }}/pki/" chdir: "{{ ipsec_pki_path }}"
executable: bash executable: bash
with_items: "{{ users }}" with_items: "{{ users }}"
register: p12 register: p12
- name: Copy the p12 certificates - name: Copy the p12 certificates
copy: copy:
src: "configs/{{ IP_subject_alt_name }}/pki/private/{{ item }}.p12" src: "{{ ipsec_pki_path }}/private/{{ item }}.p12"
dest: "configs/{{ IP_subject_alt_name }}/{{ item }}.p12" dest: "{{ ipsec_config_path }}/manual/{{ item }}.p12"
mode: 0600
with_items: with_items:
- "{{ users }}" - "{{ users }}"
@ -164,7 +165,7 @@
awk '{print $5}' | awk '{print $5}' |
sed 's/\/CN=//g' sed 's/\/CN=//g'
args: args:
chdir: "configs/{{ IP_subject_alt_name }}/pki/" chdir: "{{ ipsec_pki_path}}"
register: valid_certs register: valid_certs
- name: Revoke non-existing users - name: Revoke non-existing users
@ -176,7 +177,7 @@
-out crl/{{ item }}.crt -out crl/{{ item }}.crt
register: gencrl register: gencrl
args: args:
chdir: configs/{{ IP_subject_alt_name }}/pki/ chdir: "{{ ipsec_pki_path }}"
creates: crl/{{ item }}.crt creates: crl/{{ item }}.crt
executable: bash executable: bash
when: item not in users when: item not in users
@ -192,7 +193,7 @@
- gencrl is defined - gencrl is defined
- gencrl.changed - gencrl.changed
args: args:
chdir: configs/{{ IP_subject_alt_name }}/pki/ chdir: "{{ ipsec_pki_path }}"
executable: bash executable: bash
delegate_to: localhost delegate_to: localhost
become: no become: no
@ -201,7 +202,7 @@
- name: Copy the CRL to the vpn server - name: Copy the CRL to the vpn server
copy: copy:
src: configs/{{ IP_subject_alt_name }}/pki/crl/algo.root.pem src: "{{ ipsec_pki_path }}/crl/algo.root.pem"
dest: "{{ config_prefix|default('/') }}etc/ipsec.d/crls/algo.root.pem" dest: "{{ config_prefix|default('/') }}etc/ipsec.d/crls/algo.root.pem"
when: when:
- gencrl is defined - gencrl is defined

@ -43,6 +43,3 @@
notify: notify:
- daemon-reload - daemon-reload
- restart strongswan - restart strongswan
- include_tasks: iptables.yml
tags: iptables

@ -27,7 +27,7 @@ conn %default
right=%any right=%any
rightauth=pubkey rightauth=pubkey
rightsourceip={{ vpn_network }},{{ vpn_network_ipv6 }} rightsourceip={{ strongswan_network }},{{ strongswan_network_ipv6 }}
{% if algo_local_dns or dns_encryption %} {% if algo_local_dns or dns_encryption %}
rightdns={{ local_service_ip }} rightdns={{ local_service_ip }}
{% else %} {% else %}

@ -1,27 +0,0 @@
---
- name: Copy the keys to the strongswan directory
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ item.owner }}"
group: "{{ item.group }}"
mode: "{{ item.mode }}"
with_items:
- src: "configs/{{ IP_subject_alt_name }}/pki/cacert.pem"
dest: "{{ config_prefix|default('/') }}etc/ipsec.d/cacerts/ca.crt"
owner: strongswan
group: "{{ root_group|default('root') }}"
mode: "0600"
- src: "configs/{{ IP_subject_alt_name }}/pki/certs/{{ IP_subject_alt_name }}.crt"
dest: "{{ config_prefix|default('/') }}etc/ipsec.d/certs/{{ IP_subject_alt_name }}.crt"
owner: strongswan
group: "{{ root_group|default('root') }}"
mode: "0600"
- src: "configs/{{ IP_subject_alt_name }}/pki/private/{{ IP_subject_alt_name }}.key"
dest: "{{ config_prefix|default('/') }}etc/ipsec.d/private/{{ IP_subject_alt_name }}.key"
owner: strongswan
group: "{{ root_group|default('root') }}"
mode: "0600"
notify:
- restart strongswan

@ -1,4 +1,28 @@
--- ---
wireguard_PersistentKeepalive: 0 wireguard_PersistentKeepalive: 0
wireguard_client_ip: "{{ wireguard_network_ipv4['clients_range'] }}.{{ wireguard_network_ipv4['clients_start'] + index|int + 1 }}/{{ wireguard_network_ipv4['prefix'] }}{% if ipv6_support %},{{ wireguard_network_ipv6['clients_range'] }}{{ wireguard_network_ipv6['clients_start'] + index|int + 1 }}/{{ wireguard_network_ipv6['prefix'] }}{% endif %}" wireguard_config_path: "configs/{{ IP_subject_alt_name }}/wireguard/"
wireguard_server_ip: "{{ wireguard_network_ipv4['gateway'] }}/{{ wireguard_network_ipv4['prefix'] }}{% if ipv6_support %},{{ wireguard_network_ipv6['gateway'] }}/{{ wireguard_network_ipv6['prefix'] }}{% endif %}" wireguard_pki_path: "{{ wireguard_config_path }}/.pki/"
wireguard_interface: wg0
_wireguard_network_ipv4:
subnet: 10.19.49.0
prefix: 24
gateway: 10.19.49.1
clients_range: 10.19.49
clients_start: 2
_wireguard_network_ipv6:
subnet: 'fd9d:bc11:4021::'
prefix: 48
gateway: 'fd9d:bc11:4021::1'
clients_range: 'fd9d:bc11:4021::'
clients_start: 2
wireguard_network_ipv4: "{{ _wireguard_network_ipv4['subnet'] }}/{{ _wireguard_network_ipv4['prefix'] }}"
wireguard_network_ipv6: "{{ _wireguard_network_ipv6['subnet'] }}/{{ _wireguard_network_ipv6['prefix'] }}"
keys_clean_all: false
wireguard_dns_servers: >-
{% if local_dns|default(false)|bool or dns_encryption|default(false)|bool == true %}
{{ local_service_ip }}
{% else %}
{% for host in dns_servers.ipv4 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% if ipv6_support %},{% for host in dns_servers.ipv6 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% endif %}
{% endif %}
wireguard_client_ip: "{{ _wireguard_network_ipv4['clients_range'] }}.{{ _wireguard_network_ipv4['clients_start'] + index|int + 1 }}/{{ _wireguard_network_ipv4['prefix'] }}{% if ipv6_support %},{{ _wireguard_network_ipv6['clients_range'] }}{{ _wireguard_network_ipv6['clients_start'] + index|int + 1 }}/{{ _wireguard_network_ipv6['prefix'] }}{% endif %}"
wireguard_server_ip: "{{ _wireguard_network_ipv4['gateway'] }}/{{ _wireguard_network_ipv4['prefix'] }}{% if ipv6_support %},{{ _wireguard_network_ipv6['gateway'] }}/{{ _wireguard_network_ipv6['prefix'] }}{% endif %}"

@ -20,7 +20,7 @@
- block: - block:
- name: Save private keys - name: Save private keys
copy: copy:
dest: "{{ wireguard_config_path }}/private/{{ item['item'] }}" dest: "{{ wireguard_pki_path }}/private/{{ item['item'] }}"
content: "{{ item['stdout'] }}" content: "{{ item['stdout'] }}"
mode: "0600" mode: "0600"
no_log: true no_log: true
@ -39,7 +39,7 @@
when: wg_genkey.changed when: wg_genkey.changed
- name: Generate public keys - name: Generate public keys
shell: echo "{{ lookup('file', wireguard_config_path + '/private/' + item) }}" | wg pubkey shell: echo "{{ lookup('file', wireguard_pki_path + '/private/' + item) }}" | wg pubkey
register: wg_pubkey register: wg_pubkey
changed_when: false changed_when: false
args: args:
@ -50,7 +50,7 @@
- name: Save public keys - name: Save public keys
copy: copy:
dest: "{{ wireguard_config_path }}/public/{{ item['item'] }}" dest: "{{ wireguard_pki_path }}/public/{{ item['item'] }}"
content: "{{ item['stdout'] }}" content: "{{ item['stdout'] }}"
mode: "0600" mode: "0600"
no_log: true no_log: true

@ -1,7 +1,7 @@
--- ---
- name: Ensure the required directories exist - name: Ensure the required directories exist
file: file:
dest: "{{ wireguard_config_path }}/{{ item }}" dest: "{{ wireguard_pki_path }}/{{ item }}"
state: directory state: directory
recurse: true recurse: true
with_items: with_items:
@ -28,7 +28,7 @@
- block: - block:
- name: WireGuard user list updated - name: WireGuard user list updated
lineinfile: lineinfile:
dest: "{{ wireguard_config_path }}/index.txt" dest: "{{ wireguard_pki_path }}/index.txt"
create: true create: true
mode: "0600" mode: "0600"
insertafter: EOF insertafter: EOF
@ -37,7 +37,7 @@
with_items: "{{ users }}" with_items: "{{ users }}"
- set_fact: - set_fact:
wireguard_users: "{{ (lookup('file', wireguard_config_path + 'index.txt')).split('\n') }}" wireguard_users: "{{ (lookup('file', wireguard_pki_path + 'index.txt')).split('\n') }}"
- name: WireGuard users config generated - name: WireGuard users config generated
template: template:

@ -1,12 +1,12 @@
[Interface] [Interface]
PrivateKey = {{ lookup('file', wireguard_config_path + '/private/' + item.1) }} PrivateKey = {{ lookup('file', wireguard_pki_path + '/private/' + item.1) }}
Address = {{ wireguard_client_ip }} Address = {{ wireguard_client_ip }}
DNS = {{ wireguard_dns_servers }} DNS = {{ wireguard_dns_servers }}
{% if reduce_mtu|int > 0 %}MTU = {{ 1420 - reduce_mtu|int }} {% if reduce_mtu|int > 0 %}MTU = {{ 1420 - reduce_mtu|int }}
{% endif %} {% endif %}
[Peer] [Peer]
PublicKey = {{ lookup('file', wireguard_config_path + '/public/' + IP_subject_alt_name) }} PublicKey = {{ lookup('file', wireguard_pki_path + '/public/' + IP_subject_alt_name) }}
AllowedIPs = 0.0.0.0/0, ::/0 AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = {{ IP_subject_alt_name }}:{{ wireguard_port }} Endpoint = {{ IP_subject_alt_name }}:{{ wireguard_port }}
{{ 'PersistentKeepalive = ' + wireguard_PersistentKeepalive|string if wireguard_PersistentKeepalive > 0 else '' }} {{ 'PersistentKeepalive = ' + wireguard_PersistentKeepalive|string if wireguard_PersistentKeepalive > 0 else '' }}

@ -1,7 +1,7 @@
[Interface] [Interface]
Address = {{ wireguard_server_ip }} Address = {{ wireguard_server_ip }}
ListenPort = {{ wireguard_port }} ListenPort = {{ wireguard_port }}
PrivateKey = {{ lookup('file', wireguard_config_path + '/private/' + IP_subject_alt_name) }} PrivateKey = {{ lookup('file', wireguard_pki_path + '/private/' + IP_subject_alt_name) }}
SaveConfig = false SaveConfig = false
{% for u in wireguard_users %} {% for u in wireguard_users %}
@ -10,8 +10,8 @@ SaveConfig = false
[Peer] [Peer]
# {{ u }} # {{ u }}
PublicKey = {{ lookup('file', wireguard_config_path + '/public/' + u) }} PublicKey = {{ lookup('file', wireguard_pki_path + '/public/' + u) }}
AllowedIPs = {{ wireguard_network_ipv4['clients_range'] }}.{{ wireguard_network_ipv4['clients_start'] + index }}/32{% if ipv6_support %},{{ wireguard_network_ipv6['clients_range'] }}{{ wireguard_network_ipv6['clients_start'] + index }}/128{% endif %} AllowedIPs = {{ _wireguard_network_ipv4['clients_range'] }}.{{ _wireguard_network_ipv4['clients_start'] + index }}/32{% if ipv6_support %},{{ _wireguard_network_ipv6['clients_range'] }}{{ _wireguard_network_ipv6['clients_start'] + index }}/128{% endif %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}

@ -19,8 +19,9 @@
- role: wireguard - role: wireguard
when: wireguard_enabled when: wireguard_enabled
tags: wireguard tags: wireguard
- role: vpn - role: strongswan
tags: vpn when: ipsec_enabled
tags: ipsec
- role: ssh_tunneling - role: ssh_tunneling
when: algo_ssh_tunneling when: algo_ssh_tunneling
tags: ssh_tunneling tags: ssh_tunneling
@ -30,15 +31,17 @@
- name: Delete the CA key - name: Delete the CA key
local_action: local_action:
module: file module: file
path: "configs/{{ IP_subject_alt_name }}/pki/private/cakey.pem" path: "{{ ipsec_pki_path }}/private/cakey.pem"
state: absent state: absent
become: false become: false
when: not algo_store_cakey when:
- ipsec_enabled
- not algo_store_cakey
- name: Dump the configuration - name: Dump the configuration
local_action: local_action:
module: copy module: copy
dest: "configs/{{ IP_subject_alt_name }}/config.yml" dest: "configs/{{ IP_subject_alt_name }}/.config.yml"
content: | content: |
server: {{ 'localhost' if inventory_hostname == 'localhost' else inventory_hostname }} server: {{ 'localhost' if inventory_hostname == 'localhost' else inventory_hostname }}
server_user: {{ ansible_ssh_user }} server_user: {{ ansible_ssh_user }}
@ -55,6 +58,8 @@
algo_windows: {{ algo_windows }} algo_windows: {{ algo_windows }}
algo_store_cakey: {{ algo_store_cakey }} algo_store_cakey: {{ algo_store_cakey }}
IP_subject_alt_name: {{ IP_subject_alt_name }} IP_subject_alt_name: {{ IP_subject_alt_name }}
ipsec_enabled: {{ ipsec_enabled }}
wireguard_enabled: {{ wireguard_enabled }}
{% if tests|default(false)|bool %}ca_password: {{ CA_password }}{% endif %} {% if tests|default(false)|bool %}ca_password: {{ CA_password }}{% endif %}
become: false become: false
@ -69,9 +74,9 @@
- debug: - debug:
msg: msg:
- "{{ congrats.common.split('\n') }}" - "{{ congrats.common.split('\n') }}"
- " {{ congrats.p12_pass }}" - " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}"
- " {% if algo_store_cakey %}{{ congrats.ca_key_pass }}{% endif %}" - " {{ congrats.ca_key_pass if algo_store_cakey and ipsec_enabled else '' }}"
- " {% if algo_provider != 'local' %}{{ congrats.ssh_access }}{% endif %}" - " {{ congrats.ssh_access if algo_provider != 'local' else ''}}"
tags: always tags: always
rescue: rescue:
- debug: var=fail_hint - debug: var=fail_hint

@ -11,7 +11,11 @@ else
ansible-playbook users.yml -e "${USER_ARGS}" -t update-users ansible-playbook users.yml -e "${USER_ARGS}" -t update-users
fi fi
if sudo openssl crl -inform pem -noout -text -in configs/$LXC_IP/pki/crl/phone.crt | grep CRL #
# IPsec
#
if sudo openssl crl -inform pem -noout -text -in configs/$LXC_IP/ipsec/.pki/crl/phone.crt | grep CRL
then then
echo "The CRL check passed" echo "The CRL check passed"
else else
@ -19,10 +23,34 @@ if sudo openssl crl -inform pem -noout -text -in configs/$LXC_IP/pki/crl/phone.c
exit 1 exit 1
fi fi
if sudo openssl x509 -inform pem -noout -text -in configs/$LXC_IP/pki/certs/user1.crt | grep CN=user1 if sudo openssl x509 -inform pem -noout -text -in configs/$LXC_IP/ipsec/.pki/certs/user1.crt | grep CN=user1
then then
echo "The new user exists" echo "The new user exists"
else else
echo "The new user does not exist" echo "The new user does not exist"
exit 1 exit 1
fi fi
#
# WireGuard
#
if sudo test -f configs/$LXC_IP/wireguard/user1.conf
then
echo "WireGuard: The new user exists"
else
echo "WireGuard: The new user does not exist"
exit 1
fi
#
# SSH tunneling
#
if sudo test -f configs/$LXC_IP/ssh-tunnel/user1.ssh_config
then
echo "SSH Tunneling: The new user exists"
else
echo "SSH Tunneling: The new user does not exist"
exit 1
fi

@ -21,13 +21,15 @@
- name: Import host specific variables - name: Import host specific variables
include_vars: include_vars:
file: "configs/{{ algo_server }}/config.yml" file: "configs/{{ algo_server }}/.config.yml"
- pause: - pause:
prompt: Enter the password for the private CA key prompt: Enter the password for the private CA key
echo: false echo: false
register: _ca_password register: _ca_password
when: ca_password is undefined when:
- ca_password is undefined
- ipsec_enabled
- name: Set facts based on the input - name: Set facts based on the input
set_fact: set_fact:
@ -42,7 +44,7 @@
groups: vpn-host groups: vpn-host
ansible_ssh_user: "{{ server_user|default('root') }}" ansible_ssh_user: "{{ server_user|default('root') }}"
ansible_connection: "{% if algo_server == 'localhost' %}local{% else %}ssh{% endif %}" ansible_connection: "{% if algo_server == 'localhost' %}local{% else %}ssh{% endif %}"
ansible_python_interpreter: "/usr/bin/python2.7" ansible_python_interpreter: "/usr/bin/python3"
CA_password: "{{ CA_password }}" CA_password: "{{ CA_password }}"
rescue: rescue:
- debug: var=fail_hint - debug: var=fail_hint
@ -56,7 +58,7 @@
become: true become: true
vars_files: vars_files:
- config.cfg - config.cfg
- "configs/{{ inventory_hostname }}/config.yml" - "configs/{{ inventory_hostname }}/.config.yml"
pre_tasks: pre_tasks:
- block: - block:
@ -74,8 +76,9 @@
- role: wireguard - role: wireguard
tags: [ 'vpn', 'wireguard' ] tags: [ 'vpn', 'wireguard' ]
when: wireguard_enabled when: wireguard_enabled
- role: vpn - role: strongswan
tags: vpn when: ipsec_enabled
tags: ipsec
- role: ssh_tunneling - role: ssh_tunneling
when: algo_ssh_tunneling when: algo_ssh_tunneling

Loading…
Cancel
Save