Success in the land of the VPN

I can finally report success with my recent obsession with getting a functional VPN for my home network. Actually, I can report two...

For my IPsec VPN, I have settled upon the following configuration:

My home network is setup to use 192.168.0.0/16:
  • My main subnet range is 192.168.1.0/26
  • My secondary subnet is 192.168.2.0/24 (and is empty)
  • My OpenVPN subnet range is 192.168.3.0/24

I decided to put my IPsec VPN’s connections at 192.168.1.64/26.

I mention the subnets so the virtual_private and l2tp config make sense...

Additionally, I’ve obviously changed the x.509 certificate details...

/etc/ipsec.conf
version 2.0
config setup
nat_traversal=yes
virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!192.168.1.0/26,%v4:!192.168.2.0/24,%v4:!192.168.3.0/24
protostack=netkey
interfaces=%defaultroute

conn %default
keyingtries=1
type=tunnel
ike=aes-sha1;modp1536
phase2alg=aes-sha1;modp1536
compress=yes
left=%defaultroute
right=%any
pfs=yes

conn roadwarrior-l2tp
type=transport
leftprotoport=17/1701
rightprotoport=17/%any
rightsubnet=vhost:%no,%priv
pfs=no
also=roadwarrior

conn roadwarrior
authby=rsasig
leftrsasigkey=%cert
rightrsasigkey=%cert
leftcert=pilotCert.pem
rightid="C=ZA, ST=State, O=Organization, OU=OrgUnit CN=*, E=*"
auto=add

conn roadwarrior-l2tp-psk
type=tunnel
authby=secret
leftprotoport=17/1701
rightprotoport=17/%any
rightsubnet=vhost:%no,%priv
pfs=no
auto=add

Certificates are used for normal connections; the PSK is used by one (and only one) connection: My iPhone. For some reason,, the iPhone doesn’t support certificates when using L2TP. Since a PSK has the password as the key, it’s got a password that’s quite long, and is composed of the 96-character ASCII printable character set. According to the NIST’s password documents, it’s equivalent in difficulty of cracking encryption greater than 128 bits, which would require boiling the oceans to crack — I think I’ll be safe until quantum computing comes into its own...

I was surprised to learn that DES is slower to encrypt than AES; AES is quite a bit faster than 3DES, and is considerably more secure.
/etc/xl2tpd/xl2tpd.conf
[global]
auth file = /etc/ppp/chap-secrets
listen-addr = pilot.pariahzero.net
debug tunnel = yes
[lns default]
ip range = 192.168.1.65-192.168.1.127
local ip = 192.168.1.1
require chap = yes
refuse pap = yes
require authentication = yes
name=PilotVPN
hostname = pilot.pariahzero.net
ppp debug = yes
length bit = yes
pppoptfile = /etc/xl2tpd/options.l2tpd


/etc/xl2tpd/options.xl2tpd:
ipcp-accept-local
ipcp-accept-remote
ms-dns 192.168.1.1
auth
crtscts
idle 1800
mtu 1410
mru 1410
nodefaultroute
debug
lock
proxyarp
connect-delay 5000


After this, I was able to get an IPsec/L2TP VPN running.

Of course, there is a catch: my office (the big place I am when I’m not at home) is well... corporate. With IT guys. So in spite of the fact the network is more porous than I’d generally like, one thing that is blocked is IPsec.

Note to Network Admins: There are more internet protocols than TCP and UDP. IPsec has two: 50 is ESP, and 51 is AH. IPv6 has several. Of the two, IPv6 is potentially more dangerous... fewer people using it, sure, but there’s no NAT in IPv6, and practically nobody firewalls for it. (Who uses IPv6 anyway?!?)

Well, since my office blocks iPsec, I had to turn to its other good alternative: OpenVPN.

OpenVPN uses SSL, and any UDP port (though you can use TCP if you so desire). Because of that, OpenVPN is quite hard to block at a firewall level. As with IPsec, OpenVPN uses x.509 certificates.

My OpenVPN config is pretty much the default: After setting up x.509 certificates (which I did for my IPsec VPN), the rest was a breeze.

