I keep getting poked on this on and off and it's a real problem.
Cell carriers use "deep packet inspection" to detect people cheating on their tethering plans (they want you to pay, see) and "bust" you if you do so but don't pay them. They'd never look at anything else -- or for other purposes -- right?
You walk into a Starbucks or other place with "Free" WiFi. Never mind the store, the connection is unsecured which means anyone within 300' or so of you can see everything that goes over the link during that time using trivially-available software and an ordinary PC or cellphone with a WiFi connection. Nobody would ever do that, right?
You're in your hotel room. You log into some web site and surf around. Nobody else in the same hotel is monitoring that free, unsecured WiFi -- right?
Uh, yeah.
If you have a machine at home (or your office) that is on all the time and provides a firewall and NAT service for computers behind it, and you both can (and should), you might want to read this article.
I will assume you have such a machine. It could be running either Linux or FreeBSD. I will also assume that you want an actual secure VPN connection. There are tutorials all over the place on less-secure options such as PPTP and LT2P; these work, but have potential points of attack that may be serious trouble. Note that they're ok for casual use and will stop most of the garden-variety hackers, and certainly are better than nothing!
But today we're going to talk about setting up an IPSEC/IKEv2 gateway, and we're going to do it on FreeBSD. We'll set it up for two environments -- Windows 7 machines (8 should also work) and the new BlackBerry BB10 phones (Z-10, Q-10, etc) along with, if you wish, the Playbook.
If you do this you're putting in place no-BS high-grade secure communications, at least as far as your device and your network. This doesn't stop someone from physically breaking into your home (or hacking your gateway) but it sure as hell does stop any sort of casual (or not-so-casual!) interception of what you're sending and receiving from a mobile device where you and the device are.
The first thing to get is of course the FreeBSD machine and configure it with a firewall and in-kernel NAT. Linux also works for this, incidentally, although the steps are a bit different. I'm a FreeBSD guy so I'm doing it on that as a base.
FreeBSD requires that you add the IPSEC extensions to the kernel and recompile it. That has to be done first; the options you need in the kernel are:
options IPSEC
options IPSEC_NAT_T
device crypto
options IPSEC_FILTERTUNNEL
(If you don't know how to build and install a custom kernel see The Handbook for instructions)
The next thing we're going to do is edit our firewall. Your configuration will differ but the important point is that you will have packets coming in on a private address but on the external interface. Most firewall configurations will reject this. My setup has the following changes in it:
#
# Permit IPSEC VPN to operate
#
${fwcmd} add 1500 pass udp from any to any isakmp keep-state
${fwcmd} add 1510 pass udp from any isakmp to any keep-state
${fwcmd} add 1520 pass udp from any to any 4500 keep-state
${fwcmd} add 1530 pass udp from any 4500 to any keep-state
${fwcmd} add 1540 pass esp from any to any
${fwcmd} add 1550 pass ah from any to any
${fwcmd} add 1560 pass ipencap from any to any
# Network Address Translation. This rule is placed here deliberately
# so that it does not interfere with the surrounding address-checking
# rules. If for example one of your internal LAN machines had its IP
# address set to 192.0.2.1 then an incoming packet for it after being
# translated by natd(8) would match the `deny' rule above. Similarly
# an outgoing packet originated from it before being translated would
# match the `deny' rule below.
case ${firewall_nat_enable} in
[Yy][Ee][Ss])
if [ -n "${nat_interface}" ]; then
${fwcmd} nat 1 config ip 70.169.168.7 log
# ${fwcmd} nat 1 config if ${nat_interface} log reset
${fwcmd} add 2000 nat 1 ip from any to any via ${nat_interface}
${fwcmd} add 2010 nat 1 ip from any to any from ${nat_interface} ipsec
fi
;;
esac
# Stop RFC1918 nets on the outside interface
${fwcmd} add 3000 deny log all from 10.0.0.0/8 to any via ${oif} not ipsec
${fwcmd} add 3010 deny log all from 172.16.0.0/12 to any via ${oif} not ipsec
${fwcmd} add 3020 deny log all from 192.168.0.0/16 to any recv ${oif} not ipsec
#
# It's ok for IKE traffic to head from here
#
${fwcmd} add 4000 pass ip from any to 192.168.0.0/16 via ${oif}
What I'm doing here is telling the system first that the packet types that are intended for IPSEC are allowed to pass unmolested into the IPSEC subsystem (the top block.) I then tell the system that I must NAT anything coming in from the IPSEC system, and finally I exempt anything from the IPSEC stack from the anti-spoofing filter just underneath it. Your configuration here will vary, especially if you're using pf or Linux. Adjust to suit your requirements.
The next thing to do is download StrongSwan. The current release is 5.0.4 although there is a port in for FreeBSD that is also available (5.0.1) that will also work. I recommend compiling up 5.0.4 because you want some options that may not be in the port; the string you type to "configure" to get the correct settings to allow Windows 7 clients (which is where the tricky part comes from) is:
$ ./configure --enable-kernel-pfkey --enable-kernel-pfroute --disable-kernel-netlink --disable-tools --disable-scripts --with-group=wheel --enable-eap-gtc --enable-xauth-pam --enable-eap-mschapv2 --enable-md4 --enable-eap-identity
Yes, that's long. Just copy it over and use it. Then type "make" and assuming it builds, "make install" (the latter as root.) Now you have the software on the machine.
The next thing we need to do is set up certificates. Let me explain.
There are two ways to secure a link, basically. The first is a password. But there is a problem with passwords, in that somehow you have to get them from one end of the connection to the other. If the person who is trying to screw you can intercept that they can steal the password and now you're in trouble.
Certificates get around this problem and are the basis for "https:" connections and similar. There are two parts to a certificate -- a public key and a private key. The concept is that what you encrypt or sign with one you can only decrypt or verify with the other. That is, if you have only the public key you can sign or encrypt a message for someone, but once you've done so not even you can read it. Only the holder of the private key can decrypt the code.
This makes possible publishing the public key for anyone who wants it without breaking security. The person now "signs" and "encrypts" their transmission using this, and the other end of the connection, which is the only holder of the private key, is the only person who can verify -- or intercept -- that transmission and return it to its original form.
There is a further problem with this scheme, however, in that if I can intercept the transmission and get you to use a public key that is from an imposter I can pretend to be someone I'm not. You then encrypt your password and send it, and I steal it, possibly completely transparently to you.
To avoid this risk the public key has to be signed ("vouched for") by someone trustworthy. You can then use that trusted public key to verify the key you are about to use is authentic and really from the person who you think it's from. Now if someone tries to be an imposter you will catch them and the attempt to steal your credentials (or data) fails.
There are two options here -- one is to buy a server certificate from a trust public authority. That's what you do when you get an "SSL" certificate for your web site. But for your personal use there is nobody you trust more than yourself -- right? So what we'll do is exactly that -- we'll set up our own "Certificate Authority", or means of signing our own certificate. Note that if someone steals your CA's private key you're just as screwed, so your security is important -- that private key should never be on a network-available anything, ever, because if it's stolen the thief can then start signing things as if they are you!
To do this we're going to use "OpenSSL", and we're going to edit a few things to work with StrongSwan . If you're using OpenSSL for other things please be aware that this may break them, but if you're already using OpenSSL you probably understand the configuration changes and how to "put them back" when you're done.
OpenSSL keeps its configuration file in /etc/ssl/openssl.cnf. We're going to edit that and change just a few things:
The line "dir" will be changed to "/usr/local/etc/ipsec.d" (default is ./demoCA)
The line "certificate" will be changed to "$dir/cacerts/cacert.pem" (from $dir/cacert.pem)
The line "default_bits" we will change from 1024 to 2048 to strengthen the key.
There is a section called "[ req_distinguished_name ]" that you should update for your country, organization, state and such. You don't NEED to do this but it makes life easier if you don't have to type these all the time and can just take the defaults.
Finally, there is a section called "[ usr_cert ]" that has options in it. You want to add the following toward the end:
#
# Note - this is for IPSEC/Strongswan (extendedKeyUsage and SubjectAltName)
#
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
subjectAltName=DNS:myservers.domain.name
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
extendedKeyUsage=serverAuth
Adjust "myservers.domain.name" to be your server's public DNS address. Note that you really probably want to change these per-certificate for machines if you're issuing more than one, but this again just changes defaults (and makes it easier to type without making mistakes later.)
The reason for these two entries is that clients want them. Specifically, Windows 7 will barf if they're missing, and you will pull your hair out trying to figure out what's going on. I did exactly that but after reading the various tutorials I figured out what had to go where. Oh, and did I mention that none of the clients give you jack and crap in diagnostics telling you what they're unhappy about? Yeah, they post up cryptic numeric error codes or worse, just "authentication failed" when you get it wrong.
Now we're ready to go.
Follow the tutorial here to set up your CA and gateway certificates: http://pages.cs.wisc.edu/~zmiller/ca-howto/
When you're done you should have a "cacert.pem" file in the cacerts directory under /usr/local/etc/ipsec.d directory, and a certficate for your sever's hostname in the "certs" directory. There will also be a private key file under the "private" directory.
Now you need to remove the password you entered on the machine certificate from the private key. This is necessary because the software must be able to verify the certificate. Remember that in order to do that you need the other half of the key and since your computer is going to do this automatically it can't ask you for the password when it needs it. To do this you take these steps:
# cp myserver.pem myserver-enc.pem
# openssl rsa -in myserver-enc.pem -out myserver.pem
You will prompted for the password and then the system will write out the unsecured copy of the private key into the file. That file must not be compromised on your system.
Tired yet? We're just about done -- now we're going to set up StrongSwan using the certificates you have generated.
In /usr/local/etc you have a file called "strongswan.conf." Edit it and add a line under "charon" that reads "dns1 = xxx.xxx.xxx.xxx" This should be your local DNS nameserver. Normally this will be your gateway machine's IP address. It doesn't have to be but it must be reachable over the tunnel, which means that generally it should be on your gateway machine. This is the domain server that the clients that connect will be told to use, as their original DNS servers will "disappear" when they connect on the VPN.
Next we're going to edit "ipsec.conf"; this is where the meat is.
We want the file to look like this:
# ipsec.conf - strongSwan IPsec configuration file
# basic configuration
config setup
# strictcrlpolicy=yes
# uniqueids = no
# Add connections here.
# Sample VPN connections
conn %default
keyingtries=1
keyexchange=ikev2
conn BB10
left=%any
leftsubnet=0.0.0.0/0
right=%any
rightsourceip=192.168.2.0/24
rightid=my@email.address
rightauth=psk
leftauth=pubkey
leftcert=my-host-certificate.pem
auto=add
conn Win7
left=%any
leftsubnet=0.0.0.0/0
leftauth=pubkey
leftcert=my-host-certificate.pem
leftid=@my-host-name
right=%any
rightsourceip=192.168.2.0/24
rightauth=eap-mschapv2
rightsendcert=never
eap_identity=%any
rekey=no
dpdaction=clear
dpddelay=300s
auto=add
We need two sections here, one for clients (such as the BlackBerry 10) that can use pre-shared keys and have no special requirements and then another for Windows 7 which does. Windows 7 in particular gets pissed off about rekeying coming from the server (it wants to do it) so we turn that off. We also use Windows' "unique" way of processing passwords (MSCHAPv2.) We also tell it never to send the certificate from the right side of the connection, which it wants too.
For Windows 7 you will need to follow the instructions here to import the certificate bundle into Windows 7's store. See the "Storing a Windows 7 CA Certificate" link under that page for instructions. This is a bit tricky but it does work -- just pay attention to the warnings or you'll import the CA certificate into the wrong place and then wonder why it doesn't work.
Note that IP range up there "rightsourceip" -- this is a declaration of an address pool from which the client's IP address will be drawn. Make sure it does not collide with anything on your local network and is in "private" IP space (192.168.x.x is usable, as is 10.x.x.x.) In particular be very careful not to overlap anything that DHCP may assign on your existing network or some really bizarre things can (and will!) happen. When you connect to the VPN your client machine will get an address from this pool for the link. See StrongSwan's documentation for other options (there are several) if you want to integrate address assignment and reporting for some reason.
"leftcert" is the certificate file for your gateway machine, relative to the "cert" directory.
You must also define how the system will find these files and the password(s) you wish to use. Edit ipsec.secrets so it looks like this:
#
# Our certificate for the gateway; this is required for Windows 7
: RSA my-host-certificate.pem
#
# Passwords
#
%any : PSK "my-blackberry10-password"
%any : EAP "my-windows7-password"
The "%any" key means that any identifier is valid (any email address or login ID, for example.) If you want to set up multiple users you can of course make specific entries for each person with different passwords; replace "%any" with the identifier in question. The "RSA" line tells the system how to decode the host certificate (it's an RSA-encoded certificate file.)
Now type from the command line:
# ipsec start
You will likely get a couple of warnings; those are fine.
Type this:
# ipsec status
Security Associations (0 up, 0 connecting):
none
If you get that back from the status request it's running.
To check the machine certificate (very important!) you type this:
root@NewFS:/usr/local/etc # ipsec listcacerts
List of X.509 CA Certificates:
subject: "C=US, ST=Florida, L=Niceville, O=Cuda Systems LLC, CN=Cuda Systems LLC CA, E=customer-service@cudasystems.net"
issuer: "C=US, ST=Florida, L=Niceville, O=Cuda Systems LLC, CN=Cuda Systems LLC CA, E=customer-service@cudasystems.net"
serial: ea:e1:a3:cb:ff:b0:44:cf
validity: not before Apr 26 13:53:50 2013, ok
not after Apr 24 13:53:50 2023, ok
pubkey: RSA 2048 bits
keyid: 5d:a1:31:ae:45:18:dc:20:5d:96:0d:1d:51:05:5c:d6:7b:5f:18:2b
subjkey: 5d:d4:de:1a:41:66:ae:34:1c:1e:55:33:b0:78:e3:f8:26:5e:22:34
authkey: 5d:d4:de:1a:41:66:ae:34:1c:1e:55:33:b0:78:e3:f8:26:5e:22:34
This shows my Certificate Authority certificate, and that the system loaded it properly. Note that there is no machine name anywhere in there -- this is not the gateway's cert. Note that the "issuer" and "subject" are identical -- the CA signed its own certificate.
Now we check the gateway certificate to make sure that the software properly loaded it:
[root@NewFS /usr/local/etc]# ipsec listcerts
List of X.509 End Entity Certificates:
altNames: genesis.denninger.net
subject: "C=US, ST=Florida, O=Cuda Systems LLC, CN=genesis.denninger.net, E=karl@denninger.net"
issuer: "C=US, ST=Florida, L=Niceville, O=Cuda Systems LLC, CN=Cuda Systems LLC CA, E=customer-service@cudasystems.net"
serial: 00
validity: not before Apr 26 13:58:18 2013, ok
not after Apr 24 13:58:18 2023, ok
pubkey: RSA 2048 bits, has private key
keyid: a2:d6:7e:56:84:02:2b:35:20:84:33:0c:5e:64:33:a3:68:c7:84:da
subjkey: a6:eb:7d:3b:91:a9:69:59:a0:7a:aa:6b:9e:cc:18:f8:57:6e:72:e9
authkey: 5d:d4:de:1a:41:66:ae:34:1c:1e:55:33:b0:78:e3:f8:26:5e:22:34
The "issuer" is the above certificate (the "cacert" subject line up above) -- those two must match. They should, if you properly generated the certificate.
See that bolded line? That has to be there. If it's not then go back and make sure that the filenames in the "private" and "cert" directories are the same and that you performed the step above to strip the password off the private key. Fix whatever is wrong and then do "ipsec stop" and "ipsec start" again.
Your VPN will not authenticate against a machine certificate if that "has private key" section is missing; it is necessary for the connection to work.
Now you need to import the CA certificate to your BlackBerry. You cannot (for security reasons) do this over email (although it certainly is implied you can!) or over USB or ordinary file structure mounts as the directory won't show up! Instead, go to Storage and Access, turn on "Access Using Wifi" and set up a password and, if necessary, your workgroup. Once you do this your PC should be able to "see" the BlackBerry as a network device. Open it and there will be a directory there called "certs". Copy the file "cacert.pem" into that directory.
Then go to "Security and Privacy" and select Certificates. Click "Import", make sure you're set to "Personal Trusted CA" and choose all three checkboxes (VPN, Web and Wi-Fi.) You're only going to use VPN for now, but the other two may come in handy later (e.g. if you use this CA to sign a SSL certificate for your private web server.)
Choose "next" and the certificate you copied in should appear as importable. Import it. Now the phone knows your CA is valid and trusted.
You can now to go the BlackBerry's setup and set up a "Generic IKEv2" connection. The screens look like this:
Note a couple of things here -- the server address is your domain name for the external interface of the gateway. This must match the certificate you generated for the gateway; if it doesn't the connection will be rejected. Your authentication type is "PSK" (pre-shared key) and the identifier is your email address (which you can put into the ipsec.secrets file if you have multiple users.) The "gateway auth type" is "PKI", or Public-Key Infrastructure, and the ID type is Distinguished Name (that is, your DNS name of the gateway.) You also select from the drop-down box the CA certificate you imported for your trusted CA (you can leave this at the default which will search all of them, but this is faster.) I also clicked "Perfect Forward Security" which makes the negotiation take a bit longer (it takes six packet exchanges to set up the link instead of three) but somewhat improves security. There is no need to change anything under "Advanced" (and you shouldn't unless you know what you're doing.)
Save the configuration.
You should now see the name of your VPN gateway; select it and if everything is working you'll get this:
If it fails to connect there are a few possibilities. If you get a timeout the probability is that the server end has some sort of problem and you need to look at the log files there. If you get an Authentication Error the problem can be on either end -- look in the server logfile first and if you don't see a reject there check the certificates -- either the gateway cert is wrong or it is not validating. On FreeBSD the IPSEC log will be in /var/log/daemon if your system is reasonably close to defaults on where it logs things.
Once it's working you can select "Auto Connect" (visible at the bottom of the frame) and tell the phone you want it to use this any time you're on a cell connection. It will then do so whenever you are on cellular data. You can also apply the same profile to any WiFi connection you want -- this is very useful if you are in a coffee shop or other place with unsecured WiFi for all the obvious reasons!
One thing to note is that if the VPN is enabled it does not apply to hotspot downstream connections. As such you need to set up a separate VPN connection on your laptop or other device.
Any device that will work with a pre-shared key (password) for user authentication and a server gateway certificate and is fully IKEv2 compatible should match and work against the "BB10" definition up above. If it doesn't the problem is probably due to some hinky requirement on the client end. Note that Windows 7 has such hinky requirements, which is why there are two sections up above instead of one.
Do this and you can enjoy secure internet access while on the road, even when in "public places" that have insecure WiFi. This setup will also let you "see" inside resources (such as a fileserver) on your home or office network from your computer if desired, as the machine is for all intents and purposes on the local network when the VPN is in use.