Ansible role. FreeBSD. Configure PF firewall.
Feel free to share your feedback and report issues.
Warning:
As it manipulates the firewall, there is a risk of being locked out. It's necessary to read the handbook
- https://www.freebsd.org/doc/en/books/handbook/firewalls-pf.html
- https://www.openbsd.org/faq/pf/filter.html
When you experiment with pf on a remote host open a session and, as root, run the below command before you enable pf
shell> sleep 120; pfctl -d
This will disable pf after 2 minutes and let you to open new session to this remote host in case something went wrong.
- community.general
By default the firewall is disabled
pf_enable: False
By default sshguard, blacklistd, fail2ban, and relayd are disabled
pf_blacklistd_enable: False
pf_fail2ban_enable: False
pf_relayd_enable: False
pf_sshguard_enable: False
By default blocked packages are not logged
pf_log_all_blocked: False
Review the defaults and examples in vars.
- Change shell to /bin/sh if necessary
shell> ansible srv.example.com -e 'ansible_shell_type=csh ansible_shell_executable=/bin/csh' -a 'sudo pw usermod freebsd -s /bin/sh'
- Install the role and collections
shell> ansible-galaxy role install vbotka.freebsd_pf
Install the collection if necessary
shell> ansible-galaxy collection install community.general
- Create firewall
There are couple of templates *-pf.conf.j2 available. Pick a template that fits your purpose (router, server, balancer, ...) and review the examples of the variables .yml.sample in vars. The template default-pf.conf.j2 and the variables pfconf_example_default.yml.sample are tested. Other templates and samples will need more attention and testing.
Note: You can create nested lists (tables, options, normalization, queuing, translation, filtering, ...) for the template default-pf.conf.j2. The lists will be flattened.
- Create playbook
shell> cat freebsd-pf.yml
- hosts: srv.example.com
roles:
- vbotka.freebsd_pf
-
Review handlers to see how start/restart/reload of pf is implemented.
-
Install packages
shell> ansible-playbook -t pf_packages -e pf_install=true freebsd-pf.yml
Then, disable the installation to speed up the execution of the playbook.
- Configure the firewall
Starting and restarting of the firewall breaks the ssh connections. See the handlers for details. As a consequence, both handlers starting and reloading don't work properly and the ssh connection will stale. Therefore, let us first configure the rules
shell> ansible-playbook -e pf_enable=false freebsd-pf.yml
Before you enable the firewall open a ssh session to the remote host and run the below commands
shell> sleep 120; pfctl -d
If you lock yourself out of the remote host the above commands will disable the firewall in 2 minutes. You might want to run these commands always when you experiment with the firewall. Now, enable the firewall
shell> ansible-playbook -e pf_enable=true freebsd-pf.yml
Open ssh connection to the host for the case that something goes wrong. Update and validate the configuration. Do not reload the rules
shell> ansible-playbook -e pf_conf_only=true -e pf_conf_validate=true freebsd-pf.yml
Reload the rules after the configuration has been updated and validated
shell> ansible srv.example.com -m service -a "name=pf state=reloaded"
As a first step enable backup of the configuration files
pf_backup_conf: true
In case the configuration /etc/pf.conf does not pass the validation the play fails
TASK [vbotka.freebsd_pf : pfconf: Configure rules] **********************************************
fatal: [srv.example.com]: FAILED! => changed=false
checksum: 765302b1f0de9f200b2cab396e0271fc04e6adcc
exit_status: 1
msg: failed to validate
stderr: |-
/home/freebsd/.ansible/tmp/ansible-tmp-1554558267.39-44232067735996/source:119: syntax error
The message above shows the location of the syntax error (source:119) in the temporary file created by the template module. It's difficult to find the error if this temporary file is not available for a review.
Enable pf_conf_only=true and disable validation pf_conf_validate=false to find the problem
shell> ansible-playbook -e pf_conf_only=true -e pf_conf_validate=false freebsd-pf.yml
Locate the syntax error in the configuration file /etc/pf.conf
shell> pfctl -n -f /etc/pf.conf
Update, validate, and reload the rules after the configuration was fixed
shell> ansible srv.example.com -m service -a "name=pf state=reloaded"
The same way it is possible to troubleshoot /usr/local/etc/relayd.conf
shell> ansible-playbook -t pf_relayd -e pf_debug=true -e pf_relayd_conf_validate=false -e pf_relayd_conf_only=true freebsd-pf.yml
Locate the syntax error in the configuration file /usr/local/etc/relayd.conf
shell> relayd -n -f /usr/local/etc/relayd.conf
Update, validate, and reload the rules after the configuration was fixed
shell> ansible srv.example.com -m service -a "name=relayd state=reloaded"
To prevent not-validated configuration to be reloaded by the handler configuration file /etc/pf.conf won't be created and the play will be terminated if both pf_conf_only=false and pf_conf_validate=false
shell> ansible-playbook -e pf_conf_only=false -e pf_conf_validate=false freebsd-pf.yml
fatal: [srv.example.com]: FAILED! => changed=false
msg: Validation can be turned off if pf_conf_only=True. End of play.
The role fails the same way in case -e pf_relayd_conf_only=false -e pf_relayd_conf_validate=false
Use the configuration file .ansible-lint.local when running ansible-lint. Some rules might be disabled and some warnings might be ignored. See the notes in the configuration file.
shell> ansible-lint -c .ansible-lint.local
- Book of PF
- Firewalling with OpenBSD's PF packet filter
- A Beginner's Guide To Firewalling with pf
- PF Testing Your Firewall - OpenBSD Journal
- Quick setup of jail on ZFS using ezjail with PF NAT
- FreeBSD and blacklistd
- Blacklistd on FreeBSD
- PF and sshguard
- Enforcing Fail2ban bans with PF
- Fail2Ban with PF
- Fail2Ban pf.conf: fix multiport syntax