ipfw fwd not forwarding correctly

From: Steven <steven_at_bsd-ipfw.sdwmail.org>
Date: Sun, 28 Aug 2022 16:56:43 UTC
SUMMARY:   Incoming connections do not forward initial [SYN, ACK] packet  on 
incoming connections to the tunnel device.   The very final [ACK] after a tcp 
session close is also not forwarded to the tunnel device.   This is according 
to the ipfw fwd rule.  Instead, certain packet gets forwarded to the default 
route out my ethernet nic, re0, even with a matching ipfw fwd rule hit.
This has an effect of not allowing incoming connections and incorrect  tcp 
transmission behavior on outgoing connections.

using:
FreeBSD steven13.1-RELEASE-p1 FreeBSD 13.1-RELEASE-p1 GENERIC amd64

I have set up a VPN tunnel using interface tun1.
The test tcp seesion is (a) an outgoing ssh session (binding to the local tun1 
IP) as well as (b) an incoming ssh session  back to the tun1 IP port 22.

tun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500
        options=80000<LINKSTATE>
        inet 192.121.246.12 --> 192.121.246.1 netmask 0xffffffc0
        groups: tun
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

Internet:
Destination        Gateway            Flags     Netif Expire
default            10.2.2.1           UGS         re0
10.2.2.0/23        link#1             U           re0
10.2.2.2           link#1             UHS         lo0
192.121.246.0/26   192.121.246.1      UGS        tun1
192.121.246.1      link#5             UH         tun1
192.121.246.12     link#5             UHS         lo0

ipfw rules:
48000      6       402 fwd 192.121.246.1 ip from 192.121.246.12 22 to any out 
xmit tun1
48500     30      1800 fwd 192.121.246.1 ip from 192.121.246.12 22 to any out 
xmit re0
49000    133      7980 fwd 192.121.246.1 ip from 192.121.246.12 22 to any out
50000   6921   4255710 fwd 192.121.246.1 ip from 192.121.246.0/26 to any out

[Initially I started with rule 50000 but made more specific rules to see where 
it gets "hit"]

Now, if I add the "VPN bypass" routes:
route add -net 0.0.0.0/1 192.121.246.1
route add -net 128.0.0.0/1 192.121.246.1

when I telnet back to my hose from the outside:  telnet 192.121.246.12 22
All will work fine.   In this case, rule 48000 will be hit

Otherwise, the default route will be used and sent through 10.2.2.2, re0 and 
ipfw rule 48500 will be hit.

Furthermore, without the "VPN bypass" routes and just the default route,
a normal outgoing tcp session will work fine  until  the very end.   Initially 
all packets will be sent and received through the tunnel interface and hit on 
the ipfw fwd rule.  However, the very last packet, on tcp close, will be sent 
through the default route, re0 instead.

sent through tun1:
49      18.123367       192.121.246.12  128.200.85.17   TCP     56      
24761 → 22 [FIN, ACK] Seq=4583 Ack=4950 Win=66496 Len=0 TSval=3821441136 
TSecr=2539456840
50      18.216585       128.200.85.17   192.121.246.12  TCP     56      
22 → 24761 [ACK] Seq=4950 Ack=4583 Win=33408 Len=0 TSval=2539456938 
TSecr=3821441136
51      18.218972       128.200.85.17   192.121.246.12  TCP     56      
22 → 24761 [FIN, ACK] Seq=4950 Ack=4584 Win=33408 Len=0 TSval=2539456940 
TSecr=3821441136
last [ACK] packet, after the above sequence, sent through re0:
1       0.000000        192.121.246.12  128.200.85.17   TCP     70      
53986 → 22 [ACK] Seq=1 Ack=1 Win=1038 Len=0 TSval=3860450619 TSecr=2539249268

The above seems to be proof that something is awry.  Why would all the 
incoming and outgoing packets, with the same source IP,source port and dest 
IP,dest port go through the proper interface, tun1, but then the very last 
[ACK] packet go someplace else?

The manpage states,
             If ipaddr is not a local address, then the port number (if
             specified) is ignored, and the packet will be forwarded to the
             remote address, using the route as found in the local routing
             table for that IP.
The ipfw fwd rule is being hit, it suppose to be forwarded to 192.121.246.1, 
the "192.121.246.1      link#5             UH         tun1"  route entry 
should apply and be sent to tun1 instead of re0 default.

I just started using ipfw, so maybe I have overlooked something.   But after 
capturing packets and seeing the irregular behaviour I think something may be 
wrong.   Please let me know if I have overlooked something.

Steven