diff options
-rwxr-xr-x | deploy.sh | 61 | ||||
-rw-r--r-- | provider_base/common.json | 5 | ||||
-rw-r--r-- | provider_base/files/service-definitions/eip-service.json.erb | 8 | ||||
-rw-r--r-- | provider_base/services/openvpn.json | 9 | ||||
-rw-r--r-- | provider_base/services/webapp.json | 10 | ||||
-rw-r--r-- | provider_base/tags/local.json | 3 | ||||
-rw-r--r-- | provider_base/test/openvpn/client.ovpn.erb | 28 | ||||
-rw-r--r-- | puppet/manifests/site.pp | 2 | ||||
-rw-r--r-- | puppet/modules/site_config/manifests/eip.pp | 57 | ||||
-rw-r--r-- | puppet/modules/site_couchdb/manifests/init.pp | 1 | ||||
-rw-r--r-- | puppet/modules/site_openvpn/manifests/init.pp | 58 | ||||
-rw-r--r-- | puppet/modules/site_openvpn/manifests/keys.pp | 14 | ||||
-rw-r--r-- | puppet/modules/site_openvpn/manifests/server_config.pp | 67 | ||||
-rw-r--r-- | puppet/modules/site_shorewall/manifests/dnat_rule.pp | 4 | ||||
-rw-r--r-- | puppet/modules/site_shorewall/manifests/eip.pp | 6 |
15 files changed, 185 insertions, 148 deletions
diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index 9a8fcccf..00000000 --- a/deploy.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh -# -# missing: header, license - -bad_usage() { usage 1>&2; [ $# -eq 0 ] || echo "$@"; exit 1; } - -usage() { - cat <<EOF - -Usage: ${0##*/} [--init] - - Configures Leap services as defined from ../config/default.yaml - - options: - --init Install dependencies, should be run once at the first time. - -EOF -} - -install_prerequisites () { - PACKAGES='git puppet ruby-hiera-puppet' - echo "Installing $PACKAGES, configuring some basic puppet requirements." - dpkg -l $PACKAGES > /dev/null 2>&1 - if [ ! $? -eq 0 ] - then - apt-get update - apt-get install -y $PACKAGES - fi - - # lsb is needed for a first puppet run - puppet apply $PUPPET_ENV --execute 'include lsb' -} - - -# main - -PUPPET_ENV='--confdir=puppet' - -long_opts="init" -getopt_out=$(getopt --name "${0##*/}" \ - --options "${short_opts}" --long "${long_opts}" -- "$@") && \ - eval set -- "${getopt_out}" || bad_usage -while [ $# -ne 0 ]; do - cur=${1}; next=${2}; - case "$cur" in - --help) usage ; exit 0;; - --init) install_prerequisites ; exit 0;; - --) shift; break;; - esac - shift; -done - -[ $# -gt 0 ] && bad_usage "too many arguments" - -# keep repository up to date -git pull -git submodule init -git submodule update - -# run puppet without irritating deprecation warnings -puppet apply $PUPPET_ENV puppet/manifests/site.pp $@ | grep -v 'warning:.*is deprecated' diff --git a/provider_base/common.json b/provider_base/common.json index 4e85c9b0..6d4291c6 100644 --- a/provider_base/common.json +++ b/provider_base/common.json @@ -1,6 +1,7 @@ { "ip_address": "REQUIRED", "services": [], + "tags": [], "domain": { "full_suffix": "= global.provider.domain", "internal_suffix": "= global.provider.internal_domain", @@ -20,7 +21,7 @@ "use": false, "cert": "= x509.use ? file(:node_x509_cert, :missing => 'x509 certificate for node $node. Run `leap update-cert`') : nil", "key": "= x509.use ? file(:node_x509_key, :missing => 'x509 key for node $node. Run `leap update-cert`') : nil", - "ca_cert": "= file :ca_cert" + "ca_cert": "= try_file :ca_cert" }, - "local": "= self.vagrant?" + "local": false } diff --git a/provider_base/files/service-definitions/eip-service.json.erb b/provider_base/files/service-definitions/eip-service.json.erb index 095f3530..8dc7211d 100644 --- a/provider_base/files/service-definitions/eip-service.json.erb +++ b/provider_base/files/service-definitions/eip-service.json.erb @@ -17,7 +17,7 @@ gateway["capabilities"] = node.openvpn.pick( :ports, :protocols, :user_ips, :adblock, :filter_dns) gateway["capabilities"]["transport"] = ["openvpn"] - gateway["ip_address"] = node.ip_address + gateway["ip_address"] = node.openvpn.gateway_address gateway["host"] = node.domain.full gateway["cluster"] = underscore(node.openvpn.location) gateways << gateway @@ -28,6 +28,10 @@ end hsh["gateways"] = gateways hsh["clusters"] = clusters.values - + hsh["openvpn_configuration"] = { + "tls-cipher" => "DHE-RSA-AES128-SHA", + "auth" => "SHA1", + "cipher" => "AES-128-CBC" + } generate_json hsh %>
\ No newline at end of file diff --git a/provider_base/services/openvpn.json b/provider_base/services/openvpn.json index 71d1d2c7..15deab70 100644 --- a/provider_base/services/openvpn.json +++ b/provider_base/services/openvpn.json @@ -1,7 +1,9 @@ { "service_type": "user_service", "x509": { - "use": true + "use": true, + "ca_cert": "= file :ca_cert, :missing => 'Certificate Authority. Run `leap init-ca`'", + "dh": "= file :dh_params, :missing => 'Diffie-Hellman parameters. Run `leap init-dh`'" }, "openvpn": { "location": "Location Unknown", @@ -9,9 +11,6 @@ "protocols": ["tcp", "udp"], "filter_dns": false, "adblock": false, - "user_ips": false, - "ca_crt": "= file :ca_cert, :missing => 'Certificate Authority. Run `leap init-ca`'", - "ca_key": "= file :ca_key, :missing => 'Certificate Authority. Run `leap init-ca`'", - "dh": "= file :dh_params, :missing => 'Diffie-Hellman parameters. Run `leap init-dh`'" + "user_ips": false } } diff --git a/provider_base/services/webapp.json b/provider_base/services/webapp.json index ca9edf33..afb51ee1 100644 --- a/provider_base/services/webapp.json +++ b/provider_base/services/webapp.json @@ -1,12 +1,12 @@ { "webapp": { "modules": ["user", "billing", "help"], - "couchdb_hosts": "= nodes[:services => :couchdb].field('domain.name')", + "couchdb_hosts": "= nodes[:services => :couchdb][:local => local].field('domain.name')", "couchdb_user": "= global.services[:couchdb].couch.users[:webapp]" }, "definition_files": { - "provider": "= file 'service-definitions/provider.json.erb'", - "eip_service": "= file 'service-definitions/eip-service.json.erb'" + "provider": "= file :provider_json_template", + "eip_service": "= file :eip_service_json_template" }, "service_type": "public_service", "api_domain": "= 'api.' + domain.full_suffix", @@ -15,7 +15,9 @@ }, "x509": { "use": true, + "ca_cert": "= file :ca_cert, :missing => 'provider CA. Run `leap init-ca`'", "commercial_cert": "= file [:commercial_cert, global.provider.domain]", - "commercial_key": "= file [:commercial_key, global.provider.domain]" + "commercial_key": "= file [:commercial_key, global.provider.domain]", + "commercial_ca_cert": "= try_file :commercial_ca_cert" } }
\ No newline at end of file diff --git a/provider_base/tags/local.json b/provider_base/tags/local.json new file mode 100644 index 00000000..9cb16602 --- /dev/null +++ b/provider_base/tags/local.json @@ -0,0 +1,3 @@ +{ + "local": true +}
\ No newline at end of file diff --git a/provider_base/test/openvpn/client.ovpn.erb b/provider_base/test/openvpn/client.ovpn.erb new file mode 100644 index 00000000..96cb7177 --- /dev/null +++ b/provider_base/test/openvpn/client.ovpn.erb @@ -0,0 +1,28 @@ +client +dev tun +remote-cert-tls server +remote-random +nobind +script-security 2 +verb 3 +auth SHA1 +cipher AES-128-CBC +tls-cipher DHE-RSA-AES128-SHA + +<% manager.services['openvpn'].node_list.each_node do |node| -%> +<% unless node.local -%> +<%= "remote #{node.openvpn.gateway_address} 1194 udp"%> +<% end -%> +<% end -%> + +<ca> +<%= read_file! :ca_cert -%> +</ca> + +<cert> +<%= read_file! :test_client_cert -%> +</cert> + +<key> +<%= read_file! :test_client_key -%> +</key> diff --git a/puppet/manifests/site.pp b/puppet/manifests/site.pp index 70c97030..9da2174c 100644 --- a/puppet/manifests/site.pp +++ b/puppet/manifests/site.pp @@ -12,7 +12,7 @@ node 'default' { # configure eip if 'openvpn' in $services { - include site_config::eip + include site_openvpn } if 'couchdb' in $services { diff --git a/puppet/modules/site_config/manifests/eip.pp b/puppet/modules/site_config/manifests/eip.pp deleted file mode 100644 index 4280fb67..00000000 --- a/puppet/modules/site_config/manifests/eip.pp +++ /dev/null @@ -1,57 +0,0 @@ -class site_config::eip { - - # parse hiera config - $ip_address = hiera('ip_address') - $interface = hiera('interface') - #$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' - - include site_openvpn - - # 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", - 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', - } - - include site_shorewall::eip -} diff --git a/puppet/modules/site_couchdb/manifests/init.pp b/puppet/modules/site_couchdb/manifests/init.pp index 30ce7f54..10408094 100644 --- a/puppet/modules/site_couchdb/manifests/init.pp +++ b/puppet/modules/site_couchdb/manifests/init.pp @@ -16,6 +16,7 @@ class site_couchdb { $couchdb_ca_daemon_pw = $couchdb_ca_daemon['password'] Class['site_couchdb::package'] + -> Exec['refresh_apt'] -> Package ['couchdb'] -> File['/etc/init.d/couchdb'] -> File['/etc/couchdb/local.ini'] diff --git a/puppet/modules/site_openvpn/manifests/init.pp b/puppet/modules/site_openvpn/manifests/init.pp index e95e67d5..548d1df2 100644 --- a/puppet/modules/site_openvpn/manifests/init.pp +++ b/puppet/modules/site_openvpn/manifests/init.pp @@ -1,4 +1,62 @@ class site_openvpn { + # parse hiera config + $ip_address = hiera('ip_address') + $interface = hiera('interface') + #$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') + + include site_openvpn + + # 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', + } + + include site_shorewall::eip + package { 'openvpn': ensure => installed; diff --git a/puppet/modules/site_openvpn/manifests/keys.pp b/puppet/modules/site_openvpn/manifests/keys.pp index d029fbac..12c1bd8f 100644 --- a/puppet/modules/site_openvpn/manifests/keys.pp +++ b/puppet/modules/site_openvpn/manifests/keys.pp @@ -1,28 +1,22 @@ class site_openvpn::keys { - $openvpn_keys = hiera_hash('openvpn') - - file { '/etc/openvpn/keys/ca.key': - content => $openvpn_keys['ca_key'], - mode => '0600', - } file { '/etc/openvpn/keys/ca.crt': - content => $openvpn_keys['ca_crt'], + content => $site_openvpn::x509_config['ca_cert'], mode => '0644', } file { '/etc/openvpn/keys/dh.pem': - content => $openvpn_keys['dh_key'], + content => $site_openvpn::x509_config['dh'], mode => '0644', } file { '/etc/openvpn/keys/server.key': - content => $openvpn_keys['server_key'], + content => $site_openvpn::x509_config['key'], mode => '0600', } file { '/etc/openvpn/keys/server.crt': - content => $openvpn_keys['server_crt'], + content => $site_openvpn::x509_config['cert'], mode => '0644', } } diff --git a/puppet/modules/site_openvpn/manifests/server_config.pp b/puppet/modules/site_openvpn/manifests/server_config.pp index 482c6ab7..6fc3a3c2 100644 --- a/puppet/modules/site_openvpn/manifests/server_config.pp +++ b/puppet/modules/site_openvpn/manifests/server_config.pp @@ -1,3 +1,57 @@ +# +# 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 @@ -29,7 +83,18 @@ define site_openvpn::server_config ($port, $proto, $local, $server, $push, $mana 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', diff --git a/puppet/modules/site_shorewall/manifests/dnat_rule.pp b/puppet/modules/site_shorewall/manifests/dnat_rule.pp index 4fc62f85..68f480d8 100644 --- a/puppet/modules/site_shorewall/manifests/dnat_rule.pp +++ b/puppet/modules/site_shorewall/manifests/dnat_rule.pp @@ -6,7 +6,7 @@ define site_shorewall::dnat_rule { "dnat_tcp_port_$port": action => 'DNAT', source => 'net', - destination => "\$FW:${site_config::eip::openvpn_gateway_address}:1194", + destination => "\$FW:${site_openvpn::openvpn_gateway_address}:1194", proto => 'tcp', destinationport => $port, order => 100; @@ -16,7 +16,7 @@ define site_shorewall::dnat_rule { "dnat_udp_port_$port": action => 'DNAT', source => 'net', - destination => "\$FW:${site_config::eip::openvpn_gateway_address}:1194", + destination => "\$FW:${site_openvpn::openvpn_gateway_address}:1194", proto => 'udp', destinationport => $port, order => 100; diff --git a/puppet/modules/site_shorewall/manifests/eip.pp b/puppet/modules/site_shorewall/manifests/eip.pp index 086bf75a..57dc17e9 100644 --- a/puppet/modules/site_shorewall/manifests/eip.pp +++ b/puppet/modules/site_shorewall/manifests/eip.pp @@ -10,7 +10,7 @@ class site_shorewall::eip { $ssh_port = $ssh_config['port'] $openvpn_config = hiera('openvpn') $openvpn_ports = $openvpn_config['ports'] - $openvpn_gateway_address = $site_config::eip::openvpn_gateway_address + $openvpn_gateway_address = $site_openvpn::openvpn_gateway_address # define macro for incoming services file { '/etc/shorewall/macro.leap_eip': @@ -42,11 +42,11 @@ PARAM - - udp 1194 shorewall::masq { "${interface}_tcp": interface => $interface, - source => "$site_config::eip::openvpn_tcp_network_prefix.0/$site_config::eip::openvpn_tcp_cidr"; } + source => "$site_openvpn::openvpn_tcp_network_prefix.0/$site_openvpn::openvpn_tcp_cidr"; } shorewall::masq { "${interface}_udp": interface => $interface, - source => "$site_config::eip::openvpn_udp_network_prefix.0/$site_config::eip::openvpn_udp_cidr"; } + source => "$site_openvpn::openvpn_udp_network_prefix.0/$site_openvpn::openvpn_udp_cidr"; } shorewall::policy { 'eip-to-all': |