PFSENSE - PFCTL Basic Usage: Difference between revisions

From IT-Arts.net
No edit summary
No edit summary
Line 1: Line 1:
[[Category:Wiki]]
[[Category:wiki]]


The `pfctl` command is a powerful tool for managing the packet filter (PF) in pfSense, providing advanced capabilities for controlling, monitoring, and debugging firewall rules and states. This documentation covers advanced usage scenarios with examples for better understanding.
== Packet Filter architecture ==
pfctl is the userland control utility for PF (Packet Filter), the stateful firewall subsystem originating from OpenBSD and integrated into pfSense (FreeBSD-based). pfSense dynamically generates PF rules from its configuration and loads them into the kernel via pfctl.


== pfctl Command Overview ==
PF operates using:
* Stateful inspection
* Rule evaluation from top to bottom
* First matching rule (with quick exceptions)
* Separate rule sets for filtering, NAT, redirection, and normalization
* Anchors for modular rule management (heavily used by pfSense)


The `pfctl` command interacts with the PF firewall by managing states, rules, queues, and NAT configuration. It is a crucial tool for pfSense administrators who need to fine-tune firewall settings, troubleshoot issues, or examine the current state of the firewall.
== Rule evaluation flow ==
* Packet enters interface
* Normalization rules (scrub) applied
* NAT / RDR processed
* Filtering rules evaluated
* State table checked/updated
* Packet passed or blocked


