<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Pfctl on inetshell</title><link>https://inet.sh/en/tags/pfctl/</link><description>Recent content in Pfctl on inetshell</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 25 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/en/tags/pfctl/index.xml" rel="self" type="application/rss+xml"/><item><title>pfctl: table cheat sheet for pfSense, OPNsense and FreeBSD</title><link>https://inet.sh/en/posts/pfsense/pfctl-tables-cheat-sheet/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/pfsense/pfctl-tables-cheat-sheet/</guid><description>pfctl -t/-T commands for PF tables: list, show, add, delete, test, flush, reload from a file and expire entries. With pfSense&amp;#39;s internal tables (sshguard, virusprot, snort2c, bogons, aliases and pfBlockerNG) and what gets lost on a filter reload.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">pfctl -sT                                    <span class="c1"># loaded tables</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;table&gt; -T show                     <span class="c1"># contents</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;table&gt; -T add 192.168.1.10         <span class="c1"># add an IP or network (10.20.0.0/16 works too)</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;table&gt; -T delete 192.168.1.10
</span></span><span class="line"><span class="cl">pfctl -t &lt;table&gt; -T <span class="nb">test</span> 192.168.1.10        <span class="c1"># is it inside? (match / no match)</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;table&gt; -T flush                    <span class="c1"># empty the table</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;table&gt; -T replace -f /path/list    <span class="c1"># replace the whole contents from a file</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">pfctl -t sshguard -T flush                   <span class="c1"># pfSense: clear the failed-login lockout</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="what-a-table-is">What a table is</h2>
<p>A PF <strong>table</strong> is a set of addresses and networks that rules reference as <code>&lt;name&gt;</code>. It changes live, without reloading the ruleset, and holds thousands of entries with fast lookups; that is why PF uses tables for block lists, bogons, and anything that changes more often than the rules.</p>
<p>In <code>pf.conf</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">table &lt;blocklist&gt; persist file &#34;/etc/pf/blocklist.txt&#34;
</span></span><span class="line"><span class="cl">block in quick from &lt;blocklist&gt;
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>persist</code> keeps the table even when no rule uses it at the moment; <code>file</code> loads it from a file (one IP or network per line).</p>
<h2 id="commands">Commands</h2>
<p>All in the form <code>pfctl -t &lt;table&gt; -T &lt;command&gt;</code>:</p>
<table>
  <thead>
      <tr>
          <th>Command</th>
          <th>What it does</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>show</code></td>
          <td>Lists the entries. With <code>-v</code>, per-entry counters (packets/bytes in/out)</td>
      </tr>
      <tr>
          <td><code>add &lt;ip|net&gt; …</code></td>
          <td>Adds one or more entries</td>
      </tr>
      <tr>
          <td><code>delete &lt;ip|net&gt; …</code></td>
          <td>Removes entries</td>
      </tr>
      <tr>
          <td><code>test &lt;ip&gt; …</code></td>
          <td>Says whether the address falls inside the table (without touching it)</td>
      </tr>
      <tr>
          <td><code>flush</code></td>
          <td>Empties the table; the table keeps existing</td>
      </tr>
      <tr>
          <td><code>kill</code></td>
          <td>Deletes the whole table (if no rule uses it)</td>
      </tr>
      <tr>
          <td><code>replace -f &lt;file&gt;</code></td>
          <td>Swaps the entire contents for the file&rsquo;s, in a single operation</td>
      </tr>
      <tr>
          <td><code>expire &lt;seconds&gt;</code></td>
          <td>Deletes entries whose counters have been idle for more than N seconds</td>
      </tr>
      <tr>
          <td><code>zero</code></td>
          <td>Zeroes the table&rsquo;s counters (or one entry&rsquo;s, if you name it)</td>
      </tr>
  </tbody>
