From 25810838c39e4bb870008bf2927cab3804b2b648 Mon Sep 17 00:00:00 2001 From: Micah R Ledbetter Date: Sat, 27 Jan 2018 14:10:11 -0600 Subject: [PATCH] Configure DNS names for each user In the dns_adblocking role, assign each Algo user a domain name, allowing connected users to communicate internally without having to know each other's VPN IP addresses. The user can set this in config.cfg as vpn_domain. This required one potentially breaking change: disallowing multiple connections from the same Algo user. The server's ipsec.conf is also modified, with a connection per-user that sets an IP address based on the order the user appears in the config.cfg file. Finally, a new /etc/hosts.ipsecclients file is created, which maps from the IP addresses assigned in ipsec.conf to $user.$vpn_domain --- config.cfg | 6 ++++ requirements.txt | 1 + roles/dns_adblocking/tasks/main.yml | 7 +++++ .../dns_adblocking/templates/dnsmasq.conf.j2 | 1 + .../templates/etc.hosts.ipsecclients.j2 | 3 ++ .../templates/usr.sbin.dnsmasq.j2 | 1 + roles/vpn/templates/ipsec.conf.j2 | 30 ++++++++++++++++--- 7 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 roles/dns_adblocking/templates/etc.hosts.ipsecclients.j2 diff --git a/config.cfg b/config.cfg index 108b8cf6..5202a4cc 100644 --- a/config.cfg +++ b/config.cfg @@ -47,6 +47,12 @@ CA_PayloadIdentifier: "{{ 700000 | random | to_uuid | upper }}" # Block traffic between connected clients BetweenClients_DROP: Y +# Used for resolving hosts within the VPN, not connecting to the VPN +# If BetweenClients_DROP is set to 'N', and the dns_adblocking role is enabled, +# connected users will be able to communicate with each other using +# $user.$vpn_domain DNS names +vpn_domain: algo.internal + congrats: common: | "# Congratulations! #" diff --git a/requirements.txt b/requirements.txt index 67ec4a10..3170e46f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ apache-libcloud six pyopenssl jinja2==2.8 +netaddr diff --git a/roles/dns_adblocking/tasks/main.yml b/roles/dns_adblocking/tasks/main.yml index 2ba74b77..c93d590e 100644 --- a/roles/dns_adblocking/tasks/main.yml +++ b/roles/dns_adblocking/tasks/main.yml @@ -27,6 +27,13 @@ notify: - restart dnsmasq + - name: VPN hosts file configured + template: + src: etc.hosts.ipsecclients.j2 + dest: "{{ config_prefix|default('/') }}etc/hosts.ipsecclients" + notify: + - restart dnsmasq + - name: Adblock script created template: src: adblock.sh.j2 diff --git a/roles/dns_adblocking/templates/dnsmasq.conf.j2 b/roles/dns_adblocking/templates/dnsmasq.conf.j2 index 3424d544..b2d35f25 100644 --- a/roles/dns_adblocking/templates/dnsmasq.conf.j2 +++ b/roles/dns_adblocking/templates/dnsmasq.conf.j2 @@ -132,6 +132,7 @@ bind-interfaces # or if you want it to read another file, as well as /etc/hosts, use # this. # addn-hosts=/var/lib/dnsmasq/block.hosts +addn-hosts=/etc/hosts.ipsecclients # Set this (and domain: see below) if you want to have a domain # automatically added to simple names in a hosts-file. diff --git a/roles/dns_adblocking/templates/etc.hosts.ipsecclients.j2 b/roles/dns_adblocking/templates/etc.hosts.ipsecclients.j2 new file mode 100644 index 00000000..abafdd8d --- /dev/null +++ b/roles/dns_adblocking/templates/etc.hosts.ipsecclients.j2 @@ -0,0 +1,3 @@ +{% for user in users %} +{{ vpn_network | ipaddr(loop.index) | ipaddr('address') }} {{ user }}.{{ vpn_domain }} +{% endfor %} diff --git a/roles/dns_adblocking/templates/usr.sbin.dnsmasq.j2 b/roles/dns_adblocking/templates/usr.sbin.dnsmasq.j2 index 25a56373..2bb4085d 100644 --- a/roles/dns_adblocking/templates/usr.sbin.dnsmasq.j2 +++ b/roles/dns_adblocking/templates/usr.sbin.dnsmasq.j2 @@ -17,6 +17,7 @@ /var/lib/dnsmasq/block.hosts r, /etc/dnsmasq.d-available/ r, /etc/dnsmasq.d-available/* r, + /etc/hosts.ipsecclients r, /usr/sbin/dnsmasq mr, diff --git a/roles/vpn/templates/ipsec.conf.j2 b/roles/vpn/templates/ipsec.conf.j2 index 6c5a2d45..20f79faa 100644 --- a/roles/vpn/templates/ipsec.conf.j2 +++ b/roles/vpn/templates/ipsec.conf.j2 @@ -1,5 +1,5 @@ config setup - uniqueids=never # allow multiple connections per user + uniqueids=replace # if the same user connects twice, replace the old connection with the new one charondebug="ike {{ strongswan_log_level }}, knl {{ strongswan_log_level }}, cfg {{ strongswan_log_level }}, net {{ strongswan_log_level }}, esp {{ strongswan_log_level }}, dmn {{ strongswan_log_level }}, mgr {{ strongswan_log_level }}" conn %default @@ -25,14 +25,36 @@ conn %default leftsendcert=always leftsubnet=0.0.0.0/0,::/0 +# Client configs +# example: https://www.strongswan.org/testing/testresults/ikev2/config-payload/, especially moon.ipsec.conf +# NOTE: we specify each client config twice, identically except for the rightid parameter +# because some clients (e.g. strongswan) send the rightid as "/CN=$user" +# while others (e.g. macOS) send the rightid as "$user" + +{% for user in users %} + +conn AlgoUser-{{ user }} right=%any + rightid={{ user }} rightauth=pubkey - rightsourceip={{ vpn_network }},{{ vpn_network_ipv6 }} + rightsourceip={{ vpn_network | ipaddr(loop.index) | ipaddr('address') }} {% if local_dns is defined and local_dns == "Y" %} rightdns={{ local_service_ip }} {% else %} rightdns={% for host in dns_servers.ipv4 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% if ipv6_support is defined and ipv6_support == "yes" %},{% for host in dns_servers.ipv6 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% endif %} {% endif %} - -conn ikev2-pubkey auto=add + +conn AlgoUser-CN{{ user }} + right=%any + rightid="/CN={{ user }}" + rightauth=pubkey + rightsourceip={{ vpn_network | ipaddr(loop.index) | ipaddr('address') }} +{% if local_dns is defined and local_dns == "Y" %} + rightdns={{ local_service_ip }} +{% else %} + rightdns={% for host in dns_servers.ipv4 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% if ipv6_support is defined and ipv6_support == "yes" %},{% for host in dns_servers.ipv6 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% endif %} +{% endif %} + auto=add + +{% endfor %} \ No newline at end of file