# multiple rules fail



## bsus (May 11, 2012)

Hello,

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

pf.conf

```
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:

```
# /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


----------



## SirDice (May 11, 2012)

bsus said:
			
		

> What am I doing wrong/what is missing?



This:

```
PORT_BUILD=""
```

Will make the rule look like this:

```
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:

```
IP_JAIL_BUILD=10.0.0.2"
```
There's a quote missing.

And I suggest changing this:

```
nat pass on $ext_if from $NET_JAIL to any -> $IP_PUB
```
To this:

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


----------



## bsus (May 11, 2012)

```
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!


----------



## SirDice (May 11, 2012)

bsus said:
			
		

> For example when enabling pf I can't access the server through ssh anymore.


Remove this line:

```
rdr pass on $ext_if proto tcp from any to $IP_PUB -> $IP_JAIL_BUILD
```

It redirects _all_ ports to your jail.


----------



## bsus (May 11, 2012)

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:

```
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:

```
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:

```
# 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:

```
#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
```


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

...


----------



## bsus (May 11, 2012)

Any suggestions?


----------



## bbzz (May 11, 2012)

For one, post whole configuration again, and use :*set number* in *vi* so it's easier to see where the error is.


----------



## bsus (May 11, 2012)

```
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
~
```


```
# 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


----------



## bbzz (May 11, 2012)

```
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:

```
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


----------



## bsus (May 11, 2012)

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:


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

*M*erged together:


```
# 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


```
# 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
.
```


----------



## bbzz (May 11, 2012)

Try this:


```
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.


----------



## bsus (May 11, 2012)

Hi, thank you for the template! This helps me a lot and also others who look after a current example.


```
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 t*w*o things to do:

SSH (on port 50000) should be allowed but I don't have access when enabling pf.
The second rdr line fails. I think that it is only valid to have one rdr line. But how do I open additional ports?


----------



## bbzz (May 11, 2012)

Is the service listening on port 50000? *T*he firewall controls the traffic, but you need to have the service listen on that port.
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*).
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.


----------



## bsus (May 12, 2012)

> 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


----------



## bbzz (May 12, 2012)

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.


```
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.


----------



## bsus (May 13, 2012)

> 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


----------



## bbzz (May 13, 2012)

You are most welcome.


----------

