mirror of
https://github.com/trailofbits/algo.git
synced 2025-06-07 07:33:52 +02:00
FreeBSD / HardenedBSD (#262)
* FreeBSD draft ifconfig fix Pre-tasks fixes fix hardcoded IP some refactoring disable system-based tags disable freebsd tags FreeBSD vpn role add defaults ssh role freebsd default fix dns_adblocking freebsd ubuntu dict fix * HardenedBSD update-users BSD * Rebuild the kernel docs changing
This commit is contained in:
parent
49ba1f76b4
commit
6facb6cb4f
25 changed files with 732 additions and 414 deletions
28
docs/FreeBSD.md
Normal file
28
docs/FreeBSD.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# FreeBSD / HardenedBSD
|
||||||
|
|
||||||
|
It is only possible to install Algo on existing systems only. We support only 11 version for now.
|
||||||
|
|
||||||
|
## Pre-paring the system
|
||||||
|
|
||||||
|
Ensure that the following kernel options are enabled:
|
||||||
|
|
||||||
|
```
|
||||||
|
# sysctl kern.conftxt | grep -iE "IPSEC|crypto"
|
||||||
|
options IPSEC
|
||||||
|
options IPSEC_NAT_T
|
||||||
|
device crypto
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available roles
|
||||||
|
|
||||||
|
* vpn
|
||||||
|
* ssh_tunneling
|
||||||
|
* dns_adblocking
|
||||||
|
|
||||||
|
## Additional variables
|
||||||
|
|
||||||
|
* rebuild_kernel - set to `true` if you want to let Algo to rebuild your kernel if needed (Takes a lot of time)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
`ansible-playbook deploy.yml -t local,vpn -e "server_ip=$server_ip server_user=$server_user IP_subject_alt_name=$server_ip Store_CAKEY=N" --skip-tags cloud`
|
|
@ -1,10 +1,16 @@
|
||||||
- name: Install prerequisites
|
---
|
||||||
raw: sleep 10 && sudo apt-get update -qq && sudo apt-get install -qq -y python2.7
|
|
||||||
|
|
||||||
- name: Configure defaults
|
- name: Check the system
|
||||||
raw: sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
|
raw: uname -a
|
||||||
tags:
|
register: OS
|
||||||
- update-alternatives
|
|
||||||
|
- name: Ubuntu pre-tasks
|
||||||
|
include: ubuntu.yml
|
||||||
|
when: '"Ubuntu" in OS.stdout'
|
||||||
|
|
||||||
|
- name: FreeBSD pre-tasks
|
||||||
|
include: freebsd.yml
|
||||||
|
when: '"FreeBSD" in OS.stdout'
|
||||||
|
|
||||||
- name: Ensure the algo ssh key exist on the server
|
- name: Ensure the algo ssh key exist on the server
|
||||||
authorized_key:
|
authorized_key:
|
||||||
|
|
10
playbooks/facts/FreeBSD.yml
Normal file
10
playbooks/facts/FreeBSD.yml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
config_prefix: "/usr/local/"
|
||||||
|
root_group: wheel
|
||||||
|
ssh_service_name: sshd
|
||||||
|
apparmor_enabled: false
|
||||||
|
strongswan_additional_plugins:
|
||||||
|
- kernel-pfroute
|
||||||
|
- kernel-pfkey
|
9
playbooks/freebsd.yml
Normal file
9
playbooks/freebsd.yml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Install prerequisites
|
||||||
|
raw: sleep 10 && env ASSUME_ALWAYS_YES=YES sudo pkg install -y python27
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Configure defaults
|
||||||
|
raw: sudo ln -sf /usr/local/bin/python2.7 /usr/bin/python2.7
|
||||||
|
|
||||||
|
- include: facts/FreeBSD.yml
|
9
playbooks/ubuntu.yml
Normal file
9
playbooks/ubuntu.yml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Ubuntu | Install prerequisites
|
||||||
|
raw: sleep 10 && sudo apt-get update -qq && sudo apt-get install -qq -y python2.7
|
||||||
|
|
||||||
|
- name: Ubuntu | Configure defaults
|
||||||
|
raw: sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
|
||||||
|
tags:
|
||||||
|
- update-alternatives
|
|
@ -1,8 +1,18 @@
|
||||||
- name: restart rsyslog
|
- name: restart rsyslog
|
||||||
service: name=rsyslog state=restarted
|
service: name=rsyslog state=restarted
|
||||||
|
|
||||||
|
- name: restart ipfw
|
||||||
|
service: name=ipfw state=restarted
|
||||||
|
|
||||||
- name: flush routing cache
|
- name: flush routing cache
|
||||||
shell: echo 1 > /proc/sys/net/ipv4/route/flush
|
shell: echo 1 > /proc/sys/net/ipv4/route/flush
|
||||||
|
|
||||||
- name: restart loopback
|
- name: restart loopback
|
||||||
shell: ifdown lo:100 && ifup lo:100
|
shell: ifdown lo:100 && ifup lo:100
|
||||||
|
|
||||||
|
- name: restart loopback bsd
|
||||||
|
shell: >
|
||||||
|
ifconfig lo100 destroy || true &&
|
||||||
|
ifconfig lo100 create &&
|
||||||
|
ifconfig lo100 inet {{ local_service_ip }} netmask 255.255.255.255 &&
|
||||||
|
ifconfig lo100 inet6 FCAA::1/64; echo $?
|
||||||
|
|
51
roles/common/tasks/freebsd.yml
Normal file
51
roles/common/tasks/freebsd.yml
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
tools:
|
||||||
|
- git
|
||||||
|
- subversion
|
||||||
|
- screen
|
||||||
|
- coreutils
|
||||||
|
- openssl
|
||||||
|
- bash
|
||||||
|
- wget
|
||||||
|
sysctl:
|
||||||
|
forwarding:
|
||||||
|
- net.inet.ip.forwarding
|
||||||
|
- net.inet6.ip6.forwarding
|
||||||
|
tags:
|
||||||
|
- always
|
||||||
|
|
||||||
|
- name: Loopback included into the rc config
|
||||||
|
blockinfile:
|
||||||
|
dest: /etc/rc.conf
|
||||||
|
create: yes
|
||||||
|
block: |
|
||||||
|
cloned_interfaces="lo100"
|
||||||
|
ifconfig_lo100="inet {{ local_service_ip }} netmask 255.255.255.255"
|
||||||
|
ifconfig_lo100="inet6 FCAA::1/64"
|
||||||
|
notify:
|
||||||
|
- restart loopback bsd
|
||||||
|
tags:
|
||||||
|
- always
|
||||||
|
|
||||||
|
- name: Enable the gateway features
|
||||||
|
lineinfile: dest=/etc/rc.conf regexp='^{{ item.param }}.*' line='{{ item.param }}={{ item.value }}'
|
||||||
|
with_items:
|
||||||
|
- { param: firewall_enable, value: '"YES"' }
|
||||||
|
- { param: firewall_type, value: '"open"' }
|
||||||
|
- { param: gateway_enable, value: '"YES"' }
|
||||||
|
- { param: natd_enable, value: '"YES"' }
|
||||||
|
- { param: natd_interface, value: '"{{ ansible_default_ipv4.device|default() }}"' }
|
||||||
|
- { param: natd_flags, value: '"-dynamic -m"' }
|
||||||
|
notify:
|
||||||
|
- restart ipfw
|
||||||
|
tags:
|
||||||
|
- always
|
||||||
|
|
||||||
|
- name: FreeBSD | Activate IPFW
|
||||||
|
shell: >
|
||||||
|
kldstat -n ipfw.ko || kldload ipfw ; sysctl net.inet.ip.fw.enable=0 &&
|
||||||
|
bash /etc/rc.firewall && sysctl net.inet.ip.fw.enable=1
|
||||||
|
|
||||||
|
- meta: flush_handlers
|
|
@ -5,101 +5,24 @@
|
||||||
tags:
|
tags:
|
||||||
- always
|
- always
|
||||||
|
|
||||||
- name: Install software updates
|
- include: ubuntu.yml
|
||||||
apt: update_cache=yes upgrade=dist
|
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
|
||||||
tags:
|
|
||||||
- cloud
|
|
||||||
|
|
||||||
- name: Check if reboot is required
|
- include: freebsd.yml
|
||||||
shell: >
|
when: ansible_distribution == 'FreeBSD'
|
||||||
if [[ -e /var/run/reboot-required ]]; then echo "required"; else echo "no"; fi
|
|
||||||
args:
|
|
||||||
executable: /bin/bash
|
|
||||||
register: reboot_required
|
|
||||||
tags:
|
|
||||||
- cloud
|
|
||||||
|
|
||||||
- name: Reboot
|
|
||||||
shell: sleep 2 && shutdown -r now "Ansible updates triggered"
|
|
||||||
async: 1
|
|
||||||
poll: 0
|
|
||||||
when: reboot_required is defined and reboot_required.stdout == 'required'
|
|
||||||
ignore_errors: true
|
|
||||||
tags:
|
|
||||||
- cloud
|
|
||||||
|
|
||||||
- name: Wait until SSH becomes ready...
|
|
||||||
local_action:
|
|
||||||
module: wait_for
|
|
||||||
port: 22
|
|
||||||
host: "{{ inventory_hostname }}"
|
|
||||||
search_regex: OpenSSH
|
|
||||||
delay: 10
|
|
||||||
timeout: 320
|
|
||||||
when: reboot_required is defined and reboot_required.stdout == 'required'
|
|
||||||
become: false
|
|
||||||
tags:
|
|
||||||
- cloud
|
|
||||||
|
|
||||||
- name: Disable MOTD on login and SSHD
|
|
||||||
replace: dest="{{ item.file }}" regexp="{{ item.regexp }}" replace="{{ item.line }}"
|
|
||||||
with_items:
|
|
||||||
- { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/login' }
|
|
||||||
- { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/sshd' }
|
|
||||||
tags:
|
|
||||||
- cloud
|
|
||||||
|
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
apt: name="{{ item }}" state=latest
|
package: name="{{ item }}" state=present
|
||||||
with_items:
|
with_items:
|
||||||
- git
|
- "{{ tools }}"
|
||||||
- screen
|
|
||||||
- apparmor-utils
|
|
||||||
- uuid-runtime
|
|
||||||
- coreutils
|
|
||||||
- sendmail
|
|
||||||
- iptables-persistent
|
|
||||||
- cgroup-tools
|
|
||||||
- openssl
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
|
|
||||||
- name: Loopback for services configured
|
|
||||||
template: src=10-loopback-services.cfg.j2 dest=/etc/network/interfaces.d/10-loopback-services.cfg
|
|
||||||
notify:
|
|
||||||
- restart loopback
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
|
|
||||||
- name: Loopback included into the network config
|
|
||||||
lineinfile: dest=/etc/network/interfaces line='source /etc/network/interfaces.d/10-loopback-services.cfg' state=present
|
|
||||||
notify:
|
|
||||||
- restart loopback
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
|
|
||||||
- meta: flush_handlers
|
|
||||||
tags:
|
tags:
|
||||||
- always
|
- always
|
||||||
|
|
||||||
- name: Enable packet forwarding for IPv4
|
- name: Enable packet forwarding for IPv4
|
||||||
sysctl: name="{{ item }}" value=1
|
sysctl: name="{{ item }}" value=1
|
||||||
with_items:
|
with_items:
|
||||||
- net.ipv4.ip_forward
|
- "{{ sysctl.forwarding }}"
|
||||||
- net.ipv4.conf.all.forwarding
|
|
||||||
tags:
|
tags:
|
||||||
- always
|
- always
|
||||||
|
|
||||||
- name: Enable packet forwarding for IPv6
|
- meta: flush_handlers
|
||||||
sysctl: name=net.ipv6.conf.all.forwarding value=1
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
|
|
||||||
- name: Check apparmor support
|
|
||||||
shell: apparmor_status
|
|
||||||
ignore_errors: yes
|
|
||||||
register: apparmor_status
|
|
||||||
|
|
||||||
- set_fact:
|
|
||||||
apparmor_enabled: true
|
|
||||||
when: '"profiles are in enforce mode" in apparmor_status.stdout'
|
|
||||||
|
|
91
roles/common/tasks/ubuntu.yml
Normal file
91
roles/common/tasks/ubuntu.yml
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Install software updates
|
||||||
|
apt: update_cache=yes upgrade=dist
|
||||||
|
tags:
|
||||||
|
- cloud
|
||||||
|
|
||||||
|
- name: Check if reboot is required
|
||||||
|
shell: >
|
||||||
|
if [[ -e /var/run/reboot-required ]]; then echo "required"; else echo "no"; fi
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: reboot_required
|
||||||
|
tags:
|
||||||
|
- cloud
|
||||||
|
|
||||||
|
- name: Reboot
|
||||||
|
shell: sleep 2 && shutdown -r now "Ansible updates triggered"
|
||||||
|
async: 1
|
||||||
|
poll: 0
|
||||||
|
when: reboot_required is defined and reboot_required.stdout == 'required'
|
||||||
|
ignore_errors: true
|
||||||
|
tags:
|
||||||
|
- cloud
|
||||||
|
|
||||||
|
- name: Wait until SSH becomes ready...
|
||||||
|
local_action:
|
||||||
|
module: wait_for
|
||||||
|
port: 22
|
||||||
|
host: "{{ inventory_hostname }}"
|
||||||
|
search_regex: OpenSSH
|
||||||
|
delay: 10
|
||||||
|
timeout: 320
|
||||||
|
when: reboot_required is defined and reboot_required.stdout == 'required'
|
||||||
|
become: false
|
||||||
|
tags:
|
||||||
|
- cloud
|
||||||
|
|
||||||
|
- name: Disable MOTD on login and SSHD
|
||||||
|
replace: dest="{{ item.file }}" regexp="{{ item.regexp }}" replace="{{ item.line }}"
|
||||||
|
with_items:
|
||||||
|
- { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/login' }
|
||||||
|
- { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/sshd' }
|
||||||
|
tags:
|
||||||
|
- cloud
|
||||||
|
|
||||||
|
- name: Loopback for services configured
|
||||||
|
template: src=10-loopback-services.cfg.j2 dest=/etc/network/interfaces.d/10-loopback-services.cfg
|
||||||
|
notify:
|
||||||
|
- restart loopback
|
||||||
|
tags:
|
||||||
|
- always
|
||||||
|
|
||||||
|
- name: Loopback included into the network config
|
||||||
|
lineinfile: dest=/etc/network/interfaces line='source /etc/network/interfaces.d/10-loopback-services.cfg' state=present
|
||||||
|
notify:
|
||||||
|
- restart loopback
|
||||||
|
tags:
|
||||||
|
- always
|
||||||
|
|
||||||
|
- meta: flush_handlers
|
||||||
|
tags:
|
||||||
|
- always
|
||||||
|
|
||||||
|
- name: Check apparmor support
|
||||||
|
shell: apparmor_status
|
||||||
|
ignore_errors: yes
|
||||||
|
register: apparmor_status
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
apparmor_enabled: true
|
||||||
|
when: '"profiles are in enforce mode" in apparmor_status.stdout'
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
tools:
|
||||||
|
- git
|
||||||
|
- screen
|
||||||
|
- apparmor-utils
|
||||||
|
- uuid-runtime
|
||||||
|
- coreutils
|
||||||
|
- sendmail
|
||||||
|
- iptables-persistent
|
||||||
|
- cgroup-tools
|
||||||
|
- openssl
|
||||||
|
sysctl:
|
||||||
|
forwarding:
|
||||||
|
- net.ipv4.ip_forward
|
||||||
|
- net.ipv4.conf.all.forwarding
|
||||||
|
- net.ipv6.conf.all.forwarding
|
||||||
|
tags:
|
||||||
|
- always
|
4
roles/dns_adblocking/tasks/freebsd.yml
Normal file
4
roles/dns_adblocking/tasks/freebsd.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Enable dnsmasq
|
||||||
|
lineinfile: dest=/etc/rc.conf regexp=^dnsmasq_enable= line='dnsmasq_enable="YES"'
|
|
@ -2,55 +2,41 @@
|
||||||
setup:
|
setup:
|
||||||
|
|
||||||
- name: Dnsmasq installed
|
- name: Dnsmasq installed
|
||||||
apt: name=dnsmasq state=latest
|
package: name=dnsmasq
|
||||||
|
|
||||||
- name: Dnsmasq profile for apparmor configured
|
- name: Ensure that the dnsmasq user exist
|
||||||
template: src=usr.sbin.dnsmasq.j2 dest=/etc/apparmor.d/usr.sbin.dnsmasq owner=root group=root mode=0600
|
user: name=dnsmasq groups=nogroup append=yes state=present
|
||||||
when: apparmor_enabled is defined and apparmor_enabled == true
|
|
||||||
notify:
|
|
||||||
- restart dnsmasq
|
|
||||||
|
|
||||||
- name: The dnsmasq directory created
|
- name: The dnsmasq directory created
|
||||||
file: dest=/var/lib/dnsmasq state=directory mode=0755 owner=dnsmasq group=nogroup
|
file: dest=/var/lib/dnsmasq state=directory mode=0755 owner=dnsmasq group=nogroup
|
||||||
|
|
||||||
- name: Enforce the dnsmasq AppArmor policy
|
- include: ubuntu.yml
|
||||||
shell: aa-enforce usr.sbin.dnsmasq
|
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
|
||||||
when: apparmor_enabled is defined and apparmor_enabled == true
|
|
||||||
tags: ['apparmor']
|
|
||||||
|
|
||||||
- name: Ensure that the dnsmasq service directory exist
|
- include: freebsd.yml
|
||||||
file: path=/etc/systemd/system/dnsmasq.service.d/ state=directory mode=0755 owner=root group=root
|
when: ansible_distribution == 'FreeBSD'
|
||||||
|
|
||||||
- name: Setup the cgroup limitations for the ipsec daemon
|
|
||||||
template: src=100-CustomLimitations.conf.j2 dest=/etc/systemd/system/dnsmasq.service.d/100-CustomLimitations.conf
|
|
||||||
notify:
|
|
||||||
- daemon-reload
|
|
||||||
- restart dnsmasq
|
|
||||||
|
|
||||||
- meta: flush_handlers
|
- meta: flush_handlers
|
||||||
|
|
||||||
- name: Dnsmasq configured
|
- name: Dnsmasq configured
|
||||||
template: src=dnsmasq.conf.j2 dest=/etc/dnsmasq.conf
|
template: src=dnsmasq.conf.j2 dest="{{ config_prefix|default('/') }}etc/dnsmasq.conf"
|
||||||
notify:
|
notify:
|
||||||
- restart dnsmasq
|
- restart dnsmasq
|
||||||
|
|
||||||
- name: Adblock script created
|
- name: Adblock script created
|
||||||
template: src=adblock.sh dest=/opt/adblock.sh owner=root group=root mode=0755
|
template: src=adblock.sh dest=/usr/local/sbin/adblock.sh owner=root group="{{ root_group|default('root') }}" mode=0755
|
||||||
|
|
||||||
- name: Adblock script added to cron
|
- name: Adblock script added to cron
|
||||||
cron:
|
cron:
|
||||||
name: Adblock hosts update
|
name: Adblock hosts update
|
||||||
minute: 10
|
minute: 10
|
||||||
hour: 2
|
hour: 2
|
||||||
job: /opt/adblock.sh
|
job: /usr/local/sbin/adblock.sh
|
||||||
user: dnsmasq
|
user: dnsmasq
|
||||||
|
|
||||||
- name: Update adblock hosts
|
- name: Update adblock hosts
|
||||||
shell: >
|
shell: >
|
||||||
/opt/adblock.sh
|
sudo -u dnsmasq "/usr/local/sbin/adblock.sh"
|
||||||
become: true
|
|
||||||
become_user: dnsmasq
|
|
||||||
|
|
||||||
- name: Dnsmasq enabled and started
|
- name: Dnsmasq enabled and started
|
||||||
service: name=dnsmasq state=started enabled=yes
|
service: name=dnsmasq state=started enabled=yes
|
||||||
|
|
||||||
|
|
21
roles/dns_adblocking/tasks/ubuntu.yml
Normal file
21
roles/dns_adblocking/tasks/ubuntu.yml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Ubuntu | Dnsmasq profile for apparmor configured
|
||||||
|
template: src=usr.sbin.dnsmasq.j2 dest=/etc/apparmor.d/usr.sbin.dnsmasq owner=root group=root mode=0600
|
||||||
|
when: apparmor_enabled is defined and apparmor_enabled == true
|
||||||
|
notify:
|
||||||
|
- restart dnsmasq
|
||||||
|
|
||||||
|
- name: Ubuntu | Enforce the dnsmasq AppArmor policy
|
||||||
|
shell: aa-enforce usr.sbin.dnsmasq
|
||||||
|
when: apparmor_enabled is defined and apparmor_enabled == true
|
||||||
|
tags: ['apparmor']
|
||||||
|
|
||||||
|
- name: Ubuntu | Ensure that the dnsmasq service directory exist
|
||||||
|
file: path=/etc/systemd/system/dnsmasq.service.d/ state=directory mode=0755 owner=root group=root
|
||||||
|
|
||||||
|
- name: Ubuntu | Setup the cgroup limitations for the ipsec daemon
|
||||||
|
template: src=100-CustomLimitations.conf.j2 dest=/etc/systemd/system/dnsmasq.service.d/100-CustomLimitations.conf
|
||||||
|
notify:
|
||||||
|
- daemon-reload
|
||||||
|
- restart dnsmasq
|
|
@ -1,5 +1,5 @@
|
||||||
- name: restart ssh
|
- name: restart ssh
|
||||||
service: name=ssh state=restarted
|
service: name="{{ ssh_service_name|default('ssh') }}" state=restarted
|
||||||
|
|
||||||
- name: flush routing cache
|
- name: flush routing cache
|
||||||
shell: echo 1 > /proc/sys/net/ipv4/route/flush
|
shell: echo 1 > /proc/sys/net/ipv4/route/flush
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
- name: restart ssh
|
- name: restart ssh
|
||||||
service: name=ssh state=restarted
|
service: name="{{ ssh_service_name|default('ssh') }}" state=restarted
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
- name: Ensure that the sshd_config file has desired options
|
- name: Ensure that the sshd_config file has desired options
|
||||||
blockinfile:
|
blockinfile:
|
||||||
dest: /etc/ssh/sshd_config
|
dest: /etc/ssh/sshd_config
|
||||||
marker: '# ANSIBLE_MANAGED_ssh_tunneling_role'
|
marker: '# {mark} ANSIBLE MANAGED BLOCK ssh_tunneling_role'
|
||||||
block: |
|
block: |
|
||||||
Match Group algo
|
Match Group algo
|
||||||
AllowTcpForwarding local
|
AllowTcpForwarding local
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
group: name=algo state=present
|
group: name=algo state=present
|
||||||
|
|
||||||
- name: Ensure that the jail directory exist
|
- name: Ensure that the jail directory exist
|
||||||
file: path=/var/jail/ state=directory mode=0755 owner=root group=root
|
file: path=/var/jail/ state=directory mode=0755 owner=root group="{{ root_group|default('root') }}"
|
||||||
|
|
||||||
- name: Ensure that the SSH users exist
|
- name: Ensure that the SSH users exist
|
||||||
user:
|
user:
|
||||||
|
|
79
roles/vpn/tasks/client_configs.yml
Normal file
79
roles/vpn/tasks/client_configs.yml
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Register p12 PayloadContent
|
||||||
|
local_action: >
|
||||||
|
shell cat private/{{ item }}.p12 | base64
|
||||||
|
register: PayloadContent
|
||||||
|
become: no
|
||||||
|
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 mobileconfigs
|
||||||
|
local_action:
|
||||||
|
module: template
|
||||||
|
src: mobileconfig.j2
|
||||||
|
dest: configs/{{ IP_subject_alt_name }}/{{ item.0 }}.mobileconfig
|
||||||
|
mode: 0600
|
||||||
|
become: no
|
||||||
|
with_together:
|
||||||
|
- "{{ users }}"
|
||||||
|
- "{{ PayloadContent.results }}"
|
||||||
|
no_log: True
|
||||||
|
|
||||||
|
- name: Build the strongswan app android config
|
||||||
|
local_action:
|
||||||
|
module: template
|
||||||
|
src: sswan.j2
|
||||||
|
dest: configs/{{ IP_subject_alt_name }}/{{ item.0 }}.sswan
|
||||||
|
mode: 0600
|
||||||
|
become: no
|
||||||
|
with_together:
|
||||||
|
- "{{ users }}"
|
||||||
|
- "{{ PayloadContent.results }}"
|
||||||
|
no_log: True
|
||||||
|
|
||||||
|
- name: Build the client ipsec config file
|
||||||
|
local_action:
|
||||||
|
module: template
|
||||||
|
src: client_ipsec.conf.j2
|
||||||
|
dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.conf
|
||||||
|
mode: 0600
|
||||||
|
become: no
|
||||||
|
with_items:
|
||||||
|
- "{{ users }}"
|
||||||
|
|
||||||
|
- name: Build the client ipsec secret file
|
||||||
|
local_action:
|
||||||
|
module: template
|
||||||
|
src: client_ipsec.secrets.j2
|
||||||
|
dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.secrets
|
||||||
|
mode: 0600
|
||||||
|
become: no
|
||||||
|
with_items:
|
||||||
|
- "{{ users }}"
|
||||||
|
|
||||||
|
- name: Build the windows client powershell script
|
||||||
|
local_action:
|
||||||
|
module: template
|
||||||
|
src: client_windows.ps1.j2
|
||||||
|
dest: configs/{{ IP_subject_alt_name }}/windows_{{ item }}.ps1
|
||||||
|
mode: 0600
|
||||||
|
become: no
|
||||||
|
when: Win10_Enabled is defined and Win10_Enabled == "Y"
|
||||||
|
with_items: "{{ users }}"
|
||||||
|
|
||||||
|
- name: Restrict permissions for the local private directories
|
||||||
|
local_action:
|
||||||
|
module: file
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
mode: 0700
|
||||||
|
become: no
|
||||||
|
with_items:
|
||||||
|
- configs/{{ IP_subject_alt_name }}
|
27
roles/vpn/tasks/distribute_keys.yml
Normal file
27
roles/vpn/tasks/distribute_keys.yml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- 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
|
113
roles/vpn/tasks/freebsd.yml
Normal file
113
roles/vpn/tasks/freebsd.yml
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Get the existing kernel parameters
|
||||||
|
command: sysctl -b kern.conftxt
|
||||||
|
register: kern_conftxt
|
||||||
|
when: rebuild_kernel is defined and rebuild_kernel == "true"
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Set the rebuild_needed fact
|
||||||
|
set_fact:
|
||||||
|
rebuild_needed: true
|
||||||
|
when: item not in kern_conftxt.stdout and rebuild_kernel is defined and rebuild_kernel == "true"
|
||||||
|
with_items:
|
||||||
|
- "IPSEC"
|
||||||
|
- "IPSEC_NAT_T"
|
||||||
|
- "crypto"
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Make the kernel config
|
||||||
|
shell: >
|
||||||
|
sysctl -b kern.conftxt > /tmp/IPSEC
|
||||||
|
when: rebuild_needed is defined and rebuild_needed == true
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Ensure the all options are enabled
|
||||||
|
lineinfile:
|
||||||
|
dest: /tmp/IPSEC
|
||||||
|
line: "{{ item }}"
|
||||||
|
insertbefore: BOF
|
||||||
|
with_items:
|
||||||
|
- "options IPSEC"
|
||||||
|
- "options IPSEC_NAT_T"
|
||||||
|
- "device crypto"
|
||||||
|
when: rebuild_needed is defined and rebuild_needed == true
|
||||||
|
|
||||||
|
- name: HardenedBSD | Determine the sources
|
||||||
|
set_fact:
|
||||||
|
sources_repo: https://github.com/HardenedBSD/hardenedBSD.git
|
||||||
|
sources_version: "hardened/{{ ansible_distribution_release.split('.')[0] }}-stable/master"
|
||||||
|
when: "'Hardened' in ansible_distribution_version"
|
||||||
|
|
||||||
|
- name: FreeBSD | Determine the sources
|
||||||
|
set_fact:
|
||||||
|
sources_repo: https://github.com/freebsd/freebsd.git
|
||||||
|
sources_version: "stable/{{ ansible_distribution_major_version }}"
|
||||||
|
when: "'Hardened' not in ansible_distribution_version"
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Increase the git postBuffer size
|
||||||
|
git_config:
|
||||||
|
name: http.postBuffer
|
||||||
|
scope: global
|
||||||
|
value: 1048576000
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: FreeBSD / HardenedBSD | Fetching the sources...
|
||||||
|
git:
|
||||||
|
repo: "{{ sources_repo }}"
|
||||||
|
dest: /usr/krnl_src
|
||||||
|
version: "{{ sources_version }}"
|
||||||
|
accept_hostkey: true
|
||||||
|
async: 1000
|
||||||
|
poll: 0
|
||||||
|
register: fetching_sources
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Fetching the sources...
|
||||||
|
async_status: jid={{ fetching_sources.ansible_job_id }}
|
||||||
|
when: rebuild_needed is defined and rebuild_needed == true
|
||||||
|
register: result
|
||||||
|
until: result.finished
|
||||||
|
retries: 600
|
||||||
|
delay: 30
|
||||||
|
rescue:
|
||||||
|
- debug: var=fetching_sources
|
||||||
|
|
||||||
|
- fail:
|
||||||
|
msg: "Something went wrong. Check the debug output above."
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: FreeBSD / HardenedBSD | The kernel is being built...
|
||||||
|
shell: >
|
||||||
|
mv /tmp/IPSEC /usr/krnl_src/sys/{{ ansible_architecture }}/conf &&
|
||||||
|
make buildkernel KERNCONF=IPSEC &&
|
||||||
|
make installkernel KERNCONF=IPSEC
|
||||||
|
args:
|
||||||
|
chdir: /usr/krnl_src
|
||||||
|
executable: /usr/local/bin/bash
|
||||||
|
when: rebuild_needed is defined and rebuild_needed == true
|
||||||
|
async: 1000
|
||||||
|
poll: 0
|
||||||
|
register: building_kernel
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | The kernel is being built...
|
||||||
|
async_status: jid={{ building_kernel.ansible_job_id }}
|
||||||
|
when: rebuild_needed is defined and rebuild_needed == true
|
||||||
|
register: result
|
||||||
|
until: result.finished
|
||||||
|
retries: 600
|
||||||
|
delay: 30
|
||||||
|
rescue:
|
||||||
|
- debug: var=building_kernel
|
||||||
|
|
||||||
|
- fail:
|
||||||
|
msg: "Something went wrong. Check the debug output above."
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Reboot
|
||||||
|
shell: >
|
||||||
|
sleep 2 && shutdown -r now
|
||||||
|
args:
|
||||||
|
executable: /usr/local/bin/bash
|
||||||
|
when: rebuild_needed is defined and rebuild_needed == true
|
||||||
|
async: 1
|
||||||
|
poll: 0
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: FreeBSD / HardenedBSD | Enable strongswan
|
||||||
|
lineinfile: dest=/etc/rc.conf regexp=^strongswan_enable= line='strongswan_enable="YES"'
|
46
roles/vpn/tasks/ipec_configuration.yml
Normal file
46
roles/vpn/tasks/ipec_configuration.yml
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Setup the config files from our templates
|
||||||
|
template:
|
||||||
|
src: "{{ item.src }}"
|
||||||
|
dest: "{{ item.dest }}"
|
||||||
|
owner: "{{ item.owner }}"
|
||||||
|
group: "{{ item.group }}"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
with_items:
|
||||||
|
- src: strongswan.conf.j2
|
||||||
|
dest: "{{ config_prefix|default('/') }}etc/strongswan.conf"
|
||||||
|
owner: root
|
||||||
|
group: "{{ root_group|default('root') }}"
|
||||||
|
mode: "0644"
|
||||||
|
- src: ipsec.conf.j2
|
||||||
|
dest: "{{ config_prefix|default('/') }}etc/ipsec.conf"
|
||||||
|
owner: root
|
||||||
|
group: "{{ root_group|default('root') }}"
|
||||||
|
mode: "0644"
|
||||||
|
- src: ipsec.secrets.j2
|
||||||
|
dest: "{{ config_prefix|default('/') }}etc/ipsec.secrets"
|
||||||
|
owner: strongswan
|
||||||
|
group: "{{ root_group|default('root') }}"
|
||||||
|
mode: "0600"
|
||||||
|
notify:
|
||||||
|
- restart strongswan
|
||||||
|
|
||||||
|
- name: Get loaded plugins
|
||||||
|
shell: >
|
||||||
|
find {{ config_prefix|default('/') }}etc/strongswan.d/charon/ -type f -name '*.conf' -exec basename {} \; | cut -f1 -d.
|
||||||
|
register: strongswan_plugins
|
||||||
|
|
||||||
|
- name: Disable unneeded plugins
|
||||||
|
lineinfile: dest="{{ config_prefix|default('/') }}etc/strongswan.d/charon/{{ item }}.conf" regexp='.*load.*' line='load = no' state=present
|
||||||
|
notify:
|
||||||
|
- restart strongswan
|
||||||
|
when: item not in strongswan_enabled_plugins and item not in strongswan_additional_plugins
|
||||||
|
with_items: "{{ strongswan_plugins.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Ensure that required plugins are enabled
|
||||||
|
lineinfile: dest="{{ config_prefix|default('/') }}etc/strongswan.d/charon/{{ item }}.conf" regexp='.*load.*' line='load = yes' state=present
|
||||||
|
notify:
|
||||||
|
- restart strongswan
|
||||||
|
when: item in strongswan_enabled_plugins or item in strongswan_additional_plugins
|
||||||
|
with_items: "{{ strongswan_plugins.stdout_lines }}"
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
- name: Generate password for the CA key
|
- name: Generate password for the CA key
|
||||||
shell: >
|
shell: >
|
||||||
< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-12};echo;
|
openssl rand -hex 6
|
||||||
register: CA_password
|
register: CA_password
|
||||||
|
|
||||||
- set_fact:
|
- set_fact:
|
||||||
|
@ -21,304 +21,27 @@
|
||||||
algo_params: "rsa:2048"
|
algo_params: "rsa:2048"
|
||||||
when: Win10_Enabled is defined and Win10_Enabled == "Y"
|
when: Win10_Enabled is defined and Win10_Enabled == "Y"
|
||||||
|
|
||||||
- name: Install StrongSwan
|
|
||||||
apt: name=strongswan state=latest update_cache=yes install_recommends=yes
|
|
||||||
|
|
||||||
- name: Enforcing ipsec with apparmor
|
|
||||||
shell: aa-enforce "{{ item }}"
|
|
||||||
when: apparmor_enabled is defined and apparmor_enabled == true
|
|
||||||
with_items:
|
|
||||||
- /usr/lib/ipsec/charon
|
|
||||||
- /usr/lib/ipsec/lookip
|
|
||||||
- /usr/lib/ipsec/stroke
|
|
||||||
notify:
|
|
||||||
- restart apparmor
|
|
||||||
tags: ['apparmor']
|
|
||||||
|
|
||||||
- name: Enable services
|
|
||||||
service: name={{ item }} enabled=yes
|
|
||||||
with_items:
|
|
||||||
- apparmor
|
|
||||||
- strongswan
|
|
||||||
- netfilter-persistent
|
|
||||||
|
|
||||||
- name: Configure iptables so IPSec traffic can traverse the tunnel
|
|
||||||
iptables: table=nat chain=POSTROUTING source="{{ vpn_network }}" jump=MASQUERADE
|
|
||||||
when: (security_enabled is not defined) or
|
|
||||||
(security_enabled is defined and security_enabled != "y")
|
|
||||||
notify:
|
|
||||||
- save iptables
|
|
||||||
|
|
||||||
- name: Configure ip6tables so IPSec traffic can traverse the tunnel
|
|
||||||
iptables: ip_version=ipv6 table=nat chain=POSTROUTING source="{{ vpn_network_ipv6 }}" jump=MASQUERADE
|
|
||||||
when: ((security_enabled is not defined) or (security_enabled is defined and security_enabled != "y")) and
|
|
||||||
(ipv6_support is defined and ipv6_support == true)
|
|
||||||
notify:
|
|
||||||
- save iptables
|
|
||||||
|
|
||||||
- name: Ensure that the strongswan group exist
|
- name: Ensure that the strongswan group exist
|
||||||
group: name=strongswan state=present
|
group: name=strongswan state=present
|
||||||
|
|
||||||
- name: Ensure that the strongswan user exist
|
- name: Ensure that the strongswan user exist
|
||||||
user: name=strongswan group=strongswan state=present
|
user: name=strongswan group=strongswan state=present
|
||||||
|
|
||||||
- name: Ensure that the strongswan service directory exist
|
- include: ubuntu.yml
|
||||||
file: path=/etc/systemd/system/strongswan.service.d/ state=directory mode=0755 owner=root group=root
|
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
|
||||||
|
|
||||||
- name: Setup the cgroup limitations for the ipsec daemon
|
- include: freebsd.yml
|
||||||
template: src=100-CustomLimitations.conf.j2 dest=/etc/systemd/system/strongswan.service.d/100-CustomLimitations.conf
|
when: ansible_distribution == 'FreeBSD'
|
||||||
notify:
|
|
||||||
- daemon-reload
|
- name: Install StrongSwan
|
||||||
- restart strongswan
|
package: name=strongswan state=present
|
||||||
|
|
||||||
|
- include: ipec_configuration.yml
|
||||||
|
- include: openssl.yml
|
||||||
|
- include: distribute_keys.yml
|
||||||
|
- include: client_configs.yml
|
||||||
|
|
||||||
- meta: flush_handlers
|
- meta: flush_handlers
|
||||||
|
|
||||||
- name: Setup the strongswan.conf file from our template
|
- name: StrongSwan started
|
||||||
template: src=strongswan.conf.j2 dest=/etc/strongswan.conf owner=root group=root mode=0644
|
service: name=strongswan state=started
|
||||||
notify:
|
|
||||||
- restart strongswan
|
|
||||||
|
|
||||||
- name: Setup the ipsec.conf file from our template
|
|
||||||
template: src=ipsec.conf.j2 dest=/etc/ipsec.conf owner=root group=root mode=0644
|
|
||||||
notify:
|
|
||||||
- restart strongswan
|
|
||||||
|
|
||||||
- name: Setup the ipsec.secrets file
|
|
||||||
template: src=ipsec.secrets.j2 dest=/etc/ipsec.secrets owner=strongswan group=root mode=0600
|
|
||||||
notify:
|
|
||||||
- restart strongswan
|
|
||||||
|
|
||||||
- name: Get loaded plugins
|
|
||||||
shell: >
|
|
||||||
find /etc/strongswan.d/charon/ -type f -name '*.conf' -printf '%f\n' | cut -f1 -d.
|
|
||||||
register: strongswan_plugins
|
|
||||||
|
|
||||||
- name: Disable unneeded plugins
|
|
||||||
lineinfile: dest="/etc/strongswan.d/charon/{{ item }}.conf" regexp='.*load.*' line='load = no' state=present
|
|
||||||
notify:
|
|
||||||
- restart strongswan
|
|
||||||
when: item not in strongswan_enabled_plugins
|
|
||||||
with_items: "{{ strongswan_plugins.stdout_lines }}"
|
|
||||||
|
|
||||||
- name: Ensure that required plugins are enabled
|
|
||||||
lineinfile: dest="/etc/strongswan.d/charon/{{ item }}.conf" regexp='.*load.*' line='load = yes' state=present
|
|
||||||
notify:
|
|
||||||
- restart strongswan
|
|
||||||
when: item in strongswan_enabled_plugins
|
|
||||||
with_items: "{{ strongswan_plugins.stdout_lines }}"
|
|
||||||
|
|
||||||
- name: Ensure the pki directory is not exist
|
|
||||||
local_action:
|
|
||||||
module: file
|
|
||||||
dest: configs/{{ IP_subject_alt_name }}/pki
|
|
||||||
state: absent
|
|
||||||
become: no
|
|
||||||
when: easyrsa_reinit_existent == True
|
|
||||||
|
|
||||||
- name: Ensure the pki directories are exist
|
|
||||||
local_action:
|
|
||||||
module: file
|
|
||||||
dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}"
|
|
||||||
state: directory
|
|
||||||
recurse: yes
|
|
||||||
become: no
|
|
||||||
with_items:
|
|
||||||
- ecparams
|
|
||||||
- certs
|
|
||||||
- crl
|
|
||||||
- newcerts
|
|
||||||
- private
|
|
||||||
- reqs
|
|
||||||
|
|
||||||
- name: Ensure the files are exist
|
|
||||||
local_action:
|
|
||||||
module: file
|
|
||||||
dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}"
|
|
||||||
state: touch
|
|
||||||
become: no
|
|
||||||
with_items:
|
|
||||||
- ".rnd"
|
|
||||||
- "private/.rnd"
|
|
||||||
- "index.txt"
|
|
||||||
- "index.txt.attr"
|
|
||||||
- "serial"
|
|
||||||
|
|
||||||
- name: Generate the openssl server configs
|
|
||||||
local_action:
|
|
||||||
module: template
|
|
||||||
src: openssl.cnf.j2
|
|
||||||
dest: "configs/{{ IP_subject_alt_name }}/pki/openssl.cnf"
|
|
||||||
become: no
|
|
||||||
|
|
||||||
- name: Build the CA pair
|
|
||||||
local_action: >
|
|
||||||
shell openssl ecparam -name prime256v1 -out ecparams/prime256v1.pem &&
|
|
||||||
openssl req -utf8 -new -newkey {{ algo_params | default('ec:ecparams/prime256v1.pem') }} -config openssl.cnf -keyout private/cakey.pem -out cacert.pem -x509 -days 3650 -batch -passout pass:"{{ easyrsa_CA_password }}" &&
|
|
||||||
touch {{ IP_subject_alt_name }}_ca_generated
|
|
||||||
become: no
|
|
||||||
args:
|
|
||||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
|
||||||
creates: "{{ IP_subject_alt_name }}_ca_generated"
|
|
||||||
environment:
|
|
||||||
subjectAltName: "DNS:{{ IP_subject_alt_name }},IP:{{ IP_subject_alt_name }}"
|
|
||||||
|
|
||||||
- name: Copy the CA certificate
|
|
||||||
local_action:
|
|
||||||
module: copy
|
|
||||||
src: "configs/{{ IP_subject_alt_name }}/pki/cacert.pem"
|
|
||||||
dest: "configs/{{ IP_subject_alt_name }}/cacert.pem"
|
|
||||||
mode: 0600
|
|
||||||
become: no
|
|
||||||
|
|
||||||
- name: Generate the serial number
|
|
||||||
local_action: >
|
|
||||||
shell echo 01 > serial &&
|
|
||||||
touch serial_generated
|
|
||||||
become: no
|
|
||||||
args:
|
|
||||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
|
||||||
creates: serial_generated
|
|
||||||
|
|
||||||
- name: Build the server pair
|
|
||||||
local_action: >
|
|
||||||
shell openssl req -utf8 -new -newkey {{ algo_params | default('ec:ecparams/prime256v1.pem') }} -config openssl.cnf -keyout private/{{ IP_subject_alt_name }}.key -out reqs/{{ IP_subject_alt_name }}.req -nodes -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ IP_subject_alt_name }}" -batch &&
|
|
||||||
openssl ca -utf8 -in reqs/{{ IP_subject_alt_name }}.req -out certs/{{ IP_subject_alt_name }}.crt -config openssl.cnf -days 3650 -batch -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ IP_subject_alt_name }}" &&
|
|
||||||
touch certs/{{ IP_subject_alt_name }}_crt_generated
|
|
||||||
become: no
|
|
||||||
args:
|
|
||||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
|
||||||
creates: certs/{{ IP_subject_alt_name }}_crt_generated
|
|
||||||
environment:
|
|
||||||
subjectAltName: "DNS:{{ IP_subject_alt_name }},IP:{{ IP_subject_alt_name }}"
|
|
||||||
|
|
||||||
- name: Build the client's pair
|
|
||||||
local_action: >
|
|
||||||
shell openssl req -utf8 -new -newkey {{ algo_params | default('ec:ecparams/prime256v1.pem') }} -config openssl.cnf -keyout private/{{ item }}.key -out reqs/{{ item }}.req -nodes -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ item }}" -batch &&
|
|
||||||
openssl ca -utf8 -in reqs/{{ item }}.req -out certs/{{ item }}.crt -config openssl.cnf -days 3650 -batch -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ item }}" &&
|
|
||||||
touch certs/{{ item }}_crt_generated
|
|
||||||
become: no
|
|
||||||
args:
|
|
||||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
|
||||||
creates: certs/{{ item }}_crt_generated
|
|
||||||
environment:
|
|
||||||
subjectAltName: "DNS:{{ item }}"
|
|
||||||
with_items: "{{ users }}"
|
|
||||||
|
|
||||||
- name: Build the client's p12
|
|
||||||
local_action: >
|
|
||||||
shell openssl pkcs12 -in certs/{{ item }}.crt -inkey private/{{ item }}.key -export -name {{ item }} -out private/{{ item }}.p12 -certfile cacert.pem -passout pass:"{{ easyrsa_p12_export_password }}"
|
|
||||||
become: no
|
|
||||||
args:
|
|
||||||
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
|
||||||
with_items: "{{ users }}"
|
|
||||||
|
|
||||||
- name: Copy the p12 certificates
|
|
||||||
local_action:
|
|
||||||
module: copy
|
|
||||||
src: "configs/{{ IP_subject_alt_name }}/pki/private/{{ item }}.p12"
|
|
||||||
dest: "configs/{{ IP_subject_alt_name }}/{{ item }}.p12"
|
|
||||||
mode: 0600
|
|
||||||
become: no
|
|
||||||
with_items:
|
|
||||||
- "{{ users }}"
|
|
||||||
|
|
||||||
- name: Copy the CA cert to the strongswan directory
|
|
||||||
copy: src='configs/{{ IP_subject_alt_name }}/pki/cacert.pem' dest=/etc/ipsec.d/cacerts/ca.crt owner=strongswan group=root mode=0600
|
|
||||||
notify:
|
|
||||||
- restart strongswan
|
|
||||||
|
|
||||||
- name: Copy the server cert to the strongswan directory
|
|
||||||
copy: src='configs/{{ IP_subject_alt_name }}/pki/certs/{{ IP_subject_alt_name }}.crt' dest=/etc/ipsec.d/certs/{{ IP_subject_alt_name }}.crt owner=strongswan group=root mode=0600
|
|
||||||
notify:
|
|
||||||
- restart strongswan
|
|
||||||
|
|
||||||
- name: Copy the server key to the strongswan directory
|
|
||||||
copy: src='configs/{{ IP_subject_alt_name }}/pki/private/{{ IP_subject_alt_name }}.key' dest=/etc/ipsec.d/private/{{ IP_subject_alt_name }}.key owner=strongswan group=root mode=0600
|
|
||||||
notify:
|
|
||||||
- restart strongswan
|
|
||||||
|
|
||||||
- name: Register p12 PayloadContent
|
|
||||||
local_action: >
|
|
||||||
shell cat private/{{ item }}.p12 | base64
|
|
||||||
register: PayloadContent
|
|
||||||
become: no
|
|
||||||
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 mobileconfigs
|
|
||||||
local_action:
|
|
||||||
module: template
|
|
||||||
src: mobileconfig.j2
|
|
||||||
dest: configs/{{ IP_subject_alt_name }}/{{ item.0 }}.mobileconfig
|
|
||||||
mode: 0600
|
|
||||||
become: no
|
|
||||||
with_together:
|
|
||||||
- "{{ users }}"
|
|
||||||
- "{{ PayloadContent.results }}"
|
|
||||||
no_log: True
|
|
||||||
|
|
||||||
- name: Build the strongswan app android config
|
|
||||||
local_action:
|
|
||||||
module: template
|
|
||||||
src: sswan.j2
|
|
||||||
dest: configs/{{ IP_subject_alt_name }}/{{ item.0 }}.sswan
|
|
||||||
mode: 0600
|
|
||||||
become: no
|
|
||||||
with_together:
|
|
||||||
- "{{ users }}"
|
|
||||||
- "{{ PayloadContent.results }}"
|
|
||||||
no_log: True
|
|
||||||
|
|
||||||
- name: Build the client ipsec config file
|
|
||||||
local_action:
|
|
||||||
module: template
|
|
||||||
src: client_ipsec.conf.j2
|
|
||||||
dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.conf
|
|
||||||
mode: 0600
|
|
||||||
become: no
|
|
||||||
with_items:
|
|
||||||
- "{{ users }}"
|
|
||||||
|
|
||||||
- name: Build the client ipsec secret file
|
|
||||||
local_action:
|
|
||||||
module: template
|
|
||||||
src: client_ipsec.secrets.j2
|
|
||||||
dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.secrets
|
|
||||||
mode: 0600
|
|
||||||
become: no
|
|
||||||
with_items:
|
|
||||||
- "{{ users }}"
|
|
||||||
|
|
||||||
- name: Build the windows client powershell script
|
|
||||||
local_action:
|
|
||||||
module: template
|
|
||||||
src: client_windows.ps1.j2
|
|
||||||
dest: configs/{{ IP_subject_alt_name }}/windows_{{ item }}.ps1
|
|
||||||
mode: 0600
|
|
||||||
become: no
|
|
||||||
when: Win10_Enabled is defined and Win10_Enabled == "Y"
|
|
||||||
with_items: "{{ users }}"
|
|
||||||
|
|
||||||
- name: Restrict permissions for the remote private directories
|
|
||||||
file: path="{{ item }}" state=directory mode=0700 owner=strongswan group=root
|
|
||||||
with_items:
|
|
||||||
- /etc/ipsec.d/private
|
|
||||||
|
|
||||||
- name: Restrict permissions for the local private directories
|
|
||||||
local_action:
|
|
||||||
module: file
|
|
||||||
path: "{{ item }}"
|
|
||||||
state: directory
|
|
||||||
mode: 0700
|
|
||||||
become: no
|
|
||||||
with_items:
|
|
||||||
- configs/{{ IP_subject_alt_name }}
|
|
||||||
|
|
||||||
- include: iptables.yml
|
|
||||||
tags: iptables
|
|
||||||
|
|
117
roles/vpn/tasks/openssl.yml
Normal file
117
roles/vpn/tasks/openssl.yml
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Ensure the pki directory is not exist
|
||||||
|
local_action:
|
||||||
|
module: file
|
||||||
|
dest: configs/{{ IP_subject_alt_name }}/pki
|
||||||
|
state: absent
|
||||||
|
become: no
|
||||||
|
when: easyrsa_reinit_existent == True
|
||||||
|
|
||||||
|
- name: Ensure the pki directories are exist
|
||||||
|
local_action:
|
||||||
|
module: file
|
||||||
|
dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}"
|
||||||
|
state: directory
|
||||||
|
recurse: yes
|
||||||
|
become: no
|
||||||
|
with_items:
|
||||||
|
- ecparams
|
||||||
|
- certs
|
||||||
|
- crl
|
||||||
|
- newcerts
|
||||||
|
- private
|
||||||
|
- reqs
|
||||||
|
|
||||||
|
- name: Ensure the files are exist
|
||||||
|
local_action:
|
||||||
|
module: file
|
||||||
|
dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}"
|
||||||
|
state: touch
|
||||||
|
become: no
|
||||||
|
with_items:
|
||||||
|
- ".rnd"
|
||||||
|
- "private/.rnd"
|
||||||
|
- "index.txt"
|
||||||
|
- "index.txt.attr"
|
||||||
|
- "serial"
|
||||||
|
|
||||||
|
- name: Generate the openssl server configs
|
||||||
|
local_action:
|
||||||
|
module: template
|
||||||
|
src: openssl.cnf.j2
|
||||||
|
dest: "configs/{{ IP_subject_alt_name }}/pki/openssl.cnf"
|
||||||
|
become: no
|
||||||
|
|
||||||
|
|
||||||
|
- name: Build the CA pair
|
||||||
|
local_action: >
|
||||||
|
shell openssl ecparam -name prime256v1 -out ecparams/prime256v1.pem &&
|
||||||
|
openssl req -utf8 -new -newkey {{ algo_params | default('ec:ecparams/prime256v1.pem') }} -config openssl.cnf -keyout private/cakey.pem -out cacert.pem -x509 -days 3650 -batch -passout pass:"{{ easyrsa_CA_password }}" &&
|
||||||
|
touch {{ IP_subject_alt_name }}_ca_generated
|
||||||
|
become: no
|
||||||
|
args:
|
||||||
|
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||||
|
creates: "{{ IP_subject_alt_name }}_ca_generated"
|
||||||
|
environment:
|
||||||
|
subjectAltName: "DNS:{{ IP_subject_alt_name }},IP:{{ IP_subject_alt_name }}"
|
||||||
|
|
||||||
|
- name: Copy the CA certificate
|
||||||
|
local_action:
|
||||||
|
module: copy
|
||||||
|
src: "configs/{{ IP_subject_alt_name }}/pki/cacert.pem"
|
||||||
|
dest: "configs/{{ IP_subject_alt_name }}/cacert.pem"
|
||||||
|
mode: 0600
|
||||||
|
become: no
|
||||||
|
|
||||||
|
- name: Generate the serial number
|
||||||
|
local_action: >
|
||||||
|
shell echo 01 > serial &&
|
||||||
|
touch serial_generated
|
||||||
|
become: no
|
||||||
|
args:
|
||||||
|
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||||
|
creates: serial_generated
|
||||||
|
|
||||||
|
- name: Build the server pair
|
||||||
|
local_action: >
|
||||||
|
shell openssl req -utf8 -new -newkey {{ algo_params | default('ec:ecparams/prime256v1.pem') }} -config openssl.cnf -keyout private/{{ IP_subject_alt_name }}.key -out reqs/{{ IP_subject_alt_name }}.req -nodes -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ IP_subject_alt_name }}" -batch &&
|
||||||
|
openssl ca -utf8 -in reqs/{{ IP_subject_alt_name }}.req -out certs/{{ IP_subject_alt_name }}.crt -config openssl.cnf -days 3650 -batch -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ IP_subject_alt_name }}" &&
|
||||||
|
touch certs/{{ IP_subject_alt_name }}_crt_generated
|
||||||
|
become: no
|
||||||
|
args:
|
||||||
|
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||||
|
creates: certs/{{ IP_subject_alt_name }}_crt_generated
|
||||||
|
environment:
|
||||||
|
subjectAltName: "DNS:{{ IP_subject_alt_name }},IP:{{ IP_subject_alt_name }}"
|
||||||
|
|
||||||
|
- name: Build the client's pair
|
||||||
|
local_action: >
|
||||||
|
shell openssl req -utf8 -new -newkey {{ algo_params | default('ec:ecparams/prime256v1.pem') }} -config openssl.cnf -keyout private/{{ item }}.key -out reqs/{{ item }}.req -nodes -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ item }}" -batch &&
|
||||||
|
openssl ca -utf8 -in reqs/{{ item }}.req -out certs/{{ item }}.crt -config openssl.cnf -days 3650 -batch -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ item }}" &&
|
||||||
|
touch certs/{{ item }}_crt_generated
|
||||||
|
become: no
|
||||||
|
args:
|
||||||
|
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||||
|
creates: certs/{{ item }}_crt_generated
|
||||||
|
environment:
|
||||||
|
subjectAltName: "DNS:{{ item }}"
|
||||||
|
with_items: "{{ users }}"
|
||||||
|
|
||||||
|
- name: Build the client's p12
|
||||||
|
local_action: >
|
||||||
|
shell openssl pkcs12 -in certs/{{ item }}.crt -inkey private/{{ item }}.key -export -name {{ item }} -out private/{{ item }}.p12 -certfile cacert.pem -passout pass:"{{ easyrsa_p12_export_password }}"
|
||||||
|
become: no
|
||||||
|
args:
|
||||||
|
chdir: "configs/{{ IP_subject_alt_name }}/pki/"
|
||||||
|
with_items: "{{ users }}"
|
||||||
|
|
||||||
|
- name: Copy the p12 certificates
|
||||||
|
local_action:
|
||||||
|
module: copy
|
||||||
|
src: "configs/{{ IP_subject_alt_name }}/pki/private/{{ item }}.p12"
|
||||||
|
dest: "configs/{{ IP_subject_alt_name }}/{{ item }}.p12"
|
||||||
|
mode: 0600
|
||||||
|
become: no
|
||||||
|
with_items:
|
||||||
|
- "{{ users }}"
|
52
roles/vpn/tasks/ubuntu.yml
Normal file
52
roles/vpn/tasks/ubuntu.yml
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
strongswan_additional_plugins: []
|
||||||
|
|
||||||
|
- name: Ubuntu | Install StrongSwan
|
||||||
|
apt: name=strongswan state=latest update_cache=yes install_recommends=yes
|
||||||
|
|
||||||
|
- name: Ubuntu | Enforcing ipsec with apparmor
|
||||||
|
shell: aa-enforce "{{ item }}"
|
||||||
|
when: apparmor_enabled is defined and apparmor_enabled == true
|
||||||
|
with_items:
|
||||||
|
- /usr/lib/ipsec/charon
|
||||||
|
- /usr/lib/ipsec/lookip
|
||||||
|
- /usr/lib/ipsec/stroke
|
||||||
|
notify:
|
||||||
|
- restart apparmor
|
||||||
|
tags: ['apparmor']
|
||||||
|
|
||||||
|
- name: Ubuntu | Enable services
|
||||||
|
service: name={{ item }} enabled=yes
|
||||||
|
with_items:
|
||||||
|
- apparmor
|
||||||
|
- strongswan
|
||||||
|
- netfilter-persistent
|
||||||
|
|
||||||
|
- name: Ubuntu | Configure iptables so IPSec traffic can traverse the tunnel
|
||||||
|
iptables: table=nat chain=POSTROUTING source="{{ vpn_network }}" jump=MASQUERADE
|
||||||
|
when: (security_enabled is not defined) or
|
||||||
|
(security_enabled is defined and security_enabled != "y")
|
||||||
|
notify:
|
||||||
|
- save iptables
|
||||||
|
|
||||||
|
- name: Ubuntu | Configure ip6tables so IPSec traffic can traverse the tunnel
|
||||||
|
iptables: ip_version=ipv6 table=nat chain=POSTROUTING source="{{ vpn_network_ipv6 }}" jump=MASQUERADE
|
||||||
|
when: ((security_enabled is not defined) or
|
||||||
|
(security_enabled is defined and security_enabled != "y")) and
|
||||||
|
ipv6_support is defined and ipv6_support == "yes"
|
||||||
|
notify:
|
||||||
|
- save iptables
|
||||||
|
|
||||||
|
- name: Ubuntu | Ensure that the strongswan service directory exist
|
||||||
|
file: path=/etc/systemd/system/strongswan.service.d/ state=directory mode=0755 owner=root group=root
|
||||||
|
|
||||||
|
- name: Ubuntu | Setup the cgroup limitations for the ipsec daemon
|
||||||
|
template: src=100-CustomLimitations.conf.j2 dest=/etc/systemd/system/strongswan.service.d/100-CustomLimitations.conf
|
||||||
|
notify:
|
||||||
|
- daemon-reload
|
||||||
|
- restart strongswan
|
||||||
|
|
||||||
|
- include: iptables.yml
|
||||||
|
tags: iptables
|
|
@ -11,6 +11,16 @@ charon {
|
||||||
}
|
}
|
||||||
user = strongswan
|
user = strongswan
|
||||||
group = strongswan
|
group = strongswan
|
||||||
|
|
||||||
|
filelog {
|
||||||
|
/var/log/charon.log {
|
||||||
|
time_format = %b %e %T
|
||||||
|
ike_name = yes
|
||||||
|
append = no
|
||||||
|
default = 1
|
||||||
|
flush_line = yes
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
include strongswan.d/*.conf
|
include strongswan.d/*.conf
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
- config.cfg
|
- config.cfg
|
||||||
|
|
||||||
pre_tasks:
|
pre_tasks:
|
||||||
|
- name: Common pre-tasks
|
||||||
|
include: playbooks/common.yml
|
||||||
|
|
||||||
- set_fact:
|
- set_fact:
|
||||||
IP_subject_alt_name: "{{ IP_subject }}"
|
IP_subject_alt_name: "{{ IP_subject }}"
|
||||||
easyrsa_p12_export_password: "{{ p12_export_password|default((ansible_date_time.iso8601_basic|sha1|to_uuid).split('-')[0]) }}"
|
easyrsa_p12_export_password: "{{ p12_export_password|default((ansible_date_time.iso8601_basic|sha1|to_uuid).split('-')[0]) }}"
|
||||||
|
@ -117,7 +120,7 @@
|
||||||
- name: Copy the revoked certificates to the vpn server
|
- name: Copy the revoked certificates to the vpn server
|
||||||
copy:
|
copy:
|
||||||
src: configs/{{ IP_subject_alt_name }}/pki/crl/{{ item }}.crt
|
src: configs/{{ IP_subject_alt_name }}/pki/crl/{{ item }}.crt
|
||||||
dest: /etc/ipsec.d/crls/{{ item }}.crt
|
dest: "{{ config_prefix|default('/') }}etc/ipsec.d/crls/{{ item }}.crt"
|
||||||
when: item not in users
|
when: item not in users
|
||||||
with_items: "{{ valid_certs.stdout_lines }}"
|
with_items: "{{ valid_certs.stdout_lines }}"
|
||||||
notify:
|
notify:
|
||||||
|
|
Loading…
Add table
Reference in a new issue