# pf: rule expands to no valid combination



## dvl@ (Jul 13, 2013)

When my FreeBSD 8.2-STABLE firewall reboots, the _PF_ ruleset is not loaded. After booting, if I invoke the ruleset manually, it loads just fine: `# pfctl -f /etc/pf.rules`

Watching the boot process, I see these two messages:

```
/etc/pf.rules:136: rule expands to no valid combination
/etc/pf.rules:147: rule expands to no valid combination
pfctl: Syntax error in config file: pf rules not loaded
```
Looking at those lines:

```
1: ext_if="fxp0"
2: int_if="fxp1"
...
127: pass out quick on $ext_if proto tcp all modulate state flags S/SA
...
133: pass out quick on $int_if proto ipv6-icmp all synproxy state
134: pass in  quick on $int_if proto ipv6-icmp all synproxy state
135:
136: pass in  on $int_if inet6 proto tcp from $int_if:network flags S/SA keep state
...
147: pass in quick on $ext_if inet proto {tcp, udp} from any to $ext_if port domain keep state
```
I included 127 and 133-134 to demonstrate that other rules refer to $int_if and $ext_if without problem.

Ideas?  Suggestions?


----------



## kpa (Jul 13, 2013)

I'd guess the interfaces are taking too long to initialize fully before PF tries to load the rules and the interfaces do not yet have addresses assigned to them.  Maybe /etc/rc.d/netwait can remedy the problem?


----------



## dvl@ (Jul 13, 2013)

kpa said:
			
		

> I'd guess the interfaces are taking too long to initialize fully before PF tries to load the rules and the interfaces do not yet have addresses assigned to them.  Maybe /etc/rc.d/netwait can remedy the problem?



That's not found in this 8.4 system, but I see in it a 9.1 system.  I see this in there:


```
# The netwait script is intended to be used by systems which have
# statically-configured IP addresses in rc.conf(5).  If your system
# uses DHCP, you should use synchronous_dhclient="YES" in your
# /etc/rc.conf instead of using netwait.
```

Is that what you meant?


----------



## kpa (Jul 13, 2013)

Yes that is it. It should make the boot process wait until a known external address is reachable.


----------



## dvl@ (Jul 13, 2013)

Thanks.  It appears to be unavailable on 8.4. But what great incentive to upgrade to 9.1.


----------



## J65nko (Jul 13, 2013)

Re *synproxy*

From http://openbsd.org/faq/pf/filter.html#synproxy



> Normally when a client initiates a TCP connection to a server, PF will pass the handshake packets between the two endpoints as they arrive. PF has the ability, however, to proxy the handshake. With the handshake proxied, PF itself will complete the handshake with the client, initiate a handshake with the server, and then pass packets between the two. In the case of a TCP SYN flood attack, the attacker never completes the three-way handshake, so the attacker's packets never reach the protected server, but legitimate clients will complete the handshake and get passed. This minimizes the impact of spoofed TCP SYN floods on the protected service, handling it in PF instead. *Routine use of this option is not recommended, however, as it breaks expected TCP protocol behavior when the server can't process the request and when load balancers are involved.*


----------



## kpa (Jul 13, 2013)

Oh yes good catch @J65nko. The synproxy is meant to be turned on only when you're under an attack.


----------



## dvl@ (Jul 13, 2013)

I've changed all my 'synproxy state' instances to 'keep state'.

The problem persists, but I don't think that was meant to fix it.

FYI, I think the 'and' in the final sentence of the quote should be an 'or'.  i.e. I'm not using a load balancer, thus this should never affect me.


----------



## wblock@ (Jul 13, 2013)

dvl@ said:
			
		

> Thanks.  It appears to be unavailable on 8.4. But what great incentive to upgrade to 9.1.



Well, yes, but it is in 8.4.  Look in /etc/defaults/rc.conf.  Here's an example:


```
netwait_enable="YES"
netwait_ip="333.333.333.333"  # IP address to ping
netwait_timeout="60"
netwait_if="re0"
netwait_if_timeout="60"
```


----------



## J65nko (Jul 13, 2013)

Indeed, my remark about synproxy was not meant to solve your problem 

I don't have an 8.4 system but on a 9.1 system without an internal NIC I can reproduce your error with a lo5 device:


```
[cmd=#] cat -n dvl.pf[/cmd]
     1  int_if = 'lo5'
     2  ext_if = 're0'
     3
     4  pass out quick on $ext_if proto tcp all 
     5  pass out quick on $int_if proto ipv6-icmp all 
     6  pass in  quick on $int_if proto ipv6-icmp all
     7
     8  pass in  on $int_if inet6 proto tcp from [color=blue]$int_if:network[/color]
     9
    10  pass in quick on $ext_if inet proto {tcp, udp} from any to $ext_if port domain

[cmd=#] ifconfig lo5 create 10.1.2.3/24[/cmd]

[cmd=#] ifconfig lo5[/cmd]
lo5: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
        inet 10.1.2.3 netmask 0xffffff00 
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>

[cmd=#] pfctl -vvnf dvl.pf[/cmd]
int_if = "lo5"
ext_if = "re0"
dvl.pf:8: rule expands to no valid combination
```

If I assign an IPv6 address it works:


```
[cmd=#]ifconfig lo5 inet6 3:: ; ifconfig lo5[/cmd]
lo5: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
        inet 10.1.2.3 netmask 0xffffff00 
        inet6 3:: prefixlen 64 
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>

[cmd=#] pfctl -vvnf dvl.pf[/cmd]
int_if = "lo5"
ext_if = "re0"
@0 pass out quick on lo5 proto ipv6-icmp all keep state
@1 pass in quick on lo5 proto ipv6-icmp all keep state
@2 pass out quick on re0 proto tcp all flags S/SA keep state
[color=blue]@3 pass in on lo5 inet6 proto tcp from 3::/64 to any flags S/SA keep state[/color]
@4 pass in quick on re0 inet proto tcp from any to 88.198.14.41 port = domain flags S/SA keep state
@5 pass in quick on re0 inet proto udp from any to 88.198.14.41 port = domain keep state
```

I think the first error, about being unable to expand the $int_if:network construct is the real error. Because the internal interface does not yet have an IPv6 address it is not possible to derive the IPv6 network/subnet.


----------



## dvl@ (Jul 13, 2013)

wblock@ said:
			
		

> Well, yes, but it is in 8.4.  Look in /etc/defaults/rc.conf.  Here's an example:
> 
> 
> ```
> ...



Ahh, my error was locate... I was using locate on 9.1, but on 8.4, the locate database was out of date...

Thank you.


----------



## dvl@ (Jul 13, 2013)

J65nko said:
			
		

> I think the first error, about unable to expand the *$int_if:network* construct when the internal interface does not yet have an IPv6 address is the culprit.



Interesting... And the second error?


----------



## J65nko (Jul 13, 2013)

Just a spurious one, because the parser is too confused about the first one. Many parsers/compilers suffer from this


----------



## dvl@ (Jul 14, 2013)

wblock@ said:
			
		

> Well, yes, but it is in 8.4.  Look in /etc/defaults/rc.conf.  Here's an example:
> 
> 
> ```
> ...



I tried this:


```
netwait_enable="YES"
netwait_ip="2001:470:1f07:b80:21b:21ff:fe51:ab2d" # internal host
netwait_if="fxp1"
```

and this


```
netwait_enable="YES"
netwait_ip="10.0.0.1" # external host, not the real IP
netwait_if="fxp0"
```

In both cases, the error messages for pf appeared before the netwait was performed. FYI, this was on FreeBSD 8.4-RELEASE-p1. Now trying a `freebsd-update -r 9.1-RELEASE fetch`.


----------



## wblock@ (Jul 15, 2013)

Does fxp0 have a static or dynamic IP address?  If it's dynamic, use ifconfig_fxp0="SYNCDHCP".  Also, there was an errataum about fxp(4) interfaces having problems bouncing, but I don't recall which release that was on.


----------



## dvl@ (Jul 15, 2013)

Yes, fxp0 has a dynamic address. I will try that option after this freebsd-update finishes.

Fetching 9107 patches.....10....20

Two hours later: 1580....1590....1600â€¦ 

Might be a while*.*


----------



## wblock@ (Jul 15, 2013)

That's it, then. 
	
	



```
ifconfig_fxp0="DHCP"
```
 continues with the startup scripts before dhclient(8) finishes, and other startup scripts like /etc/rc.d/pf can run before fxp0 has an address.


----------



## dvl@ (Jul 16, 2013)

dvl@ said:
			
		

> I tried this:
> 
> 
> ```
> ...



FYI, on FreeBSD 9.1-RELEASE-p4, netwait worked.  After boot, my rules were correctly loaded.


----------



## dvl@ (Jul 16, 2013)

wblock@ said:
			
		

> Does fxp0 have a static or dynamic IP address?  If it's dynamic, use ifconfig_fxp0="SYNCDHCP".  Also, there was an errataum about fxp(4) interfaces having problems bouncing, but I don't recall which release that was on.



This worked too.  Thank you. I think I'll be using this.


----------

