Estimated reading time: 7 minutes (1384 words)
A quick post regarding setting up StrongSwan to connect to a Cisco IPsec endpoint, as the Cisco configuration makes a number of unnamed assumptions and it took a few hours to figure it out. This is specifically for configuring authentication with a shared key on ikev1
Configured on Ubuntu 24.04 LTS
1. Install packages
Just need to install strongswan
sudo apt install strongswan2. Get your variables prepared.
In order to make sense of the config, it’s easier if you get all your variables you’ll need to replace ready ahead of time. You’ll need the following variables, with some examples provided.
user_name = "client1" # Your client connections user name
user_password = "0xDADBEEF" # Your client connections password
local_id = "remote-site-1" # The unqiue name of the clients local id, this can be whatever you want.
remote_id = "outpost-x" # Your made up name for this configuration, it's the same name you use when you bring it up later.
remote_shared_secret = "LetMeInnnn" # Secure Pre-Sharked IKE secret key, also called a PSK
remote_endpoint = "192.168.9.12" # IP or DNS name of the IPsec server
right_subnet = "192.168.10.0/24" # The configured server subnet to route traffic to3. Configure your secrets
This should be located at /etc/ipsec.secrets configured with the owner as root and permissions as 0400.
"{{ remote_id }}" %any : PSK "{{ remote_shared_secret }}"
{{ user_name }}} %any : XAUTH "{{ user_password }}"4. Configure your IPsec config
This should be located at /etc/ipsec.conf with the owner as root and permissions more lax at 0644.
Things to know about the IPsec config:
- IPsec for some awful reason refers to all of it’s config as a
leftandrightnomenclature whereleftis your local client connection (your local host) andrightis the remote server. - The config makes use of a
%varsyntax to make sure of specific macros. These are documented upstream https://wiki.strongswan.org/projects/strongswan/wiki/ConnSection .
# ipsec.conf - strongSwan IPsec configuration file
# Basic config
config setup
charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2"
conn {{ local_id }}
# "Cisco/IKEv1" as it's often referred to
# isn't really a thing, it's just "ikev1"
# with some preconfigured params.
keyexchange=ikev1
authby=secret
# local (client) side
## Can define custom routes if needed by defining the src ip
left=%defaultroute
# What the IP you'll use in the remote network is.
# by defining "%config" the upstream can provide you with what IP it sees fit.
leftsourceip=%config
leftauth=psk
leftauth2=xauth
# This should match the id of your PSK from /etc/ipsec.secrets
# Confusingly it uses the "right" (remote) information.
# Many Cisco devices will reject your connection if your "leftid" and "rightid" don't match.
leftid="{{ remote_id }}"
# This should match the id of your XAUTH user password entry from /etc/ipsec.secrets
xauth_identity={{ user_name }}
# remote (gateway) side
right={{ remote_endpoint }}
rightid="{{ remote_id }}"
# Subnet to route packets through (generally needs to match what the IPsec server has configured)
rightsubnet={{ right_subnet }}
rightauth=psk
# Try Aggressive Mode - many Cisco PSK+XAuth setups use this
# If you don't enable this, the IPsec server may just never respond to you.
aggressive=yes
# Broader proposals to match average Cisco defaults
ike=aes256-sha1-modp1024,aes128-sha1-modp1024,3des-sha1-modp1024!
esp=aes256-sha1,aes128-sha1,3des-sha1!
ikelifetime=24h
lifetime=8h
# Most Cisco gateways don't use PFS in Phase
pfs=no
dpdaction=restart
dpddelay=30s
dpdtimeout=120s
auto=add
5. Start the Server
For first time setup, you’ll need restart the Charon (in strongswan-start) and then bring up your IPSec connection. (On many systems the “ipsec” and “strongswan-starter” are the same service unit.
# Restart the Charon
user@host:~# sudo systemctl restart strongswan-starter.service
# Bring up the network
user@host:~# sudo ipsec up {{ local_id }}
...
XAuth authentication of 'user_name' (myself) successful
IKE_SA {{ local_id }}[1] established between {{ local_ip }}}[{{ remote_id }}]...{{ remote_ip }}[{{ remote_id }}]
...
installing new virtual IP 192.168.10.100
...
received packet: from {{ remote server ip }}[4500] to {{ local_ip }}[4500] (156 bytes)
connection '{{ local_id }}' established successfullyHopefully at this point things should just work for you (note in the current format you still need to run sudo ipsec up {{ local_id }} again after a reboot).
6. Debugging Tips
I spent a few too many hours debugging this, so let’s start walking through some things you can do to debug:
sudo ipsec status- A general status command, a good starting place for “am I connected already or not?”
- Charon log levels
- Can be fairly useful, just add the block
log_level = Xto thecharonsection of/etc/strongswan.d/charon.conf(or as a drop-in to/etc/strongswan.d/charon/). - Log levels are
-1(no logging) to4(everything including sensitive info), usuallylog_level = 2will cover most of your cases.
- Can be fairly useful, just add the block
tcpdump- Old faithful, just run a
tcpdump -i any -n "host {{ remote_server_ip }} and (udp port 500 or udp port 4500)" - Genuinely, I spent most of the time figuring out to set this up by doing TCP Dumps, and seeing what the remote actually responded to and didn’t.
- Wireshark also works fine for this.
- Old faithful, just run a
- Don’t look at
ip route!- Don’t look at
ip routeoriptable-savefor the routes to your remote! Most of the time StrongSwan will configure it as an XFRM policy base. Instead try looking atsudo ipsec xfrm policy
- Don’t look at
- System logs (or journald)
- The usual place may often have some useful info
journalctl --unit strongswan-start(if you try to specify the unit asipsec, you won’t get results, surprisingly against how earlier aliasing works for status/start/stop/etc).
- The usual place may often have some useful info
- Percussive Maintenance
- Sometimes it helps, or at least makes you feel better.
- It’s a Cisco switch, it could use reminder who’s boss anyways.