IPSec VPN via IPv6 | No traffic

I want to connect with a client device (iOS) to my router (OS 7.15.3, model C53UiG+5HPaxD2HPaxD) using IPSec VPN, config below.
LAN is 172.16.1.0/24, VPN is 172.16.2.0/24.
The router has two public IP addresses, one IPv4, the other IPv6.

When I connect to the public IPv4 address, everything works perfectly fine - I can access internal resources without issue.

When I connect to the public IPv6 address, I see that the Security Association establishes, and the IPSec tunnel is up.
However, there is no traffic going to devices on the LAN, either using internal IPv4, or using internal IPv6 addresses.
The client is assigned an IPv4 address in the 172.16.2.0/24 range even when connecting via the IPv6 public address, and I would expect traffic to flow just as it does when connected to the IPv4 public address.

Here is the configuration I used to create the tunnel.

# Create CA certificate and sign it
/certificate add name="Router_CA" common-name="Router_CA" key-size=4096 days-valid=365 key-usage=key-cert-sign,crl-sign
/certificate sign "Router_CA"
/certificate set Router_CA trusted=yes

# Create server certificate and sign it 
/certificate add name="Router_certificate" common-name="router.fqdn.com" subject-alt-name="DNS:router.fqdn.com" key-size=4096 days-valid=180 key-usage=tls-server
/certificate sign "Router_certificate" ca="Router_CA"
/certificate set Router_certificate trusted=yes

# Create client certificate, sign it and export it as PKCS12 keystore (contains client certificate, client private key and CA)
# ## Needs subject-alt-name for iOS!
/certificate add name="client_device" common-name="client_device.fqdn.com" subject-alt-name="DNS:client_device.fqdn.com" key-size=4096 days-valid=180 key-usage=tls-client
/certificate sign "client_device" ca="Router_CA"
/certificate export-certificate "client_device" file-name="client_device" type=pkcs12 export-passphrase=1234567890

# Create IP pool for VPN users
/ip pool add name=vpn ranges=172.16.2.0/24

# Add firewall rules for IKE2 VPN
/ip firewall filter add action=accept chain=input comment="Allow IPSEC/IKE2 connections" dst-port=500,4500 protocol=udp
/ip firewall filter add action=accept chain=forward comment="Accept in ipsec policy" ipsec-policy=in,ipsec
/ip firewall filter add action=accept chain=forward comment="Accept out ipsec policy" ipsec-policy=out,ipsec
# Alow access to router from "172.16.2.1-172.16.2.254" IPs and masquerade traffic coming from VPN clients, so devices on your LAN sees that traffic is coming from the router IP rather than VPN IP
/ip firewall address-list add address=172.16.2.0/24 comment=VPN list=allowed_to_router
/ip firewall nat add action=masquerade chain=srcnat comment="Masquerade VPN traffic so devices see connections made from router IP" src-address=172.16.2.0/24

# Configure IPSEC settings 
/ip ipsec mode-config add address-pool=vpn name=vpn
/ip ipsec policy group add name=vpn
/ip ipsec profile add dh-group=ecp256,ecp384,ecp521 enc-algorithm=aes-256 hash-algorithm=sha256 name=vpn
/ip ipsec peer add exchange-mode=ike2 name=vpn passive=yes profile=vpn send-initial-contact=no
/ip ipsec proposal add auth-algorithms=sha256 enc-algorithms=aes-256-cbc,chacha20poly1305 lifetime=1h name=vpn pfs-group=ecp521
/ip ipsec identity add auth-method=digital-signature certificate="Router_certificate" comment="client_device" generate-policy=port-strict match-by=certificate mode-config=vpn peer=vpn policy-template-group=vpn remote-certificate="client_device"
/ip ipsec policy add dst-address=0.0.0.0/0 group=vpn proposal=vpn src-address=0.0.0.0/0 template=yes

# To address possible disconnects with iOS (not used)
#/ip firewall mangle add action=change-mss chain=forward comment="Fix MSS for VPN server" new-mss=1360 passthrough=yes protocol=tcp src-address=172.16.2.0/24 tcp-flags=syn tcp-mss=!0-1360
#/ip firewall mangle add action=change-mss chain=forward comment="Fix MSS for VPN server" dst-address=172.16.2.0/24 new-mss=1360 passthrough=yes protocol=tcp tcp-flags=syn tcp-mss=!0-1360

