PF reply-to help

Currently I am using OpenVPN to redirect all my traffic and it works great! However, there are a few servers on the network and they require access to some ports on the WAN. Here is my current pf.conf, I am going to remove most of the rdr rules and just keep it simple.
Code:
# Variables and Macro
lan="igb1"
egress="igb0"
lan_ip="192.168.1.1"
egress_ip="192.168.0.2"
gateway="192.168.0.1"
webserver="192.168.1.8
vpn="tun0"

# Global Policy
set block-policy drop
set loginterface $egress
set skip on lo
scrub all no-df max-mss 1440 random-id reassemble tcp
scrub out on $egress proto udp from $egress_ip to any port 443 set-tos lowdelay

# NAT and RDR rules :
# 1 - only NAT trough the VPN connection. If the VPN is down, there is no Internet access for the LAN.
# 2 - catch DNS leaks from the LAN to the Internet and redirect them to our router
nat on $vpn from ($lan:network) to any -> ($vpn:0)
nat on $egress from ($lan:network) to any -> ($egress)
rdr on $lan proto { tcp udp } from $lan:network to ! $lan_ip port 53 -> $lan_ip

# Services
rdr pass on $egress inet proto tcp from any to ($egress) port 80 tag webserver -> $webserver port 443
rdr pass on $egress inet proto tcp from any to ($egress) port 443 tag webserver -> $webserver port 443

# Default deny and log all
block log all

# Antispoof
antispoof log quick for ($egress)
antispoof quick for ($lan)
block in quick log on $egress from { no-route urpf-failed } to any
block out quick log on $egress from any to no-route

# Block IPV6
block quick inet6 all

# Prevent VPN bypass
block out quick log on $egress from ($lan:network) to any

# Drop outbound DNS requests (53), as we use DNSCrypt
block out quick log on $egress proto { tcp udp } from any to any port 53

# Standard rules
pass out quick inet modulate state
pass in quick on $egress reply-to ( $egress $egress_ip ) tagged webserver keep state
pass in on $lan

This network is behind another router that is forwarding ports 80 and 443 to $egress_ip. pftop is showing that the reply-to rule is not being used at all when bringing up to the website.

I also have fibs=2 so using rtable 1 will work, however making a rule to use it does not seem to work well, or I'm not doing it properly.

Any help would be most appreciated!
 
I found a workaround and no longer need reply-to, but if someone wants to give some examples that would be great! :)
 
There was an explicit block on your ruleset preventing your setup from working with reply-to. Below is a fixed one:
Code:
# Variables and Macro
lan="igb1"
egress="igb0"
lan_ip="192.168.1.1"
egress_ip="192.168.0.2"
gateway="192.168.0.1"
webserver="192.168.1.8" ### there was a missing quote here
vpn="tun0"

table <lan_network> { $lan:network, !$webserver } ### this is needed to not block your webserver with the rule "prevent vpn bypass" below

# Global Policy
set block-policy drop
set loginterface $egress
set skip on lo
scrub all no-df max-mss 1440 random-id reassemble tcp
scrub out on $egress proto udp from $egress_ip to any port 443 set-tos lowdelay

# NAT and RDR rules :
# 1 - only NAT trough the VPN connection. If the VPN is down, there is no Internet access for the LAN.
# 2 - catch DNS leaks from the LAN to the Internet and redirect them to our router
nat on $vpn from <lan_network> to any -> ($vpn:0) ### rule modified a bit here
nat on $egress from $webserver to any -> $egress ### rule modified a bit here
rdr on $lan proto { tcp udp } from $lan:network to ! $lan_ip port 53 -> $lan_ip

# Services
rdr pass on $egress inet proto tcp from any to $egress port { 80 443 } tag webserver -> $webserver port 443

# Default deny and log all
block log all

# Antispoof
antispoof log quick for $egress
antispoof quick for $lan
block in quick log on $egress from { no-route urpf-failed } to any
block out quick log on $egress from any to no-route

# Block IPV6
block quick inet6 all

# Prevent VPN bypass
block out quick log on $egress from <lan_network> to any ### webserver will not be blocked

# Drop outbound DNS requests (53), as we use DNSCrypt
block out quick log on $egress proto { tcp udp } from any to any port 53

# Standard rules
pass out quick inet modulate state
pass in quick on $egress reply-to ( $egress $gateway ) tagged webserver keep state ### this rule was not correct, you have to specify both your local outbound interface and your gateway (isp router)
pass in on $lan

How does it behave with this ruleset?

Guillaume
 
  • Thanks
Reactions: Ult
Nope, that didn't work. I thought my first router forwarding to the second router would mean I need $egress_ip instead of $gateway but neither are not working.

I really should have made sure it was at error free before posting the pf.conf.
 
And if you up your reply-to rule just below your rdr rule, and modify them like this?
Code:
# Services
rdr on $egress inet proto tcp from any to $egress port { 80 443 } tag webserver -> $webserver port 443
pass in quick on $egress reply-to ( $egress $gateway ) tagged webserver keep state
If that is not working, what could make the setup easier would be making the web server listen on the $egress interface instead, removing the NAT for it and the redirect rule, and modifying the port forwarding on your ISP router to point to your web server's IP address. Only remain the reply-to would remain. I can rewrite the ruleset if needed.

Guillaume
 
  • Thanks
Reactions: Ult
Ah! that's what it was! Thank you so much for all your help Guillaume. I can't wait to get home and finish this up. My services seem to be kind of laggy using rtables 1 . I doubt it was meant for what I was using it for.
 
I successfully created a similar environment with a web server like you, listening on the $egress interface, and got it working with reply-to :) Below is the beginning of my ruleset:
Code:
lan="re0"
lan_ip="10.0.0.1"
egress_ip="192.168.1.2"
egress="re1"
gateway="192.168.1.1"
vpn="tun0"
jaildns="10.0.0.2"

webserver="192.168.1.3" ### I created a jail with Apache listening on the $egress interface

# Global Policy
set block-policy drop
set loginterface $egress
set skip on lo
scrub all no-df max-mss 1440 random-id reassemble tcp
scrub out on $egress proto udp from $egress_ip to any port 443 set-tos lowdelay

# NAT and RDR rules
nat on $vpn from $lan:network to any -> ($vpn:0)
nat on $vpn from $webserver to any -> ($vpn:0) ### this rule allows the webserver to access directly the Internet (i.e package install), it can be commented
rdr on $lan proto { tcp udp } from $lan:network to ! $jaildns port 53 -> $jaildns

# Webserver reply bypass VPN
pass in quick on $egress reply-to ( $egress $gateway ) proto tcp from any to $webserver port 80 keep state

I did a port forward on my ISP router from a high port such as 42984 to my web server on port 80, and I accessed it from a mobile phone successfully. I lost a lot of time because of a wrong syntax on the reply-to rule, I used a { character at first (splitting the rule in two) instead of (. I did not try it with a web server listening on the LAN interface, and using a redirect like you did however.

Guillaume
 
  • Thanks
Reactions: Ult
Yeah, I tried so many different syntaxes for it as well a couple days ago. Go figure it's because I had it in the wrong order the entire time. I didn't think it could be above the block section to be honest. The very first reply-to syntax I tried was correct ironically.
 
Back
Top