StrongSwan Ipsec VPN for Remote Users with Certificate Based Authentication

This is a working strongswan ipsec config that can be used for a roadwarrior setup for remote users utilizing certificate based authentication instead of id/pw.

This is a pure IPSEC with ESP setup, not L2tp.
This is not 2 factor, it is cert only.

To get started:

sudo apt-get install strongswan

You need is a CA that is capable of registering AltNames in a cert. OpenSSL can do this easily. I used this guide to setup the basic openssl CA. http://www.freebsdmadeeasy.com/tutorials/freebsd/create-a-ca-with-openssl.php

Once the CA is ready and you have generated your ca cert and ca private key, you next need to create a cert for the ipsec host and a cert for the end user.

For the Server:
Since I need the Alt Names in the certs, make a copy of /etc/ssl/openssl.cnf to be used for the Server.

cp /etc/ssl/openssl.cnf /etc/ssl/openssl-for-server.cnf
# Extension copying option: use with caution. copy_extensions = copy [ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName=@alt_names [alt_names] DNS.1 = ipsecvpn.mydomain.com DNS.2 = another_name.mydomain.com

Now, using Openssl, create the request for the server, fill in the details of the req as needed, then sign the request.

openssl req -new -nodes -out ipsechost-req.pem -keyout private/ipsechost-key.pem -config /etc/ssl/openssl-for-server.cnf
openssl ca -config /etc/ssl/openssl-for-server.cnf -out ipsechost-cert.pem -in ipsechost-req.pem

Copy the certs to the correct locations for strongswan to use.

cp cacert.pem /etc/ipsec.d/cacerts
cp ipsechost-cert.pem /etc/ipsec.d/certs
cp private/ipsechost-key.pem /etc/ipsec.d/private/

Stongswan is configured using the /etc/ipsec.conf and /etc/ipsec.secrets files.
This is a very simple config that will work for providing access to remote users:
Edit /etc/ipsec.conf

 
# /etc/ipsec.conf - strongSwan IPsec configuration file
config setup

conn %default
        ikelifetime=60m
        keylife=20m
        rekeymargin=3m
        keyingtries=1

conn common
        left=IP_OF_IPSEC_HOST          # Ip of the host
        leftcert=ipsechost-cert.pem    # the cert we just created and copied
        leftid=@ipsecvpn.mydomain.com  # the Alt name in the Cert we just created
        leftsubnet=172.16.31.0/24      # The internal subnet the remote user wants to access
        right=%any                     # Connections can come from anywhere
        rightsourceip=192.168.1.0/24   # Use this pool of IPs to assign to these inbound connections
        auto=add

conn ikev2
        keyexchange=ikev2 
        also=common

Edit the /etc/ipsec.secrets file

: RSA ipsechost-key.pem

Restart/Reload IPsec.

 
ipsec restart

I like to watch logs just to be sure there are no errors:

 
tail -f /var/log/syslog /var/log/auth.log

Next we create a client cert. We need another copy of the openssl config file for user requests since the Alt Name changes from DNS to Email.

