PF PF rule "route-to" syntax error

Hi,

Hope all are doing well.

I am trying to set up a HTTPS traffic alone route to another machine ip instead of default route .

So I am trying the "route-to" option in PF.
Code:
lan_net="172.20.0.0/16"
int_if="vtnet0"
ext_gw="172.20.133.221"

block in
block out
pass in on $int_if proto tcp from $lan_net to port https route-to $ext_gw
It's not working and getting syntax errors.

Please help me on this.
 
It would be very helpful to have the actual syntax error reported.

If I'm reading pf.conf(5) correctly, route-to needs an interface name in parentheses on Freebsd:
routehost = "(" interface-name [ address [ "/" mask-bits ] ] ")"

You're giving it an address. What are you trying to do?
 
I am trying to set up a HTTPS traffic alone route to another machine ip instead of default route .
Rule of thumb, a firewall is not a router. So don't try to route with PF. Use route(8) for that. You can add routes to specific address:
route add 1.2.3.4/32 1.1.1.1
Traffic destined for 1.2.3.4/32 will be sent to 1.1.1.1 for further routing.


If I'm reading pf.conf(5) correctly, route-to needs an interface name in parentheses on FreeBSD
Yes, the address (or address plus CIDR mask) is optional, the interface and parentheses are mandatory.
 
It would be very helpful to have the actual syntax error reported.

If I'm reading pf.conf(5) correctly, route-to needs an interface name in parentheses on Freebsd:


You're giving it an address. What are you trying to do?
Sorry, I am not familiar in PF.

Actually In Linux ,

/sbin/iptables -t nat -A PREROUTING -p tcp --dport 443 -m tos --tos 0x08 -j CONNMARK --set-mark 1
/sbin/iptables -t mangle -A OUTPUT -p tcp --sport 443 -m connmark --mark 1 -j MARK --set-mark 1

ip rule add fwmark 1 table test
ip route add default via 192.168.0.1 table test
How can I do that on FreeBSD?
 
From what I get from pf.conf() I'd try:
Code:
pass in on $int_if route-to ($ext_gw) proto tcp port https from $lan_net

And yes, please also post the error message when you have tried.
 
From what I get from pf.conf() I'd try:
Code:
pass in on $int_if route-to ($ext_gw) proto tcp port https from $lan_net

And yes, please also post the error message when you have tried.
I am getting syntax error only.

Now i am trying another one command to route the outgoing https traffic to next remote machine using bellow comman,

pass in on egress proto tcp from any to any port 443 rdr-to "remote machine ip "

But it's also getting syntax error . Pls help me on this
 
PF is hard to figure out and FreeBSD has a very specific and weird version of it that is missing features found elsewhere. Somehow this isn't seen as a very pressing problem to solve.

for rdr-to, try specifying an interface identifier instead of "any" for the "to" section and also specify the port after the remote machine IP
 
Unless you do not copy-paste the errors here. I'm not willing to do.
Yeah, I'm going to need the exact error(s) you are experiencing and your entire rule set copy pasted into a code block before I spend any more time on this.
 
Yeah, I'm going to need the exact error(s) you are experiencing and your entire rule set copy pasted into a code block before I spend any more time on this.
root@:~ # cat /etc/pf.conf
block all
pass in on egress proto tcp from any to any port 443 rdr-to 172.20.133.221
root@:~ #
root@:~ # service pf check
Checking pf rules.
/etc/pf.conf:2: syntax error
root@:~ #
 
I think for the use cases you're describing net/haproxy is much more suitable. I made very good experiences with it.
Hi, I am trying to test LVS NAT mode with freebsd real server,

For that I want to make an L3 host as a default gateway for outgoing traffic on specific port (Policy Based Routing) eg. 443. in FreeBSD.

I am not getting any solution on this,So please anybody help to me .
 
Progress, but please look into using code tags.

You've got the syntax of redirection rules backwards. It's rdr pass..., not pass...rdr-to. Look at the syntax definition in the pf.conf(5) man page.
Code:
rdr-rule        = [    "no" ] "rdr" [ "pass" [    "log" [    "(" logopts ")"    ] ] ]
              [    "on" ifspec ] [    af ]
              [    protospec ] hosts [ "tag" string ] [ "tagged" string ]
              [    "->" ( redirhost | "{" redirhost-list "}" )
              [    portspec ] [ pooltype ]    ]

Note that you'll also need an arrow (->) in the redirection rule. There are clear examples in the man page:
rdr on $ext_if inet proto udp from any to ($ext_if) port 8080 -> 10.1.2.151 port 53

There is no egress keyword in Freebsd pf. Stop looking at the Openbsd pf documentation. Openbsd's version has diverged significantly from the Freebsd version.

The Handbook has an example of exactly what you're trying to accomplish:
A common practice is to have a publically accessible web server or mail server segregated to an internal network segment. The traffic from these servers still has to undergo NAT, but port redirection is needed to direct inbound traffic to the correct server. For example, to map a web server using the internal address 10.0.10.25 to its public IP address of 20.20.20.5, use this rule:
rdr dc0 20.20.20.5/32 port 80 -> 10.0.10.25 port 80 Edit: the Handbook is wrong here! Someone file a doc bug. It should be rdr on dc0 from any to 20.20.20.5/32 port 80 -> 10.0.10.25 port 80
 
T
Progress, but please look into using code tags.

