PF-BADHOST(8) System Manager's Manual PF-BADHOST(8)

pf-badhostfetch, validate and parse blocklist data for pf

pf-badhost [-4 | -6 | -B] [-ADVbnx] [-C config-file] [-H maxauthtries [-E extract-tool -J log-file -K log-file]] [-P maxprocs] [-R retrylimit] [-T allow|block|block-exit] [-U useragent] [-W output-file] [-a asn] [-f blocklist-file] [-g cctld] [-j asn-file] [-l url-file] [-m asn-url-file] [-o long-option] [-r rule] [-s cctld-file] [-t asn-url] [-u url] [-w rule-file] [file ...]

pf-badhost -h | -v

pf-badhost fetches, validates and parses IP, ASN, and geo-location data into a format suitable for ingestion by the pf(4) firewall.

By default the generated blocklist is output to the file /etc/pf-badhost.txt and loaded into a pf(4) table named .

pf-badhost expects to be run as an unprivileged user named _pfbadhost. This user must have permission to use pfctl(8) granted to it via either doas(1) or sudo(1).

Blocklists may be generated and exported to stdout without any special permissions.

Comments can be included in the various files passed to pf-badhost by starting the line with a hash mark (‘#’) or semi-colon (‘;’) and will continue to the end of the line.

The options are as follows:

Generate an IPv4-only blocklist. This is the default behavior.
Generate an IPv6-only blocklist.
Enable IP subnet aggregation. This option will format blocklist data into the smallest possible representation using CIDR notation. It is strongly recommended to enable this option when performing Geoblocking, ASN or bogon filtering.
Generate a mixed IPv4 and IPv6 blocklist.
config-file
Specify path to a configuration file.
Disable UID checking. Normally pf-badhost expects to be run as the unpriviliged user _pfbadhost and this option disables that check.
extract-tool
Specify sshd(8) authlog decompression tool. Typically either zcat(1) or bzcat(1) is used.
maxauthtries
Enable sshd(8) authentication log analysis. This will search the system logs for sshd(8) bruteforcers and add any IP addresses to the blocklist which have failed int or more login attempts.

When enabled, the systems default authentication logs will be used. Alternate log files can be passed with the -J and -K options.

log-file
Specify path to an sshd(8) authentication log to be searched for bruteforcers. This file may optionally be compressed.
log-file
Specify path to a secondary sshd(8) authentication log to be searched for bruteforcers. This file may optionally be compressed.
maxproc
Set the maximum number of processes to run in parallel. Default is 3. 0 can be specified to disable this feature.
retrylimit
Set the maximum number of URL fetch attempts. Default is 5. The behavior of this option varies based upon specified URL fetch utility. 0 can be specified to disable re-attempts.
arg
Enable Tor filtering. Valid arguments are:

Whitelist all Tor relays and exit nodes.
Block all Tor relays and exit nodes.
Block all Tor exit nodes.
useragent
Define a custom HTTP user agent.
Disable printing all non-fatal error messages.
output-file
Specify path to a file to output the generated blocklist to.
asn
Specify a single ASN to block. This option is case insensitive and can be specified multiple times.
Enable bogon filtering.
blocklist-file
Specify path to a file containing IP blocklist data.
cctld
Specify a two letter ISO 3166 country code to block. This option is case insensitive and can be specified multiple times.
Print the help message and exit.
asn-file
Specify path to a file containing a list of one or more ASNs to block. ASNs must be formatted one per line.
url-file
Specify path to a file containing a list of one or more IP blocklist URLs to fetch. URLs must be formatted one per line. Supports HTTP(S) and FTP URLs. Support for additional URL schemas is dependent upon the URL fetch utility used. This option may be specified multiple times.
asn-url-file
Specify path to a file containing a list of one or more ASN blocklist URLs to fetch. URLs must be formatted one per line. Supports HTTP(S) and FTP URLs. Support for additional URL schemas is dependent upon the URL fetch utility used. This option may be specified multiple times.
Check that the configuration is valid and exit.
long-option
In addition to short command line options, some options are supported in long form. This option may be specified multiple times.

|
Enable/disable the use of the CUSTOM_FILTER function from an external configuration file specified with the -C option. Disabled by default.
Export raw blocklist data with no embedded statistics, dates, or comments etc. Disable printing all non-fatal error messages.
|
Enable/disable whitelisting IPv4 addresses from the IANA IPv4 Special-Purpose Address Registry. Enabled by default.
|
Enable/disable whitelisting IPv6 addresses from the IANA IPv6 Special-Purpose Address Registry. Enabled by default.
|
Enable/disable logging of all informational and warning messages. Enabled by default.
|
Enable/disable the use of RIR GitHub mirror. Enabled by default.
Print debugging information/statistics and exit.
Enable alternate regex for SSH authlog analysis with password authentication disabled. See -H description. Use of this option with SSH password authentication enabled will likely result in incorrect accounting of bruteforcer attempts.
|
Enable/disable aborting when a blocklist fails to download. Enabled by default.
|
Enable/disable the forced use of the _pfbadhost user. See -D description. Enabled by default.
|
Enabled/disable printing of all informational and non-fatal errors messages. Enabled by default.

The following URL fetch utilities are supported and unless overridden by defining one of the options below, will be used in the following order of preference if found on the system: aria2c, wget, curl, fetch, ftp.

Use aria2c.
Use curl.
Use the FreeBSD fetch(1) utility.
Use the OpenBSD ftp(1) utility.
Use wget.

The following grep(1) utilities are supported and unless overridden by defining one of the options below, will be used in the following order of preference if found on the system: ripgrep, ugrep, ggrep, grep.

Use GNU grep.
Use the systems default grep(1).
Use ripgrep.
Use ugrep.

The following awk(1) utilities are supported and unless overridden by defining one of the options below, will be used in the following order of preference if found on the system: mawk, gawk, goawk, awk.

Use the systems default awk(1).
Use GNU awk.
Use GoAWK.
Use mawk.
rule
Specify a custom rule to add to the blocklist. A valid rule consists of an IP address or CIDR range optionally prefaced with an exclamation mark (‘!’) for whitelisting. This option may be specified multiple times.
cctld-file
Specify path to a file containing one or more two letter ISO 3166 country codes to block. Country codes must be formatted one per line and are case insensitive.
asn-url
Specify a single URL to fetch ASN blocklist data from. Supports HTTP(S) and FTP URLs. Support for additional URL schemas is dependent upon the URL fetch utility used. This option may be specified multiple times.
url
Specify a single URL to fetch IP blocklist data from. Supports HTTP(S) and FTP URLs. Support for additional URL schemas is dependent upon the URL fetch utility used. This option may be specified multiple times.
Print version information and exit.
rule-file
Specify path to a file containing a list of one or more custom rules. A valid rule consists of an IP address or CIDR range optionally prefaced with an exclamation mark (‘!’) for whitelisting. Rules must be formatted one per line. This option may be specified multiple times.
Print the generated blocklist to stdout instead of adding to pf(4). Use of this option implies -D and -o no-log.

The pf-badhost utility exits 0 on success, and >0 if an error occurs.

Fetch IP blocklist data from URL list and print to stdout:

# doas -u _pfbadhost pf-badhost -Bxl /etc/pf-badhost/urls

Verify configuration file validity:

# doas -u _pfbadhost pf-badhost -C /etc/pf-badhost.conf -n

Block bogons and specify custom rule to whitelist local subnet:

# doas -u _pfbadhost pf-badhost -br '!192.0.2.0/24'

Block an aggregated list of all IP addresses registered to Australia:

# doas -u _pfbadhost pf-badhost -ABg AU

Block an aggregated list of all IPv4 addresses announced from Apple's ASN:

# doas -u _pfbadhost pf-badhost -4Aa AS714

Enforce sanctions by blocking a list of country codes from a file:

# doas -u _pfbadhost pf-badhost -s /etc/pf-badhost/axis-of-evil

Add any IP address with 25 or more failed sshd(8) logins to blocklist:

# doas -u _pfbadhost pf-badhost -H 25

Enabled sshd(8) authentication log analysis with custom paths:

# doas -u _pfbadhost pf-badhost -H 25 -J /tmp/authlog

pf(4), pf.conf(5), pfctl(8)

pf-badhost does not strictly conform to the POSIX shell specification and instead aims for ksh(1) compatibility.

Jordan Geoghegan <jordan@geoghegan.ca>

The IPv6 address parser may fail to match against IPv6 addresses terminated with a carriage return (0x0d). This is due to a limitation in both BSD and GNU grep(1) but can be mitigated by using ripgrep or ugrep.

The IPv6 address parser requires addresses to be formatted one per line. This is in contrast to the IPv4 address parser which supports arbitrary input formatting (text, JSON, XML, HTML, etc).

On platforms that use FreeGrep (OpenBSD, MacOS) performance may be very slow and may even (on MacOS) segfault on the IPv6 regex. It is strongly recommended to replace the use of FreeGrep with ripgrep or ugrep.

If the _pfbadhost table exceeds the default pf(4) table size limit of 100,000 entries then the limit will need to be raised. Users with large blocklists are additionally encouraged to enable subnet aggregation. The pf(4) table size limit can be raised by adding the following line to pf.conf(5).

set limit table-entries 500000
June 21, 2021 OpenBSD 6.8