cp /etc/ssl/openssl-for-server.cnf /etc/ssl/openssl-for-users.cnf
[ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName=email:copy #[alt_names] #DNS.1 = ipsecvpn.mydomain.com #DNS.2 = another_name.mydomain.com

Create the request, fill in the details as needed for the user especially the email address, and Sign the request. The email address specified in the request prompts will be used in the cert for the Alt name and in the config for the user’s side of the tunnel.

openssl req -new -nodes -out user1-req.pem -keyout private/user1-key.pem -config /etc/ssl/openssl.cnf 
openssl ca -config /etc/ssl/openssl-for-users.cnf -out user1-cert.pem -in user1-req.pem 

You need to copy the user1-cert.pem, user1-key.pem, and the cacert.pem to the user’s machine. We will need these file to complete the VPN.

On the User’s Side:

sudo apt-get install strongswan

Copy the files into the proper directories
user1-cert.pem to /etc/ipsec.d/certs
user1-key.pem to /etc/ipsec.d/private
cacert.pem to /etc/ipsec.d/cacerts

Edit the client side ipsec.conf. This is a working config:

conn %default
     ikelifetime=60m
     keylife=20m
     rekeymargin=3m
     keyingtries=1
     keyexchange=ikev2

conn roadwarrior
     leftsourceip=%config                # This will take an IP from the ip pool on server
     leftcert=ipsecuser1-cert.pem        # The user cert we copied in
     leftid=ipsecuser1@openpeak.org      # This is the email included in the Alt Name in the user cert
     leftfirewall=yes
     right=cert-ipsec-vpn.openpeak.org   # The location of the host, FQDN or IP 
     rightid=cert-ipsec-vpn.openpeak.org # the Altname used by the ipsec host
     rightsubnet=172.16.31.0/24          # the subnet on the servers side you want to access. 
     auto=start

Edit the ipsec.secrets file

: RSA ipsecuser1-key.pem

On the client, issue an “ipsec restart” and it should attempt to build the tunnel with that you are done.

Troubleshooting:
Use “ipsec statusall” to get details on the tunnels. From the server, a healthy tunnel looks like this:

Security Associations (1 up, 0 connecting):
       ikev2[11]: ESTABLISHED 3 minutes ago, HOST_IP[vpnhost.mydomain.com]...REMOTE_IP[ipsecuser1@mydomain.com]
       ikev2[11]: IKEv2 SPIs: 49c4512b56436e5b_i 6276554588ce1803_r*, public key reauthentication in 50 minutes
       ikev2[11]: IKE proposal: AES_CBC_128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_2048
       ikev2{9}:  INSTALLED, TUNNEL, ESP in UDP SPIs: cd1e015f_i cd3cb1c1_o
       ikev2{9}:  AES_CBC_128/HMAC_SHA1_96, 0 bytes_i, 0 bytes_o, rekeying in 12 minutes
       ikev2{9}:   HOST_INTERNAL_SUBNET=== POOL_IP_ASSIGNED_TO_REMOTEUSER

Use “ipsec listall” for details on the host’s certs and configs. Here we want to be sure Alt Names are good, and the CA and certs are loaded correctly.

List of X.509 End Entity Certificates:
  altNames:  ipsecvpn.mydomain.com
  subject:  "C=US, ST=NY, O=OpenPeak, OU=IT, CN=ipsecvpn.mydomain.com, E=ipsechost@mydomain.com"
  issuer:   "C=US, ST=NY, L=NY, O=mydomain, OU=IT, CN=ipsecserver-ca, E=ca@mydomain.com"
  serial:    10:03
  validity:  not before Mar 18 20:44:25 2015, ok
             not after  Nov 24 20:44:25 2028, ok 
  pubkey:    RSA 2048 bits, has private key
  keyid:     10:15:77:ae:2e:a4:e8:3f:cc:1f:6d:a9:d9:80:bd:9f:41:fb:63:e5
  subjkey:   3f:0c:bf:01:2f:c7:16:be:d4:83:5c:76:81:56:a9:f1:3a:84:b4:5f
  authkey:   b7:61:d7:32:19:65:c3:10:1a:43:23:27:bc:46:29:e5:ff:df:03:1c

List of X.509 CA Certificates:

  subject:  "C=US, ST=NY, L=NY, O=mydomain, OU=IT, CN=ipsecserver-ca, E=ca@mydomain.com"
  issuer:   "C=US, ST=NY, L=NY, O=mydomain, OU=IT, CN=ipsecserver-ca, E=ca@mydomain.com"
  serial:    db:e9:16:e0:44:a3:57:83
  validity:  not before Mar 18 15:49:45 2015, ok
             not after  Mar 15 15:49:45 2025, ok 
  pubkey:    RSA 2048 bits
  keyid:     18:47:07:92:b8:3d:a0:bb:88:bf:27:2b:4d:0b:a7:79:8b:c1:1b:ba
  subjkey:   b7:61:d7:32:19:65:c3:10:1a:43:23:27:bc:46:29:e5:ff:df:03:1c
  authkey:   b7:61:d7:32:19:65:c3:10:1a:43:23:27:bc:46:29:e5:ff:df:03:1c

Note that if you want to enable 2 factor with this, change the openssl request for the Clients to omit the -nodes option. This will prompt you for a password during the certificate creation that must be entered every time the client wants to connect.

OpenSwan Error – One Way Traffic with Cisco ASA

Openswan 2.6.37

Symptom: OpenSwan to Cisco ASA Site to Site Tunnel has one way traffic.
Description: The Ipsec Tunnel builds, both the openswan host and the ASA show the tunnel up but traffic only flows from the ASA into Openswan, traffic does not flow back from openswan. No errors were shown in the auth.log.

Solution: It turns out that the issue was related to the openswan ipsec conf file for this connection. The Leftid and rightid were setup as shown here in the problematic conf file:

conn tunnel-to-HQ
  left=10.1.0.50
  leftid=@openswan
  leftsubnet=10.1.0.0/24
  right=PUBLIC.IP.OF.ASA
  rightid=@asa
  rightsubnet=10.2.0.0/24
  .
  .

  auto=add

This conf file would would just fin for an Openswan to Openswan IPSEC tunnel. But for an ASA to Openswan tunnel, it failed to pass two way traffic.

The simple fix was to replace the leftid and rightid with the IP addresses of the 2 peers as shown below:

conn tunnel-to-HQ
  left=10.1.0.50
  leftid=10.1.0.50
  leftsubnet=10.1.0.0/24
  right=PUBLIC.IP.OF.ASA
  rightid=PUBLIC.IP.OF.ASA
  rightsubnet=10.2.0.0/24
  .
  .
  auto=add

The secrets file should reflect the IP addresses in the conf for this PSK setup:

10.1.0.50 PUBLIC.IP.OF.ASA: PSK "123456789"

Restart the tunnel and traffic flowed normally.

Setup L2TP IPSEC VPN on Ubuntu

Having an L2TP/IPSEC VPN comes in very handy if you have a Macbook, iOS device, or run Stock Android and want to be able to remotely access your network from on the road. L2TP over IPSEC is a better choice than PPTP which is now considered insecure. Plus L2TP/IPSEC is supported natively by those devices, so no additional client software would be needed unlike OpenVPN.

To get started, let’s imagine a small network that runs on a fairly standard private address range. 192.168.1.0/24. This setup would be run on an internal Ubuntu Server that is networked to the internal network you wish to access. In this example, you only need 1 network card.

Forward Ports
Since the server resides on the internal network behind a router or firewall, you will need to forward certain ports to the server from your perimeter device for this to work.

You need to forward
UDP 500
UDP 4500
ESP Traffic (protocol 50)
AH Traffic (protocol 51)

ESP and AH are not ports, they are protocols. Most comsumer routers can’t forward these protocols, so you may be forced to use a “Forward All traffic” option to the internal server or use a “Internal DMZ Host” setup that can be found on many device. Test it out and find the best option that works for you.

 

Install IPSEC

sudo aptitude install openswan

Openswan is the package that provides the IPSEC functionality. You can use it for site to site VPNs using Preshared Keys, certificates, or other back-end auth mechanisms. In this setup, I’ll keep it simple and just use a Pre-Shared Key (PSK). A PSK with id and password would be good enough for most people who want to securely access a small or home network.

Edit the file /etc/ipsec.conf so that it looks like this
SANITY CHECK: Make sure you keep the spacing intact under the config headers and conn headers. You might get format errors without it…

version 2.0

config setup
  dumpdir=/var/run/pluto/
  nat_traversal=yes
  virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
  oe=off
  protostack=netkey
  keep_alive=10

include /etc/ipsec.d/*.conf

Edit the /etc/ipsec.secrets file and add in the following to the bottom of the file:

 
include /etc/ipsec.d/*.secrets

Now lets setup the files that define the Connection.
Create/edit a file and call it /etc/ipsec.d/road-warrior.conf

conn L2TP-PSK-noNAT
  authby=secret
  pfs=no
  auto=add
  keyingtries=3
  rekey=no
  ikelifetime=8h
  keylife=1h
  type=transport
  left=IP.ADDRESS.OF.SERVER 
  leftprotoport=17/1701
  right=%any
  rightprotoport=17/%any

conn L2TP-PSK-NAT
  rightsubnet=vhost:%priv
  also=L2TP-PSK-noNAT

Next, Create/edit a file called /etc/ipsec.d/road-warrior.secrets

IP.ADDRESS.OF.SERVER %any: PSK "YourPreSharedKey"

Next, for OPENSWAN to function correctly, you need to run to following at the bash prompt:

for each in /proc/sys/net/ipv4/conf/*
do
echo 0 > $each/accept_redirects
echo 0 > $each/send_redirects
done

echo 1 > /proc/sys/net/ipv4/ip_forward

To verify the OPENSWAN config use the IPSEC VERIFY command. Your output should match the output below.

root@opk-dfw-vpn01:/etc/ipsec.d# ipsec verify
Checking your system to see if IPsec got installed and started correctly:
Version check and ipsec on-path                                 [OK]
Linux Openswan U2.6.37/K3.2.0-51-virtual (netkey)
Checking for IPsec support in kernel                            [OK]
 SAref kernel support                                           [N/A]
 NETKEY:  Testing XFRM related proc values                      [OK]
        [OK]
        [OK]
Checking that pluto is running                                  [OK]
 Pluto listening for IKE on udp 500                             [OK]
 Pluto listening for NAT-T on udp 4500                          [OK]
Checking for 'ip' command                                       [OK]
Checking /bin/sh is not /bin/dash                               [WARNING]
Checking for 'iptables' command                                 [OK]
Opportunistic Encryption Support                                [DISABLED]

Lastly, restart the IPSEC service

/etc/init.d/ipsec restart

 

Install L2TP

Next up we need to install an L2TP package. L2TP works with IPSEC in that L2TP provides the Tunnel, where IPSEC provides the encryption.

Install the L2TP package:

sudo aptitude install xl2tpd

Edit the /etc/xl2tpd/xl2tpd.conf

[global]
ipsec saref = yes

[lns default]
ip range = 10.10.10.2-10.10.10.200  
local ip = 10.10.10.1
refuse chap = yes
refuse pap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes

The IP range is used by the L2tp Tunnel. You want to be sure that this range does not overlap with any internal network subnet. The Server IP address should not be part of the ip range.

 

Install PPP

The final piece of this setup is the user authentication. Every user can share a PreSharedKey, but each user should have a unique ID/PW.

Install PPP

sudo aptitude install ppp

Edit/create /etc/ppp/options.xl2tpd

require-mschap-v2
ms-dns 4.2.2.1
ms-dns 4.2.2.2
asyncmap 0
auth
crtscts
lock
hide-password
modem
debug
name l2tpd
proxyarp
lcp-echo-interval 30
lcp-echo-failure 4

Change the DNS servers to fit your needs. These servers are public, but you could just as easily use your private DNS in there as well.

Now add users by editing /etc/ppp/chap-secrets

# Secrets for authentication using CHAP
# client        server  secret                  IP addresses
user1           l2tpd   user1password           *
user2           l2tpd   user2password           *

sudo /etc/init.d/xl2tpd restart

Now setup your remote device with the proper servername, PSK, and id/pw and give it a test.

Final Note, if your OpenSwan doesn’t startup correctly after a reboot, you probably need to add the following to run on startup:

Edit /etc/rc.local to contain:

iptables --table nat --append POSTROUTING --jump MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
for each in /proc/sys/net/ipv4/conf/*
do
echo 0 > $each/accept_redirects
echo 0 > $each/send_redirects
done
/etc/init.d/ipsec restart

 

Troubleshooting:
If you run into trouble:

  • Look at the logs. “tail -f /var/log/syslog /var/log/auth.log” These will give you a lot of insight.
  • Double check that the ports are forwarded. The logs would show an inbound connection of some kind if the ports are open.
  • Double check the PSK matches on client and server
  • From logsd, Server Sends MR2 and waits for MI3 forever indicated ports are partially open, check the perimeter device.
  • The Command IPSEC whack –status” gives you a lot if instant info on the configuration. Plus it’s nice output to GREP for other scripts.

Finally, here are some little facts that threw me for a loop the first time I played with openswan and I wished someone would have pointed out to me when I started:

  • in the road-warrior.conf file, Right and Left simply differentiate the 2 sides of the VPN. You could switch the values for left and right without any issues. There is no difference.
  • Traffic leaving the OpenSwan server into the internal network will masquerade as the Server’s IP. All VPN traffic will look like it originates from the Server if you take a packet capture from any internal target.
  • You can have many *.conf files and *.secrets files as needed. You can mix Road Warrior confs with Site to site confs on the same host. Each with it’s own secrets file. No problem.

Good Luck.

Loading MS Certificate Server CRL to F5 BIGIP 11.3

I was asked to manually load a Certificate Revocation List (CRL) from an MS Server 2008 R2 Certificate Server to a F5 BIPIP appliance for use when authenticating client certificates.

Having a CRL loaded as a local file into the BIGIP is probably the easiest way to get it to check a CRL since you are avoiding the use of MS Enterprise/Datacenter Servers with OCSP. I also had various issues that the F5 tech support could not explain with CRLDP and MS cert services. So the CRL is an easy fix for a lab environment. I also could not find the proper method to do this in the online knowledge-base for F5’s product either.

For starters, you need to get a copy of the CRL from your MS Certificate Server.

Download CRL

1) Browse to http://SERVERNAME/CertSrv Sign in if needed.
2) Click on Download a CA certificate, certificate chain, or CRL.
3) Select DER format and click on Download Latest Base CRL
4) Save the file to your machine.

Load the CRL to the BIGIP
1) Open up your BIGIP Admin Gui
2) Navigate to Sytem -> File Management -> SSL Certificate List -> Import
3) From the Import Type PullDown, Select ‘Certificate Revocation List’
4) Enter in the Name you want use when referencing this File in BIGIP. Select Create New or Overwrite as needed.
5) Use the Browse Button to select the cert file called ‘certcrl.crl’
6) Click Import to finish the Process.
Import CRL to F5 BIGIP

Now that the CRL is imported, it can be used in any SSL Client Profile in the Certificate Revocation List (CRL) Dropdown.

This CRL is static. Any newly revoked certs on the MS Server will, of course, not be seen by the F5 until the CRL file is updated.

OpenVPN with ID and Password Authentication or Two Factor Authentication

In a recent post, we did a step by step on installing OpenVPN to an Ubuntu server 12.04. http://www.slsmk.com/installing-openvpn-on-ubuntu-server-12-04/

The default install used certificate based authentication for the client. So if the client has the proper files, it can connect to the server.

So lets say you want to use an ID and Password instead of a client cert. Although it is less secure than the cert method, it is much easier to administer. Plus, in certain instances, such as a VPN provider, the creation and delivery of certs to the end user may cause alot of confusion and result in hours of support calls.

Building off of the previous example, lets change to server to use id/pw from the local user list instead of client certs.

This is done through a plugin that is provided with OpenVpn in the Ubuntu package.

Start by copying the required plugin to the openvpn directory

 
cp /usr/lib/openvpn/openvpn-auth-pam.so /etc/openvpn/

Now edit the /etc/openvpn/server.conf file and add the following:

client-cert-not-required 
username-as-common-name 
tmp-dir "/etc/openvpn/tmp/"                      
plugin /etc/openvpn/openvpn-auth-pam.so /etc/pam.d/login 

Create the temp directory mentioned above and allow all writes to it:

mkdir /etc/openvpn/tmp
chmod 777 /etc/openvpn/tmp

Restart OpenVPN

/etc/init.d/openvpn restart

And that’s it. Change your client’s settings so that it uses the id/pw method instead of certs and give it a test.

In a Two Factor Authentication Solution, the client would need a valid Cert and a valid id/pw on the host system. This is more secure than either of the 2 previous examples.

To get the OpenVPN server to use both id/pw and check for a valid cert, just comment out the following line in /etc/openvpn/server.conf

#client-cert-not-required 

Restart openvpn service on the host then give it a test with the client.

/etc/init.d/openvpn restart