[Openswan Users] Request for configuration help for non-trivial AWS VPC OpenSwan Remote User L2TP/IPsec VPN configuration

Michael Crawford michael.crawford at mjcconsulting.com
Fri Aug 30 20:05:40 UTC 2013

I'm having some trouble getting an L2TP/IPSec VPN fully working with a
non-trivial AWS VPC setup.
Hoping those on this list can help spot what may be the problem.

I also thought this configuration may be of use to others attempting
something similar once the
kinks are worked out, so I'm including all aspects of the configuration.


Summary of current status:

* I have the VPC fully setup with all subnets and routing tables. All
internal inter-host
  communications working as expected.
* Not relevant to this problem, but I have setup successfully a
site-to-site VPN using the AWS VGW,
  CGW and VPN connection into a Cisco ASA at company HQ.
  This VPN is intended for use by employees when in the office.
* I also want to create an L2TP/Ipsec "remote-user" VPN, allowing direct
access to all hosts
  in the VPC, from primarily Mac OS X and IOS devices in arbitrary
  This VPN is intended for use by system administrators when on the road
or at home.
  This is what I have partially working now.
* The current remote-user VPN is routing what appears to be a /24 route,
which lets me get to
  instances which are on subnets which are within this /24 CIDR block. I
can not get to instances
  which are not within this /24 CIDR, and fixing this is what I need help


Here's the network details of the VPC configuration. This is a multi-AZ
(availability zone) HA
configuration, with all key functions provided by a pair of hosts which
consist of a primary
active host in AZ A, and a second failover host in AZ B. We're using Route
53 failover DNS and
similar techniques to handle failover, mirroring, etc. I mention this only
to setup the subnet
and routing table layout.

VPC CIDR: - this is the overall CIDR which defines the VPC
and all IP addresses
within it.

  Tier/Use        Type     AZ-A CIDR        AZ-B CIDR
  --------------  -------  ---------------  -------------
  Web Servers     Public
  App Servers     Private
  DB Servers      Private
  Build Servers   Private
  Config Servers  Private
  VPN Users       Private

Subnet Notes:
* I'm using specified Private IP addresses for all AWS hosts, so that I
can setup firewall rules
  on the HQ end of the site-to-site VPN to control traffic flow.
* I want to include the subnet range assigned to remote-user vpn users who
directly VPN into 
  this VPC via OpenSwan, so that it's clear they are coming from this
source, and I can use the
  single high-level VPC CIDR to both host and remote-user
traffic where needed.
  Using this same technique for remote-user VPNs into other offices
managed by Cisco ASAs.

