OpenStack Debug VPN

Find the VPN server and the relevant router UUID

# get VPN connection ID
openstack vpn ipsec site connection list | grep foo
openstack vpn ipsec site connection list --long | grep <project_id>
 
VPN_CONNECTION_ID=142dc25f-13bb-4fda-b093-edf13df98ed8
openstack vpn ipsec site connection show ${VPN_CONNECTION_ID}
 
VPN_SERVICE_ID=$(openstack vpn ipsec site connection show ${VPN_CONNECTION_ID} -c 'VPN Service' -f value)
openstack vpn service show ${VPN_SERVICE_ID}
 
# get router ID
ROUTER_ID=$(openstack vpn service show ${VPN_SERVICE_ID} -c Router -f value)
echo "ROUTER_ID=${ROUTER_ID}"

Find the ctl Node where the active router is running

ROUTER_PORT_ID=$(openstack port list --device-owner network:router_gateway -f value -c id --router ${ROUTER_ID})
CONTROL_NODE=$(openstack port show ${ROUTER_PORT_ID} -c binding_host_id -f value)
echo "CONTROL_NODE: ${CONTROL_NODE}"
 
echo "ssh ${CONTROL_NODE} sudo ip netns exec qrouter-${ROUTER_ID} ip a s"

Connect to that ctl node and "jump" in its neutron-l3-agent docker container

ssh ${CONTROL_NODE}
docker exec -u root -ti neutron_l3_agent bash

Enable file logging in strongswan configuration

ROUTER_ID=b7ed736e-8f38-4be6-8ce4-644c5c7bfedf
 
cp /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf{,.org}
 
sed -i "s|# <name> {|charon {|g" /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf
sed -i "s|# path =|path = /var/log/charon-${ROUTER_ID}.log|g" /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf
sed -i "s|# append = yes|append = no|g" /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf
## loglevel 1 should be enough. Use 2 for more details or read: https://docs.strongswan.org/docs/5.9/config/logging.html
sed -i "s|# default = 1|default = 1|g" /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf
sed -i "s|# ike_name = no|ike_name = yes|g" /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf
sed -i "s|# time_add_ms = no|time_add_ms = yes|g" /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf
sed -i "s|# time_format =|time_format = %b %e %T|g" /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf
sed -i '0,/# }/s/# }/}/' /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf
 
# debug
diff /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf{,.org}

Restart the strongswan connection

ip netns exec qrouter-${ROUTER_ID} neutron-vpn-netns-wrapper --mount_paths="/etc:/var/lib/neutron/ipsec/${ROUTER_ID}/etc,/var/run:/var/lib/neutron/ipsec/${ROUTER_ID}/var/run" --cmd="ipsec,restart"

Debug VPN logs

# read log inside IP namespace
tail -f /var/log/charon-${ROUTER_ID}.log
 
# read log on crontrol node
ROUTER_ID=b7ed736e-8f38-4be6-8ce4-644c5c7bfedf
tail -f /var/lib/docker/overlay2/*/merged/var/log/charon-${ROUTER_ID}.log

Debug IPsec/IKE
https://book.hacktricks.xyz/network-services-pentesting/ipsec-ike-vpn-pentesting

nmap -sU -p 500 172.16.21.200
ike-scan -M 172.16.21.200

Cleanup

# disable file logging
mv /var/lib/neutron/ipsec/${ROUTER_ID}/etc/strongswan.d/charon-logging.conf{.org,}
 
# restart strongswan again
ip netns exec qrouter-${ROUTER_ID} neutron-vpn-netns-wrapper --mount_paths="/etc:/var/lib/neutron/ipsec/${ROUTER_ID}/etc,/var/run:/var/lib/neutron/ipsec/${ROUTER_ID}/var/run" --cmd="ipsec,restart"
 
# delete logfile
rm /var/log/charon-${ROUTER_ID}.log

Miscellaneous

SERVER_ID=$(openstack server list --all-project -f json | jq -r '.[] | select(."Name" == "'develop'") | .ID'); declare -p SERVER_ID
NETWORK_ID=$(openstack port list --server ${SERVER_ID} -c network_id -f value); declare -p NETWORK_ID
ROUTER_ID=$(openstack port list --network ${NETWORK_ID} --device-owner network:ha_router_replicated_interface -c device_id -f value); declare -p ROUTER_ID
openstack router show "$ROUTER_ID" -f json
PROJECT_ID=$(openstack router show "$ROUTER_ID" -f json | jq -r '.project_id')
 
#list SUBNETS:
openstack subnet list --project "PROJECT_ID" -c ID -f value | while read i; do openstack subnet show $i -c id -c name -c cidr -f json | jq -c .; done
 
#list VPN SERVICES:
openstack vpn service list --long -c ID -c Project -f value | awk "\$2 == \"PROJECT_ID\" {print \$1}" | while read i; do openstack vpn service show $i -c ID -c Name -c Router -c State -c Status -f json | jq -c .; done
 
#list VPN ENDPOINT GROUPS:
openstack vpn endpoint group list --long -c ID -c Project -f value | awk "\$2 == \"PROJECT_ID\" {print \$1}" | while read i; do openstack vpn endpoint group show $i -c ID -c Name -c Endpoints -f json | jq -c .; done
 
#list VPN IPSEC SITE CONNECTIONS:
openstack vpn ipsec site connection list --long -c ID -c Project -f value | awk "\$2 == \"PROJECT_ID\" {print \$1}" | while read i; do openstack vpn ipsec site connection show $i -c ID -c Name -c "Local Endpoint Group ID" -c "Peer Endpoint Group ID" -c "Peer Address" -c "Peer ID" -c State -c Status -f json | jq -c .; done
 
#list L3 AGENTS:
neutron l3-agent-list-hosting-router "$ROUTER_ID"
 
#list IP ROUTES:
pdsh -l root -w ctl[1-3] "ip netns exec qrouter-$ROUTER_ID ip r && ip a" | dshbak -c
 
#list IPTABLES:
pdsh -l root -w ctl[1-3] "ip netns exec qrouter-$ROUTER_ID iptables-save | sed -e 's/[\[0-9:\]*]//'" | dshbak -c

Links
https://docs.strongswan.org/docs/5.9/config/logging.html
https://www.atlantic.net/vps-hosting/how-to-install-and-configure-strongswan-vpn-on-ubuntu-18-04/