multiple rules fail

Hello,

I want to route my jails internal with pf like descriped in: http://forums.freebsd.org/showthread.php?t=30063

pf.conf
Code:
ext_if="em0"
#jail_if="lo111" #because no use in pf.conf

IP_PUB="192.168.178.10"

NET_JAIL="10.0.0.0/24"

IP_JAIL_WWW="10.0.0.1"
IP_JAIL_BUILD=[B]"[/B]10.0.0.2"

PORT_WWW="{80,443}"
PORT_BUILD=""

scrub in all

nat pass on $ext_if from $NET_JAIL to any -> $IP_PUB
                                        
rdr pass on $ext_if proto tcp from any to $IP_PUB port $PORT_WWW -> $IP_JAIL_WWW
rdr pass on $ext_if proto tcp from any to $IP_PUB port $PORT_BUILD -> $IP_JAIL_BUILD

pass out
pass in

fails with:
Code:
# /etc/rc.d/pf restart
Disabling pf.
Enabling pf/etc/pf.conf:19: syntax error
pfctl: Syntax error in config file: pf rules not loaded
.

When I remove the second rdr pass rule it works.

What am I doing wrong/what is missing?

Regards
 
bsus said:
What am I doing wrong/what is missing?

This:
Code:
PORT_BUILD=""

Will make the rule look like this:
Code:
rdr pass on em0 proto tcp from any to 192.168.178.10 port -> 10.0.0.2
Which is a syntax error.

This isn't going to work either:
Code:
IP_JAIL_BUILD=10.0.0.2"
There's a quote missing.

And I suggest changing this:
Code:
nat pass on $ext_if from $NET_JAIL to any -> $IP_PUB
To this:
Code:
nat pass on $ext_if from $NET_JAIL to any -> ($ext_if)
 
Code:
ext_if="em0"

IP_PUB="192.168.178.10"

NET_JAIL="{ 10.0.0.0/24 }"

IP_JAIL_WWW="10.0.0.1"
IP_JAIL_BUILD="10.0.0.2"

PORT_WWW="{ 80,443 }"
PORT_BUILD="" #when no port don't mention in rule with port keyword

scrub in all

nat pass on $ext_if from $NET_JAIL to any -> ($ext_if)

rdr pass on $ext_if proto tcp from any to $IP_PUB port $PORT_WWW -> $IP_JAIL_WWW
rdr pass on $ext_if proto tcp from any to $IP_PUB -> $IP_JAIL_BUILD

pass out
pass in

You're right.

Have updated the config. How can I open ports for the host system? For example when enabling pf I can't access the server through ssh anymore.

Regards!
 
bsus said:
For example when enabling pf I can't access the server through ssh anymore.
Remove this line:
Code:
rdr pass on $ext_if proto tcp from any to $IP_PUB -> $IP_JAIL_BUILD

It redirects all ports to your jail.
 
So, I now handled the basic firewall for the system. I only fail with the nat for the jails.

I used the OpenBSD PF FAQ for configuring it. I am just confused about the difference to the tutorial.

Any one an idea how I:
1. Map the internal network for the jails (10.0.0.0/24)
2. Open Ports for ftp (downloading files) and http(s) (webserver)
3. Blocking all other ports for the jails?

How do I do this?

All fail when adding:
Code:
nat pass on $HOST_IF from $JAIL_NET to any -> ($HOST_IF)
rdr pass on $HOST_IF proto tcp from any to $HOST_IP port $JAIL_PORTS_WWW -> $JAIL_IP_WWW
rdr pass on $HOST_IF proto tcp from any to $HOST_IP -> $JAIL_IP_BUILD
over the pass/block rulesets with an syntax error:
Code:
Disabling pf.
Enabling pf/etc/pf.conf:19: Rules must be in order: options, normalization, queueing, translation, filtering
/etc/pf.conf:22: syntax error
pfctl: Syntax error in config file: pf rules not loaded

Following man pf.conf the order should be right (translation above filtering)
I also can't find any rdr nat prefixed rules in the OpenBSD pf FAQ

Here is the config:
Code:
# general
EXT_IF="{ em0 }"
INT_IF="{ lo111 }"
HOST_IP="192.168.178.10"
HOST_PORTS="{ 50000 }"

# jails
JAIL_NET="{ 10.0.0.0/24 }"
JAIL_IP_BUILD="10.0.0.1"
JAIL_IP_WWW="10.0.0.2"
JAIL_PORTS_WWW="{ 80,443 }"

# tables
table <intranet> { 192.168.178.0/24, !192.168.178.1 }
table <bruteforce> persist

# options
set skip on lo0
scrub in all
antispoof for $EXT_IF inet

# nat
#match out on $EXT_IF from $INT_IF:network nat-to ($EXT_IF)
#pass out on $EXT_IF proto tcp from $JAIL_NET port $JAIL_PORTS_WWW to $HOST_IP

# rulesets block
block
block in quick from { urpf-failed, <bruteforce> }

# rulesets pass
pass in on $EXT_IF proto tcp from <intranet> modulate state
pass in on $EXT_IF proto tcp from any to any port $HOST_PORTS flags S/SA keep state (max-src-conn 100, max-src-conn-rate 15/5, overload <bruteforce> flush global)
pass out on $EXT_IF all keep state

I googled aroung a bit more and found out that there where significant changes in the nat syntax.
nat and rdr are depreacted now there is match, nat-to (and pass)

it should look a bit like this:
Code:
#match out on $EXT_IF from $INT_IF:network nat-to ($EXT_IF)
#pass out on $EXT_IF proto tcp from $JAIL_NET port $JAIL_PORTS_WWW to $HOST_IP

Code:
# service pf restart
Disabling pf.
Enabling pf/etc/pf.conf:35: syntax error
pfctl: Syntax error in config file: pf rules not loaded

...
 
For one, post whole configuration again, and use :set number in vi so it's easier to see where the error is.
 
Code:
      1 # general
      2 EXT_IF="{ em0 }"
      3 INT_IF="{ lo111 }"
      4 HOST_IP="192.168.178.10"
      5 HOST_PORTS="{ 50000 }"
      6
      7 # jails
      8 JAIL_NET="{ 10.0.0.0/24 }"
      9 JAIL_IP_BUILD="10.0.0.1"
     10 JAIL_IP_WWW="10.0.0.2"
     11 JAIL_PORTS_WWW="{ 80,443 }"
     12
     13 # tables
     14 table <intranet> { 192.168.178.0/24, !192.168.178.1 }
     15 table <bruteforce> persist
     16
     17 # options
     18 set skip on lo0
     19 scrub in all
     20 antispoof for $EXT_IF inet
     21
     22 # nat
     [color="red"]23[/color] match out on $EXT_IF from $INT_IF:network nat-to ($EXT_IF)
     [color="Red"]24[/color] pass out on $EXT_IF proto tcp from $JAIL_NET port $JAIL_PORTS_WWW to $HOST_IP
     25
     26 # rulesets block
     27 block
     28 block in quick from { urpf-failed, <bruteforce> }
     29
     30 # rulesets pass
     31 pass in on $EXT_IF proto tcp from <intranet> modulate state
     32 pass in on $EXT_IF proto tcp from any to any port $HOST_PORTS flags S/SA keep state (max-src-conn 100, max-src-conn-rate 15/5, overload <bruteforce> flush global)
     33 pass out on $EXT_IF all keep state
~

Code:
# service pf restart
Disabling pf.
Enabling pf/etc/pf.conf:23: syntax error
pfctl: Syntax error in config file: pf rules not loaded
.

Marked the bad lines red
 
Code:
 23 match out on $EXT_IF from $INT_IF:network nat-to ($EXT_IF)
 24 pass out on $EXT_IF proto tcp from $JAIL_NET port $JAIL_PORTS_WWW to $HOST_IP

Line 23 doesn't work since that's pf 5.0 syntax. Use this:
Code:
nat on $ext_if from $int_if:network to any -> ($ext_if)

