Skip to content

Instantly share code, notes, and snippets.

@borisisok
Last active December 17, 2021 07:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save borisisok/857638adbeb4cf98c415475151f14c78 to your computer and use it in GitHub Desktop.
Save borisisok/857638adbeb4cf98c415475151f14c78 to your computer and use it in GitHub Desktop.
LAB: VPN with BGP
#!/bin/bash
# debug: print all vars and function
env
set
# debug: print all commands during execution
set -x
TUNNEL_NAME="${PLUTO_CONNECTION}"
TUNNEL_MARK="${PLUTO_MARK_IN%%/*}"
TUNNEL_PHY_INTERFACE="${PLUTO_INTERFACE}"
TUNNEL_LOCAL_ENDPOINT="${PLUTO_ME}"
TUNNEL_REMOTE_ENDPOINT="${PLUTO_PEER}"
TUNNEL_PHY_INTERFACE_IP=$(ip a s ${TUNNEL_PHY_INTERFACE} | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}' | cut -f1 -d"/")
while [[ $# > 1 ]]; do
case ${1} in
-ln|--link-name)
TUNNEL_NAME="${2}"
shift
;;
-ll|--link-local)
TUNNEL_LOCAL_NET="${2}"
TUNNEL_LOCAL_ADDRESS="${TUNNEL_LOCAL_NET%%/*}"
shift
;;
-lr|--link-remote)
TUNNEL_REMOTE_NET="${2}"
TUNNEL_REMOTE_ADDRESS="${TUNNEL_REMOTE_NET%%/*}"
shift
;;
-m|--mark)
TUNNEL_MARK="${2}"
shift
;;
-r|--static-route)
TUNNEL_STATIC_ROUTE="${2}"
shift
;;
*)
echo "${0}: Unknown argument \"${1}\"" >&2
;;
esac
shift
done
command_exists() {
type "$1" >&2 2>&2
}
create_interface() {
echo "create_interface()"
ip link add ${TUNNEL_NAME} type vti local ${TUNNEL_LOCAL_ENDPOINT} remote ${TUNNEL_REMOTE_ENDPOINT} key ${TUNNEL_MARK}
ip addr add ${TUNNEL_LOCAL_NET} remote ${TUNNEL_REMOTE_NET} dev ${TUNNEL_NAME}
ip link set ${TUNNEL_NAME} up mtu 1419
}
configure_sysctl() {
echo "configure_sysctl()"
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.conf.${TUNNEL_NAME}.rp_filter=2
sysctl -w net.ipv4.conf.${TUNNEL_NAME}.disable_policy=1
sysctl -w net.ipv4.conf.${TUNNEL_PHY_INTERFACE}.disable_xfrm=1
sysctl -w net.ipv4.conf.${TUNNEL_PHY_INTERFACE}.disable_policy=1
# experimental and not so sane settings
#sysctl -w net.ipv4.conf.${TUNNEL_NAME}.rp_filter=0
#sysctl -w net.ipv4.conf.${TUNNEL_NAME}.accept_local=1
#sysctl -w net.ipv4.conf.${TUNNEL_NAME}.accept_source_route=1
#sysctl -w net.ipv4.conf.${TUNNEL_NAME}.log_martians=1
#sysctl -w net.ipv4.conf.${TUNNEL_NAME}.route_localnet=1
#sysctl -w net.ipv4.conf.${TUNNEL_NAME}.secure_redirects=0
#sysctl -w net.ipv4.conf.${TUNNEL_NAME}.arp_accept=1
#sysctl -w net.ipv4.conf.${TUNNEL_NAME}.arp_announce=1
}
add_route() {
echo "add_route()"
iptables -t mangle -A FORWARD -o ${TUNNEL_NAME} -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -A INPUT -p esp -s ${TUNNEL_REMOTE_ENDPOINT} -d ${TUNNEL_LOCAL_ENDPOINT} -j MARK --set-xmark ${TUNNEL_MARK}
ip route flush table 220
#ip route add ${TUNNEL_STATIC_ROUTE} via ${TUNNEL_LOCAL_ADDRESS}
#iptables -t nat -A POSTROUTING -j SNAT -o ${TUNNEL_NAME} -d ${TUNNEL_STATIC_ROUTE} --to-source ${TUNNEL_PHY_INTERFACE_IP}
#iptables -t nat -A POSTROUTING -j SNAT -o ${TUNNEL_NAME} --to-source ${TUNNEL_PHY_INTERFACE_IP}
# remove policy that prevents incomming tunnel traffic from getting routed
}
enable_vti_forwarding() {
# incomming traffic from the vti tunnel is dropped until this policy is active
ip xfrm policy del src 0.0.0.0/0 dst 0.0.0.0/0 \
dir in \
mark ${TUNNEL_MARK}
}
cleanup() {
echo "cleanup()"
iptables -t mangle -D FORWARD -o ${TUNNEL_NAME} -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -D INPUT -p esp -s ${TUNNEL_REMOTE_ENDPOINT} -d ${TUNNEL_LOCAL_ENDPOINT} -j MARK --set-xmark ${TUNNEL_MARK}
#ip route del ${TUNNEL_STATIC_ROUTE} via ${TUNNEL_LOCAL_ADDRESS}
#iptables -t nat -D POSTROUTING -j SNAT -o ${TUNNEL_NAME} -d ${TUNNEL_STATIC_ROUTE} --to-source ${TUNNEL_PHY_INTERFACE_IP}
#iptables -t nat -D POSTROUTING -j SNAT -o ${TUNNEL_NAME} --to-source ${TUNNEL_PHY_INTERFACE_IP}
# ip route flush cache
}
delete_interface() {
echo "delete_interface()"
ip link set ${TUNNEL_NAME} down
ip link del ${TUNNEL_NAME}
}
# main execution starts here
command_exists ip || echo "ERROR: ip command is required to execute the script, check if you are running as root, mostly to do with path, /sbin/" >&2 2>&2
command_exists iptables || echo "ERROR: iptables command is required to execute the script, check if you are running as root, mostly to do with path, /sbin/" >&2 2>&2
command_exists sysctl || echo "ERROR: sysctl command is required to execute the script, check if you are running as root, mostly to do with path, /sbin/" >&2 2>&2
case "${PLUTO_VERB}" in
up-client)
echo up-client
create_interface
configure_sysctl
add_route
#enable_vti_forwarding
;;
down-client)
echo down-client
cleanup
delete_interface
;;
up-host)
echo up-client
create_interface
configure_sysctl
add_route
#enable_vti_forwarding
;;
down-host)
echo down-client
cleanup
delete_interface
;;
esac
# File: /etc/bird.conf
# Host: gw1-net1
log syslog all;
debug protocols all;
router id 10.100.101.1;
protocol device {
}
protocol direct {
#interface "lo";
interface "enp0s9";
interface "enp0s3";
}
protocol kernel {
learn;
import none;
export all;
}
protocol bgp gw1_net2 {
local as 9010;
neighbor 10.2.1.2 as 9020;
export all;
import all;
}
protocol bgp gw2_net2 {
local as 9010;
neighbor 10.2.2.2 as 9020;
export all;
import all;
}
# Host: gw2-net1
log syslog all;
debug protocols all;
router id 10.100.101.2;
protocol device {
}
protocol direct {
# interface "lo";
interface "enp0s9";
interface "enp0s3";
}
protocol kernel {
learn;
import none;
export all;
}
protocol bgp gw1_net2 {
local as 9010;
neighbor 10.2.3.2 as 9020;
export all;
import all;
}
protocol bgp gw2_net2 {
local as 9010;
neighbor 10.2.4.2 as 9020;
export all;
import all;
}
# Host: gw1-net2
log syslog all;
debug protocols all;
router id 10.100.102.1;
protocol device {
}
protocol direct {
# interface "lo";
interface "enp0s9";
interface "enp0s3";
}
protocol kernel {
learn;
import none;
export all;
}
protocol bgp gw1_net1 {
local as 9020;
neighbor 10.2.1.1 as 9010;
export all;
import all;
}
protocol bgp gw2_net1 {
local as 9020;
neighbor 10.2.3.1 as 9010;
export all;
import all;
}
# Host: gw2-net2
log syslog all;
debug protocols all;
router id 10.100.102.2;
protocol device {
}
protocol direct {
# interface "lo";
interface "enp0s9";
interface "enp0s3";
}
protocol kernel {
learn;
import none;
export all;
}
protocol bgp gw1_net1 {
local as 9020;
neighbor 10.2.2.1 as 9010;
export all;
import all;
}
protocol bgp gw2_net1 {
local as 9020;
neighbor 10.2.4.1 as 9010;
export all;
import all;
}
config setup
# strictcrlpolicy=yes
uniqueids = no
# Host: gw1-net1
conn g1n1-g1n2
auto=add
left=%defaultroute
leftid=10.100.101.1
right=10.100.102.1
type=tunnel
leftauth=psk
rightauth=psk
keyexchange=ikev1
ike=aes128-sha1-modp1024
ikelifetime=8h
esp=aes128-sha1-modp1024
lifetime=1h
keyingtries=%forever
leftsubnet=0.0.0.0/0,::/0
rightsubnet=0.0.0.0/0,::/0
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
#mark=100
mark=%unique
leftupdown="/etc/strongswan/ipsec.d/aws-updown.sh -ll 10.2.1.1 -lr 10.2.1.2"
conn g1n1-g2n2
auto=add
left=%defaultroute
leftid=10.100.101.1
right=10.100.102.2
type=tunnel
leftauth=psk
rightauth=psk
keyexchange=ikev1
ike=aes128-sha1-modp1024
ikelifetime=8h
esp=aes128-sha1-modp1024
lifetime=1h
keyingtries=%forever
leftsubnet=0.0.0.0/0,::/0
rightsubnet=0.0.0.0/0,::/0
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
#mark=200
mark=%unique
leftupdown="/etc/strongswan/ipsec.d/aws-updown.sh -ll 10.2.2.1 -lr 10.2.2.2"
# Host: gw2-net1
conn g2n1-g1n2
auto=add
left=%defaultroute
leftid=10.100.101.2
right=10.100.102.1
type=tunnel
leftauth=psk
rightauth=psk
keyexchange=ikev1
ike=aes128-sha1-modp1024
ikelifetime=8h
esp=aes128-sha1-modp1024
lifetime=1h
keyingtries=%forever
leftsubnet=0.0.0.0/0,::/0
rightsubnet=0.0.0.0/0,::/0
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
#mark=100
mark=%unique
leftupdown="/etc/strongswan/ipsec.d/aws-updown.sh -ll 10.2.3.1 -lr 10.2.3.2"
conn g2n1-g2n2
auto=add
left=%defaultroute
leftid=10.100.101.2
right=10.100.102.2
type=tunnel
leftauth=psk
rightauth=psk
keyexchange=ikev1
ike=aes128-sha1-modp1024
ikelifetime=8h
esp=aes128-sha1-modp1024
lifetime=1h
keyingtries=%forever
leftsubnet=0.0.0.0/0,::/0
rightsubnet=0.0.0.0/0,::/0
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
#mark=200
mark=%unique
leftupdown="/etc/strongswan/ipsec.d/aws-updown.sh -ll 10.2.4.1 -lr 10.2.4.2"
# Host: gw1-net2
conn g1n2-g1n1
auto=start
left=%defaultroute
leftid=10.100.102.1
right=10.100.101.1
type=tunnel
leftauth=psk
rightauth=psk
keyexchange=ikev1
ike=aes128-sha1-modp1024
ikelifetime=8h
esp=aes128-sha1-modp1024
lifetime=1h
keyingtries=%forever
leftsubnet=0.0.0.0/0,::/0
rightsubnet=0.0.0.0/0,::/0
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
mark=%unique
leftupdown="/etc/strongswan/ipsec.d/aws-updown.sh -ll 10.2.1.2 -lr 10.2.1.1"
conn g1n2-g2n1
auto=start
left=%defaultroute
leftid=10.100.102.1
right=10.100.101.2
type=tunnel
leftauth=psk
rightauth=psk
keyexchange=ikev1
ike=aes128-sha1-modp1024
ikelifetime=8h
esp=aes128-sha1-modp1024
lifetime=1h
keyingtries=%forever
leftsubnet=0.0.0.0/0,::/0
rightsubnet=0.0.0.0/0,::/0
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
mark=%unique
leftupdown="/etc/strongswan/ipsec.d/aws-updown.sh -ll 10.2.3.2 -lr 10.2.3.1"
# Host: gw2-net2
conn g2n2-g1n1
auto=start
left=%defaultroute
leftid=10.100.102.2
right=10.100.101.1
type=tunnel
leftauth=psk
rightauth=psk
keyexchange=ikev1
ike=aes128-sha1-modp1024
ikelifetime=8h
esp=aes128-sha1-modp1024
lifetime=1h
keyingtries=%forever
leftsubnet=0.0.0.0/0,::/0
rightsubnet=0.0.0.0/0,::/0
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
mark=%unique
leftupdown="/etc/strongswan/ipsec.d/aws-updown.sh -ll 10.2.2.2 -lr 10.2.2.1"
conn g2n2-g2n1
auto=start
left=%defaultroute
leftid=10.100.102.2
right=10.100.101.2
type=tunnel
leftauth=psk
rightauth=psk
keyexchange=ikev1
ike=aes128-sha1-modp1024
ikelifetime=8h
esp=aes128-sha1-modp1024
lifetime=1h
keyingtries=%forever
leftsubnet=0.0.0.0/0,::/0
rightsubnet=0.0.0.0/0,::/0
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
mark=%unique
leftupdown="/etc/strongswan/ipsec.d/aws-updown.sh -ll 10.2.4.2 -lr 10.2.4.1"
# Current state
+ IPSec conn working OK.
+ Traffic inside the vti tunnel is OK.
+ BGP Session + route exchange OK.
- Forwarding real traffic over the vti tunnel FAILS. Strongswans Xfrm policy is messing things up.
- https://lists.strongswan.org/pipermail/users/2015-March/007628.html
# network manger cli examples
nmcli con add type ethernet con-name nat_internet ifname enp0s3
nmcli con add type ethernet con-name fake_internet ifname enp0s8
nmcli con add type ethernet con-name host_net_a ifname enp0s9
nmcli con add type ethernet con-name fake_internet ifname enp0s3 ip4 10.210.210.1/24
nmcli con up fake_internet
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment