Skip to content
Open
111 changes: 87 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# puppet-roadwarrior

The year is 2016. Giant clouds rule the internet. Microsoft supports linux. Yet
The year is 2016. Giant clouds rule the internet. Microsoft supports Linux. Yet
in this strange new world, not all is well. Your home network is still stuck
behind an IPv4 NAT gateway. And your apps still haven't all figured out how to
do secure HTTPS encrypted connections yet.

But wait! There in the distance... a savior emerges! The Road Warror VPN!
But wait! There in the distance... a savior emerges! The Road Warrior VPN!

This module sets up a StrongSwan-based IKEv2 VPN suitable for use with the
native IKEv2 VPN client available on devices like iOS and Android, as well as
Expand All @@ -15,10 +15,21 @@ It intentionally tries not to do everything for everyone, the module is smart
in some areas (eg automatic generation of keys/certs) but dumb in other areas
(eg limited configurability to keep things simple for users).

If you're wanting the simpliest possible way to configure a VPN for your iOS
If you're wanting the simplest possible way to configure a VPN for your iOS
or Android device this is the module for you. If you want a module that exposes
every possible StrongSwan option, it's not.

... time passes ...

**It's now the future, 2024 to be precise.** Some stuff happened between 2016 and
now, but I wouldn't look too deeply into it if I were you... just pretend
everything is fine.

One big change, it's now really easy to connect to devices securely without a
RoadWarrior VPN... haha, only kidding. But there are at least lots of other
options to make it simple to create and manage configs... haha, got you again.

**You still need this.**

# Features

Expand All @@ -31,27 +42,49 @@ every possible StrongSwan option, it's not.

# Compatibility

Tested and confirmed on:
~~Tested and confirmed on:~~

* Debian 8/Jessie [Server]
* Debian 9/Stretch [Server]
* Ubuntu 16.04 [Server]
* iOS 9.3.1 [Client]
* iOS 10.0.1 [Client]
* iOS 11.4.1 [Client]
* MacOS X 10.11.4 [Client]
* Android 5 w/ StrongSwan [Client]
~~* Debian 8/Jessie [Server]~~
~~* Debian 9/Stretch [Server]~~
~~* Ubuntu 16.04 [Server]~~
~~* iOS 9.3.1 [Client]~~
~~* iOS 10.0.1 [Client]~~
~~* iOS 11.4.1 [Client]~~
~~* MacOS X 10.11.4 [Client]~~
~~* Android 5 w/ StrongSwan [Client]~~


The VPN *should* work on any OS released in 2015-2016 onwards, but many
~~The VPN *should* work on any OS released in 2015-2016 onwards, but many
earlier OS releases didn't ship with IKEv2 VPN support. The following are
known minimum versions for working clients:
known minimum versions for working clients:~~

* iOS 9+
* MacOS X 10.11 (El Capitan)
* Android 4.4.3+ (with use of third party StrongSwan client)
~~* iOS 9+~~
~~* MacOS X 10.11 (El Capitan)~~
~~* Android 4.4.3+ (with use of third party StrongSwan client)~~

Uncertain on above compatibility.

Tested and confirmed on:

* Ubuntu 24.04 [Server]
- strongswan/noble,now 5.9.13-2ubuntu4 all [installed]
- ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [x86_64-linux-gnu]
- Puppet: 8.6.0
- NOTE: Puppet 8.x is installed when using `gem install puppet` & Puppet
8 has legacy facts disabled by default. Built-in legacy facts have been removed,
but external dependency `thias-sysctl` appears to have been abandoned. Alternative
package `puppet-augeasproviders_sysctl` does not currently work for `24.04` might be
usable in future, but for now, re-enable legacy facts with:
`echo "include_legacy_facts=true" >> /etc/puppetlabs/puppet/puppet.conf`
* Ubuntu 22.04 [Server]
- strongswan/jammy-updates,jammy-security 5.9.5-2ubuntu2.2 all
- ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux-gnu]
- Puppet: 7.30.0

<details>
<summary>Command to list versions</summary>
<pre>apt list strongswan 2>&1 | grep -v "Listing" | grep -v "CLI" && ruby --version && echo Puppet: $(puppet --version)</pre>
</details>


# Usage
Expand All @@ -68,6 +101,20 @@ as the IP range to route back to the client devices.
vpn_route_v4 => '192.168.0.0/16',
}

Any destination within `vpn_route_v4` CIDR range with route through the VPN.
To route **all** traffic through it, set this to `0.0.0.0/0`. Make sure you also
set `vpn_dns_servers` to either your internal DNS server (if you wish to access
anything in your network via DNS name) or to external public DNS server(s).

class { 'roadwarrior':
manage_firewall_v4 => true,
manage_firewall_v6 => true,
vpn_name => 'vpn.example.com',
vpn_range_v4 => '10.10.10.0/24',
vpn_route_v4 => '0.0.0.0/0',
vpn_dns_servers => '1.1.1.1,8.8.8.8',
}