You use $int_if for loopback which makes it harder to follow (usually it's internal LAN interface).

Line 24 doesn't make sense. What is it you are trying to do exactly?

Remember there are two two sets of rules which you need to implement to make sure jail with loopback IP can communicate. One is rdr on which redirects packets from incoming interface to loopback. This works for both LAN and external interface. Second is nat on which translates packets from loopback to LAN/external interface as loopback is not known outside firewall itself. Again, for both LAN and external interface. Both these rules are NAT, its just that pf uses "redirection" to specify destination address translation, whereas uses "nat" for source address translation.

Aside from these translations rules you still need to let firewall know what packets to even let through to be translated in the first place. For example if you want port 80 and 443 to be initiated from internet, you need to let pass in on on external interface. Only then these rules are permitted to go to loopback interface.

Finally, loopback itself needs permission to let packets in. You could have set skip on lo0 here, for instance.

Keep in mind firewall inspects packets on each individual interface.

hth
 
Hi,

Thank you for the rescuing answer!

You use $int_if for loopback which makes it harder to follow (usually it's internal LAN interface).
Which macro name do you suggest?

Line 24 doesn't make sense. What is it you are trying to do exactly?
This should forward all webserver ports from the jails to the Internet or at least to the ext_if.

Remember there are two two sets of rules which you need to implement to make sure jail with loopback IP can communicate. One is rdr on which redirects packets from incoming interface to loopback. This works for both LAN and external interface. Second is nat on which translates packets from loopback to LAN/external interface as loopback is not known outside firewall itself. Again, for both LAN and external interface. Both these rules are NAT, its just that pf uses "redirection" to specify destination address translation, whereas uses "nat" for source address translation.

So rdr redirects from em0 to lo111 (jail) and nat redirects from lo111 (jail) to em0. This makes sense. But how would a rdr look now? I always get a syntax error when uncommenting the rdr line.

Aside from these translations rules you still need to let firewall know what packets to even let through to be translated in the first place. For example if you want port 80 and 443 to be initiated from internet, you need to let pass in on on external interface. Only then these rules are permitted to go to loopback interface.
This would be:

Code:
pass in on $ext_if proto tcp from any to any port $JAIL_PORTS_WWW modulate state
?

Merged together:

Code:
# general
ext_if="{ em0 }"
int_if="{ lo111 }"
HOST_IP="192.168.178.10"
HOST_PORTS="{ 50000 }"

# jails
JAIL_NET="{ 10.0.0.0/24 }"
JAIL_IP_BUILD="10.0.0.1"
JAIL_IP_WWW="10.0.0.2"
JAIL_PORTS_WWW="{ 80,443 }"

# tables
table <intranet> { 192.168.178.0/24, !192.168.178.1 }
table <bruteforce> persist

# options
set skip on lo0
scrub in all
antispoof for $ext_if inet

# nat
[color="Red"]nat on $ext_if from $int_if:network to any -> ($ext_if)[/color]
[color="Red"]rdr pass on $ext_if proto tcp from any to $HOST_IP -> ($int_if)[/color]

# rulesets block
block
block in quick from { urpf-failed, <bruteforce> }

# rulesets pass
pass in on $ext_if proto tcp from <intranet> modulate state
pass in on $ext_if proto tcp from any to any port $HOST_PORTS flags S/SA keep state (max-src-conn 100, \
max-src-conn-rate 15/5, overload <bruteforce> flush global)
[color="blue"]pass in on $ext_if proto tcp from any to any port $JAIL_PORTS_WWW modulate state[/color]
pass out on $ext_if all keep state

*) added lines
*) error causing lines

Code:
# service pf restart
Disabling pf.
Enabling pf/etc/pf.conf:23: syntax error
/etc/pf.conf:24: syntax error
pfctl: Syntax error in config file: pf rules not loaded
.
 
Try this:

Code:
ext_if="em0"
int_if="em1"
jail_if="lo111"

jbuild="10.0.0.1"
jwww="10.0.0.2"
www_ports="{ 80 443 }"

table <martians> const { 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
                        10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
                        0.0.0.0/8, 240.0.0.0/4 }
table <ssh_abuse> persist
table <firewall> const { self }

# NORMALIZATION #
scrub on $ext_if all random-id min-ttl 254 max-mss 1452 reassemble tcp fragment reassemble

# TRANSLATION #
nat on $int_if from $jail_if to any -> ($int_if:0)
nat on $ext_if from $jail_if to any -> ($ext_if:0)
nat on $ext_if from $int_if:network to any -> ($ext_if:0)
rdr on $int_if proto tcp to $int_if port 80-> $jwww port 80
rdr on $int_if proto tcp to $int_if port 443-> $jwww port 443
rdr on $ext_if proto tcp to $ext_if port 80 -> $jwww port 80
rdr on $ext_if proto tcp to $ext_if port 443 -> $jwww port 443
no rdr

# OPTIONS #
set skip on lo0
set skip on lo111
antispoof log quick for $ext_if inet

# TRAFFIC RULES #
block in quick from <ssh_abuse>
block in quick on $ext_if from any to 255.255.255.255
block in quick on $ext_if from <martians>
block log all

#internal interface
pass  in  quick on $int_if from $int_if:network proto tcp to $int_if port $www_ports modulate state
pass  in  log quick on $int_if from $int_if:network proto tcp to $int_if port ssh modulate state \
			(max-src-conn 10, max-src-conn-rate 3/5, overload <ssh_abuse> flush global)
