White space fix only. Translators can ignore.

Sponsored by: iXsystems
This commit is contained in:
Dru Lavigne 2014-02-18 22:23:51 +00:00
parent 9bb337e084
commit 73c10cce60
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=43988

View file

@ -628,15 +628,16 @@ pass proto udp to any port $udp_services keep state</programlisting>
<title>A Simple Gateway with NAT</title> <title>A Simple Gateway with NAT</title>
<para>This section demonstrates how to configure a &os; system <para>This section demonstrates how to configure a &os; system
running <application>PF</application> to act running <application>PF</application> to act as a gateway
as a gateway for at least one other machine. The gateway for at least one other machine. The gateway needs at least
needs at least two network interfaces, each connected to a two network interfaces, each connected to a separate
separate network. In this example, <filename>xl1</filename> is connected to the network. In this example, <filename>xl1</filename> is
Internet and <filename>xl0</filename> is connected to the internal network.</para> connected to the Internet and <filename>xl0</filename> is
connected to the internal network.</para>
<para>First, enable the gateway in order to let the <para>First, enable the gateway in order to let the machine
machine forward the network traffic it receives on one forward the network traffic it receives on one interface to
interface to another interface. This <application>sysctl</application> another interface. This <application>sysctl</application>
setting will forward <acronym>IPv4</acronym> packets:</para> setting will forward <acronym>IPv4</acronym> packets:</para>
<screen>&prompt.root; <userinput>sysctl net.inet.ip.forwarding=1</userinput></screen> <screen>&prompt.root; <userinput>sysctl net.inet.ip.forwarding=1</userinput></screen>
@ -645,73 +646,70 @@ pass proto udp to any port $udp_services keep state</programlisting>
<screen>&prompt.root; <userinput>sysctl net.inet6.ip6.forwarding=1</userinput></screen> <screen>&prompt.root; <userinput>sysctl net.inet6.ip6.forwarding=1</userinput></screen>
<para>To enable these settings at system boot, add the following <para>To enable these settings at system boot, add the
to following to <filename>/etc/rc.conf</filename>:</para>
<filename>/etc/rc.conf</filename>:</para>
<programlisting>gateway_enable="YES" #for ipv4 <programlisting>gateway_enable="YES" #for ipv4
ipv6_gateway_enable="YES" #for ipv6</programlisting> ipv6_gateway_enable="YES" #for ipv6</programlisting>
<para>Verify with <command>ifconfig</command> that <para>Verify with <command>ifconfig</command> that both of the
both of the interfaces are up and interfaces are up and running.</para>
running.</para>
<para>Next, create the <application>PF</application> rules to <para>Next, create the <application>PF</application> rules to
allow the gateway to pass traffic. While the following rule allows stateful traffic to allow the gateway to pass traffic. While the following rule
pass from the Internet allows stateful traffic to pass from the Internet to hosts
to hosts on the network, the <literal>to</literal> keyword does not on the network, the <literal>to</literal> keyword does not
guarantee passage all the way from source to destination:</para> guarantee passage all the way from source to
destination:</para>
<programlisting>pass in on xl1 from xl1:network to xl0:network port $ports keep state</programlisting> <programlisting>pass in on xl1 from xl1:network to xl0:network port $ports keep state</programlisting>
<para>That rule only lets the traffic pass in to the gateway on <para>That rule only lets the traffic pass in to the gateway
the internal interface. To let the packets go further, a on the internal interface. To let the packets go further, a
matching rule is needed:</para> matching rule is needed:</para>
<programlisting>pass out on xl0 from xl1:network to xl0:network port $ports keep state</programlisting> <programlisting>pass out on xl0 from xl1:network to xl0:network port $ports keep state</programlisting>
<para>While these two rules will work, rules this specific are <para>While these two rules will work, rules this specific are
rarely needed. For a busy network admin, a readable ruleset is a safer rarely needed. For a busy network admin, a readable ruleset
ruleset. The remainder of this section demonstrates how to is a safer ruleset. The remainder of this section
keep the rules as simple as possible demonstrates how to keep the rules as simple as possible for
for readability. For example, those two rules could be readability. For example, those two rules could be
replaced with one rule:</para> replaced with one rule:</para>
<programlisting>pass from xl1:network to any port $ports keep state</programlisting> <programlisting>pass from xl1:network to any port $ports keep state</programlisting>
<para>The <para>The <literal>interface:network</literal> notation can be
<literal>interface:network</literal> notation can be replaced with a macro to make the ruleset even more
replaced with a macro to make the ruleset even readable. For example, a <literal>$localnet</literal> macro
more readable. For example, a <literal>$localnet</literal> macro could could be defined as the network directly attached to the
be defined as the network directly attached to the
internal interface (<literal>$xl1:network</literal>). internal interface (<literal>$xl1:network</literal>).
Alternatively, the definition of Alternatively, the definition of
<literal>$localnet</literal> could be changed to an <literal>$localnet</literal> could be changed to an
<emphasis>IP address/netmask</emphasis> notation to denote <emphasis>IP address/netmask</emphasis> notation to denote
a network, such as <literal>192.168.100.1/24</literal> for a network, such as <literal>192.168.100.1/24</literal> for a
a subnet of private addresses.</para> subnet of private addresses.</para>
<para>If required, <literal>$localnet</literal> could even be <para>If required, <literal>$localnet</literal> could even be
defined as a list of networks. Whatever the specific needs, defined as a list of networks. Whatever the specific needs,
a sensible <literal>$localnet</literal> definition could be a sensible <literal>$localnet</literal> definition could be
used in a used in a typical pass rule as follows:</para>
typical pass rule as follows:</para>
<programlisting>pass from $localnet to any port $ports keep state</programlisting> <programlisting>pass from $localnet to any port $ports keep state</programlisting>
<para>The following sample ruleset allows all traffic initiated by <para>The following sample ruleset allows all traffic
machines on the internal network. It first defines two initiated by machines on the internal network. It first
macros to represent the external and internal 3COM interfaces of defines two macros to represent the external and internal
the gateway.</para> 3COM interfaces of the gateway.</para>
<note> <note>
<para>For dialup users, the external interface will use <para>For dialup users, the external interface will use
<filename>tun0</filename>. For an <filename>tun0</filename>. For an
<acronym>ADSL</acronym> connection, specifically those <acronym>ADSL</acronym> connection, specifically those
using <acronym>PPP</acronym> over Ethernet (<acronym>PPPoE</acronym>), the correct external using <acronym>PPP</acronym> over Ethernet
interface is <filename>tun0</filename>, (<acronym>PPPoE</acronym>), the correct external
not the physical Ethernet interface is <filename>tun0</filename>, not the physical
interface.</para> Ethernet interface.</para>
</note> </note>
<programlisting>ext_if = "xl0" # macro for external interface - use tun0 for PPPoE <programlisting>ext_if = "xl0" # macro for external interface - use tun0 for PPPoE
@ -722,20 +720,20 @@ nat on $ext_if from $localnet to any -&gt; ($ext_if)
block all block all
pass from { lo0, $localnet } to any keep state</programlisting> pass from { lo0, $localnet } to any keep state</programlisting>
<para>This ruleset introduces the <literal>nat</literal> rule which is used to <para>This ruleset introduces the <literal>nat</literal> rule
handle the network address translation from the which is used to handle the network address translation from
non-routable addresses inside the internal network to the <acronym>IP</acronym> address the non-routable addresses inside the internal network to
assigned to the external interface. The parentheses surrounding the last part of the nat the <acronym>IP</acronym> address assigned to the external
rule <literal>($ext_if)</literal> is included interface. The parentheses surrounding the last part of the
when the <acronym>IP</acronym> address of the external nat rule <literal>($ext_if)</literal> is included when the
interface is dynamically assigned. It <acronym>IP</acronym> address of the external interface is
ensures that network traffic runs without serious dynamically assigned. It ensures that network traffic runs
interruptions even if the external <acronym>IP</acronym> address without serious interruptions even if the external
changes.</para> <acronym>IP</acronym> address changes.</para>
<para>Note that this ruleset probably allows more <para>Note that this ruleset probably allows more traffic to
traffic to pass out of the network than is needed. pass out of the network than is needed. One reasonable
One reasonable setup could create this macro:</para> setup could create this macro:</para>
<programlisting>client_out = "{ ftp-data, ftp, ssh, domain, pop3, auth, nntp, http, \ <programlisting>client_out = "{ ftp-data, ftp, ssh, domain, pop3, auth, nntp, http, \
https, cvspserver, 2628, 5999, 8000, 8080 }"</programlisting> https, cvspserver, 2628, 5999, 8000, 8080 }"</programlisting>
@ -751,27 +749,24 @@ pass from { lo0, $localnet } to any keep state</programlisting>
<programlisting>pass in inet proto tcp to $ext_if port ssh</programlisting> <programlisting>pass in inet proto tcp to $ext_if port ssh</programlisting>
<para>This macro definition and rule allows <para>This macro definition and rule allows
<acronym>DNS</acronym> and <acronym>NTP</acronym> for internal <acronym>DNS</acronym> and <acronym>NTP</acronym> for
clients:</para> internal clients:</para>
<programlisting>udp_services = "{ domain, ntp }" <programlisting>udp_services = "{ domain, ntp }"
pass quick inet proto { tcp, udp } to any port $udp_services keep state</programlisting> pass quick inet proto { tcp, udp } to any port $udp_services keep state</programlisting>
<para>Note the <literal>quick</literal> keyword in this <para>Note the <literal>quick</literal> keyword in this rule.
rule. Since the ruleset consists of Since the ruleset consists of several rules, it is important
several rules, it is important to understand the to understand the relationships between the rules in a
relationships between the rules in a ruleset. Rules ruleset. Rules are evaluated from top to bottom, in the
are evaluated from top to bottom, in the sequence they are sequence they are written. For each packet or connection
written. For each packet or evaluated by <application>PF</application>,
connection evaluated by <application>PF</application>,
<emphasis>the last matching rule</emphasis> in the ruleset <emphasis>the last matching rule</emphasis> in the ruleset
is the one which is applied. However, is the one which is applied. However, when a packet matches
when a packet matches a rule which a rule which contains the <literal>quick</literal> keyword,
contains the <literal>quick</literal> keyword,
the rule processing stops and the packet is treated the rule processing stops and the packet is treated
according to that rule. This is very according to that rule. This is very useful when an
useful when an exception to the general rules exception to the general rules is needed.</para>
is needed.</para>
</sect3> </sect3>
<sect3 xml:id="pftut-ftp"> <sect3 xml:id="pftut-ftp">
@ -781,7 +776,8 @@ pass quick inet proto { tcp, udp } to any port $udp_services keep state</program
problematic due to the nature of the <acronym>FTP</acronym> problematic due to the nature of the <acronym>FTP</acronym>
protocol. <acronym>FTP</acronym> pre-dates firewalls by protocol. <acronym>FTP</acronym> pre-dates firewalls by
several decades and is insecure in its design. The most several decades and is insecure in its design. The most
common points against using <acronym>FTP</acronym> include:</para> common points against using <acronym>FTP</acronym>
include:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -800,52 +796,49 @@ pass quick inet proto { tcp, udp } to any port $udp_services keep state</program
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>All of these points present security challenges, <para>All of these points present security challenges, even
even before considering any potential security weaknesses in client before considering any potential security weaknesses in
or server software. More client or server software. More secure alternatives for
secure alternatives for file transfer exist, such as &man.sftp.1; file transfer exist, such as &man.sftp.1; or &man.scp.1;,
or &man.scp.1;, which both feature authentication and data which both feature authentication and data transfer over
transfer over encrypted connections..</para> encrypted connections..</para>
<para>For those situations when <acronym>FTP</acronym> is <para>For those situations when <acronym>FTP</acronym> is
required, <application>PF</application> provides required, <application>PF</application> provides
redirection of <acronym>FTP</acronym> traffic to a small redirection of <acronym>FTP</acronym> traffic to a small
proxy program called proxy program called &man.ftp-proxy.8;, which is included in
&man.ftp-proxy.8;, which is included in the base system of &os;. the base system of &os;. The role of the proxy is to
The role of dynamically insert and delete rules in the ruleset, using a
the proxy is to dynamically insert and delete rules in the ruleset, using set of anchors, in order to correctly handle
a set of anchors, in order to correctly handle
<acronym>FTP</acronym> traffic.</para> <acronym>FTP</acronym> traffic.</para>
<para>To enable the <acronym>FTP</acronym> proxy, add this line to <para>To enable the <acronym>FTP</acronym> proxy, add this
<filename>/etc/rc.conf</filename>:</para> line to <filename>/etc/rc.conf</filename>:</para>
<programlisting>ftpproxy_enable="YES"</programlisting> <programlisting>ftpproxy_enable="YES"</programlisting>
<para>Then start the proxy by running <para>Then start the proxy by running <command>service
<command>service ftp-proxy start</command>.</para> ftp-proxy start</command>.</para>
<para>For a basic configuration, three elements need to <para>For a basic configuration, three elements need to be
be added to <filename>/etc/pf.conf</filename>. First, the added to <filename>/etc/pf.conf</filename>. First, the
anchors which the proxy will use to insert the rules it generates for the anchors which the proxy will use to insert the rules it
<acronym>FTP</acronym> sessions:</para> generates for the <acronym>FTP</acronym> sessions:</para>
<programlisting>nat-anchor "ftp-proxy/*" <programlisting>nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"</programlisting> rdr-anchor "ftp-proxy/*"</programlisting>
<para>Second, a pass rule is <para>Second, a pass rule is needed to allow
needed to allow <acronym>FTP</acronym> traffic in to the <acronym>FTP</acronym> traffic in to the proxy.</para>
proxy.</para>
<para>Third, redirection and <acronym>NAT</acronym> rules need <para>Third, redirection and <acronym>NAT</acronym> rules need
to be defined before the to be defined before the filtering rules. Insert this
filtering rules. Insert this <literal>rdr</literal> rule immediately <literal>rdr</literal> rule immediately after the
after the <literal>nat</literal> rule:</para> <literal>nat</literal> rule:</para>
<programlisting>rdr pass on $int_if proto tcp from any to any port ftp -&gt; 127.0.0.1 port 8021</programlisting> <programlisting>rdr pass on $int_if proto tcp from any to any port ftp -&gt; 127.0.0.1 port 8021</programlisting>
<para>Finally, allow the redirected traffic to <para>Finally, allow the redirected traffic to pass:</para>
pass:</para>
<programlisting>pass out proto tcp from $proxy to any port ftp</programlisting> <programlisting>pass out proto tcp from $proxy to any port ftp</programlisting>
@ -882,45 +875,43 @@ rdr-anchor "ftp-proxy/*"</programlisting>
<sect3 xml:id="pftut-icmp"> <sect3 xml:id="pftut-icmp">
<title>Managing <acronym>ICMP</acronym></title> <title>Managing <acronym>ICMP</acronym></title>
<para>Many of the tools used for debugging or <para>Many of the tools used for debugging or troubleshooting
troubleshooting a <acronym>TCP/IP</acronym> network rely on the a <acronym>TCP/IP</acronym> network rely on the Internet
Internet Control Message Protocol (<acronym>ICMP</acronym>), which Control Message Protocol (<acronym>ICMP</acronym>), which
was designed specifically with debugging in mind.</para> was designed specifically with debugging in mind.</para>
<para>The <acronym>ICMP</acronym> protocol sends and <para>The <acronym>ICMP</acronym> protocol sends and receives
receives <emphasis>control messages</emphasis> between <emphasis>control messages</emphasis> between hosts and
hosts and gateways, mainly to provide feedback to a sender gateways, mainly to provide feedback to a sender about any
about any unusual or difficult conditions enroute to the unusual or difficult conditions enroute to the target host.
target host.
Routers use <acronym>ICMP</acronym> to negotiate packet Routers use <acronym>ICMP</acronym> to negotiate packet
sizes and other transmission parameters in a process often sizes and other transmission parameters in a process often
referred to as <emphasis>path <acronym>MTU</acronym> referred to as <emphasis>path <acronym>MTU</acronym>
discovery</emphasis>.</para> discovery</emphasis>.</para>
<para>From a firewall perspective, some <acronym>ICMP</acronym> <para>From a firewall perspective, some
control messages are vulnerable to known attack vectors. <acronym>ICMP</acronym> control messages are vulnerable to
Also, letting all diagnostic traffic pass unconditionally known attack vectors. Also, letting all diagnostic traffic
makes debugging easier, but it also makes it pass unconditionally makes debugging easier, but it also
easier for others to extract information about makes it easier for others to extract information about the
the network. For these reasons, the following rule may not be network. For these reasons, the following rule may not be
optimal:</para> optimal:</para>
<programlisting>pass inet proto icmp from any to any</programlisting> <programlisting>pass inet proto icmp from any to any</programlisting>
<para>One solution is to let all <para>One solution is to let all <acronym>ICMP</acronym>
<acronym>ICMP</acronym> traffic from the local network through traffic from the local network through while stopping all
while stopping all probes from outside the network:</para> probes from outside the network:</para>
<programlisting>pass inet proto icmp from $localnet to any keep state <programlisting>pass inet proto icmp from $localnet to any keep state
pass inet proto icmp from any to $ext_if keep state</programlisting> pass inet proto icmp from any to $ext_if keep state</programlisting>
<para>Additional <para>Additional options are available which demonstrate some
options are available which demonstrate some of of <application>PF</application>'s flexibility. For
<application>PF</application>'s flexibility. For example, example, rather than allowing all <acronym>ICMP</acronym>
rather than allowing all <acronym>ICMP</acronym> messages, messages, one can specify the messages used by &man.ping.8;
one can specify the messages used by &man.ping.8; and and &man.traceroute.8;. Start by defining a macro for that
&man.traceroute.8;. Start by defining a macro for type of message:</para>
that type of message:</para>
<programlisting>icmp_types = "echoreq"</programlisting> <programlisting>icmp_types = "echoreq"</programlisting>
@ -928,32 +919,30 @@ pass inet proto icmp from any to $ext_if keep state</programlisting>
<programlisting>pass inet proto icmp all icmp-type $icmp_types keep state</programlisting> <programlisting>pass inet proto icmp all icmp-type $icmp_types keep state</programlisting>
<para>If other types of <acronym>ICMP</acronym> packets <para>If other types of <acronym>ICMP</acronym> packets are
are needed, expand <literal>icmp_types</literal> needed, expand <literal>icmp_types</literal> to a list of
to a list of those packet types. Type those packet types. Type <command>more
<command>more /usr/src/contrib/pf/pfctl/pfctl_parser.c</command> /usr/src/contrib/pf/pfctl/pfctl_parser.c</command> to see
to see the list of <acronym>ICMP</acronym> message the list of <acronym>ICMP</acronym> message types supported
types supported by <application>PF</application>. Refer to by <application>PF</application>. Refer to <link
<link
xlink:href="http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml">http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml</link> xlink:href="http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml">http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml</link>
for an explanation of each message type.</para> for an explanation of each message type.</para>
<para>Since Unix <command>traceroute</command> uses <acronym>UDP</acronym> <para>Since Unix <command>traceroute</command> uses
by default, another rule is needed to allow Unix <acronym>UDP</acronym> by default, another rule is needed to
<command>traceroute</command>:</para> allow Unix <command>traceroute</command>:</para>
<programlisting># allow out the default range for traceroute(8): <programlisting># allow out the default range for traceroute(8):
pass out on $ext_if inet proto udp from any to any port 33433 &gt;&lt; 33626 keep state</programlisting> pass out on $ext_if inet proto udp from any to any port 33433 &gt;&lt; 33626 keep state</programlisting>
<para>Since <command>TRACERT.EXE</command> on Microsoft Windows systems <para>Since <command>TRACERT.EXE</command> on Microsoft
uses <acronym>ICMP</acronym> echo request messages, Windows systems uses <acronym>ICMP</acronym> echo request
only the messages, only the first rule is needed to allow network
first rule is needed to allow network traces from those systems. Unix <command>traceroute</command> traces from those systems. Unix
can be instructed to use other protocols as well, and will <command>traceroute</command> can be instructed to use other
use <acronym>ICMP</acronym> echo request messages if protocols as well, and will use <acronym>ICMP</acronym> echo
<option>-I</option> is used. Check the &man.traceroute.8; request messages if <option>-I</option> is used. Check the
man page for &man.traceroute.8; man page for details.</para>
details.</para>
<sect4 xml:id="pftut-pathmtudisc"> <sect4 xml:id="pftut-pathmtudisc">
<title>Path <acronym>MTU</acronym> Discovery</title> <title>Path <acronym>MTU</acronym> Discovery</title>
@ -962,66 +951,62 @@ pass out on $ext_if inet proto udp from any to any port 33433 &gt;&lt; 33626 kee
independent, and one consequence of device independence is independent, and one consequence of device independence is
that the optimal packet size for a given connection cannot that the optimal packet size for a given connection cannot
always be predicted reliably. The main constraint on always be predicted reliably. The main constraint on
packet size is the packet size is the <firstterm>Maximum Transmission
<firstterm>Maximum Transmission Unit</firstterm> Unit</firstterm> (<acronym>MTU</acronym>) which sets the
(<acronym>MTU</acronym>) which sets the upper limit on the upper limit on the packet size for an interface. Type
packet size for an interface. Type <command>ifconfig</command> to view the <command>ifconfig</command> to view the
<acronym>MTU</acronym>s for a system's network interfaces.</para> <acronym>MTU</acronym>s for a system's network
interfaces.</para>
<para><acronym>TCP/IP</acronym> uses a process known as path <para><acronym>TCP/IP</acronym> uses a process known as path
<acronym>MTU</acronym> discovery to <acronym>MTU</acronym> discovery to determine the right
determine the right packet size for a connection. This packet size for a connection. This process sends packets
process sends packets of of varying sizes with the <quote>Do not fragment</quote>
varying sizes with the <quote>Do not fragment</quote> flag flag set, expecting an <acronym>ICMP</acronym> return
set, expecting an <acronym>ICMP</acronym> return packet packet of <quote>type 3, code 4</quote> when the upper
of <quote>type 3, code 4</quote> when the upper
limit has been reached. Type 3 means <quote>destination limit has been reached. Type 3 means <quote>destination
unreachable</quote>, and code 4 is short for unreachable</quote>, and code 4 is short for
<quote>fragmentation needed, but the do-not-fragment flag <quote>fragmentation needed, but the do-not-fragment flag
is set</quote>. To allow path MTU discovery in order is set</quote>. To allow path MTU discovery in order
to support connections to other <acronym>MTU</acronym>s, add to support connections to other <acronym>MTU</acronym>s,
the add the <literal>destination unreachable</literal> type to
<literal>destination unreachable</literal> type to the the <literal>icmp_types</literal> macro:</para>
<literal>icmp_types</literal> macro:</para>
<programlisting>icmp_types = "{ echoreq, unreach }"</programlisting> <programlisting>icmp_types = "{ echoreq, unreach }"</programlisting>
<para>Since <para>Since the pass rule already uses that macro, it does
the pass rule already uses that macro, it does not need to not need to be modified in order to support the new
be modified in order to support the new
<acronym>ICMP</acronym> type:</para> <acronym>ICMP</acronym> type:</para>
<programlisting>pass inet proto icmp all icmp-type $icmp_types keep state</programlisting> <programlisting>pass inet proto icmp all icmp-type $icmp_types keep state</programlisting>
<para><application>PF</application> allows filtering on all <para><application>PF</application> allows filtering on all
variations of <acronym>ICMP</acronym> types and codes. variations of <acronym>ICMP</acronym> types and codes.
The list of possible The list of possible types and codes are documented in
types and codes are documented in &man.icmp.4; and &man.icmp.4; and &man.icmp6.4;.</para>
&man.icmp6.4;.</para>
</sect4> </sect4>
</sect3> </sect3>
<sect3 xml:id="pftut-tables"> <sect3 xml:id="pftut-tables">
<title>Using Tables</title> <title>Using Tables</title>
<para>Some types of data <para>Some types of data are relevant to filtering and
are relevant to filtering and redirection at a given time, redirection at a given time, but their definition is too
but their definition is too long to be included in the ruleset file. long to be included in the ruleset file.
<application>PF</application> supports the use of tables, <application>PF</application> supports the use of tables,
which are defined lists that can be which are defined lists that can be manipulated without
manipulated without needing to reload the entire ruleset, needing to reload the entire ruleset, and which can provide
and which can provide fast lookups. Table names are fast lookups. Table names are always enclosed within
always enclosed within <literal>&lt; &gt;</literal>, like <literal>&lt; &gt;</literal>, like this:</para>
this:</para>
<programlisting>table &lt;clients&gt; { 192.168.2.0/24, !192.168.2.5 }</programlisting> <programlisting>table &lt;clients&gt; { 192.168.2.0/24, !192.168.2.5 }</programlisting>
<para>In this example, the <literal>192.168.2.0/24</literal> network <para>In this example, the <literal>192.168.2.0/24</literal>
is part of the table, except for the address network is part of the table, except for the address
<literal>192.168.2.5</literal>, which is excluded using <literal>192.168.2.5</literal>, which is excluded using the
the <literal>!</literal> operator. It is <literal>!</literal> operator. It is also possible to load
also possible to load tables from files where each item is tables from files where each item is on a separate line, as
on a separate line, as seen in this example seen in this example
<filename>/etc/clients</filename>:</para> <filename>/etc/clients</filename>:</para>
<programlisting>192.168.2.0/24 <programlisting>192.168.2.0/24
@ -1036,33 +1021,34 @@ pass out on $ext_if inet proto udp from any to any port 33433 &gt;&lt; 33626 kee
<programlisting>pass inet proto tcp from &lt;clients&gt; to any port $client_out flags S/SA keep state</programlisting> <programlisting>pass inet proto tcp from &lt;clients&gt; to any port $client_out flags S/SA keep state</programlisting>
<para>A table's contents can be manipulated live, using <command>pfctl</command>. <para>A table's contents can be manipulated live, using
This example adds another network to the table:</para> <command>pfctl</command>. This example adds another network
to the table:</para>
<screen>&prompt.root; <userinput>pfctl -t clients -T add 192.168.1.0/16</userinput></screen> <screen>&prompt.root; <userinput>pfctl -t clients -T add 192.168.1.0/16</userinput></screen>
<para>Note that any changes made this way will take affect now, <para>Note that any changes made this way will take affect
making them ideal for testing, now, making them ideal for testing, but will not survive a
but will not survive a power power failure or reboot. To make the changes permanent,
failure or reboot. To make the changes permanent, modify the modify the definition of the table in the ruleset or edit
definition of the table in the ruleset or edit the file that the the file that the table refers to. One can maintain the
table refers to. One can maintain the on-disk copy of the table on-disk copy of the table using a &man.cron.8; job which
using a &man.cron.8; job which dumps the table's contents to dumps the table's contents to disk at regular intervals,
disk at regular intervals, using a command such as using a command such as <command>pfctl -t clients -T show
<command>pfctl -t clients -T show
&gt;/etc/clients</command>. Alternatively, &gt;/etc/clients</command>. Alternatively,
<filename>/etc/clients</filename> can be updated with <filename>/etc/clients</filename> can be updated with the
the in-memory table contents:</para> in-memory table contents:</para>
<screen>&prompt.root; <userinput>pfctl -t clients -T replace -f /etc/clients</userinput></screen> <screen>&prompt.root; <userinput>pfctl -t clients -T replace -f /etc/clients</userinput></screen>
</sect3> </sect3>
<sect3 xml:id="pftut-overload"> <sect3 xml:id="pftut-overload">
<title>Using Overload Tables to Protect <acronym>SSH</acronym></title> <title>Using Overload Tables to Protect
<acronym>SSH</acronym></title>
<para>Those who run <acronym>SSH</acronym> on an external interface <para>Those who run <acronym>SSH</acronym> on an external
have probably seen something interface have probably seen something like this in the
like this in the authentication logs:</para> authentication logs:</para>
<programlisting>Sep 26 03:12:34 skapet sshd[25771]: Failed password for root from 200.72.41.31 port 40992 ssh2 <programlisting>Sep 26 03:12:34 skapet sshd[25771]: Failed password for root from 200.72.41.31 port 40992 ssh2
Sep 26 03:12:34 skapet sshd[5279]: Failed password for root from 200.72.41.31 port 40992 ssh2 Sep 26 03:12:34 skapet sshd[5279]: Failed password for root from 200.72.41.31 port 40992 ssh2
@ -1072,29 +1058,26 @@ Sep 26 03:12:44 skapet sshd[24703]: input_userauth_request: invalid user admin
Sep 26 03:12:44 skapet sshd[24703]: Failed password for invalid user admin from 200.72.41.31 port 41484 ssh2</programlisting> Sep 26 03:12:44 skapet sshd[24703]: Failed password for invalid user admin from 200.72.41.31 port 41484 ssh2</programlisting>
<para>This is indicative of a brute force attack where <para>This is indicative of a brute force attack where
somebody or some program somebody or some program is trying to discover the user name
is trying to discover the and password which will let them into the system.</para>
user name and password which will let them
into the system.</para>
<para>If external <acronym>SSH</acronym> access is needed for <para>If external <acronym>SSH</acronym> access is needed for
legitimate users, changing the default port used by legitimate users, changing the default port used by
<acronym>SSH</acronym> can offer some protection. <acronym>SSH</acronym> can offer some protection. However,
However, <application>PF</application> provides a more <application>PF</application> provides a more elegant
elegant solution. Pass rules can contain solution. Pass rules can contain limits on what connecting
limits on what connecting hosts can do and hosts can do and violators can be banished to a table of
violators can be banished to a table of addresses which are denied some or all access. It is even
addresses which are denied some or all access. It possible to drop all existing connections from machines
is even possible to drop all existing connections from which overreach the limits.</para>
machines which overreach the limits.</para>
<para>To configure this, create this table in the tables section <para>To configure this, create this table in the tables
of the ruleset:</para> section of the ruleset:</para>
<programlisting>table &lt;bruteforce&gt; persist</programlisting> <programlisting>table &lt;bruteforce&gt; persist</programlisting>
<para>Then, somewhere early in the ruleset, add rules <para>Then, somewhere early in the ruleset, add rules to block
to block brute access while allowing legitimate access:</para> brute access while allowing legitimate access:</para>
<programlisting>block quick from &lt;bruteforce&gt; <programlisting>block quick from &lt;bruteforce&gt;
pass inet proto tcp from any to $localnet port $tcp_services \ pass inet proto tcp from any to $localnet port $tcp_services \
@ -1110,18 +1093,20 @@ pass inet proto tcp from any to $localnet port $tcp_services \
simultaneous connections allowed from one host.</para> simultaneous connections allowed from one host.</para>
<para><literal>max-src-conn-rate</literal> is the rate of new <para><literal>max-src-conn-rate</literal> is the rate of new
connections allowed from any single host (<replaceable>15</replaceable>) connections allowed from any single host
per number of seconds (<replaceable>5</replaceable>).</para> (<replaceable>15</replaceable>) per number of seconds
(<replaceable>5</replaceable>).</para>
<para><literal>overload &lt;bruteforce&gt;</literal> means <para><literal>overload &lt;bruteforce&gt;</literal> means
that any host which exceeds these limits gets its address that any host which exceeds these limits gets its address
added to the <literal>bruteforce</literal> table. The ruleset added to the <literal>bruteforce</literal> table. The
blocks all traffic from addresses in the <literal>bruteforce</literal> ruleset blocks all traffic from addresses in the
table.</para> <literal>bruteforce</literal> table.</para>
<para>Finally, <literal>flush global</literal> says that when <para>Finally, <literal>flush global</literal> says that when
a host reaches the limit, that all (<literal>global</literal>) of that host's connections will be a host reaches the limit, that all
terminated (<literal>flush</literal>).</para> (<literal>global</literal>) of that host's connections will
be terminated (<literal>flush</literal>).</para>
<note> <note>
<para>These rules will <emphasis>not</emphasis> block slow <para>These rules will <emphasis>not</emphasis> block slow
@ -1129,10 +1114,10 @@ pass inet proto tcp from any to $localnet port $tcp_services \
xlink:href="http://home.nuug.no/~peter/hailmary2013/">http://home.nuug.no/~peter/hailmary2013/</link>.</para> xlink:href="http://home.nuug.no/~peter/hailmary2013/">http://home.nuug.no/~peter/hailmary2013/</link>.</para>
</note> </note>
<para>This example ruleset <para>This example ruleset is intended mainly as an
is intended mainly as an illustration. For example, if a generous number of connections in illustration. For example, if a generous number of
general are wanted, but the desire is to be more connections in general are wanted, but the desire is to be
restrictive when it comes to more restrictive when it comes to
<application>ssh</application>, supplement the rule above <application>ssh</application>, supplement the rule above
with something like the one below, early on in the rule with something like the one below, early on in the rule
set:</para> set:</para>
@ -1146,47 +1131,43 @@ pass inet proto tcp from any to $localnet port $tcp_services \
<title>It May Not be Necessary to Block All <title>It May Not be Necessary to Block All
Overloaders</title> Overloaders</title>
<para>It is worth noting that the <para>It is worth noting that the overload mechanism is a
overload mechanism is a general general technique which does not apply exclusively to
technique which does not apply exclusively to <acronym>SSH</acronym>, and it is not always optimal to
<acronym>SSH</acronym>, and it is not always entirely block all traffic from offenders.</para>
optimal to entirely block all traffic from offenders.</para>
<para>For example, an overload rule could be used to <para>For example, an overload rule could be used to
protect a mail service or a web service, and the overload protect a mail service or a web service, and the overload
table could be used in a rule to assign offenders to a table could be used in a rule to assign offenders to a
queue with a minimal bandwidth allocation or queue with a minimal bandwidth allocation or to redirect
to redirect to a specific web page.</para> to a specific web page.</para>
</note> </note>
<para>Over time, tables will be filled by <para>Over time, tables will be filled by overload rules and
overload rules and their size their size will grow incrementally, taking up more memory.
will grow incrementally, taking up more memory.
Sometimes an <acronym>IP</acronym> address that is blocked Sometimes an <acronym>IP</acronym> address that is blocked
is a dynamically assigned is a dynamically assigned one, which has since been assigned
one, which has since been assigned to a host who to a host who has a legitimate reason to communicate with
has a legitimate reason to communicate with hosts in hosts in the local network.</para>
the local network.</para>
<para>For situations like these, <para>For situations like these,
<application>pfctl</application> provides the ability to <application>pfctl</application> provides the ability to
expire table entries. For example, this expire table entries. For example, this command will remove
command will remove <literal>&lt;bruteforce&gt;</literal> <literal>&lt;bruteforce&gt;</literal> table entries which
table entries which have not been referenced for <literal>86400</literal> have not been referenced for <literal>86400</literal>
seconds:</para> seconds:</para>
<screen>&prompt.root; <userinput>pfctl -t bruteforce -T expire 86400</userinput></screen> <screen>&prompt.root; <userinput>pfctl -t bruteforce -T expire 86400</userinput></screen>
<para>Similar functionality is provided by <para>Similar functionality is provided by
<package>security/expiretable</package>, which <package>security/expiretable</package>, which removes table
removes table entries which have not been accessed for a entries which have not been accessed for a specified period
specified period of time.</para> of time.</para>
<para>Once installed, <para>Once installed, <application>expiretable</application>
<application>expiretable</application> can be run to remove can be run to remove <literal>&lt;bruteforce&gt;</literal>
<literal>&lt;bruteforce&gt;</literal> table entries older table entries older than a specified age. This example
than a specified age. This example removes all entries removes all entries older than 24 hours:</para>
older than 24 hours:</para>
<programlisting>/usr/local/sbin/expiretable -v -d -t 24h bruteforce</programlisting> <programlisting>/usr/local/sbin/expiretable -v -d -t 24h bruteforce</programlisting>
</sect3> </sect3>
@ -1227,9 +1208,9 @@ pass inet proto tcp from any to $localnet port $tcp_services \
implementation with one byte SMTP replies is often implementation with one byte SMTP replies is often
referred to as <firstterm>stuttering</firstterm>.</para> referred to as <firstterm>stuttering</firstterm>.</para>
<para>This example demonstrates the basic procedure for setting up <para>This example demonstrates the basic procedure for
<application>spamd</application> with automatically setting up <application>spamd</application> with
updated blacklists:</para> automatically updated blacklists:</para>
<procedure> <procedure>
<step> <step>
@ -1315,8 +1296,7 @@ rdr pass on $ext_if inet proto tcp from !&lt;spamd-white&gt; to \
<literal>file</literal> in a mounted file system or <literal>file</literal> in a mounted file system or
via <literal>exec</literal> of an external program. via <literal>exec</literal> of an external program.
Finally the <literal>file</literal> field specifies Finally the <literal>file</literal> field specifies
the name of the file spamd expects to the name of the file spamd expects to receive.</para>
receive.</para>
<para>The definition of a whitelist follows much the <para>The definition of a whitelist follows much the
same pattern:</para> same pattern:</para>
@ -1344,16 +1324,14 @@ rdr pass on $ext_if inet proto tcp from !&lt;spamd-white&gt; to \
</tip> </tip>
<para>Put the lines for spamd and any startup <para>Put the lines for spamd and any startup
parameters desired in parameters desired in <filename>/etc/rc.conf</filename>,
<filename>/etc/rc.conf</filename>, for for example:</para>
example:</para>
<programlisting>spamd_flags="-v" # for normal use: "" and see spamd-setup(8)</programlisting> <programlisting>spamd_flags="-v" # for normal use: "" and see spamd-setup(8)</programlisting>
<para>When done with editing the setup, <para>When done with editing the setup, reload the
reload the ruleset, start ruleset, start <application>spamd</application> with the
<application>spamd</application> with the options options desired using the
desired using the
<filename>/usr/local/etc/rc.d/obspamd</filename> <filename>/usr/local/etc/rc.d/obspamd</filename>
script, and complete the configuration using script, and complete the configuration using
<command>spamd-setup</command>. Finally, create a <command>spamd-setup</command>. Finally, create a