# Addresses
/ip pool add name=dhcp ranges=172.16.1.100-172.16.1.250
/ip pool add name=vpn ranges=172.16.2.0/24

# Firewall IPv4
/ip firewall filter add action=accept chain=input comment="Allow IPSEC/IKE2 connections" disabled=no dst-port=500,4500 protocol=udp
/ip firewall filter add action=accept chain=forward comment="defconf: accept in ipsec policy" disabled=no ipsec-policy=in,ipsec
/ip firewall filter add action=accept chain=forward comment="defconf: accept out ipsec policy" disabled=no ipsec-policy=out,ipsec
/ip firewall filter add action=masquerade chain=srcnat comment="defconf: masquerade" ipsec-policy=out,none out-interface-list=WAN !to-addresses !to-ports
/ip firewall filter add action=masquerade chain=srcnat comment="Masquerade VPN traffic so devices see connections made from router IP" !connection-bytes !connection-limit !connection-mark !connection-rate \
    !connection-type !content disabled=no !dscp !dst-address !dst-address-list !dst-address-type !dst-limit !fragment !in-bridge-port !in-bridge-port-list !in-interface \
    !in-interface-list !ingress-priority !ipsec-policy !ipv4-options !layer7-protocol !limit log=no log-prefix="" !nth !out-bridge-port !out-bridge-port-list !out-interface \
    !out-interface-list !packet-mark !packet-size !per-connection-classifier !priority !protocol !psd !random !routing-mark src-address=172.16.2.0/24 !src-address-list \
    !src-address-type !src-mac-address !time !to-addresses !to-ports !ttl

# Firewall IPv6
/ipv6 firewall filter add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 protocol=udp
/ipv6 firewall filter add action=accept chain=input comment="defconf: accept ipsec AH" protocol=ipsec-ah
/ipv6 firewall filter add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=ipsec-esp
/ipv6 firewall filter add action=accept chain=input comment="defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
/ipv6 firewall filter add action=accept chain=forward comment="defconf: accept IKE" dst-port=500,4500 protocol=udp
/ipv6 firewall filter add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=ipsec-ah
/ipv6 firewall filter add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=ipsec-esp
/ipv6 firewall filter add action=accept chain=forward comment="defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec

#Logging
/system logging add topics=ipsec,!packet
/log print follow-only file=ipsec-start where topics~"ipsec"

I expect to lose the public IPv4 soon because my carrier is rolling out CGNAT.
What changes do I need to make so I can access resources on the LAN when connecting to the public IPv6 address?

You would need to add an IPv6 loopback address, use an IPv6 pool for the mode-config or use static addressing, add an IPv6 IPsec policy and use IPv6 LAN addresses to access resources.

Please refer to the following topic:

http://forum.mikrotik.com/t/vpn-gateway-ikev2-roadwarriors-and-ipv6/173511/1

Thanks for the response.
The solution in the link doesn’t really achieve what I want, as it addresses the LAN side with IPv6 addresses.
This would require a lot of overhead, such as moving from stateless to stateful addressing and setting up DNS (since the prefix may change).

It should be possible to configure unicast routing between the IPv6 WAN interface and the IPv4 LAN interface.
Where I get stuck is that the IPSec tunnel (unlike Wireguard for example) isn’t its own interface.
Does anybody know how to do that?

I since found a similar question was asked here http://forum.mikrotik.com/t/ipv4-over-ipv6-tunnel/132600/1 without resolution.

AFAIK in principle it should work.

I think the issue might be a mismatch of traffic policies: they are expresses via IPv4 masks in RouterOS config, but actual addresses in SA are IPv6. Or it might be limitations of the legacy mode-config configuration (iOS really wants proper IKEv2 and RouterOS does not support that). Unfortunately I do not have a testbed to verify this hunch and both RouterOS and iOS are not great for IPsec debugging. Did you check if any ticker at /ip/ipsec/staticics grows?

My advice would be to make it work with a more pliable client first (e.g. strongswan).