block in  quick on $int_if to <firewall>
pass  in  quick on $int_if from $int_if:network

#external interface
pass  in  quick on $ext_if proto tcp to $ext_if port $www_ports modulate state
pass  in  log quick on $ext_if proto tcp to $ext_if port ssh modulate state \
			(max-src-conn 10, max-src-conn-rate 3/5, overload <ssh_abuse> flush global)
pass  out quick on $ext_if

note 1: change internal interface to whatever you have
note 2: you can use this as template since I'm still not sure what setup exactly are you running
note 3: this lets any host on internal LAN communicate both ssh and www services on firewall, but blocks all other.
note 4: same for external interface
note 5: I haven't parsed this in pf, there might be errors so try it out first if there's errors.
 
Hi, thank you for the template! This helps me a lot and also others who look after a current example.

Code:
ext_if="em0"
#int_if="em1" # because server is no router, only a normal server :)
jail_if="lo111"

pub_ip="192.168.178.10"
pub_ports="50000" #custom ssh port

jbuild="10.0.0.1"
jwww="10.0.0.2"
jftp="10.0.0.3"
www_ports="{ 80 443 }"
ftp_ports="{ 21 22 }"

table <intranet> const { 127.0.0.0/8, 192.168.178.0/16, 10.0.0.0/8, 0.0.0.0/8 }
table <ssh_abuse> persist
table <firewall> const { self }

# NORMALIZATION #
scrub on $ext_if all random-id min-ttl 254 max-mss 1452 reassemble tcp fragment reassemble

# TRANSLATION #
nat on $ext_if from $jail_if to any -> ($ext_if:0)
rdr on $ext_if proto tcp from any to $pub_ip port $www_ports -> $jwww port $www_ports
rdr on $ext_if proto tcp from any to $pub_ip port $ftp_ports -> $jftp port $ftp_ports
no rdr

# OPTIONS #
set skip on lo0
set skip on lo111
antispoof log quick for $ext_if inet

# TRAFFIC RULES #
block in quick from <ssh_abuse>
block in quick on $ext_if from any to 255.255.255.0 # what does the netmask do?
block in quick on $ext_if from <intranet>
block log all

#external interface
pass  in  quick on $ext_if proto tcp to $ext_if port $www_ports modulate state
pass  in  log quick on $ext_if proto tcp to $ext_if port $pub_ports modulate state \
                        (max-src-conn 10, max-src-conn-rate 3/5, overload <ssh_abuse> flush global)
pass  out quick on $ext_if

There are only two things to do:
  1. SSH (on port 50000) should be allowed but I don't have access when enabling pf.
  2. The second rdr line fails. I think that it is only valid to have one rdr line. But how do I open additional ports?
 
  1. Is the service listening on port 50000? The firewall controls the traffic, but you need to have the service listen on that port.
  2. You can have as many redirection rules as you need, as long as you are careful which IP/port translates to which IP/port. That is, use individual rules, don't group them. pf expands these rules when you load them anyway (check pfctl -sa).
  3. That is not a mask, 255.255.255.255 is broadcast address. If you are on cable service you'll have a lot of this noise.
 
Is the service listening on port 50000? The firewall controls the traffic, but you need to have the service listen on that port.
Yes, when I disable pf I can log in :)

You can have as many redirection rules as you need, as long as you are careful which IP/port translates to which IP/port. That is, use individual rules, don't group them. pf expands these rules when you load them anyway (check pfctl -sa).
But why do I get a syntax error when adding another rpf rule? There different ports (80,443 vs 21,22)

That is not a mask, 255.255.255.255 is broadcast address. If you are on cable service you'll have a lot of this noise.
So something like a wildcard?

Regards
 
bsus said:
Yes, when I disable pf I can log in :)

The rule is ok. You are missing something else.

But why do I get a syntax error when adding another rpf rule? There different ports (80,443 vs 21,22)

Individual ports.

Code:
rdr on $ext_if proto tcp from any to $ext_if port 80 -> $jwww port 80
rdr on $ext_if proto tcp from any to $ext_if port 443 -> $jwww port 443
So something like a wildcard?
Regards

Something like it.

Also, FTP might require additional configuration.
 
The rule is ok. You are missing something else.
Question is what is missing :)

Individual ports.
I thought that this happens while parsing the config because the values in the lists are getting executed like a foreach loop?

Also, FTP might require additional configuration.
Ah ok, the ftp port was mainly a placeholder but I will remind me if I have to fallback from http to ftp.

Thank you for your help and patience, I think I will get the last issues at my own ;)
 
Back
Top