IPSEC problems with pf

From: Peter Jeremy <peter_at_rulingia.com>
Date: Fri, 24 Sep 2021 23:03:06 UTC
I'm trying to setup an IPSEC transport connection between my home and
one of my VPS hosts.  I can successfully setup an IPv6 connection from
an internal host to the VPS but can't setup an IPv4 connection from my
firewall to that host.  I'm using openiked-portable in esp transport
mode using psk (at least for testing).
 
My configuration (much simplified) looks like:
Host ---- firewall ---- (internet) ---- VPS
 
'Host' has a public IPv6 address and I can successfully setup an IPSEC
transport connection between it and 'VPS'.
 
IPSEC doesn't work through NAT so I have setup an IPv4 IPSEC transport
layer from firewall to VPS.  The iked processes can exchange isakmp
packets and appear to setup the connection.  Running tcpdump on both
ends, I see:
* "ping VPS" from firewall sends ICMP packets in the clear.  They arrive
  at VPS but there's no response.
* "ping firewall" from VPS sends IPSEC esp packets which arrive at
  firewall but there's no response.

Comparing the pf configurations between firewall and VPS, the main
difference is that the firewall is configured to NAT internal hosts
onto the Internet and RDR some inbound ports to internal hosts.  I
am logging blocked packets so I'm confident that pf is not blocking
the esp packets.

I've tried enabling net.inet.ipsec.debug and that generates occasional
message like "kernel: key_acqdone: ACQ 19 is not found." but that
hasn't helped me solve the problem.

I don't understand:
a) Why outgoing ICMP packets from firewall to VPS aren't going through
   the IPSEC transport.
b) Why firewall is ignoring incoming IPSEC esp packets.

Is anyone able to help?

-- 
Peter Jeremy