Side2Side IPSec VPN connection between OpenStack VPN and AVM Fritz!Box

Define variables for OpenStack VPN configuration

FRITZBOX_EXTERNAL_IP=x.x.x.x                    # curl ipinfo.io/ip
FRITZBOX_NETWORK=192.168.178.0/24               # Heimnetz > Netzwerk > Netzwerkeinstellungen > IPv4-Einstellungen
PASSWORD='xxxxxxxx'                             # apg -m 32
OPENSTACK_SUBNET_ID=$(openstack subnet list -c ID -f value)
OPENSTACK_ROUTER_ID=$(openstack router list -c ID -f value)

Define variables

# Create ike v1 policy
openstack vpn ike policy create vpn_ike_1 \
  --ike-version v1 \
  --encryption-algorithm aes-256 \
  --auth-algorithm sha256 \
  --pfs group14
 
# Create ipsec policy
openstack vpn ipsec policy create vpn_ipsec_1 \
  --encryption-algorithm aes-256 \
  --auth-algorithm sha256 \
  --pfs group14
 
# Create service
openstack vpn service create vpn_service_1 \
  --router ${OPENSTACK_ROUTER_ID} 
 
# Create local endpoint group
openstack vpn endpoint group create vpn_endpoint_openstack \
  --type subnet \
  --value ${OPENSTACK_SUBNET_ID}
 
# Create peer endpoint group
openstack vpn endpoint group create vpn_endpoint_fritzbox \
  --type cidr \
  --value ${FRITZBOX_NETWORK}
 
# Create connection
openstack vpn ipsec site connection create vpn_connection_1 \
  --vpnservice vpn_service_1 \
  --ikepolicy vpn_ike_1 \
  --ipsecpolicy vpn_ipsec_1 \
  --peer-address ${FRITZBOX_EXTERNAL_IP} \
  --peer-id ${FRITZBOX_EXTERNAL_IP} \
  --psk ${PASSWORD} \
  --local-endpoint-group vpn_endpoint_openstack \
  --peer-endpoint-group vpn_endpoint_fritzbox

Define variables for Frtizbox VPN configuration