/etc/openvpn/server.conf:
port 1194
proto udp
dev tun
ca /etc/ipsec.d/cacerts/cacert.pem
cert certs/openvpnCert.pem
key certs/openvpnKey.pem
crl-verify /etc/ipsec.d/crls/crl.pem
dh certs/dh1024.pem
server 192.168.3.0 255.255.255.0
ifconfig-pool-persist ipp.txt
# This allows connections to _only_ 192.168.1.0/26
#push "route 192.168.1.0 255.255.255.0"
# This allows connections everywhere...
push "redirect-gateway def1"
push "dhcp-option DNS 192.168.3.1"
push "dhcp-option DOMAIN pariahzero.net"
push "dhcp-option NTP dns.pariahzero.net”
keepalive 10 120
tls-auth certs/ta.key 0 # This file is secret
cipher AES-128-CBC # AES
comp-lzo
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 3

The only ‘tricky’ things was configuring the dh cert, and the tls-auth cert.
Do build the DH paramaters, you run:
openssl dhparam -out [dir]/dh[key_size].pem [key size]

For additional security, with OpenVPN, you can create a TLS shared secret key:
openvpn --genkey --secret ta.key

Lastly, there’s the jewels (to me, at least): Creating and using your own x.509 Certificate Authority and certificates.

I started by grabbing the system openssl.cnf (the default isn’t overly useful), and modified it for my use.
The config file itself is pretty self-explanatory. I decided to have my own config and just load it when I need it, rather than editing the system config.

To set the config, use the environment variable:
# export OPENSSL_CONF=/etc/ipsec.d/openssl.cnf

One important note: If you are going to be using OS X or iOS clients, you need the VPN server’s certificate to have:
subjectAltName=DNS:your.full.fdqn.net
Note: This is for the server’s certificate, not the x.509 Certificate Authority.

To create your own CA using OpenSSL:
# openssl req -x509 -days 3652 -newkey rsa:1024 -keyout caKey.pem -out caCert.pem

There are a few prompts - you feed in your country, state, city, organization, org uniit, hostname, and an email address. Nothing too interesting.

Next, from /etc/ipsec.d:
# mkdir newcerts
# touch index.txt
# echo “00” > serial
(Some have “01” to serial - it’s just a number, so it doesn’t really matter.)

Next, to create host certificates:
For the VPN server, I modified the openssl.cnf to add
subjectAltName=DNS:your.full.fdqn.net

And generated its key. Then for the clients, I commented out the subjectAltName=DNS:your.full.fdqn.net line.

To generate the key, use:
# openssl req -key -newkey rsa:1024 -keyout mykey.pem -out keyReq.pem

This generates the private key and an x.509 certificate signing request.

Next, we sign the certificate signing request using our CA:
# openssl ca -in keyReq.pem -days 365 -out myCert.pem -notext -cert caCert.pem -keyfile caKey.pem

Next, you update the /etc/ipsec.secrets to have the server’s private key passphrase, as well as the PSK password for the iPhone VPN.

For Windows (and OS X, actually), it’s useful to put the CA Certificate, client certificate, and client private key into a PKCS#12 file:
# openssl pkcs12 -export -inkey mykey.pem -in myCert.pem -name UserName -certfile caCert.pem -caname “YourOrg Root CA” -out clientcert.p12
I think you can leave the -name UserName and -caname “YourOrg Root CA” out...

Last, we set up x.509 certificate revocation lists:
# echo “00” > /etc/ipsec.d/crlnumber
# openssl ca -gencrl -crldays 15 -out crl.pem -keyfile caKey.pem -cert caCert.pem


To revoke a certificate, you need the public certificate. (Look at /etc/ipsec.d/index.txt to get them - they should be in /etc/ipsec.d/newcerts.)
# openssl ca -revoke revokedCert.pem -keyfile caKey.pem -cert caCert.pem

Next, update the crl.pem:
# openssl crl -in crl.pem -noout -text

OpenVPN will automatically re-read the revocation list - revocation is effective immediately. With Openswan, you have to notify ipsec:
# ipsec auto --rereadcrls

In both cases, revoking a cert won’t cause the server to drop any current connections with that cert. The connection will stay up until the next rekey or reconnect — and then it will be rejected.