Different gateway for specific TCP ports

You may find this trivial, but I'm not an expert in packet filtering.
What's the best way to use a different gateway for an email client's traffic from a bhyve VM (see below)?
In particular, IMAP (993) and SMTP (587) are blocked on the LAN, so, the corresponding traffic should go through Wireguard VPN (WG).
Code:
           -----------      -----------
           |         |      |         |
LAN -------| FreeBSD | NAT  |  Win10  |
           |  host   |------|  bhyve  |
     WG ---|         |      |  VM     |
           |         |      |         |
           -----------      -----------
Thanks for advises!
 
Don't know if this will work but something like these pf rules might help in the right direction:

Code:
fbsd_eth = "re0"
win10 = "a.b.c.d"
wg_far_end = "w.x.y.z"
mail = "{ 587, 993 }"

scrub on wg0 max-mss 1380
nat on wg0 from $win10 to any -> (wg0)
pass in quick on $fbsd_eth route-to (wg0 $wg_far_end) from $win10 to any port $mail
 
Thanks kjeacle !
The rule:
Code:
nat on wg0 from $win10 to any -> (wg0)
has no effect, maybe becaus I already have:
Code:
nat on $fbsd_eth from $win10_if to any -> ($fbsd_eth)
Instead I tried:
Code:
rdr pass on $win10_if proto tcp to any port 993 -> $wg_far_end port 993
and packets are forwarded to WG server, but do not reach it: tcpdump() doesn't catch anything.
I don't understand how it's possible.
 
My rules assume that the traffic from Win10 has come through the FreeBSD host with its original IP address intact. The host has gateway_enable="YES" and the pass line forwards the traffic to the Wireguard tunnel. Finally, on the way out, the nat line translates the original Win10 IP to the IP used on the tunnel.

In your case, perhaps you are NATing to the FreeBSD host address before it reaches the tunnel so tcpdump never finds the Win10 IP address?

Can't remember why I used pass instead of rdr but it worked for me in the end.
 
My rules assume that the traffic from Win10 has come through the FreeBSD host with its original IP address intact. The host has gateway_enable="YES"
That's correct.

nat line translates the original Win10 IP to the IP used on the tunnel.
Here my point is that can I have two nat lines for the same network?
Code:
nat on wg0 from $win10 to any -> (wg0)
nat on $fbsd_eth from $win10_if to any -> ($fbsd_eth)
For all other traffic from Win10 to WAN and LAN I do need NAT on the regular external interface.
 
I haven't configured this with pf but I don't see a problem. If you have two external interfaces then you should be able to apply different nat rules for traffic going out each interface. In my case, I have a physically separate device on the LAN that comes in on the FreeBSD ethernet port and goes out the Wireguard tunnel. In your case, the bhyve VM is presumably on the FreeBSD host so that needs to be handled differently. I would focus on getting the packets routing correctly first and then worry about the nat i.e. tcpdump should show your Win10 traffic going out on wg0 with its original IP address - obviously it will be dropped but then you can work on the nat rule to fix.
 
Back
Top