Routing Tables:
  Name     Subnets                      Routes
  Public   Web Servers A+B (Public) -> "local"
                                   -> IGW (Internet
                                        10.x.0.0/x    -> VGW (VPN Gateway,
  Private  All other subnets (Private) -> "local"
                                   -> "vn01" instance
                                        10.x.0.0/x    -> VGW (VPN Gateway,

Routing Notes:
* This is a pretty standard VPC routing table configuration, with public
subnets routed via
  a public route table which has the IGW (Internet Gateway) as it's
default gateway, and private
  subnets using the "main" private route table which has an instance
configured to run NAT as
  it's default gateway.
* Instead of using the NAT "appliance" which AWS provides, I've built my
own Ubuntu 12.04 
  instance to run both the NAT and VPN function, to minimize cost. The NAT
functionality basically
  boils down to a single masquerade statement in iptables. More on that
* There are a couple of web/proxy servers in the web subnets, one in each
AZ. These have EIPs
  associated for inbound traffic.
* There's a single VPN + NAT instance in the Web Server Subnet for AZ A,
which I'll refer to as
  host "vn01", which also has an EIP associated.

Security Group notes:
* There's a security group around each pair of servers performing a
specific role.
* There's a security group around the "vn01" VPN/NAT instance, which
allows all traffic from each
  of the other security groups, to allow for outbound private network
traffic going through NAT.
* This security group also allows in (for VPN functionality) from
  TCP 4500
  UDP 4500
  UDP 500
  ESP (50)

VPN/NAT host NAT setup:

* This host runs Ubuntu 12.04 Server
* This host's private IP address is: with IGW (default
* The ufw firewall is installed and setup to start at boot, and allows SSH
* This script snippet shows the actions taken to configure NAT on the vn01
# Configure Networking to allow VPN/NAT Gateway

# - Uncomment IP forwarding, accept/send redirects
sed -i -r -e '/^#net.ipv4.ip_forward/s/^#//' \
          -e '/^#net.ipv4.conf.all.accept_redirects/s/^#//' \
          -e '/^#net.ipv4.conf.all.send_redirects/s/^#//' \

sysctl -p

# Configure UFW
# - Uncomment IP forwarding
sed -i -r -e '/^#net\/ipv4\/ip_forward/s/^#//' /etc/ufw/sysctl.conf

# Configure ufw to act as outbound NAT gateway
# - Set forward policy to accept
sed -i -e "/DEFAULT_FORWARD_POLICY/s/=.*$/=\"ACCEPT\"/" /etc/default/ufw

# Modify the ufw "before" rules to create the iptables nat table...
# - This sed script inserts the appropriate NAT table rules to perform NAT
#   on the VPC CIDR
# - I reverse engineered how this works by studying how the AWS NAT
#   configured IP tables.

cat << EOF > /tmp/ufw_before_$$.sed
/^# Don't delete these required lines, otherwise there will be errors/i\\
# Don't delete these required lines, otherwise there will be errors\\
# End required lines\\
# Forward traffic from VPC with NAT\\
# don't delete the 'COMMIT' line or these nat table rules won't be


sed -i -f /tmp/ufw_before_$$.sed /etc/ufw/before.rules

rm -f /tmp/ufw_before_$$.sed

# Reload ufw rules

ufw disable
ufw --force enable

Summary of what works at this point:
* Outside of this remote-user VPN, everything works as expected...
* All public hosts can communicate with any internet site as needed, via
ping, http, etc.
* All private hosts can communicate with any internet site as needed, via
ping, http, etc
  - in this case via the vn01 VPN/NAT instance. This is per VPC standard
design pattern.
* I'm able to SSH into the vn01 instance, and from there "hop" to any
other instance via SSH
  to configure and manage. One main goal of this remote-user VPN, is to
allow direct SSH
  access to all hosts, private or public, without having to jump through
this vn01 host, while
  the VPN is active.

==== Start of Openswan L2TP/Ipsec Configuration


I've used these references to help me figure out how to set this up (kudos
to the authors!)
- http://blog.riobard.com/2010/04/30/l2tp-over-ipsec-ubuntu/
- https://raymii.org/cms/m.php?title=IPSEC_L2TP_VPN_on_ubuntu_12.04

Here's a shell script snippet which shows the actions I've taken to
install and configure
openswan. As above, I'm creating most config documents as "in-line"
document steps, and modifying
existing config files via sed scripts. I can update this email with the
end-result of running the
sed scripts on request:

For those interested, I'm creating the VPC via CloudFormation, and all
this stuff runs via a
UserData script as the vn01 instance is being created and hooked into the
routing tables. Same
for the NAT logic.

# Install openswan

apt-get install -y openswan

# Configure openswan
cat << EOF > /etc/ipsec.conf
version 2.0

config setup

include /etc/ipsec.d/*.conf

cat << EOF > /etc/ipsec.d/l2tp-psk.conf

conn L2TP-PSK-noNAT
    leftsubnet=       <== added later, still doesn't work
with this.

cat << EOF >> /etc/ipsec.secrets  %any: PSK "<redacted_long_string>"

# Confirm IPsec setup
#     - showing current output commented out

ipsec verify
# Output from this is:
# Version check and ipsec on-path                    [OK]
# Linux Openswan U2.6.37/K3.2.0-52-virtual (net key)
# 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]

# Restart openswan to pick up changes

service ipsec restart

# Install xl2tpd
apt-get install -y xl2tpd

# Configure xl2tp
cat << EOF > /etc/xl2tpd/xl2tpd.conf
ipsec saref = yes

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

# Install ppp
apt-get install -y ppp

# Configure ppp
cat << EOF > /etc/ppp/options.xl2tpd
asyncmap 0
name l2tpd
lcp-echo-interval 30
lcp-echo-failure 4

# Configure test pop users
cat << EOF >> /etc/ppp/chap-secrets
testuser  l2tpd  <initial_password>  *

# Configure openswan to start on boot
update-rc.d ipsec defaults

# Configure Networking for Openswan
#     - This is in addition to the NAT configuration applied to this file
in the NAT section above.
echo '# Extra needed by Openswan' >> /etc/sysctl.conf
echo 'net.ipv4.conf.default.accept_redirects=0' >> /etc/sysctl.conf
echo 'net.ipv4.conf.default.send_redirects=0' >> /etc/sysctl.conf

sysctl -p

# Configure ufw firewall to allow IPsec and L2TP traffic
# - We can use standard statements to allow the NAT-T traffic
# - But we must edit the before.rules to restrict L2TP to over Ipsec
#   - The statement for this is inserted via the sed script below

ufw allow 500/udp
ufw allow 4500

cat << EOF > /tmp/ufw_before_$$.sed
/^-A ufw-before-input -p udp --sport 67 --dport 68 -j ACCEPT/a\\
# Allow L2TP only over IPSEC\\
-A ufw-before-input -m policy --dir in --pol ipsec -p udp --dport 1701 -j

sed -i -f /tmp/ufw_before_$$.sed /etc/ufw/before.rules

rm -f /tmp/ufw_before_$$.sed

# Restart ufw to pick up changes
ufw disable
ufw --force enable


Here's what works at this point:
* I have configured standard "L2TP over IPSec" VPN on a Mac running Mac
OSX 10.8.4 with this VPN
  configuration, using the Public EIP associated with the "vn01" VPN/NAT
* I've done the same with most recent IOS on an iPad.
* In both cases, the VPN is connecting, and I'm showing log activity which
indicates it's working.
* On the Mac, I show the provided IP address as, the first
address in the range
  I've configured, as expected, and the IP address of the Router as, also as expected.
* Here's the relevant sections of the Mac's routing table:

  Destination   Gateway       Flags  Refs  Use  Netif  My Comments
  ------------  ------------  -----  ----  ---  -----
  default      UGSc   262   0    en1
  default  UGScI  1     0    ppp0
  . . .
  10.240.3/24   ppp0          Usc    1     0    ppp0   What configured
this as a /24?  Uhr    2     0    ppp0

* I can ssh into all hosts which fall within this 10.240.3/24 route,
meaning hosts on the subnets and
* I cannot ssh into any hosts outside this route, such as a host on the subnet.

Summary of help needed:
* I'm thinking this must be simple, probably missing one line to tell the
client end that the
  route it should use must be bigger, to use instead of, but I can't
  seem to find any documentation which describes how to do this. Hopefully
an expert on this list
  can help me get this last bit working.
* At that point, I think this configuration may be useful to many others,
as I've seen many 
  references on Google from people attempting to get something similar to
this to work.

Thanks in advance for any help!


Michael Crawford

More information about the Users mailing list