370 Configure pf
Use case
Use the role vbotka.freebsd.pf to configure pf.
Tree
shell> tree .
.
├── ansible.cfg
├── host_vars
│ └── iocage_04.yml
├── iocage.ini
└── pb.yml
Synopsis
The Ansible controller connects to the iocage host
iocage_04at IP 10.1.0.29 configured in/etc/rc.conf:cloned_interfaces="bridge0" create_args_bridge0="addm igb0" ifconfig_bridge0="inet 10.1.0.29/24" ifconfig_igb0="up -tso -vlanhwtso"
In the playbook
pb.ymlforiocage_04, configure:blacklistd, fail2ban, and sshguard
NAT
log all blocked
pass from localnet to any
Requirements
Role vbotka.freebsd.pf
Root privileges on the managed nodes.
Notes
TBD
Note
vbotka.freebsd.pf is the role pf in the collection vbotka.freebsd.
vbotka.freebsd_pf is the role freebsd_pf in the namespace vbotka.
See also
FreeBSD Handbook Firewalls
FreeBSD Forum pf and bridge
ansible.cfg
[defaults]
callback_result_format = yaml
display_skipped_hosts = False
gathering = explicit
interpreter_python = auto_silent
log_path = /var/log/ansible.log
deprecation_warnings = False
[connection]
pipelining = true
Inventory iocage.ini
iocage_04 ansible_host=10.1.0.29
[iocage]
iocage_04
[iocage:vars]
ansible_user=admin
ansible_become=true
ansible_python_interpreter=auto_silent
host_vars
host_vars/iocage_04.yml
pf_install: false
pf_blacklistd: true
pf_fail2ban: true
pf_sshguard: true
pf_enable: true
pf_blacklistd_enable: true
pf_fail2ban_enable: true
pf_sshguard_enable: true
pf_log_enable: true
pf_backup_conf: true
# /etc/pf.conf
pf_type: default2
pf_ext_if: bridge0
pf_log_all_blocked: log
pf_pass_icmp_types: [echoreq, unreach]
pf_pass_icmp6_types: [echoreq, unreach]
pf_local_net: 10.1.0.0/24
pf_macros:
ext_if: "{{ pf_ext_if }}"
localnet: "{{ pf_local_net }}"
logall: "{{ pf_log_all_blocked }}"
icmp_types: "{{ pf_pass_icmp_types }}"
icmp6_types: "{{ pf_pass_icmp6_types }}"
# pf blocks
pf_options:
- set skip on lo0
- set block-policy return
- set loginterface $ext_if
pf_tables:
- table <sshabuse> persist
pf_normalization:
- scrub in on $ext_if all fragment reassemble
pf_translation:
- nat on $ext_if from $localnet to any -> ($ext_if)
pf_filtering:
- antispoof for $ext_if
- "{{ pf_anchors }}"
- block $logall all
- pass inet proto icmp icmp-type $icmp_types
- pass inet6 proto icmp6 icmp6-type $icmp6_types
- pass from { self, $localnet } to any keep state
# blacklistd
pf_blacklistd_conf_local:
- {adr: ssh, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
- {adr: ftp, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
- {adr: smtp, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
- {adr: smtps, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
- {adr: submission, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
- {adr: '*', type: '*', proto: '*', owner: '*', name: '*', nfail: '3', disable: '60'}
pf_blacklistd_flags: '-r'
pf_blacklistd_rcconf:
- {name: blacklistd_flags, value: "{{ pf_blacklistd_flags }}"}
Playbook pb.yml
- name: Test role vbotka.freebsd.pf
hosts: iocage
gather_facts: true
roles:
- vbotka.freebsd.pf
Playbook output - Install packages
(env) > ansible-playbook -i iocage.ini \
-t pf_packages -e pf_install=true \
pb.yml
PLAY [Test role vbotka.freebsd.pf] *********************************************
TASK [Gathering Facts] *********************************************************
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Packages: Install packages.] *************************
ok: [iocage_04]
PLAY RECAP *********************************************************************
iocage_04 : ok=2 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
Playbook output - Configure pf
Starting and restarting the firewall breaks active SSH connections (see the handlers for details). Consequently, both the start and reload handlers can fail to complete cleanly, causing the SSH session to go stale. Therefore, configure the rules first before enabling the service:
(env) > ansible-playbook -i iocage.ini -e pf_enable=false pb.yml
PLAY [Test role vbotka.freebsd.pf] *********************************************
TASK [Gathering Facts] *********************************************************
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Rcconf-blacklistd: Stat /etc/rc.d/blacklistd] ********
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Blacklistd: Backup /etc/blacklistd.conf.orig] ********
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Blacklistd: Configure /etc/blacklistd.conf] **********
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Rcconf-fail2ban: Stat /usr/local/etc/rc.d/fail2ban] ***
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Fail2ban: Configure /usr/local/etc/fail2ban/fail2ban.local] ***
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Fail2ban: Configure /usr/local/etc/fail2ban/jail.local] ***
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Rcconf-sshguard: Stat /usr/local/etc/rc.d/sshguard] ***
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Configure sshguard.conf] *****************************
ok: [iocage_04] => (item={'key': 'BACKEND', 'value': '/usr/local/libexec/sshg-fw-pf'})
ok: [iocage_04] => (item={'key': 'WHITELIST_FILE', 'value': '/usr/local/etc/sshguard.whitelist'})
TASK [vbotka.freebsd.pf : Pfconf: Configure and validate rules using template default2-pf.conf.j2] ***
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Rcconf-blacklistd: Enable and start blacklistd.] *****
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Rcconf-blacklistd: Configure blacklistd.] ************
ok: [iocage_04] => (item={'name': 'blacklistd_flags', 'value': '-r'})
TASK [vbotka.freebsd.pf : Rcconf-fail2ban: Enable and start fail2ban.] *********
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Rcconf-fail2ban: Configure fail2ban.] ****************
ok: [iocage_04] => (item={'name': 'fail2ban_flags', 'value': ''})
TASK [vbotka.freebsd.pf : Rcconf-sshguard: Enable and start sshguard.] *********
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Rcconf-pf: Disable and stop pf.] *********************
changed: [iocage_04]
TASK [vbotka.freebsd.pf : Rcconf-pflog: Enable and start pflog.] ***************
ok: [iocage_04]
RUNNING HANDLER [vbotka.freebsd.pf : Disable and stop pf] **********************
changed: [iocage_04]
PLAY RECAP *********************************************************************
iocage_04 : ok=18 changed=2 unreachable=0 failed=0 skipped=39 rescued=0 ignored=0
Playbook output - Enable pf
(env) > ansible-playbook -i iocage.ini -t pf_rcconf_pf pb.yml
PLAY [Test role vbotka.freebsd.pf] *********************************************
TASK [Gathering Facts] *********************************************************
ok: [iocage_04]
TASK [vbotka.freebsd.pf : Rcconf-pf: Enable and start pf.] *********************
changed: [iocage_04]
RUNNING HANDLER [vbotka.freebsd.pf : Start pf] *********************************
changed: [iocage_04]
PLAY RECAP *********************************************************************
iocage_04 : ok=3 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
Result
pf status
shell> ssh admin@10.1.0.29 sudo service pf status
Status: Disabled for 0 days 00:00:04 Debug: Urgent
Interface Stats for bridge0 IPv4 IPv6
Bytes In 0 0
Bytes Out 0 0
Packets In
Passed 233387 987
Blocked 394 0
Packets Out
Passed 0 0
Blocked 174948 0
State Table Total Rate
current entries 164
searches 426626 106656.5/s
inserts 8549 2137.2/s
removals 8385 2096.2/s
Counters
match 12205 3051.2/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 107 26.8/s
proto-cksum 872 218.0/s
state-mismatch 6 1.5/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
translate 0 0.0/s
/etc/pf.conf
shell> ssh admin@10.1.0.29 cat /etc/pf.conf
# Ansible managed
# template: default2-pf.conf.j2
# MACROS
ext_if = "bridge0"
localnet = "10.1.0.0/24"
logall = "log"
icmp_types = "{ echoreq, unreach }"
icmp6_types = "{ echoreq, unreach }"
# TABLES
table <sshabuse> persist
# OPTIONS
set skip on lo0
set block-policy return
set loginterface $ext_if
# NORMALIZATION
scrub in on $ext_if all fragment reassemble
# TRANSLATION
nat on $ext_if from $localnet to any -> ($ext_if)
# FILTERING
antispoof for $ext_if
anchor "blacklistd/*" in on $ext_if
anchor "f2b/*"
block $logall all
pass inet proto icmp icmp-type $icmp_types
pass inet6 proto icmp6 icmp6-type $icmp6_types
pass from { self, $localnet } to any keep state
# EOF