You've got the syntax of redirection rules backwards. It's rdr pass..., not pass...rdr-to. Look at the syntax definition in the pf.conf(5) man page.
Code:
rdr-rule        = [    "no" ] "rdr" [ "pass" [    "log" [    "(" logopts ")"    ] ] ]
              [    "on" ifspec ] [    af ]
              [    protospec ] hosts [ "tag" string ] [ "tagged" string ]
              [    "->" ( redirhost | "{" redirhost-list "}" )
              [    portspec ] [ pooltype ]    ]

Note that you'll also need an arrow (->) in the redirection rule. There are clear examples in the man page:


There is no egress keyword in Freebsd pf. Stop looking at the Openbsd pf documentation. Openbsd's version has diverged significantly from the Freebsd version.

The Handbook has an example of exactly what you're trying to accomplish:
Thanks for your prompt reply. I will check
 
Progress, but please look into using code tags.

You've got the syntax of redirection rules backwards. It's rdr pass..., not pass...rdr-to. Look at the syntax definition in the pf.conf(5) man page.
Code:
rdr-rule        = [    "no" ] "rdr" [ "pass" [    "log" [    "(" logopts ")"    ] ] ]
              [    "on" ifspec ] [    af ]
              [    protospec ] hosts [ "tag" string ] [ "tagged" string ]
              [    "->" ( redirhost | "{" redirhost-list "}" )
              [    portspec ] [ pooltype ]    ]

Note that you'll also need an arrow (->) in the redirection rule. There are clear examples in the man page:


There is no egress keyword in Freebsd pf. Stop looking at the Openbsd pf documentation. Openbsd's version has diverged significantly from the Freebsd version.

The Handbook has an example of exactly what you're trying to accomplish:
I am trying below ,
Code:
root@:~ # cat /etc/pf.conf 
rdr vtnet0 0.0.0.0/0 port 443 -> 172.20.133.221 port 443 
root@:~ # service pf check
Checking pf rules.
/etc/pf.conf:1: syntax error
root@:~ #
Sorry, what i have missed here , why it's throws error ?
 
Code:
rdr on vtnet0 ...

Code:
     rdr-rule       = [ "no" ] "rdr" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
                      [ "on" ifspec ] [ af ]
                      [ protospec ] hosts [ "tag" string ] [ "tagged" string ]
                      [ "->" ( redirhost | "{" redirhost-list "}" )
                      [ portspec ] [ pooltype ] ]
You really need to learn how to read those syntax rules.
 
Apologies on giving you bad information. The example from the Handbook is wrong. I've corrected it inline in my previous post.
Sorry, what i have missed here , why it's throws error ?
Does rdr vtnet0 0.0.0.0/0 port 443 match the syntax definition "rdr"[ "pass" ] ["on" ifspec]? Text in quotes has to appear exactly as written in the rule. Anything between square brackets ([]) is optional.

Look again at an example from the man page
Code:
rdr pass on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 port 8080

Do you see how rdr pass on $ext_if matches this part "rdr" [ "pass" ] [ "on" ifspec ]
of the rdr rule syntax? (Optional bits elided for clarity).

And how proto tcp matches protospec?
Code:
protospec = "proto" ( proto-name | proto-number | "{" proto-list "}" )
The vertical bar | means "exclusive or". You can have exactly one of proto-name, proto-number, or "{" proto-list "}".
 
Code:
rdr on vtnet0 ...

Code:
     rdr-rule       = [ "no" ] "rdr" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
                      [ "on" ifspec ] [ af ]
                      [ protospec ] hosts [ "tag" string ] [ "tagged" string ]
                      [ "->" ( redirhost | "{" redirhost-list "}" )
                      [ portspec ] [ pooltype ] ]
You really need to learn how to read those syntax rules.
Turns out there's a bug in the man page too. Reading that rule suggests that this should be a valid pf.conf
Code:
rdr all
But that does not parse
Code:
pfctl -vnf foo.pf                                         
foo.pf:1: translation rule requires '-> address'
There should not be brackets around this part of the rule
Code:
[ "->" ( redirhost | "{" redirhost-list "}" ) [ portspec ] [ pooltype ] ]
 
Meet the same issue, but sad to say, the route-to never implement in FreeBSD, the patch of route-to only available in pfsense.
Original patch (many fix after that)

To set nexhop of packet, try this:
1. add new route table, then assign id in ipfw
Code:
# example
ipfw add 1007 setfib 1 ip from table(local_nodes) to any in via eth0

2. add fwd rule in ipfw, (Note this will drop packet direct to ethernet, so nat should before this)
Code:
# example
ipfw add 2003 fwd 192.168.192.11 ip from 192.168.192.0/24{100-120} to not 192.168.192.0/24{90-120}

The both rules were currently I using, so I believe it could works.
 
For singe port/service forwards use 'rdr':
pf.conf(5)
Code:
     rdr   The packet is redirected to another destination and possibly a
           different port.  rdr rules can optionally specify port ranges
           instead of single ports.  rdr ... port 2000:2999 -> ... port 4000
           redirects ports 2000 to 2999 (inclusive) to port 4000.  rdr ...
           port 2000:2999 -> ... port 4000:* redirects port 2000 to 4000, 2001
           to 4001, ..., 2999 to 4999.

The host that receives the forwarded traffic of course still needs to have the proper routes in place to send out reply traffic.


'route-to' should _never_ be used for actual routing, as the replies won't be affected by the rule. This will lead to very weird and almost non-debuggable asymmetric routing problems and should only be used for *very* special and temporary use cases (e.g. during transitions of IPs/hosts).
 
Back
Top