summaryrefslogtreecommitdiff
path: root/puppet/modules/site_openvpn
diff options
context:
space:
mode:
Diffstat (limited to 'puppet/modules/site_openvpn')
-rw-r--r--puppet/modules/site_openvpn/manifests/init.pp108
-rw-r--r--puppet/modules/site_openvpn/manifests/keys.pp51
-rw-r--r--puppet/modules/site_openvpn/manifests/resolver.pp36
-rw-r--r--puppet/modules/site_openvpn/manifests/server_config.pp166
4 files changed, 361 insertions, 0 deletions
diff --git a/puppet/modules/site_openvpn/manifests/init.pp b/puppet/modules/site_openvpn/manifests/init.pp
new file mode 100644
index 00000000..e3d2a9af
--- /dev/null
+++ b/puppet/modules/site_openvpn/manifests/init.pp
@@ -0,0 +1,108 @@
+class site_openvpn {
+ tag 'leap_service'
+ # parse hiera config
+ $ip_address = hiera('ip_address')
+ $interface = getvar("interface_${ip_address}")
+ #$gateway_address = hiera('gateway_address')
+ $openvpn_config = hiera('openvpn')
+ $openvpn_gateway_address = $openvpn_config['gateway_address']
+ $openvpn_tcp_network_prefix = '10.1.0'
+ $openvpn_tcp_netmask = '255.255.248.0'
+ $openvpn_tcp_cidr = '21'
+ $openvpn_udp_network_prefix = '10.2.0'
+ $openvpn_udp_netmask = '255.255.248.0'
+ $openvpn_udp_cidr = '21'
+ $x509_config = hiera('x509')
+
+ # deploy ca + server keys
+ include site_openvpn::keys
+
+ # create 2 openvpn config files, one for tcp, one for udp
+ site_openvpn::server_config { 'tcp_config':
+ port => '1194',
+ proto => 'tcp',
+ local => $openvpn_gateway_address,
+ server => "${openvpn_tcp_network_prefix}.0 ${openvpn_tcp_netmask}",
+ push => "\"dhcp-option DNS ${openvpn_tcp_network_prefix}.1\"",
+ management => '127.0.0.1 1000'
+ }
+ site_openvpn::server_config { 'udp_config':
+ port => '1194',
+ proto => 'udp',
+ server => "${openvpn_udp_network_prefix}.0 ${openvpn_udp_netmask}",
+ push => "\"dhcp-option DNS ${openvpn_udp_network_prefix}.1\"",
+ local => $openvpn_gateway_address,
+ management => '127.0.0.1 1001'
+ }
+
+ # add second IP on given interface
+ file { '/usr/local/bin/leap_add_second_ip.sh':
+ content => "#!/bin/sh
+ip addr show dev $interface | grep -q ${openvpn_gateway_address}/24 || ip addr add ${openvpn_gateway_address}/24 dev $interface
+/bin/echo 1 > /proc/sys/net/ipv4/ip_forward
+",
+ mode => '0755',
+ }
+
+ exec { '/usr/local/bin/leap_add_second_ip.sh':
+ subscribe => File['/usr/local/bin/leap_add_second_ip.sh'],
+ }
+
+ cron { 'leap_add_second_ip.sh':
+ command => "/usr/local/bin/leap_add_second_ip.sh",
+ user => 'root',
+ special => 'reboot',
+ }
+
+ # setup the resolver to listen on the vpn IP
+ include site_openvpn::resolver
+
+ include site_shorewall::eip
+
+ package {
+ 'openvpn':
+ ensure => installed;
+ }
+ service {
+ 'openvpn':
+ ensure => running,
+ hasrestart => true,
+ hasstatus => true,
+ require => Exec['concat_/etc/default/openvpn'];
+ }
+
+ file {
+ '/etc/openvpn':
+ ensure => directory,
+ require => Package['openvpn'];
+ }
+
+ file {
+ '/etc/openvpn/keys':
+ ensure => directory,
+ require => Package['openvpn'];
+ }
+
+ concat {
+ '/etc/default/openvpn':
+ owner => root,
+ group => root,
+ mode => 644,
+ warn => true,
+ notify => Service['openvpn'];
+ }
+
+ concat::fragment {
+ 'openvpn.default.header':
+ content => template('openvpn/etc-default-openvpn.erb'),
+ target => '/etc/default/openvpn',
+ order => 01;
+ }
+
+ concat::fragment {
+ "openvpn.default.autostart.${name}":
+ content => 'AUTOSTART=all',
+ target => '/etc/default/openvpn',
+ order => 10;
+ }
+}
diff --git a/puppet/modules/site_openvpn/manifests/keys.pp b/puppet/modules/site_openvpn/manifests/keys.pp
new file mode 100644
index 00000000..f3c5b423
--- /dev/null
+++ b/puppet/modules/site_openvpn/manifests/keys.pp
@@ -0,0 +1,51 @@
+class site_openvpn::keys {
+
+ x509::key {
+ 'leap_openvpn':
+ content => $site_openvpn::x509_config['key'],
+ notify => Service[openvpn];
+ }
+
+ x509::cert {
+ 'leap_openvpn':
+ content => $site_openvpn::x509_config['cert'],
+ notify => Service[openvpn];
+ }
+
+ x509::ca {
+ 'leap_ca':
+ content => $site_openvpn::x509_config['ca_cert'],
+ notify => Service[openvpn];
+ }
+
+ file { '/etc/openvpn/keys/dh.pem':
+ content => $site_openvpn::x509_config['dh'],
+ mode => '0644',
+ }
+
+ #
+ # CA bundle -- we want to have the possibility of allowing multiple CAs.
+ # For now, the reason is to transition to using client CA. In the future,
+ # we will want to be able to smoothly phase out one CA and phase in another.
+ # I tried "--capath" for this, but it did not work.
+ #
+
+ concat {
+ '/etc/openvpn/ca_bundle.pem':
+ owner => root,
+ group => root,
+ mode => 644,
+ warn => true,
+ notify => Service['openvpn'];
+ }
+
+ concat::fragment {
+ 'client_ca_cert':
+ content => $site_openvpn::x509_config['client_ca_cert'],
+ target => '/etc/openvpn/ca_bundle.pem';
+ 'ca_cert':
+ content => $site_openvpn::x509_config['ca_cert'],
+ target => '/etc/openvpn/ca_bundle.pem';
+ }
+
+}
diff --git a/puppet/modules/site_openvpn/manifests/resolver.pp b/puppet/modules/site_openvpn/manifests/resolver.pp
new file mode 100644
index 00000000..d3963c95
--- /dev/null
+++ b/puppet/modules/site_openvpn/manifests/resolver.pp
@@ -0,0 +1,36 @@
+class site_openvpn::resolver {
+
+ # this is an unfortunate way to get around the fact that the version of
+ # unbound we are working with does not accept a wildcard include directive
+ # (/etc/unbound/conf.d/*), when it does, these line definitions should
+ # go away and instead the caching_resolver should be configured to
+ # include: /etc/unbound/conf.d/*
+
+ line {
+ 'add_tcp_resolver':
+ ensure => present,
+ file => '/etc/unbound/unbound.conf',
+ line => 'server: include: /etc/unbound/conf.d/vpn_tcp_resolver',
+ notify => Service['unbound'];
+
+ 'add_udp_resolver':
+ ensure => present,
+ file => '/etc/unbound/unbound.conf',
+ line => 'server: include: /etc/unbound/conf.d/vpn_udp_resolver',
+ notify => Service['unbound'];
+ }
+
+ file {
+ '/etc/unbound/conf.d/vpn_udp_resolver':
+ content => "interface: ${site_openvpn::openvpn_udp_network_prefix}.1\naccess-control: ${site_openvpn::openvpn_udp_network_prefix}.0/${site_openvpn::openvpn_udp_cidr} allow\n",
+ owner => root, group => root, mode => '0644',
+ require => Service['openvpn'],
+ notify => Service['unbound'];
+
+ '/etc/unbound/conf.d/vpn_tcp_resolver':
+ content => "interface: ${site_openvpn::openvpn_tcp_network_prefix}.1\naccess-control: ${site_openvpn::openvpn_tcp_network_prefix}.0/${site_openvpn::openvpn_tcp_cidr} allow\n",
+ owner => root, group => root, mode => '0644',
+ require => Service['openvpn'],
+ notify => Service['unbound'];
+ }
+}
diff --git a/puppet/modules/site_openvpn/manifests/server_config.pp b/puppet/modules/site_openvpn/manifests/server_config.pp
new file mode 100644
index 00000000..de273b46
--- /dev/null
+++ b/puppet/modules/site_openvpn/manifests/server_config.pp
@@ -0,0 +1,166 @@
+#
+# Cipher discussion
+# ================================
+#
+# We want to specify explicit values for the crypto options to prevent a MiTM from forcing
+# a weaker cipher. These should be set in both the server and the client ('auth' and 'cipher'
+# MUST be the same on both ends or no data will get transmitted).
+#
+# tls-cipher DHE-RSA-AES128-SHA
+#
+# dkg: For the TLS control channel, we want to make sure we choose a
+# key exchange mechanism that has PFS (meaning probably some form of ephemeral
+# Diffie-Hellman key exchange), and that uses a standard, well-tested cipher
+# (I recommend AES, and 128 bits is probably fine, since there are some known
+# weaknesses in the 192- and 256-bit key schedules). That leaves us with the
+# choice of public key algorithms: /usr/sbin/openvpn --show-tls | grep DHE |
+# grep AES128 | grep GCM.
+#
+# elijah:
+# I could not get any of these working:
+# * openvpn --show-tls | grep GCM
+# * openvpn --show-tls | grep DHE | grep AES128 | grep SHA256
+# so, i went with this:
+# * openvpn --show-tls | grep DHE | grep AES128 | grep -v SHA256 | grep -v GCM
+# Also, i couldn't get any of the elliptical curve algorithms to work. Not sure how
+# our cert generation interacts with the tls-cipher algorithms.
+#
+# note: in my tests, DHE-RSA-AES256-SHA is the one it negotiates if no value is set.
+#
+# auth SHA1
+#
+# dkg: For HMAC digest to authenticate packets, we just want SHA256. OpenVPN lists
+# a number of “digest” with names like “RSA-SHA256”, but this are legacy and
+# should be avoided.
+#
+# elijah: i am not so sure that the digest algo matters for 'auth' option, because
+# i think an attacker would have to forge the digest in real time, which is still far from
+# a possibility for SHA1. So, i am leaving the default for now (SHA1).
+#
+# cipher AES-128-CBC
+#
+# dkg: For the choice of cipher, we need to select an algorithm and a
+# cipher mode. OpenVPN defaults to Blowfish, which is a fine algorithm — but
+# our control channel is already relying on AES not being broken; if the
+# control channel is cracked, then the key material for the tunnel is exposed,
+# and the choice of algorithm is moot. So it makes more sense to me to rely on
+# the same cipher here: AES128. As for the cipher mode, OFB seems cleaner to
+# me, but CBC is more well-tested, and the OpenVPN man page (at least as of
+# version 2.2.1) says “CBC is recommended and CFB and OFB should be considered
+# advanced modes.”
+#
+# note: the default is BF-CBC (blowfish)
+#
+
+define site_openvpn::server_config ($port, $proto, $local, $server, $push, $management ) {
+
+ $openvpn_configname = $name
+
+ concat {
+ "/etc/openvpn/$openvpn_configname.conf":
+ owner => root,
+ group => root,
+ mode => 644,
+ warn => true,
+ require => File['/etc/openvpn'],
+ notify => Service['openvpn'];
+ }
+
+ openvpn::option {
+ "ca $openvpn_configname":
+ key => 'ca',
+ value => '/etc/openvpn/ca_bundle.pem',
+ server => $openvpn_configname;
+ "cert $openvpn_configname":
+ key => 'cert',
+ value => '/etc/x509/certs/leap_openvpn.crt',
+ server => $openvpn_configname;
+ "key $openvpn_configname":
+ key => 'key',
+ value => '/etc/x509/keys/leap_openvpn.key',
+ server => $openvpn_configname;
+ "dh $openvpn_configname":
+ key => 'dh',
+ value => '/etc/openvpn/keys/dh.pem',
+ server => $openvpn_configname;
+ "tls-cipher $openvpn_configname":
+ key => 'tls-cipher',
+ value => 'DHE-RSA-AES128-SHA',
+ server => $openvpn_configname;
+ "auth $openvpn_configname":
+ key => 'auth',
+ value => 'SHA1',
+ server => $openvpn_configname;
+ "cipher $openvpn_configname":
+ key => 'cipher',
+ value => 'AES-128-CBC',
+ server => $openvpn_configname;
+ "dev $openvpn_configname":
+ key => 'dev',
+ value => 'tun',
+ server => $openvpn_configname;
+ "duplicate-cn $openvpn_configname":
+ key => 'duplicate-cn',
+ server => $openvpn_configname;
+ "keepalive $openvpn_configname":
+ key => 'keepalive',
+ value => '5 20',
+ server => $openvpn_configname;
+ "local $openvpn_configname":
+ key => 'local',
+ value => $local,
+ server => $openvpn_configname;
+ "mute $openvpn_configname":
+ key => 'mute',
+ value => '5',
+ server => $openvpn_configname;
+ "mute-replay-warnings $openvpn_configname":
+ key => 'mute-replay-warnings',
+ server => $openvpn_configname;
+ "management $openvpn_configname":
+ key => 'management',
+ value => $management,
+ server => $openvpn_configname;
+ "proto $openvpn_configname":
+ key => 'proto',
+ value => $proto,
+ server => $openvpn_configname;
+ "push1 $openvpn_configname":
+ key => 'push',
+ value => $push,
+ server => $openvpn_configname;
+ "push2 $openvpn_configname":
+ key => 'push',
+ value => '"redirect-gateway def1"',
+ server => $openvpn_configname;
+ "script-security $openvpn_configname":
+ key => 'script-security',
+ value => '2',
+ server => $openvpn_configname;
+ "server $openvpn_configname":
+ key => 'server',
+ value => $server,
+ server => $openvpn_configname;
+ "status $openvpn_configname":
+ key => 'status',
+ value => '/var/run/openvpn-status 10',
+ server => $openvpn_configname;
+ "status-version $openvpn_configname":
+ key => 'status-version',
+ value => '3',
+ server => $openvpn_configname;
+ "topology $openvpn_configname":
+ key => 'topology',
+ value => 'subnet',
+ server => $openvpn_configname;
+ # no need for server-up.sh right now
+ #"up $openvpn_configname":
+ # key => 'up',
+ # value => '/etc/openvpn/server-up.sh',
+ # server => $openvpn_configname;
+ "verb $openvpn_configname":
+ key => 'verb',
+ value => '3',
+ server => $openvpn_configname;
+ }
+}