It is recommended that you consider backing up the `/etc/ipsec.d` directory. If
replacing/autoscaling the server running your roadwarror VPN, you will want to
populate the directory with the same data across the fleet, otherwises certs would
Expand Down Expand Up @@ -247,7 +294,15 @@ the module and then running your config directly from a file.

The following is an example of how to do this:

apt-get install puppet
## Note: apt-get install puppet installs an older version of Puppet (v5.x).

apt-get update && apt-get upgrade -y
apt-get install ruby

gem install puppet

## Ubuntu 24.04 only:
echo "include_legacy_facts=true" >> /etc/puppetlabs/puppet/puppet.conf

puppet module install jethrocarr/roadwarrior

Expand Down Expand Up @@ -290,9 +345,17 @@ StrongSwan/IKEv2 VPN configuration module.
This module is licensed under the Apache License, Version 2.0 (the "License").
See the LICENSE or http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Copyright 2016-2024 jethrocarr
Copyright 2024 sec-ml

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
2 changes: 1 addition & 1 deletion manifests/client.pp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
# Whilst not needed by StrongSwan itself, generate a PKCS12 (.p12) file with the
# combined cert and key, using $cert_password as the container password.
exec { "generate_client_pkcs12_${vpn_client}":
command => "openssl pkcs12 -export -inkey ${cert_dir}/private/client_${vpn_client}Key.pem -in ${cert_dir}/certs/client_${vpn_client}Cert.pem -name \"${vpn_client}\" -certfile ${cert_dir}/cacerts/strongswanCert.pem -caname \"${vpn_name} CA\" -password \"pass:${cert_password}\" -out ${cert_dir}/dist/${vpn_client}/${vpn_client}.p12",
command => "openssl pkcs12 -legacy -export -inkey ${cert_dir}/private/client_${vpn_client}Key.pem -in ${cert_dir}/certs/client_${vpn_client}Cert.pem -name \"${vpn_client}\" -certfile ${cert_dir}/cacerts/strongswanCert.pem -caname \"${vpn_name} CA\" -password \"pass:${cert_password}\" -out ${cert_dir}/dist/${vpn_client}/${vpn_client}.p12",
creates => "${cert_dir}/dist/${vpn_client}/${vpn_client}.p12",
} ->

Expand Down
16 changes: 8 additions & 8 deletions manifests/firewall.pp
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@

# Standard IPSec port
firewall { '100 V4 Permit StrongSwan 500':
provider => 'iptables',
protocol => 'iptables',
proto => 'udp',
dport => '500',
action => 'accept',
jump => 'accept',
}

# NAT-friendly IPSec port
firewall { '100 V4 Permit StrongSwan 4500':
provider => 'iptables',
protocol => 'iptables',
proto => 'udp',
dport => '4500',
action => 'accept',
jump => 'accept',
}
}

Expand All @@ -46,18 +46,18 @@

# Standard IPSec port
firewall { '100 V6 Permit StrongSwan 500':
provider => 'ip6tables',
protocol => 'ip6tables',
proto => 'udp',
dport => '500',
action => 'accept',
jump => 'accept',
}

# NAT-friendly IPSec port
firewall { '100 V6 Permit StrongSwan 4500':
provider => 'ip6tables',
protocol => 'ip6tables',
proto => 'udp',
dport => '4500',
action => 'accept',
jump => 'accept',
}
}

Expand Down
6 changes: 3 additions & 3 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
$cert_password = $::roadwarrior::params::cert_password,
) inherits ::roadwarrior::params {

validate_string( $vpn_dns_servers )
assert_type(String, $vpn_dns_servers)

# Compat checks
if ($::operatingsystem != "Debian" and $::operatingsystem != "Ubuntu") {
if ($::facts['os']['name'] != "Debian" and $::facts['os']['name'] != "Ubuntu") {
fail("Sorry, only Debian or Ubuntu distributions are supported by the roadwarrior module at this time. PRs welcome")
}

# Ensure resources is brilliant witchcraft, we can install all the StrongSwan
# dependencies in a single run and avoid double-definitions if they're already
# defined elsewhere.
ensure_packages([$packages_strongswan], {
stdlib::ensure_packages($packages_strongswan, {
'ensure' => 'present',
'before' => [ Service[$service_strongswan], File['/etc/ipsec.conf'], File['/etc/ipsec.secrets'] ]
})
Expand Down
4 changes: 2 additions & 2 deletions manifests/params.pp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

# TODO: This will (probably) be Debian specific
# Define the name of the service.
$service_strongswan = 'strongswan'
$service_strongswan = 'strongswan-starter'

# By default, we should manage the firewall. Ideally the user will be taking
# advantage of puppetlabs/firewall to manage their ruleset, but if another
Expand All @@ -23,7 +23,7 @@
# Name the VPN based on the hostname by default. This name is then used to
# populate all the certs that is generated, so pick a name you wish to keep,
# since changing means re-generating all the client certs/config.
$vpn_name = $::fqdn
$vpn_name = $::facts['fqdn']

# Default IP range for the VPN clients to use
$vpn_range_v4 = '10.10.10.0/24'
Expand Down