</table>
<p>And without <code>-t</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">pfctl -sT                    <span class="c1"># names of all tables</span>
</span></span><span class="line"><span class="cl">pfctl -vvsT                  <span class="c1"># global info per table: entries, evaluations, references</span>
</span></span><span class="line"><span class="cl">pfctl -T load -f /etc/pf.conf   <span class="c1"># reload only the table definitions from pf.conf</span>
</span></span><span class="line"><span class="cl">pfctl -sr <span class="p">|</span> grep <span class="s1">&#39;&lt;name&gt;&#39;</span>    <span class="c1"># which rules use a table</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="tables-on-pfsense">Tables on pfSense</h2>
<ul>
<li><strong>Aliases are tables.</strong> A Host, Network, or URL Table alias called <code>Admins</code> exists in PF as <code>&lt;Admins&gt;</code>; <code>pfctl -t Admins -T show</code> shows what pfSense resolved, including the FQDNs it already turned into IPs.</li>
<li><strong><code>sshguard</code></strong>: where IPs blocked for failed SSH or webGUI logins land. If you locked yourself out, <code>pfctl -t sshguard -T flush</code> (documented by Netgate under <a href="https://docs.netgate.com/pfsense/en/latest/troubleshooting/locked-out.html">Locked out of the WebGUI</a>).</li>
<li><strong><code>virusprot</code></strong>: hosts blocked for exceeding a rule&rsquo;s <em>Max. src. conn. rate</em> or <em>Max. states</em> limits. <code>pfctl -t virusprot -T show</code> and <code>-T delete &lt;ip&gt;</code> to release one.</li>
<li><strong><code>snort2c</code></strong>: Snort/Suricata blocks in legacy mode. <code>-T flush</code> to unblock everything.</li>
<li><strong><code>bogons</code> / <code>bogonsv6</code></strong>: the lists that update themselves when you enable <em>Block bogon networks</em> on an interface.</li>
<li><strong>pfBlockerNG</strong>: every list is a <code>pfB_*</code> alias. To know whether an IP is blocked by one: <code>pfctl -t pfB_Top_v4 -T test 203.0.113.7</code>.</li>
</ul>
<p>On OPNsense the mechanics are the same (<code>pfctl -sT</code> to see the names); the login lockout table is called <code>sshlockout</code>.</p>
<h2 id="what-gets-lost-on-reload">What gets lost on reload</h2>
<p>Any <code>-T add</code>, <code>-T delete</code>, or <code>-T flush</code> lives until the next <strong>filter reload</strong>: saving almost anything in the GUI, <code>Filter Reload</code> under Status → Filter Reload, or the alias update cron. At that point pfSense regenerates every table from its alias and your manual changes are gone. To make something permanent, edit the alias; for quick tests and unblocking, <code>pfctl</code> is perfect.</p>
<h2 id="beyond-tables">Beyond tables</h2>
<p>What gets used most alongside the above:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">pfctl -sr                    <span class="c1"># loaded rules (with -vv, counters and rule numbers)</span>
</span></span><span class="line"><span class="cl">pfctl -ss                    <span class="c1"># state table</span>
</span></span><span class="line"><span class="cl">pfctl -si                    <span class="c1"># global statistics</span>
</span></span><span class="line"><span class="cl">pfctl -k 192.168.1.10        <span class="c1"># kill a host&#39;s states</span>
</span></span><span class="line"><span class="cl">pfctl -F states              <span class="c1"># kill all states (cuts every connection)</span>
</span></span><span class="line"><span class="cl">pfctl -d / pfctl -e          <span class="c1"># disable / enable PF (no PF means no NAT: only to get out of a lockout)</span>
</span></span><span class="line"><span class="cl">pfctl -nf /etc/pf.conf       <span class="c1"># syntax check without loading</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Full reference: the OpenBSD Handbook&rsquo;s <a href="https://www.openbsdhandbook.com/pf/cheat_sheet/">pfctl cheat sheet</a> and <code>man pfctl</code> on FreeBSD.</p>
]]></content:encoded></item></channel></rss>