FRITZBOX_NETWORK_CIDR=${FRITZBOX_NETWORK%/*}
FRITZBOX_NETWORK_NETMASK=255.255.255.0
OPENSTACK_EXTERNAL_VPN_IP=$(openstack vpn service show -c external_v4_ip -f value vpn_service_1)
OPENSTACK_SUBNET_CIDR=$(openstack subnet show ${OPENSTACK_SUBNET_ID} -c cidr -f value | cut -d"/" -f1)
OPENSTACK_SUBNET_NETMASK=255.255.255.0

Create Frtizbox IPSec configuration

cat<<EOF> openstack_fritzbox_vpn.conf
vpncfg {
        connections {
                enabled = yes;
                editable = yes;
                use_ikev2 = no;
                conn_type = conntype_lan;
                name = "OpenStack Fritzbox VPN";
                boxuser_id = 0;
                always_renew = yes;
                reject_not_encrypted = no;
                dont_filter_netbios = no;
                localip = ::;
                remoteip = ${OPENSTACK_EXTERNAL_VPN_IP};
                local_virtualip_v4 = 0.0.0.0;
                local_virtualip_v6 = ::;
                remote_virtualip_v4 = 0.0.0.0;
                remote_virtualip_v6 = ::;
                keepalive_ip = 0.0.0.0;
                localid {
                        ipaddr = ${FRITZBOX_EXTERNAL_IP};
                }
                remoteid {
                        ipaddr = ${OPENSTACK_EXTERNAL_VPN_IP};
                }
                mode = phase1_mode_idp;
                phase1ss = "all/all/all";
                keytype = connkeytype_pre_shared;
                key = "${PASSWORD}";
                cert_do_server_auth = no;
                use_nat_t = no;
                use_xauth = no;
                use_cfgmode = no;
                phase2localid {
                        ipnet {
                                ipaddr = ${FRITZBOX_NETWORK_CIDR};
                                mask = ${FRITZBOX_NETWORK_NETMASK};
                        }
                }
                phase2remoteid {
                        ipnet {
                                ipaddr = ${OPENSTACK_SUBNET_CIDR};
                                mask = ${OPENSTACK_SUBNET_NETMASK};
                        }
                }
                phase2ss = "esp-all-all/ah-none/comp-all/pfs";
                accesslist = "permit ip any ${OPENSTACK_SUBNET_CIDR} ${OPENSTACK_SUBNET_NETMASK}";
                app_id = 0;
                wg_persistent_keepalive = 0;
                wg_slave_network_4v = 0.0.0.0;
                wg_slave_mask_4v = 0.0.0.0;
                wg_slave_network_6v = ::;
                wg_slave_prefixlen_6v = 0;
                wg_hide_network = no;
                wg_fulltunnel = no;
                wg_configured = no;
        }
}
EOF
 
cat openstack_fritzbox_vpn.conf

Import Frtizbox IPSec configuration

Internet > Freigaben > VPN (IPSec) > VPN-Verbindung hinzufügen
Eine VPN-Konfiguration aus einer VPN-Einstellungsdatei importieren.
Weiter
Datei auswählen: openstack_fritzbox_vpn.conf
Übernehmen
<Verify with a button on the Fritzbox>
OK
OK

Allow PING from VPN

openstack security group rule create default 
  --protocol icmp \
  --remote-ip 0.0.0.0/0

Allow SSH access from VPN

openstack security group rule create default \
  --protocol tcp \
  --dst-port 22 \
  --remote-ip 192.168.178.0/24

old: AVM VPN import

vpncfg {
        connections {
                enabled = yes;
                conn_type = conntype_lan;
                name = "Fritzbox to OpenStack VPNaaS";
                always_renew = yes;
                reject_not_encrypted = no;
                dont_filter_netbios = yes;
                localip = 0.0.0.0;
                local_virtualip = 0.0.0.0;
                remoteip = ${VPN_SERVER_IP};
                remote_virtualip = 0.0.0.0;
                localid {
                        ipaddr = ${FRITZBOX_WAN_IP};
                }
                remoteid {
                        ipaddr = ${VPN_SERVER_EXTERNAL_IP};
                }
                mode = phase1_mode_idp;
                phase1ss = "all/all/all";
                keytype = connkeytype_pre_shared;
                key = "${PSK}";
                cert_do_server_auth = no;
                use_nat_t = yes;
                use_xauth = no;
                use_cfgmode = no;
                phase2localid {
                        ipnet {
                                ipaddr = 192.168.178.0;
                                mask = 255.255.255.0;
                        }
                }
                phase2remoteid {
                        ipnet {
                                ipaddr = 10.0.1.0;
                                mask = 255.255.255.0;
                        }
                }
                phase2ss = "esp-all-all/ah-none/comp-all/pfs";
                accesslist = "permit ip any 10.0.1.0 255.255.255.0";
        }
        ike_forward_rules = "udp 0.0.0.0:500 0.0.0.0:500", 
                            "udp 0.0.0.0:4500 0.0.0.0:4500";
}

Create S2S VPN connection on Fritz!Box
Broken since Fritz!Box UI does not provide option to set phase1 mode to main

Fritz!Box Admin
Internet > Freigaben > VPN (IPSec)
VPN-Verbindung hinzufügen
Ihr Heimnetz mit einem anderen FRITZ!Box-Netzwerk verbinden (LAN-LAN-Kopplung)
VPN-Kennwort (Preshared Key): <psk>
Internet-Adresse: OpenStack VPN Services IPv4

Delete OpenStack VPNaaS

PROJECT_ID=xxxxxxxxxxxxxx
 
openstack vpn ipsec site connection list --long | grep ${PROJECT_ID}
openstack vpn ipsec site connection delete ${IPSEC_SITE_CONNECTION_ID}
 
openstack vpn endpoint group list --long | grep ${PROJECT_ID}
openstack vpn endpoint group delete ${VPN_ENDPOINT_CIDR_GROUP_ID} ${VPN_ENDPOINT_SUBNET_GROUP_ID}
 
openstack vpn service list --long | grep ${PROJECT_ID}
openstack vpn service delete ${VPN_SERVICE_ID}
 
openstack vpn ipsec policy list --long | grep ${PROJECT_ID}
openstack vpn ipsec policy delete ${VPN_IPSEC_POLICY_ID}
 
openstack vpn ike policy list --long | grep ${PROJECT_ID}
openstack vpn ike policy delete ${VPN_IKE_POLICY_ID}

Links
https://docs.openstack.org/python-neutronclient/latest/cli/osc/v2/vpn-ipsec-site-connection.html
https://docs.openstack.org/neutron/rocky/admin/vpnaas-scenario.html
https://hit-systemhaus.net/2015/12/01/securepoint-ipsec-vpn-zu-avm-fritzbox/
https://docs.openstack.org/neutron/rocky/admin/vpnaas-scenario.html
https://mlohr.com/fritzbox-lan-2-lan-vpn-with-pfsense/
https://docs.netgate.com/pfsense/en/latest/troubleshooting/ipsec.html
https://wiki.securepoint.de/UTM/IPSec_-_Fritzbox