mirror of
https://github.com/trailofbits/algo.git
synced 2025-04-16 22:27:20 +02:00
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 ```  </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.
This commit is contained in:
parent
7e7476ec6b
commit
273c7665d3
42 changed files with 360 additions and 365 deletions
|
@ -123,9 +123,9 @@ Install strongSwan, then copy the included ipsec_user.conf, ipsec_user.secrets,
|
|||
#### Ubuntu Server 18.04 example
|
||||
|
||||
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`
|
||||
3. `/etc/ipsec.d/private`: copy `<name>.key` from `algo-master/configs/<server_ip>/pki/private/<name>.key`
|
||||
4. `/etc/ipsec.d/cacerts`: copy `cacert.pem` from `algo-master/configs/<server_ip>/pki/cacert.pem`
|
||||
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>/ipsec/manual/<name>.key`
|
||||
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`
|
||||
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
|
||||
|
@ -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.
|
||||
|
||||
`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
|
||||
|
||||
|
|
18
config.cfg
18
config.cfg
|
@ -18,8 +18,14 @@ keys_clean_all: False
|
|||
# Clean up cloud python environments
|
||||
clean_environment: false
|
||||
|
||||
vpn_network: 10.19.48.0/24
|
||||
vpn_network_ipv6: 'fd9d:bc11:4020::/48'
|
||||
# Deploy StrongSwan to enable IPsec support
|
||||
ipsec_enabled: true
|
||||
|
||||
# StrongSwan log level
|
||||
# https://wiki.strongswan.org/projects/strongswan/wiki/LoggerConfiguration
|
||||
strongswan_log_level: 2
|
||||
|
||||
# Deploy WireGuard
|
||||
wireguard_enabled: true
|
||||
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.
|
||||
|
@ -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
|
||||
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
|
||||
# after deployment by modifying the line starting "BLOCKLIST_URLS=" at:
|
||||
# /usr/local/sbin/adblock.sh
|
||||
|
@ -90,10 +92,6 @@ unattended_reboot:
|
|||
enabled: false
|
||||
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
|
||||
BetweenClients_DROP: true
|
||||
|
||||
|
|
71
input.yml
71
input.yml
|
@ -48,30 +48,45 @@
|
|||
when:
|
||||
- server_name is undefined
|
||||
- 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:
|
||||
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:
|
||||
prompt: |
|
||||
Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to Wi-Fi?
|
||||
[y/N]
|
||||
register: _ondemand_wifi
|
||||
when: ondemand_wifi is undefined
|
||||
|
||||
- pause:
|
||||
prompt: |
|
||||
Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to Wi-Fi?
|
||||
[y/N]
|
||||
register: _ondemand_wifi
|
||||
when: ondemand_wifi is undefined
|
||||
- pause:
|
||||
prompt: |
|
||||
List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand"
|
||||
(e.g., your home network. Comma-separated value, e.g., HomeNet,OfficeWifi,AlgoWiFi)
|
||||
register: _ondemand_wifi_exclude
|
||||
when:
|
||||
- ondemand_wifi_exclude is undefined
|
||||
- (ondemand_wifi|default(false)|bool) or
|
||||
(booleans_map[_ondemand_wifi.user_input|default(omit)]|default(false))
|
||||
|
||||
- pause:
|
||||
prompt: |
|
||||
List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand"
|
||||
(e.g., your home network. Comma-separated value, e.g., HomeNet,OfficeWifi,AlgoWiFi)
|
||||
register: _ondemand_wifi_exclude
|
||||
when:
|
||||
- ondemand_wifi_exclude is undefined
|
||||
- (ondemand_wifi|default(false)|bool) or
|
||||
(booleans_map[_ondemand_wifi.user_input|default(omit)]|default(false))
|
||||
- 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
|
||||
when: ipsec_enabled
|
||||
|
||||
- pause:
|
||||
prompt: |
|
||||
|
@ -87,20 +102,6 @@
|
|||
register: _ssh_tunneling
|
||||
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
|
||||
set_fact:
|
||||
algo_server_name: >-
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
groups: vpn-host
|
||||
ansible_connection: "{% if cloud_instance_ip == 'localhost' %}local{% else %}ssh{% endif %}"
|
||||
ansible_ssh_user: "{{ ansible_ssh_user }}"
|
||||
ansible_python_interpreter: "/usr/bin/python2.7"
|
||||
ansible_python_interpreter: "/usr/bin/python3"
|
||||
algo_provider: "{{ algo_provider }}"
|
||||
algo_server_name: "{{ algo_server_name }}"
|
||||
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 }}"
|
||||
dest: "{{ item.dest }}"
|
||||
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"
|
||||
- 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"
|
||||
- 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"
|
||||
notify:
|
||||
- restart strongswan
|
||||
|
|
|
@ -19,3 +19,9 @@
|
|||
ifconfig lo100 create &&
|
||||
ifconfig lo100 inet {{ local_service_ip }} netmask 255.255.255.255 &&
|
||||
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
|
||||
setup:
|
||||
|
||||
|
@ -15,7 +27,6 @@
|
|||
strongswan_additional_plugins:
|
||||
- kernel-pfroute
|
||||
- kernel-pfkey
|
||||
ansible_python_interpreter: /usr/local/bin/python2.7
|
||||
tools:
|
||||
- git
|
||||
- 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
|
||||
setup:
|
||||
|
||||
|
@ -115,15 +95,20 @@
|
|||
value: 1
|
||||
|
||||
- name: Install tools
|
||||
package: name="{{ item }}" state=present
|
||||
apt:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
with_items:
|
||||
- "{{ tools|default([]) }}"
|
||||
|
||||
- name: Install headers
|
||||
apt:
|
||||
name: "{{ item }}"
|
||||
name:
|
||||
- linux-headers-generic
|
||||
- "linux-headers-{{ ansible_kernel }}"
|
||||
state: present
|
||||
when: install_headers
|
||||
with_items:
|
||||
- linux-headers-generic
|
||||
- "linux-headers-{{ ansible_kernel }}"
|
||||
|
||||
- include_tasks: iptables.yml
|
||||
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
|
||||
# This table allows us to modify packet headers
|
||||
# Packets enter this table first
|
||||
|
@ -10,8 +13,8 @@
|
|||
:OUTPUT ACCEPT [0:0]
|
||||
:POSTROUTING ACCEPT [0:0]
|
||||
|
||||
{% if reduce_mtu|int > 0 %}
|
||||
-A FORWARD -s {{ vpn_network }} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss {{ 1360 - reduce_mtu|int }}
|
||||
{% if reduce_mtu|int > 0 and ipsec_enabled %}
|
||||
-A FORWARD -s {{ strongswan_network }} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss {{ 1360 - reduce_mtu|int }}
|
||||
{% endif %}
|
||||
|
||||
COMMIT
|
||||
|
@ -27,7 +30,7 @@ COMMIT
|
|||
:POSTROUTING ACCEPT [0:0]
|
||||
|
||||
# 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
|
||||
|
@ -54,12 +57,15 @@ COMMIT
|
|||
-A INPUT -p ah -j ACCEPT
|
||||
# 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
|
||||
# Accept IPSEC traffic to ports 500 (IPSEC) and 4500 (MOBIKE aka IKE + NAT traversal)
|
||||
-A INPUT -p udp -m multiport --dports 500,4500{% if wireguard_enabled %},{{ wireguard_port}}{% endif %} -j ACCEPT
|
||||
# Accept IPSEC/WireGuard traffic to ports {{ subnets|join(',') }}
|
||||
-A INPUT -p udp -m multiport --dports {{ ports|join(',') }} -j ACCEPT
|
||||
# Allow new traffic to port 22 (SSH)
|
||||
-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
|
||||
{% endif %}
|
||||
|
||||
# TODO:
|
||||
# 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
|
||||
|
||||
# Drop traffic between VPN clients
|
||||
{% if BetweenClients_DROP %}
|
||||
{% 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") }}
|
||||
-A FORWARD -s {{ subnets|join(',') }} -d {{ subnets|join(',') }} -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
|
||||
|
||||
# Forward any packet that's part of an established connection
|
||||
-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 tcp -m multiport --ports 137,139 -j DROP
|
||||
|
||||
{% if ipsec_enabled %}
|
||||
# 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 %}
|
||||
-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 %}
|
||||
|
||||
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
|
||||
# This table allows us to modify packet headers
|
||||
# Packets enter this table first
|
||||
|
@ -10,8 +13,8 @@
|
|||
:OUTPUT ACCEPT [0:0]
|
||||
:POSTROUTING ACCEPT [0:0]
|
||||
|
||||
{% if reduce_mtu|int > 0 %}
|
||||
-A FORWARD -s {{ vpn_network_ipv6 }} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss {{ 1340 - reduce_mtu|int }}
|
||||
{% if reduce_mtu|int > 0 and ipsec_enabled %}
|
||||
-A FORWARD -s {{ strongswan_network_ipv6 }} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss {{ 1340 - reduce_mtu|int }}
|
||||
{% endif %}
|
||||
|
||||
COMMIT
|
||||
|
@ -26,7 +29,7 @@ COMMIT
|
|||
:POSTROUTING ACCEPT [0:0]
|
||||
|
||||
# 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
|
||||
|
||||
|
@ -60,8 +63,8 @@ COMMIT
|
|||
-A INPUT -m ah -j ACCEPT
|
||||
# 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
|
||||
# Accept IPSEC traffic to ports 500 (IPSEC) and 4500 (MOBIKE aka IKE + NAT traversal)
|
||||
-A INPUT -p udp -m multiport --dports 500,4500{% if wireguard_enabled %},{{ wireguard_port}}{% endif %} -j ACCEPT
|
||||
# Accept IPSEC/WireGuard traffic to ports {{ subnets|join(',') }}
|
||||
-A INPUT -p udp -m multiport --dports {{ ports|join(',') }} -j ACCEPT
|
||||
# Allow new traffic to port 22 (SSH)
|
||||
-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
|
||||
|
||||
# Drop traffic between VPN clients
|
||||
{% if BetweenClients_DROP %}
|
||||
{% 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 -s {{ subnets|join(',') }} -d {{ subnets|join(',') }} -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
|
||||
|
||||
-A FORWARD -j ICMPV6-CHECK
|
||||
-A FORWARD -p tcp --dport 445 -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 -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 %}
|
||||
-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 %}
|
||||
|
||||
# Use the ICMPV6-CHECK chain, described above
|
2
roles/ssh_tunneling/defaults/main.yml
Normal file
2
roles/ssh_tunneling/defaults/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
ssh_tunnels_config_path: "configs/{{ IP_subject_alt_name }}/ssh-tunnel/"
|
|
@ -25,65 +25,93 @@
|
|||
owner: root
|
||||
group: "{{ root_group|default('root') }}"
|
||||
|
||||
- name: Ensure that the SSH users exist
|
||||
user:
|
||||
name: "{{ item }}"
|
||||
groups: algo
|
||||
home: '/var/jail/{{ item }}'
|
||||
createhome: yes
|
||||
generate_ssh_key: false
|
||||
shell: /bin/false
|
||||
state: present
|
||||
append: yes
|
||||
with_items: "{{ users }}"
|
||||
tags: update-users
|
||||
- block:
|
||||
- name: Ensure that the SSH users exist
|
||||
user:
|
||||
name: "{{ item }}"
|
||||
groups: algo
|
||||
home: '/var/jail/{{ item }}'
|
||||
createhome: yes
|
||||
generate_ssh_key: false
|
||||
shell: /bin/false
|
||||
state: present
|
||||
append: yes
|
||||
with_items: "{{ users }}"
|
||||
|
||||
- name: The authorized keys file created
|
||||
authorized_key:
|
||||
user: "{{ item }}"
|
||||
key: "{{ lookup('file', 'configs/' + IP_subject_alt_name + '/pki/public/' + item + '.pub') }}"
|
||||
state: present
|
||||
manage_dir: true
|
||||
exclusive: true
|
||||
with_items: "{{ users }}"
|
||||
tags: update-users
|
||||
- block:
|
||||
- name: Clean up the ssh-tunnel directory
|
||||
file:
|
||||
dest: "{{ ssh_tunnels_config_path }}"
|
||||
state: absent
|
||||
when: keys_clean_all|bool == True
|
||||
|
||||
- name: Generate SSH fingerprints
|
||||
shell: ssh-keyscan {{ IP_subject_alt_name }} 2>/dev/null
|
||||
register: ssh_fingerprints
|
||||
- name: Ensure the config directories exist
|
||||
file:
|
||||
dest: "{{ ssh_tunnels_config_path }}"
|
||||
state: directory
|
||||
recurse: yes
|
||||
mode: '0700'
|
||||
|
||||
- name: Fetch the known_hosts file
|
||||
local_action:
|
||||
module: template
|
||||
src: known_hosts.j2
|
||||
dest: configs/{{ IP_subject_alt_name }}/known_hosts
|
||||
become: no
|
||||
- name: Check if the private keys exist
|
||||
stat:
|
||||
path: "{{ ssh_tunnels_config_path }}/{{ item }}.pem"
|
||||
register: privatekey
|
||||
with_items: "{{ users }}"
|
||||
|
||||
- name: Build the client ssh config
|
||||
local_action:
|
||||
module: template
|
||||
src: ssh_config.j2
|
||||
dest: configs/{{ IP_subject_alt_name }}/{{ item }}.ssh_config
|
||||
mode: 0600
|
||||
become: false
|
||||
tags: update-users
|
||||
with_items: "{{ users }}"
|
||||
- name: Build ssh private keys
|
||||
openssl_privatekey:
|
||||
path: "{{ ssh_tunnels_config_path }}/{{ item.item }}.pem"
|
||||
passphrase: "{{ p12_export_password }}"
|
||||
cipher: aes256
|
||||
force: false
|
||||
no_log: true
|
||||
when: not item.stat.exists
|
||||
with_items: "{{ privatekey.results }}"
|
||||
register: openssl_privatekey
|
||||
|
||||
- name: Get active users
|
||||
getent:
|
||||
database: group
|
||||
key: algo
|
||||
split: ':'
|
||||
tags: update-users
|
||||
- name: Build ssh public keys
|
||||
openssl_publickey:
|
||||
path: "{{ ssh_tunnels_config_path }}/{{ item.item.item }}.pub"
|
||||
privatekey_path: "{{ ssh_tunnels_config_path }}/{{ item.item.item }}.pem"
|
||||
privatekey_passphrase: "{{ p12_export_password }}"
|
||||
format: OpenSSH
|
||||
force: true
|
||||
no_log: true
|
||||
when: item.changed
|
||||
with_items: "{{ openssl_privatekey.results }}"
|
||||
|
||||
- name: Delete non-existing users
|
||||
user:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
remove: yes
|
||||
force: yes
|
||||
when: item not in users
|
||||
with_items: "{{ getent_group['algo'][2].split(',') }}"
|
||||
- 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
|
||||
user:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
remove: yes
|
||||
force: yes
|
||||
when: item not in users
|
||||
with_items: "{{ getent_group['algo'][2].split(',') }}"
|
||||
tags: update-users
|
||||
rescue:
|
||||
- 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_home: /var/lib/strongswan
|
||||
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_wifi: false
|
||||
algo_ondemand_wifi_exclude: '_null'
|
||||
|
@ -65,3 +45,7 @@ ciphers:
|
|||
compat:
|
||||
ike: aes256gcm16-prfsha512-ecp384,aes256-sha2_512-prfsha512-ecp384,aes256-sha2_384-prfsha384-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
|
||||
service: name=apparmor state=restarted
|
||||
|
||||
- name: save iptables
|
||||
shell: service netfilter-persistent save
|
||||
|
||||
- name: restart iptables
|
||||
service: name=netfilter-persistent state=restarted
|
||||
|
||||
- name: rereadcrls
|
||||
shell: ipsec rereadcrls; ipsec purgecrls
|
|
@ -1,20 +1,19 @@
|
|||
---
|
||||
|
||||
- name: Register p12 PayloadContent
|
||||
shell: cat private/{{ item }}.p12 | base64
|
||||
register: PayloadContent
|
||||
args:
|
||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||
chdir: "{{ ipsec_pki_path }}"
|
||||
with_items: "{{ users }}"
|
||||
|
||||
- name: Set facts for mobileconfigs
|
||||
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
|
||||
template:
|
||||
src: mobileconfig.j2
|
||||
dest: configs/{{ IP_subject_alt_name }}/{{ item.0 }}.mobileconfig
|
||||
dest: "{{ ipsec_config_path }}/apple/{{ item.0 }}.mobileconfig"
|
||||
mode: 0600
|
||||
with_together:
|
||||
- "{{ users }}"
|
||||
|
@ -24,7 +23,7 @@
|
|||
- name: Build the client ipsec config file
|
||||
template:
|
||||
src: client_ipsec.conf.j2
|
||||
dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.conf
|
||||
dest: "{{ ipsec_config_path }}/manual/{{ item }}.conf"
|
||||
mode: 0600
|
||||
with_items:
|
||||
- "{{ users }}"
|
||||
|
@ -32,7 +31,7 @@
|
|||
- name: Build the client ipsec secret file
|
||||
template:
|
||||
src: client_ipsec.secrets.j2
|
||||
dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.secrets
|
||||
dest: "{{ ipsec_config_path }}/manual/{{ item }}.secrets"
|
||||
mode: 0600
|
||||
with_items:
|
||||
- "{{ users }}"
|
||||
|
@ -40,7 +39,7 @@
|
|||
- name: Build the windows client powershell script
|
||||
template:
|
||||
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
|
||||
when: algo_windows
|
||||
with_together:
|
||||
|
@ -49,8 +48,6 @@
|
|||
|
||||
- name: Restrict permissions for the local private directories
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
path: "{{ ipsec_config_path }}"
|
||||
state: directory
|
||||
mode: 0700
|
||||
with_items:
|
||||
- configs/{{ IP_subject_alt_name }}
|
27
roles/strongswan/tasks/distribute_keys.yml
Normal file
27
roles/strongswan/tasks/distribute_keys.yml
Normal file
|
@ -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
|
||||
template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ item.dest }}"
|
||||
dest: "{{ config_prefix|default('/') }}etc/{{ item.dest }}"
|
||||
owner: "{{ item.owner }}"
|
||||
group: "{{ item.group }}"
|
||||
mode: "{{ item.mode }}"
|
||||
with_items:
|
||||
- src: strongswan.conf.j2
|
||||
dest: "{{ config_prefix|default('/') }}etc/strongswan.conf"
|
||||
dest: "strongswan.conf"
|
||||
owner: root
|
||||
group: "{{ root_group|default('root') }}"
|
||||
mode: "0644"
|
||||
- src: ipsec.conf.j2
|
||||
dest: "{{ config_prefix|default('/') }}etc/ipsec.conf"
|
||||
dest: "ipsec.conf"
|
||||
owner: root
|
||||
group: "{{ root_group|default('root') }}"
|
||||
mode: "0644"
|
||||
- src: ipsec.secrets.j2
|
||||
dest: "{{ config_prefix|default('/') }}etc/ipsec.secrets"
|
||||
dest: "ipsec.secrets"
|
||||
owner: strongswan
|
||||
group: "{{ root_group|default('root') }}"
|
||||
mode: "0600"
|
|
@ -1,11 +1,5 @@
|
|||
---
|
||||
- block:
|
||||
- name: Include WireGuard role
|
||||
include_role:
|
||||
name: wireguard
|
||||
tags: wireguard
|
||||
when: wireguard_enabled and ansible_distribution == 'Ubuntu'
|
||||
|
||||
- include_tasks: ubuntu.yml
|
||||
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
|
||||
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
- name: Ensure the pki directory does not exist
|
||||
file:
|
||||
dest: configs/{{ IP_subject_alt_name }}/pki
|
||||
dest: "{{ ipsec_pki_path }}"
|
||||
state: absent
|
||||
when: keys_clean_all|bool == True
|
||||
|
||||
- name: Ensure the pki directories exist
|
||||
file:
|
||||
dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}"
|
||||
dest: "{{ ipsec_pki_path }}/{{ item }}"
|
||||
state: directory
|
||||
recurse: yes
|
||||
mode: '0700'
|
||||
|
@ -26,9 +26,20 @@
|
|||
- public
|
||||
- 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
|
||||
file:
|
||||
dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}"
|
||||
dest: "{{ ipsec_pki_path }}/{{ item }}"
|
||||
state: touch
|
||||
with_items:
|
||||
- ".rnd"
|
||||
|
@ -40,7 +51,7 @@
|
|||
- name: Generate the openssl server configs
|
||||
template:
|
||||
src: openssl.cnf.j2
|
||||
dest: "configs/{{ IP_subject_alt_name }}/pki/openssl.cnf"
|
||||
dest: "{{ ipsec_pki_path }}/openssl.cnf"
|
||||
|
||||
- name: Build the CA pair
|
||||
shell: >
|
||||
|
@ -55,20 +66,19 @@
|
|||
-passout pass:"{{ CA_password }}" &&
|
||||
touch {{ IP_subject_alt_name }}_ca_generated
|
||||
args:
|
||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||
chdir: "{{ ipsec_pki_path }}"
|
||||
creates: "{{ IP_subject_alt_name }}_ca_generated"
|
||||
executable: bash
|
||||
|
||||
- name: Copy the CA certificate
|
||||
copy:
|
||||
src: "configs/{{ IP_subject_alt_name }}/pki/cacert.pem"
|
||||
dest: "configs/{{ IP_subject_alt_name }}/cacert.pem"
|
||||
mode: 0600
|
||||
src: "{{ ipsec_pki_path }}/cacert.pem"
|
||||
dest: "{{ ipsec_config_path }}/manual/cacert.pem"
|
||||
|
||||
- name: Generate the serial number
|
||||
shell: echo 01 > serial && touch serial_generated
|
||||
args:
|
||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||
chdir: "{{ ipsec_pki_path }}"
|
||||
creates: serial_generated
|
||||
|
||||
- name: Build the server pair
|
||||
|
@ -90,7 +100,7 @@
|
|||
-subj "/CN={{ IP_subject_alt_name }}" &&
|
||||
touch certs/{{ IP_subject_alt_name }}_crt_generated
|
||||
args:
|
||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||
chdir: "{{ ipsec_pki_path }}"
|
||||
creates: certs/{{ IP_subject_alt_name }}_crt_generated
|
||||
executable: bash
|
||||
|
||||
|
@ -113,23 +123,15 @@
|
|||
-subj "/CN={{ item }}" &&
|
||||
touch certs/{{ item }}_crt_generated
|
||||
args:
|
||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||
chdir: "{{ ipsec_pki_path }}"
|
||||
creates: certs/{{ item }}_crt_generated
|
||||
executable: bash
|
||||
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
|
||||
openssl_publickey:
|
||||
path: "configs/{{ IP_subject_alt_name }}/pki/public/{{ item }}.pub"
|
||||
privatekey_path: "configs/{{ IP_subject_alt_name }}/pki/private/{{ item }}.key"
|
||||
path: "{{ ipsec_pki_path }}/public/{{ item }}.pub"
|
||||
privatekey_path: "{{ ipsec_pki_path }}/private/{{ item }}.key"
|
||||
format: OpenSSH
|
||||
with_items: "{{ users }}"
|
||||
|
||||
|
@ -144,16 +146,15 @@
|
|||
-out private/{{ item }}.p12
|
||||
-passout pass:"{{ p12_export_password }}"
|
||||
args:
|
||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||
chdir: "{{ ipsec_pki_path }}"
|
||||
executable: bash
|
||||
with_items: "{{ users }}"
|
||||
register: p12
|
||||
|
||||
- name: Copy the p12 certificates
|
||||
copy:
|
||||
src: "configs/{{ IP_subject_alt_name }}/pki/private/{{ item }}.p12"
|
||||
dest: "configs/{{ IP_subject_alt_name }}/{{ item }}.p12"
|
||||
mode: 0600
|
||||
src: "{{ ipsec_pki_path }}/private/{{ item }}.p12"
|
||||
dest: "{{ ipsec_config_path }}/manual/{{ item }}.p12"
|
||||
with_items:
|
||||
- "{{ users }}"
|
||||
|
||||
|
@ -164,7 +165,7 @@
|
|||
awk '{print $5}' |
|
||||
sed 's/\/CN=//g'
|
||||
args:
|
||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||
chdir: "{{ ipsec_pki_path}}"
|
||||
register: valid_certs
|
||||
|
||||
- name: Revoke non-existing users
|
||||
|
@ -176,7 +177,7 @@
|
|||
-out crl/{{ item }}.crt
|
||||
register: gencrl
|
||||
args:
|
||||
chdir: configs/{{ IP_subject_alt_name }}/pki/
|
||||
chdir: "{{ ipsec_pki_path }}"
|
||||
creates: crl/{{ item }}.crt
|
||||
executable: bash
|
||||
when: item not in users
|
||||
|
@ -192,7 +193,7 @@
|
|||
- gencrl is defined
|
||||
- gencrl.changed
|
||||
args:
|
||||
chdir: configs/{{ IP_subject_alt_name }}/pki/
|
||||
chdir: "{{ ipsec_pki_path }}"
|
||||
executable: bash
|
||||
delegate_to: localhost
|
||||
become: no
|
||||
|
@ -201,7 +202,7 @@
|
|||
|
||||
- name: Copy the CRL to the vpn server
|
||||
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"
|
||||
when:
|
||||
- gencrl is defined
|
|
@ -43,6 +43,3 @@
|
|||
notify:
|
||||
- daemon-reload
|
||||
- restart strongswan
|
||||
|
||||
- include_tasks: iptables.yml
|
||||
tags: iptables
|
|
@ -27,7 +27,7 @@ conn %default
|
|||
|
||||
right=%any
|
||||
rightauth=pubkey
|
||||
rightsourceip={{ vpn_network }},{{ vpn_network_ipv6 }}
|
||||
rightsourceip={{ strongswan_network }},{{ strongswan_network_ipv6 }}
|
||||
{% if algo_local_dns or dns_encryption %}
|
||||
rightdns={{ local_service_ip }}
|
||||
{% 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_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 %}"
|
||||
wireguard_config_path: "configs/{{ IP_subject_alt_name }}/wireguard/"
|
||||
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:
|
||||
- name: Save private keys
|
||||
copy:
|
||||
dest: "{{ wireguard_config_path }}/private/{{ item['item'] }}"
|
||||
dest: "{{ wireguard_pki_path }}/private/{{ item['item'] }}"
|
||||
content: "{{ item['stdout'] }}"
|
||||
mode: "0600"
|
||||
no_log: true
|
||||
|
@ -39,7 +39,7 @@
|
|||
when: wg_genkey.changed
|
||||
|
||||
- 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
|
||||
changed_when: false
|
||||
args:
|
||||
|
@ -50,7 +50,7 @@
|
|||
|
||||
- name: Save public keys
|
||||
copy:
|
||||
dest: "{{ wireguard_config_path }}/public/{{ item['item'] }}"
|
||||
dest: "{{ wireguard_pki_path }}/public/{{ item['item'] }}"
|
||||
content: "{{ item['stdout'] }}"
|
||||
mode: "0600"
|
||||
no_log: true
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
- name: Ensure the required directories exist
|
||||
file:
|
||||
dest: "{{ wireguard_config_path }}/{{ item }}"
|
||||
dest: "{{ wireguard_pki_path }}/{{ item }}"
|
||||
state: directory
|
||||
recurse: true
|
||||
with_items:
|
||||
|
@ -28,7 +28,7 @@
|
|||
- block:
|
||||
- name: WireGuard user list updated
|
||||
lineinfile:
|
||||
dest: "{{ wireguard_config_path }}/index.txt"
|
||||
dest: "{{ wireguard_pki_path }}/index.txt"
|
||||
create: true
|
||||
mode: "0600"
|
||||
insertafter: EOF
|
||||
|
@ -37,7 +37,7 @@
|
|||
with_items: "{{ users }}"
|
||||
|
||||
- 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
|
||||
template:
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
[Interface]
|
||||
PrivateKey = {{ lookup('file', wireguard_config_path + '/private/' + item.1) }}
|
||||
PrivateKey = {{ lookup('file', wireguard_pki_path + '/private/' + item.1) }}
|
||||
Address = {{ wireguard_client_ip }}
|
||||
DNS = {{ wireguard_dns_servers }}
|
||||
{% if reduce_mtu|int > 0 %}MTU = {{ 1420 - reduce_mtu|int }}
|
||||
{% endif %}
|
||||
|
||||
[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
|
||||
Endpoint = {{ IP_subject_alt_name }}:{{ wireguard_port }}
|
||||
{{ 'PersistentKeepalive = ' + wireguard_PersistentKeepalive|string if wireguard_PersistentKeepalive > 0 else '' }}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[Interface]
|
||||
Address = {{ wireguard_server_ip }}
|
||||
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
|
||||
|
||||
{% for u in wireguard_users %}
|
||||
|
@ -10,8 +10,8 @@ SaveConfig = false
|
|||
|
||||
[Peer]
|
||||
# {{ u }}
|
||||
PublicKey = {{ lookup('file', wireguard_config_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 %}
|
||||
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 %}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
|
21
server.yml
21
server.yml
|
@ -19,8 +19,9 @@
|
|||
- role: wireguard
|
||||
when: wireguard_enabled
|
||||
tags: wireguard
|
||||
- role: vpn
|
||||
tags: vpn
|
||||
- role: strongswan
|
||||
when: ipsec_enabled
|
||||
tags: ipsec
|
||||
- role: ssh_tunneling
|
||||
when: algo_ssh_tunneling
|
||||
tags: ssh_tunneling
|
||||
|
@ -30,15 +31,17 @@
|
|||
- name: Delete the CA key
|
||||
local_action:
|
||||
module: file
|
||||
path: "configs/{{ IP_subject_alt_name }}/pki/private/cakey.pem"
|
||||
path: "{{ ipsec_pki_path }}/private/cakey.pem"
|
||||
state: absent
|
||||
become: false
|
||||
when: not algo_store_cakey
|
||||
when:
|
||||
- ipsec_enabled
|
||||
- not algo_store_cakey
|
||||
|
||||
- name: Dump the configuration
|
||||
local_action:
|
||||
module: copy
|
||||
dest: "configs/{{ IP_subject_alt_name }}/config.yml"
|
||||
dest: "configs/{{ IP_subject_alt_name }}/.config.yml"
|
||||
content: |
|
||||
server: {{ 'localhost' if inventory_hostname == 'localhost' else inventory_hostname }}
|
||||
server_user: {{ ansible_ssh_user }}
|
||||
|
@ -55,6 +58,8 @@
|
|||
algo_windows: {{ algo_windows }}
|
||||
algo_store_cakey: {{ algo_store_cakey }}
|
||||
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 %}
|
||||
become: false
|
||||
|
||||
|
@ -69,9 +74,9 @@
|
|||
- debug:
|
||||
msg:
|
||||
- "{{ congrats.common.split('\n') }}"
|
||||
- " {{ congrats.p12_pass }}"
|
||||
- " {% if algo_store_cakey %}{{ congrats.ca_key_pass }}{% endif %}"
|
||||
- " {% if algo_provider != 'local' %}{{ congrats.ssh_access }}{% endif %}"
|
||||
- " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}"
|
||||
- " {{ congrats.ca_key_pass if algo_store_cakey and ipsec_enabled else '' }}"
|
||||
- " {{ congrats.ssh_access if algo_provider != 'local' else ''}}"
|
||||
tags: always
|
||||
rescue:
|
||||
- debug: var=fail_hint
|
||||
|
|
|
@ -11,7 +11,11 @@ else
|
|||
ansible-playbook users.yml -e "${USER_ARGS}" -t update-users
|
||||
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
|
||||
echo "The CRL check passed"
|
||||
else
|
||||
|
@ -19,10 +23,34 @@ if sudo openssl crl -inform pem -noout -text -in configs/$LXC_IP/pki/crl/phone.c
|
|||
exit 1
|
||||
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
|
||||
echo "The new user exists"
|
||||
else
|
||||
echo "The new user does not exist"
|
||||
exit 1
|
||||
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
|
||||
|
|
15
users.yml
15
users.yml
|
@ -21,13 +21,15 @@
|
|||
|
||||
- name: Import host specific variables
|
||||
include_vars:
|
||||
file: "configs/{{ algo_server }}/config.yml"
|
||||
file: "configs/{{ algo_server }}/.config.yml"
|
||||
|
||||
- pause:
|
||||
prompt: Enter the password for the private CA key
|
||||
echo: false
|
||||
register: _ca_password
|
||||
when: ca_password is undefined
|
||||
when:
|
||||
- ca_password is undefined
|
||||
- ipsec_enabled
|
||||
|
||||
- name: Set facts based on the input
|
||||
set_fact:
|
||||
|
@ -42,7 +44,7 @@
|
|||
groups: vpn-host
|
||||
ansible_ssh_user: "{{ server_user|default('root') }}"
|
||||
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 }}"
|
||||
rescue:
|
||||
- debug: var=fail_hint
|
||||
|
@ -56,7 +58,7 @@
|
|||
become: true
|
||||
vars_files:
|
||||
- config.cfg
|
||||
- "configs/{{ inventory_hostname }}/config.yml"
|
||||
- "configs/{{ inventory_hostname }}/.config.yml"
|
||||
|
||||
pre_tasks:
|
||||
- block:
|
||||
|
@ -74,8 +76,9 @@
|
|||
- role: wireguard
|
||||
tags: [ 'vpn', 'wireguard' ]
|
||||
when: wireguard_enabled
|
||||
- role: vpn
|
||||
tags: vpn
|
||||
- role: strongswan
|
||||
when: ipsec_enabled
|
||||
tags: ipsec
|
||||
- role: ssh_tunneling
|
||||
when: algo_ssh_tunneling
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue