PF Tunnel from VPS to jail + multi-home

I'm using FreeBSD 15 and have a VPS with two public interfaces. One for VPS-hosted services and one that I want to use to forward traffic to a jail running elsewhere. There's also a wireguard tunnel to a jail. (I'm using two interfaces because I want to use the VPS as a backup MX, its own SSH, etc. and also use it to forward over the tunnel to my mail server, its own SSH, etc.)

I have the multi-home jail working. It has these relevant PF rules where $wg is the wireguard tunnel:

Code:
wg_net = $wg:network

otel_tcp_port = "{ 4318, 14318 }"

# wg
block in log on $wg
pass from { self, $wg_net } to any keep state
pass in on $wg reply-to ( $wg 10.1.1.1 ) proto tcp to port $otel_tcp_port keep state

The wireguard tunnel has Table = off and AllowedIPs = 0.0.0.0/0 so the default route for the jail is to vnet0.

Tunneled traffic for port 4138 fully works, traffic for port 14318 tries its best (SYN → SYN/ACK).

My problem is on the VPS, I can't get replies from the tunnel port 14318 to be sent out on the correct interface.

For the VPS rules I have $ext_if and $ext_addr for the VPS-hosted services, $fwd_if and $fwd_addr for forwarded services, $wg for the wireguard tunnel.

I've trimmed the rules to just the ones that seem relevant to my problem:

Code:
wg_net = $wg:network

otel_host = "10.1.1.100"

set block-policy return
set fail-policy return
set reassemble yes
set skip on lo

# block
block log all

# all interfaces
pass from { self, $wg_net } to any keep state

# fwd_if
pass out log on $fwd_if inet proto tcp from ! ( $fwd_if ) to any nat-to ( $fwd_if )
pass in log on $fwd_if inet proto tcp from any to port 14318 rdr-to $otel_host port 14318

# wg
pass in log on $wg reply-to ( $fwd_if $otel_host ) proto tcp to $otel_host port 14318 keep state
pass out log on $wg proto tcp to $otel_host port 14318 keep state

With the above rules packets returning from the tunnel are sent out on $ext_if, not $fwd_if due to $ext_if being the default route. I used $otel_host in reply-to hoping that the packet will be processed by nat-to but that's not matching (I've tried variations of the reply-to and nat-to rules as well).

Instead of the final rule I've also tried this:

Code:
pass out log on $wg reply-to ( $fwd_if $fwd_addr ) proto tcp to $otel_host port 14318 keep state

But with this rule returning SYN/ACK packets are blocked per pflog:
Code:
rule 0/0(match): block in on $fwd_if: $fwd_addr.14318 > $laptop_public_addr.56904

Adding this rule changes nothing, the rule 0/0 (block log all) always wins

Code:
pass in log on $fwd_if inet proto tcp from any port 14318 to any

The combination of rdr-to and nat-to with reply-to on the VPS have me stumped
 
Back
Top