Skip to content

Instantly share code, notes, and snippets.

@heri16
Last active February 21, 2023 05:40
Show Gist options
  • Save heri16/2f59d22d1d5980796bfb to your computer and use it in GitHub Desktop.
Save heri16/2f59d22d1d5980796bfb to your computer and use it in GitHub Desktop.
AWS VPC VPN StrongSwan Virtual Tunnel Interface (VTI)
#@ /etc/quagga/bgpd.conf (Centos & Ubuntu)
hostname <Local OS hostname>
password <Any random phrase>
enable password <Any random phrase>
!
log file /var/log/quagga/bgpd
!debug bgp events
!debug bgp zebra
debug bgp updates
!
router bgp <Your Customer Gateway ASN>
bgp router-id <Any integer number - smaller means higher priority routes>
network <Your internal LAN subnet - e.g. 10.130.0.0/16>
!network 169.254.x.x/32
!network 169.254.x.x/32
!
! aws tunnel #1 neighbour
neighbor <Your VGW1 Inside IP> remote-as 17493
!
! aws tunnel #2 neighbour
neighbor <Your VGW2 Inside IP> remote-as 17493
!
! Uncomment the line below if you prefer to use 'Connection B' as your backup (Connection A will # be used as your primary for all traffic). By default if you do not uncomment the next lines, traffic can #be sent and received down both of your connections at any time (asymmetric routing).
!neighbor <Your VGW2 Inside IP> route-map RM_LOWER_PRIORITY out
!
route-map RM_LOWER_PRIORITY permit 10
set as-path prepend <Your Customer Gateway ASN> <Your Customer Gateway ASN> <Your Customer Gateway ASN>
!
line vty
# LEGEND
# https://s3-us-west-2.amazonaws.com/youtubetutorials/racoon_config.txt
#
# <Your Customer Gateway ASN> is the local autonomous system (Customer Gateway ASN)
# 17493 is the remote autonomous system of AWS (Virtual Private Gateway ASN)
#
# <Your VGW1 Inside IP> is the 169.x address on the REMOTE side of the first peer. (Neighbor IP Address)
# <Your VGW2 Inside IP> is the 169.x address on the REMOTE side of the second peer. (Neighbor IP Address)
#
# <Your internal LAN subnet - e.g. 10.0.0.0/16> is the local private subnet/LAN (Private Network Subnet)
# 169.254.x.x/32 is the 169.x address on LOCAL side of the first peer. Use /32
# 169.254.x.x/32 is the 169.x address on the LOCAL side of the second peer. Use /32
#@ /etc/strongswan/ipsec-vti.sh (Centos) or /etc/strongswan.d/ipsec-vti.sh (Ubuntu)
#!/bin/bash
# AWS VPC Hardware VPN Strongswan updown Script
# Usage Instructions:
# Add "install_routes = no" to /etc/strongswan/strongswan.d/charon.conf or /etc/strongswan.d/charon.conf
# Add "install_virtual_ip = no" to /etc/strongswan/strongswan.d/charon.conf or /etc/strongswan.d/charon.conf
# For Ubuntu: Add "leftupdown=/etc/strongswan.d/ipsec-vti.sh" to /etc/ipsec.conf
# For RHEL/Centos: Add "leftupdown=/etc/strongswan/ipsec-vti.sh" to /etc/strongswan/ipsec.conf
# For RHEL/Centos 6 and below: git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git && cd iproute2 && make && cp ./ip/ip /usr/local/sbin/ip
# Adjust the below according to the Generic Gateway Configuration file provided to you by AWS.
# Sample: http://docs.aws.amazon.com/AmazonVPC/latest/NetworkAdminGuide/GenericConfig.html
IP=$(which ip)
IPTABLES=$(which iptables)
PLUTO_MARK_OUT_ARR=(${PLUTO_MARK_OUT//// })
PLUTO_MARK_IN_ARR=(${PLUTO_MARK_IN//// })
case "$PLUTO_CONNECTION" in
AWS-VPC-GW1)
VTI_INTERFACE=vti1
VTI_LOCALADDR=<Your CGW1 Inside IP 169.254.x.x/30>
VTI_REMOTEADDR=<Your VGW1 Inside IP 169.254.x.x/30>
;;
AWS-VPC-GW2)
VTI_INTERFACE=vti2
VTI_LOCALADDR=<Your CGW2 Inside IP 169.254.x.x/30>
VTI_REMOTEADDR=<Your VGW2 Inside IP 169.254.x.x/30>
;;
esac
case "${PLUTO_VERB}" in
up-client)
#$IP tunnel add ${VTI_INTERFACE} mode vti local ${PLUTO_ME} remote ${PLUTO_PEER} okey ${PLUTO_MARK_OUT_ARR[0]} ikey ${PLUTO_MARK_IN_ARR[0]}
$IP link add ${VTI_INTERFACE} type vti local ${PLUTO_ME} remote ${PLUTO_PEER} okey ${PLUTO_MARK_OUT_ARR[0]} ikey ${PLUTO_MARK_IN_ARR[0]}
sysctl -w net.ipv4.conf.${VTI_INTERFACE}.disable_policy=1
sysctl -w net.ipv4.conf.${VTI_INTERFACE}.rp_filter=2 || sysctl -w net.ipv4.conf.${VTI_INTERFACE}.rp_filter=0
$IP addr add ${VTI_LOCALADDR} remote ${VTI_REMOTEADDR} dev ${VTI_INTERFACE}
$IP link set ${VTI_INTERFACE} up mtu 1436
$IPTABLES -t mangle -I FORWARD -o ${VTI_INTERFACE} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
$IPTABLES -t mangle -I INPUT -p esp -s ${PLUTO_PEER} -d ${PLUTO_ME} -j MARK --set-xmark ${PLUTO_MARK_IN}
$IP route flush table 220
#/etc/init.d/bgpd reload || /etc/init.d/quagga force-reload bgpd
;;
down-client)
#$IP tunnel del ${VTI_INTERFACE}
$IP link del ${VTI_INTERFACE}
$IPTABLES -t mangle -D FORWARD -o ${VTI_INTERFACE} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
$IPTABLES -t mangle -D INPUT -p esp -s ${PLUTO_PEER} -d ${PLUTO_ME} -j MARK --set-xmark ${PLUTO_MARK_IN}
;;
esac
# Enable IPv4 forwarding
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.conf.eth1.disable_xfrm=1
sysctl -w net.ipv4.conf.eth1.disable_policy=1
# References:
# http://docs.aws.amazon.com/AmazonVPC/latest/NetworkAdminGuide/Introduction.html
# http://end.re/2015-01-06_vti-tunnel-interface-with-strongswan.html
# https://www-01.ibm.com/support/knowledgecenter/#!/SST55W_4.3.0/liaca/liaca_cfg_ipsec_vti.html
#@ /etc/strongswan/ipsec.conf (Centos) or /etc/ipsec.conf (Ubuntu)
# ipsec.conf - strongSwan IPsec configuration file
# basic configuration
config setup
charondebug="cfg 2, ike 3"
# strictcrlpolicy=yes
# uniqueids = no
# Add connections here.
# Sample VPN connections
#conn sample-self-signed
# leftsubnet=10.1.0.0/16
# leftcert=selfCert.der
# leftsendcert=never
# right=192.168.0.2
# rightsubnet=10.2.0.0/16
# rightcert=peerCert.der
# auto=start
#conn sample-with-ca-cert
# leftsubnet=10.1.0.0/16
# leftcert=myCert.pem
# right=192.168.0.2
# rightsubnet=10.2.0.0/16
# rightid="C=CH, O=Linux strongSwan CN=peer name"
# auto=start
# Usage Instructions:
# Adjust the below according to the Generic Gateway Configuration file provided to you by AWS.
# Sample: http://docs.aws.amazon.com/AmazonVPC/latest/NetworkAdminGuide/GenericConfig.html
conn %default
# Authentication Method : Pre-Shared Key
#authby=psk
leftauth=psk
rightauth=psk
# Encryption Algorithm : aes-128-cbc
# Authentication Algorithm : sha1
# Perfect Forward Secrecy : Diffie-Hellman Group 2
ike=aes256-sha256-modp2048s256,aes128-sha1-modp1024!
# Lifetime : 28800 seconds
ikelifetime=28800s
# Phase 1 Negotiation Mode : main
aggressive=no
# Protocol : esp
# Encryption Algorithm : aes-128-cbc
# Authentication Algorithm : hmac-sha1-96
# Perfect Forward Secrecy : Diffie-Hellman Group 2
esp=aes128-sha256-modp2048s256,aes128-sha1-modp1024!
# Lifetime : 3600 seconds
lifetime=3600s
# Mode : tunnel
type=tunnel
# DPD Interval : 10
dpddelay=10s
# DPD Retries : 3
dpdtimeout=30s
# Tuning Parameters for AWS Virtual Private Gateway:
keyexchange=ikev1
#keyingtries=%forever
rekey=yes
reauth=no
dpdaction=restart
closeaction=restart
left=%defaultroute
leftsubnet=0.0.0.0/0,::/0
rightsubnet=0.0.0.0/0,::/0
leftupdown=/etc/strongswan/ipsec-vti.sh
installpolicy=yes
compress=no
mobike=no
conn AWS-VPC-GW1
# Customer Gateway: : <Your Strongswan-CGW Public IP>
left=<Your Strongswan-CGW Public IP>
# Virtual Private Gateway : <Your VGW1 Outside IP>
right=<Your VGW1 Outside IP>
auto=start
mark=100
#reqid=1
conn AWS-VPC-GW2
# Customer Gateway: : <Your Strongswan-CGW Public IP>
left=<Your Strongswan-CGW Public IP>
# Virtual Private Gateway : <Your VGW2 Outside IP>
right=<Your VGW2 Outside IP>
auto=start
mark=200
#reqid=2
# References:
# http://docs.aws.amazon.com/AmazonVPC/latest/NetworkAdminGuide/Introduction.html
# http://end.re/2015-01-06_vti-tunnel-interface-with-strongswan.html
# https://www-01.ibm.com/support/knowledgecenter/#!/SST55W_4.3.0/liaca/liaca_cfg_ipsec_vti.html
# https://aravindkrishnaswamy.wordpress.com/tag/multiple-vpn-tunnels-with-strongswan/
# https://aravindkrishnaswamy.wordpress.com/2014/11/26/site-to-site-vpn-between-openvpn-and-aws/
# http://www.mynameistoby.com/blog/2015/01/21/setting-up-strongswan-on-centos-6-to-connect-to-your-amazon-vpc-vpn/
# https://wiki.strongswan.org/projects/strongswan/wiki/ConnSection
# https://wiki.strongswan.org/projects/strongswan/wiki/IKEv2CipherSuites
#@ /etc/strongswan/ipsec.secrets (Centos) or /etc/ipsec.secrets (Ubuntu)
<Your Strongswan-CGW Public IP> <Your VGW1 Outside IP> : PSK "<Replace with VGW1 secret phrase provided by AWS>"
<Your Strongswan-CGW Public IP> <Your VGW2 Outside IP> : PSK "<Replace with VGW2 secret phrase provided by AWS>"
#@ /etc/sysconfig/iptables (Centos) or /etc/iptables/rules.v4 (Ubuntu with iptables-persistent package)
# Generated by iptables-save v1.4.7
*filter
:INPUT DROP [1:60]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [21:2888]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i eth0 -p esp -j ACCEPT
-A INPUT -i eth0 -p udp -m udp --sport 500 --dport 500 -j ACCEPT
-A INPUT -i eth0 -p udp -m udp --sport 4500 --dport 4500 -j ACCEPT
-A INPUT -i vti+ -p tcp -m tcp --dport 179 -j ACCEPT
-A INPUT -i eth+ -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A FORWARD -i eth1 -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A FORWARD -p icmp -m icmp --icmp-type 0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -p icmp -m icmp --icmp-type 0 -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
# Completed
#@ /etc/quagga/zebra.conf (Centos & Ubuntu)
hostname <Local OS hostname>
password <Any random phrase>
enable password <Any random phrase>
!
! Configure interfaces
interface lo
! Change preferred source ip address of received routes
route-map RM_SET_SRC permit 10
set src <Your host ip-address on Your internal LAN subnet interface - e.g. 10.130.0.5>
ip protocol bgp route-map RM_SET_SRC
!
line vty
@aprudnev
Copy link

aprudnev commented Apr 28, 2021 via email

@edvinaskairys
Copy link

There is a lot of specifics, how it all works. For me, I created working system, it is used in more than 30 - 40 cases in our company, we have it all tuned for auto restart, never fail, and so on, and so, as maybe other configurations can work, I do not see a reason to investigate them - as I need working tunnel and not R&D research what else can be done. MARK is required to label traffic for the tunnel. As it works this way - interface add MARK and then IP level forward marked traffic into the IPSEC. Do not forget that IPSEC, in it's classic form, use IP addresses to decide which traffic to encrypt and wrap in IPSEC. GRE + IPSEC combination is DIFFERENT way to create encrypted tunnels. We do use it in our company for usual site/site traffic. But it contains some overhead (as IPSEC itself is tunnel) and so Cisco introduce special IPSEC type, VTI, which presents IPSEC to the routing layer as any interface (and they called it VTI interface). When we use strongswan, we simulate VTI by labeling traffic (on pseudo interface vti*) and they saying to IPSEC to encrypt and tunnel it by recognizing it by the lavel. IPSEC tunnel, in case of VTI, has security domain as 0.0.0.0/0_0.0.0.0/0 which means encrypt any traffic (so it does not use IP to decide what to encrypt) and we add MARK as a label (so it encrypt only MARKED traffic). Alternative is POLICY BASED IPSEC, AZURE has it, but it is extremely inconvenient and difficult to manage thing. AWS choose do not implement it, as it can not be used in routing.

On Wed, Apr 28, 2021 at 2:05 AM Edvinas K @.> wrote: @.* commented on this gist. ------------------------------ hello, currently i'm trying to establish Strongswan to AWS VPC using BGP. My first question: do the the MARKs and vti-sh script is needed ? Why it's not enough to have just vti tunnel created and route traffic like in GRE case ? Thanks — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://gist.github.com/2f59d22d1d5980796bfb#gistcomment-3722804, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFQ2RZLMVD7KEQUNIKRLKZ3TK7FWHANCNFSM4KYQIE7Q .

thanks for such a quick answer. You know - i tried to do 'simple` VTI + Strongswan + FRR (BGP) configuration between two internal nodes.

    left=10.34.32.154
    leftsubnet=10.34.32.154/32
    rightsubnet=10.34.32.155/32
    leftfirewall=no
    ike=aes-sha1-modp1024
    esp=aes128gcm16-modp1024
    right=10.34.32.155
    type=tunnel
    authby=psk
    auto=start
    keyexchange=ikev2
    mobike=no
    reauth=no

4: ipip0@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ipip 10.34.32.154 peer 10.34.32.155
    inet 169.1.1.1/30 scope global ipip0
       valid_lft forever preferred_lft forever

And it works. So i thought the same should work connecting to AWS VPC. But sadly something is not OK. So trying to understand where's the catch. Why it works OK between two internal nodes but not between Strongswan - and VPC.

@aprudnev
Copy link

aprudnev commented Apr 28, 2021 via email

@edvinaskairys
Copy link

thanks, somehow i manage ,y configuration to work.

The only strange thing i see that when i look into mangle table. I see no packets which supposed to be marked MATCHED. But it's still works. Can you check how it's on your side ? Thanks

 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 171M packets, 170G bytes)
 pkts bytes target     prot opt in     out     source               destination         
      0     0 MARK       esp  --  *      *       18.138.xx.63        xx.xx.4.251         MARK set 0x64
      0     0 MARK       esp  --  *      *       54.169.xx.249       xx.xx.4.251         MARK set 0xc8

Chain FORWARD (policy ACCEPT 83M packets, 108G bytes)
 pkts bytes target     prot opt in     out     source               destination         
64837 3889K TCPMSS     tcp  --  *      VTI_awssg1  0.0.0.0/0            0.0.0.0/0            tcp flags:0x06/0x02 TCPMSS clamp to PMTU
  807 48404 TCPMSS     tcp  --  *      VTI_awssg2  0.0.0.0/0            0.0.0.0/0            tcp flags:0x06/0x02 TCPMSS clamp to PMTU

Chain OUTPUT (policy ACCEPT 74M packets, 61G bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 159M packets, 170G bytes)
 pkts bytes target     prot opt in     out     source               destination         
You have mail in /var/spool/mail/root```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment