PF pf won't load rules at boot time

Hi there,

I've been having this problem since … well to be honest I don't know. Fact is, when my box (FreeBSD 12.2 stable, home compiled) boots, the pf service enabled in both /etc/rc.conf and /etc/defaults/rc.conf, with the same parameters, (I know, that's an overkill) won't load any rules. After booting, I end up with an enabled service but an empty set of rules, which is quite problematic since I have a few desktop clients waiting to be NAT-ted (inter alia).

I've put rc in debug mode, and the message "Enabling pf" (or whatever) is not in the flow of output. I've tried to comment out the pf_enable='YES' and germane lines in /etc/rc.conf and /etc/default/rc.conf in turn: duds.

As a workaround, I have installed an '@reboot root service pf start' line in /etc/crontab, and that works. But it's a kludge, I'm not happy about it, and I'm a bit annoyed by that behaviour.

The pf KLM is in my 'loader.conf' file, so that can't be it (at least, I assume so).

If anyone comes up with an idea, I'd really welcome it.

Thanks a bunch,
Vincent
 
You'll have to post your ruleset. My guess is that you're trying to use DNS names in the rules and pf gets before your DNS resolution works.

Does pf start correctly when you start it manually after boot (i.e. service pf start)?
 
Don’t mess with the defaults file. it is not necessary. Anything you want to set should be done in /etc/rc.conf.

Are you using the standard path for the rules file or your own?
What pf setting do you have in rc.conf?
What are the permissions on pf.conf? (likely not a problem if it works manually but I seem to remember pf is one of those utilities that complains if the config isn’t secure.
Do you have rules that might rely on something that isn’t available until after boot (such as a custom bridge interface, etc)?
 
Hi!
I agree with you about unnecessary /etc/default/rc.conf changes, I wanted to rule out a possible override of /etc/rc.conf by /etc/defaults/rc.conf for whatever reason.

Here is the setting:

Code:
# PF
pf_enable="NO"         # Set to YES to enable packet filter (pf)
pf_rules="/etc/pf.conf"     # rules definition file for pf
pf_program="/sbin/pfctl"    # where the pfctl program lives
pf_flags=""                     # additional flags for pfctl
pflog_enable="NO"      # Set to YES to enable packet filter logging
pflog_logfile="/var/log/pflog"  # where pflogd should store the logfile
pflog_program="/sbin/pflogd"    # where the pflogd program lives
pflog_flags=""          # additional flags for pflogd

Note that the "NO" is simply part of my kludge.
Code:
ll /etc/pf.conf
-rw-r--r--  1 root  wheel  1396 24 Jan 20:55 /etc/pf.conf

The rules depend on the two interfaces, and there are anchors for blacklistd. If it can be of any help, here they are:

Code:
# PF rules

# MACROS
ext_if = "re0"
ext_ip = blah
ext_pf = "blah/30"

int_if = "ale0"
int_ip = 172.31.0.1
int_pf = "172.31.0.0/16"

# Normalise traffic
scrub in on $ext_if all fragment reassemble
scrub in on $int_if all fragment reassemble

# NAT
nat on $ext_if from $int_pf to any -> $ext_ip

# Default is drop from outside
block in on $ext_if from ! $ext_pf

# PING
pass proto icmp
pass proto icmp6

# Allow traffic on a variety of ports
# FTP, SSH, HTTP, IMAPS and POP3s are protected by state limitation
block quick from <blacklisted>
pass inet proto {tcp, udp} from any to $ext_ip port {ftp-data, ftp, ssh, smtps, submission, imaps, pop3s} \
    keep state (max-src-conn-rate 5/1 overload <blacklisted> flush global)

pass inet proto {tcp, udp} from any to $ext_ip port {smtp, http, https, domain, ntp, isakmp, ipsec-msft}

# PASV for vsftp
pass inet proto tcp from any to $ext_ip port 65000:65010

# ANCHORS FOR BLACKLISTD
anchor "blacklistd" all {
        anchor "21" all
        anchor "22" all
        anchor "25" all
        anchor "465" all
        anchor "587" all
        anchor "993" all
        anchor "995" all
}

# Allow all output from localhost and the local network
pass from {localhost, ::1, 127.0.0.1, $ext_ip, $int_ip}
pass on {$int_if, lo0}

Thanks!
V.
 
I wanted to rule out a possible override of /etc/rc.conf by /etc/defaults/rc.conf for whatever reason.
It works the other way around. Settings in /etc/rc.conf always overrule /etc/defaults/rc.conf. Never edit or modify the files in /etc/defaults/*.
 
It works the other way around. Settings in /etc/rc.conf always overrule /etc/defaults/rc.conf. Never edit or modify the files in /etc/defaults/*.
Sure, but you know, I've seen stranger things in my life :)
 
> nat on $ext_if from $int_pf to any -> $ext_ip

That will only work if the IP address is assigned somewhere.
Write that as this instead:

> nat on $ext_if from $int_pf to any -> (re0)
 
> nat on $ext_if from $int_pf to any -> $ext_ip

That will only work if the IP address is assigned somewhere.
Write that as this instead:

> nat on $ext_if from $int_pf to any -> (re0)
Thanks for that, I'll try next time I'm in office (you know, home working and caboodle). Can I use ($ext_if) instead of (re0)?
One thing I'm dead certain about is that this never happened in the 20+ years I've used FreeBSD.
It's not FreeBSD sturdiness I'm challenging. I wanted to check I hadn't done, and let live, something stupid that was reversing this behaviour.
 
I'm struck by the similarity of the solution I have to my ZFS problems: Restarting a service that was supposed to start on boot. I'm compelled to check 12.1 to 12.2 diffs now...

Anyway, I have only a couple debug things to add from my previous pf experience

* kldstat to check for the kernel module
* Putting this stuff in /etc/rc.conf
gateway_enable="YES"
Which seems to be a more permanent version of sysctl net.inet.ip.forwarding=1
pf_rules="/etc/pf.conf"


Checking kldstat is probably the only one applicable to you, though, since it seems to work on restarting the service
 
I'm struck by the similarity of the solution I have to my ZFS problems: Restarting a service that was supposed to start on boot. I'm compelled to check 12.1 to 12.2 diffs now...

Anyway, I have only a couple debug things to add from my previous pf experience

* kldstat to check for the kernel module
* Putting this stuff in /etc/rc.conf
gateway_enable="YES"
Which seems to be a more permanent version of sysctl net.inet.ip.forwarding=1
pf_rules="/etc/pf.conf"


Checking kldstat is probably the only one applicable to you, though, since it seems to work on restarting the service
Darn. I just saw that my /boot/loader.conf did not contain the name of the kernel.
Checking now…
No dice (sorry Sir :p)! See below

Code:
Cimax> sudo pfctl -s info
Status: Enabled for 0 days 00:01:25           Debug: Urgent

State Table                          Total             Rate
  current entries                        0               
  searches                            1731           20.4/s
  inserts                                0            0.0/s
  removals                               0            0.0/s
Counters
  match                               1731           20.4/s
  bad-offset                             0            0.0/s
  fragment                               0            0.0/s
  short                                  0            0.0/s
  normalize                              0            0.0/s
  memory                                 0            0.0/s
  bad-timestamp                          0            0.0/s
  congestion                             0            0.0/s
  ip-option                              4            0.0/s
  proto-cksum                            0            0.0/s
  state-mismatch                         0            0.0/s
  state-insert                           0            0.0/s
  state-limit                            0            0.0/s
  src-limit                              0            0.0/s
  synproxy                               0            0.0/s
  map-failed                             0            0.0/s
Cimax> sudo pfctl -s rules
Cimax> sudo kldstat
Id Refs Address                Size Name
 1   20 0xffffffff80200000  115fe50 kernel
 2    2 0xffffffff81360000    54dd0 pf.ko
 3    1 0xffffffff813b6000    27c78 fuse.ko
 4    1 0xffffffff81521000   24b908 zfs.ko
 5    1 0xffffffff8176d000     75a8 opensolaris.ko
 6    1 0xffffffff81775000     1a10 fdescfs.ko
 7    1 0xffffffff81777000      9a8 pflog.ko
 8    1 0xffffffff81778000     4700 autofs.ko
Cimax>
That would've been curious anyway, since pfctl loads the KLM in case this has not been done before.
 
I mean on reboot, check if the module even got loaded before you service pf start in crontab or wherever.
That's what I did. The snippet I posted was the output following a reboot with pf_enable="YES" in /etc/rc.conf and the @reboot line in /etc/crontab commented out.
 
You just said pfctl loads the kernel module, so running pfctl won't tell you if the module loaded with the rc subsystem like it was supposed to, because it will then load the module. Use kldstat.
 
You just said pfctl loads the kernel module, so running pfctl won't tell you if the module loaded with the rc subsystem like it was supposed to, because it will then load the module. Use kldstat.
Yeah, my bad, that was corrected by Kristof (see above). Pfctl doesn't load the module if it is not already loaded; /etc/rc.d/pf does.
 
Alright, well, weirder things have happened, I would still check it.

If you don't see 'Enabling pf' then maybe it is time to jam debugging echo statements directly into /etc/rc.subr...
 
That's what I did using the standard procedure (setting the dedicated variable) – but no luck.
I'm not sure how I can investigate further. Maybe by digging inside pfctl to see why it doesn't access rules or why it ignores them.
 
You didn't see anything like
Code:
Jan 28 18:00:44 FreeBSD kernel: /etc/rc: DEBUG: checkyesno: pf_enable is set to YES.
Jan 28 17:48:30 FreeBSD kernel: /etc/rc: DEBUG: run_rc_command: doit: pf_start
 
Back
Top