General Syntax
== Anchors and pfSense integration ==
pfSense uses anchors extensively to isolate automatically generated rules:
* <nowiki>pfSense</nowiki>
* <nowiki>pfSense/*</nowiki>
* <nowiki>relayd</nowiki>


Anchors allow dynamic insertion and removal of rules without reloading the entire ruleset.
Example:
  <nowiki>
  <nowiki>
pfctl [options]</nowiki>
pfctl -a pfSense -sr</nowiki>


The options provide the functionality for various tasks such as listing rules, monitoring states, and managing filters.
== State table management ==
PF is a stateful firewall; every allowed connection is tracked.


== Viewing Firewall Information ==
Display states:
<nowiki>
pfctl -s state</nowiki>


To view general information about the firewall, including statistics about the packet filter (PF), you can run:
Kill a specific state:
<nowiki>
pfctl -k 192.0.2.10 -k 198.51.100.20</nowiki>


Clear all states:
  <nowiki>
  <nowiki>
pfctl -s info</nowiki>
pfctl -Fs</nowiki>


This command displays details such as the number of rules, states, packets processed, and the status of PF. Example output might look like:
=== Tables and dynamic address management ===
PF tables provide high-performance lookups for large address lists.


List tables:
  <nowiki>
  <nowiki>
Status: Enabled for 56 days 2 hours 31 minutes
pfctl -s Tables</nowiki>
Filters: 8 rules
States: 1454 active, 220 new</nowiki>


Displaying Firewall Rules
Show table content:
 
<nowiki>
To display all active rules, run:
pfctl -t bogons -T show</nowiki>


Add an IP to a table:
  <nowiki>
  <nowiki>
pfctl -sr</nowiki>
pfctl -t blocked_hosts -T add 203.0.113.45</nowiki>
 
This shows the entire ruleset in use by PF, which could include rules for filtering traffic, NAT, and queueing.
 
If you want to filter and see only specific types of rules (such as NAT rules), you can use:


Remove an IP:
  <nowiki>
  <nowiki>
pfctl -sn</nowiki>
pfctl -t blocked_hosts -T delete 203.0.113.45</nowiki>
 
This will show only the NAT rules configured in PF.
 
Viewing Active States and Connections
 
To view the list of active states or connections, use:


=== NAT and redirection inspection ===
Display NAT rules:
  <nowiki>
  <nowiki>
pfctl -ss</nowiki>
pfctl -s nat</nowiki>
 
This command displays active states (connections) in the firewall, which could be essential for monitoring real-time traffic or troubleshooting connectivity issues. For example:


Display redirection rules:
  <nowiki>
  <nowiki>
TCP 192.168.1.100:12345 -> 93.184.216.34:80
pfctl -s rdr</nowiki>
TCP 192.168.1.101:34567 -> 216.58.204.14:443</nowiki>
 
Each line represents an established or related connection with source and destination IPs and ports.
 
Flushing Rules and States
 
To clear the active states (flush states), use the following command:


Show all translation rules:
  <nowiki>
  <nowiki>
pfctl -F states</nowiki>
pfctl -s rules | grep nat</nowiki>


This is useful when you need to reset all active connections, such as after a change in firewall rules.
=== Rule counters and performance metrics ===
 
PF tracks packets and bytes per rule.
To flush (clear) all rules from the firewall, use:


Show rules with counters:
  <nowiki>
  <nowiki>
pfctl -F rules</nowiki>
pfctl -vvsr</nowiki>
 
This command removes the entire ruleset, effectively disabling filtering until new rules are loaded.
 
Reloading the pf Configuration
 
To reload the PF configuration after editing `/etc/pf.conf` or after changes in the firewall rules, use:


Reset counters:
  <nowiki>
  <nowiki>
pfctl -f /etc/pf.conf</nowiki>
pfctl -z</nowiki>


This will reapply the entire configuration, ensuring the latest rules are in effect.
This is critical for traffic analysis and policy validation.


Enabling and Disabling the Firewall
=== Normalization and packet scrubbing ===
 
Scrub rules normalize packets to prevent evasion techniques:
You can temporarily disable the PF firewall with:
* MSS clamping
* Fragment reassembly
* Invalid flag dropping


Display scrub rules:
  <nowiki>
  <nowiki>
pfctl -d</nowiki>
pfctl -s all | grep scrub</nowiki>


This turns off the firewall, which might be useful for debugging or performing maintenance. To enable the firewall again:
== Security concepts ==


<nowiki>
=== Stateful filtering ===
pfctl -e</nowiki>
Only packets belonging to a valid state are allowed to pass, reducing attack surface.


It's important to be cautious when using these commands, as disabling the firewall could expose the system to potential security risks.
=== Default deny policy ===
 
pfSense enforces an implicit block at the end of rule sets.
== Managing IP Blocklists ==
 
You can dynamically manage IP blocklists using pfctl. For example, to add an IP address to a blocklist (such as blocking a malicious IP), use the following command:


Verify block rules:
  <nowiki>
  <nowiki>
pfctl -t blocklist -T add 192.168.1.100</nowiki>
pfctl -sr | grep block</nowiki>


This command adds the IP address `192.168.1.100` to a predefined table called `blocklist`. To remove an IP from the blocklist:
=== Antispoofing ===
PF can prevent IP spoofing on interfaces.


Example:
  <nowiki>
  <nowiki>
pfctl -t blocklist -T delete 192.168.1.100</nowiki>
antispoof quick for em0</nowiki>
 
Tables can be defined in the `/etc/pf.conf` configuration file, and the `-t` option is used to specify the table, while the `-T` option manages entries within that table.
 
== Debugging pfctl Output ==


If you need more detailed information for debugging purposes, you can add verbosity to any pfctl command. For example, to display detailed information about rules:
=== SYN flood protection ===
PF supports SYN proxies and connection rate limiting.


Example rule:
  <nowiki>
  <nowiki>
pfctl -v -s rules</nowiki>
pass in proto tcp from any to any flags S/SA keep state (max-src-conn 100, max-src-conn-rate 50/10)</nowiki>


The `-v` flag increases verbosity, showing additional information about the rules, including rule match statistics and more.
=== Table-based threat mitigation ===
Dynamic tables allow automatic blocking via IDS/IPS or scripts.


To debug rule matching for a specific source or destination, use the `-vv` flag for even more detailed output:
Example integration:
* Snort / Suricata populating PF tables
* Fail2ban-style blocking


<nowiki>
=== Logging and diagnostics ===
pfctl -vv -s rules</nowiki>
PF logs packets to pflog interfaces.
 
Monitoring Packets with pfctl
 
You can also monitor packet counters and match statistics with:


Enable logging on a rule:
  <nowiki>
  <nowiki>
pfctl -s stats</nowiki>
pass in log proto tcp from any to any port 22</nowiki>
 
This will provide statistics on the number of packets that matched a specific rule, the number of packets dropped, passed, or rejected, and more. Example output might look like:


View logs:
  <nowiki>
  <nowiki>
match 2345 pass 1432 block 80
tcpdump -n -e -ttt -i pflog0</nowiki>
total 5800</nowiki>


This is useful for assessing the impact of specific firewall rules.
== Troubleshooting ==


== Managing NAT Rules ==
=== Rules not matching ===
 
* Verify rule order
To manage Network Address Translation (NAT) settings, pfctl provides an option to list NAT rules:
* Check for quick rules
* Inspect active rules instead of GUI configuration


  <nowiki>
  <nowiki>
pfctl -sn</nowiki>
pfctl -sr</nowiki>


To view NAT statistics, use:
=== NAT not working ===
* Confirm NAT rules are loaded
* Ensure outbound NAT mode is correct
* Check rule auto-generation


  <nowiki>
  <nowiki>
pfctl -s nat</nowiki>
pfctl -s nat</nowiki>


This command shows the NAT states, including address translations and port forwarding rules. You can also use pfctl to apply NAT settings dynamically after modifications in the `/etc/pf.conf` file.
=== Traffic blocked unexpectedly ===
 
* Inspect states
Controlling Packet Queueing and Limitations
* Check floating rules
 
* Analyze logs in pflog
You can manage packet queueing for traffic shaping and bandwidth control by using:


  <nowiki>
  <nowiki>
pfctl -sq</nowiki>
pfctl -s state</nowiki>


This command lists all the configured queues and their current status, including packet counts and throughput. To add or modify queue settings, you would typically edit the `/etc/pf.conf` file and then reload the configuration using:
=== Performance degradation ===
* Check state table size
* Inspect table sizes
* Reset counters and monitor


  <nowiki>
  <nowiki>
pfctl -f /etc/pf.conf</nowiki>
pfctl -si</nowiki>
 
Viewing Anchor Rules
 
In pfSense, you can configure rules that act as anchors, allowing for more modular configurations. To list all anchor rules, use:
 
<nowiki>
pfctl -sa</nowiki>
 
This will show all loaded anchors and the rules associated with each anchor.


== Conclusion ==
=== Rules disappear after reload ===
pfSense regenerates rules automatically. Manual pfctl changes are ephemeral and overwritten on reload or reboot.


The `pfctl` command in pfSense is an advanced and powerful tool for managing the PF firewall. Whether you're managing states, modifying rules dynamically, debugging firewall traffic, or configuring NAT and queues, `pfctl` provides the flexibility and control needed for sophisticated network security management. By mastering `pfctl`, administrators can fine-tune their pfSense configurations to meet their unique security and networking requirements.
=== Useful links ===
* https://man.openbsd.org/pfctl
* https://man.openbsd.org/pf.conf
* https://docs.netgate.com/pfsense/en/latest/firewall/index.html
* https://www.freebsd.org/cgi/man.cgi?query=pfctl
* https://www.openbsd.org/faq/pf/

Revision as of 19:28, 12 January 2026


Packet Filter architecture

pfctl is the userland control utility for PF (Packet Filter), the stateful firewall subsystem originating from OpenBSD and integrated into pfSense (FreeBSD-based). pfSense dynamically generates PF rules from its configuration and loads them into the kernel via pfctl.

PF operates using:

  • Stateful inspection
  • Rule evaluation from top to bottom
  • First matching rule (with quick exceptions)
  • Separate rule sets for filtering, NAT, redirection, and normalization
  • Anchors for modular rule management (heavily used by pfSense)

Rule evaluation flow

  • Packet enters interface
  • Normalization rules (scrub) applied
  • NAT / RDR processed
  • Filtering rules evaluated
  • State table checked/updated
  • Packet passed or blocked

Anchors and pfSense integration

pfSense uses anchors extensively to isolate automatically generated rules:

  • pfSense
  • pfSense/*
  • relayd

Anchors allow dynamic insertion and removal of rules without reloading the entire ruleset.

Example:

pfctl -a pfSense -sr

State table management

PF is a stateful firewall; every allowed connection is tracked.

Display states:

pfctl -s state

Kill a specific state:

pfctl -k 192.0.2.10 -k 198.51.100.20

Clear all states:

pfctl -Fs

Tables and dynamic address management

PF tables provide high-performance lookups for large address lists.

List tables:

pfctl -s Tables

Show table content:

pfctl -t bogons -T show

Add an IP to a table:

pfctl -t blocked_hosts -T add 203.0.113.45

Remove an IP:

pfctl -t blocked_hosts -T delete 203.0.113.45

NAT and redirection inspection

Display NAT rules:

pfctl -s nat

Display redirection rules:

pfctl -s rdr

Show all translation rules:

pfctl -s rules | grep nat

Rule counters and performance metrics

PF tracks packets and bytes per rule.

Show rules with counters:

pfctl -vvsr

Reset counters:

pfctl -z

This is critical for traffic analysis and policy validation.

Normalization and packet scrubbing

Scrub rules normalize packets to prevent evasion techniques:

  • MSS clamping
  • Fragment reassembly
  • Invalid flag dropping

Display scrub rules:

pfctl -s all | grep scrub

Security concepts

Stateful filtering

Only packets belonging to a valid state are allowed to pass, reducing attack surface.

Default deny policy

pfSense enforces an implicit block at the end of rule sets.

Verify block rules:

pfctl -sr | grep block

Antispoofing

PF can prevent IP spoofing on interfaces.

Example:

antispoof quick for em0

SYN flood protection

PF supports SYN proxies and connection rate limiting.

Example rule:

pass in proto tcp from any to any flags S/SA keep state (max-src-conn 100, max-src-conn-rate 50/10)

Table-based threat mitigation

Dynamic tables allow automatic blocking via IDS/IPS or scripts.

Example integration:

  • Snort / Suricata populating PF tables
  • Fail2ban-style blocking

Logging and diagnostics

PF logs packets to pflog interfaces.

Enable logging on a rule:

pass in log proto tcp from any to any port 22

View logs:

tcpdump -n -e -ttt -i pflog0

Troubleshooting

Rules not matching

  • Verify rule order
  • Check for quick rules
  • Inspect active rules instead of GUI configuration
pfctl -sr

NAT not working

  • Confirm NAT rules are loaded
  • Ensure outbound NAT mode is correct
  • Check rule auto-generation
pfctl -s nat

Traffic blocked unexpectedly

  • Inspect states
  • Check floating rules
  • Analyze logs in pflog
pfctl -s state

Performance degradation

  • Check state table size
  • Inspect table sizes
  • Reset counters and monitor
pfctl -si

Rules disappear after reload

pfSense regenerates rules automatically. Manual pfctl changes are ephemeral and overwritten on reload or reboot.