diff options
Diffstat (limited to 'puppet/modules/site_openvpn/manifests')
-rw-r--r-- | puppet/modules/site_openvpn/manifests/init.pp | 108 | ||||
-rw-r--r-- | puppet/modules/site_openvpn/manifests/keys.pp | 51 | ||||
-rw-r--r-- | puppet/modules/site_openvpn/manifests/resolver.pp | 36 | ||||
-rw-r--r-- | puppet/modules/site_openvpn/manifests/server_config.pp | 166 |
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; + } +} |