Tighten up this subsection.
Sponsored by: iXsystems
This commit is contained in:
parent
c4a79914aa
commit
68e4a86d99
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=43928
1 changed files with 69 additions and 86 deletions
|
@ -540,104 +540,87 @@ options ALTQ_PRIQ # Priority Queuing (PRIQ)</programlisting>
|
|||
</info>
|
||||
|
||||
<para>This section demonstrates how to create a customized
|
||||
ruleset, using several examples.</para>
|
||||
ruleset. It starts with the simplest of rulesets and builds
|
||||
upon its concepts using several examples to demonstrate
|
||||
real-world usage of <application>PF</application>'s many
|
||||
features.</para>
|
||||
|
||||
<para>The simplest possible setup is for a single machine
|
||||
which will not run any services, and which will talk to one
|
||||
network which may be the Internet. A minimal
|
||||
<filename>/etc/pf.conf</filename> looks like this:</para>
|
||||
<para>The simplest possible ruleset is for a single machine
|
||||
that does not run any services and which needs access to one
|
||||
network, which may be the Internet. To create this minimal
|
||||
ruleset, edit
|
||||
<filename>/etc/pf.conf</filename> so it looks like this:</para>
|
||||
|
||||
<programlisting>block in all
|
||||
pass out all keep state</programlisting>
|
||||
|
||||
<para>Here we deny any incoming traffic, allow traffic we make
|
||||
ourselves to pass, and retain state information on our
|
||||
connections. Keeping state information allows return
|
||||
traffic for all connections we have initiated to pass back
|
||||
to us. This rule set is used on machines that can be
|
||||
trusted. The rule set can be loaded with</para>
|
||||
<para>The first rule denies all incoming traffic by default.
|
||||
The second rule allows
|
||||
connections created by this system
|
||||
to pass out, while retaining state information on those
|
||||
connections. This state information allows return
|
||||
traffic for those connections to pass back and
|
||||
should only be used on machines that can be
|
||||
trusted. The ruleset can be loaded with:</para>
|
||||
|
||||
<screen>&prompt.root; <userinput>pfctl -e ; pfctl -f /etc/pf.conf</userinput></screen>
|
||||
|
||||
<para>For a slightly more structured and complete setup, we
|
||||
start by denying everything and then allowing only those
|
||||
things we know that we need
|
||||
<footnote><para>Why write the rule set to default deny? The
|
||||
short answer is, it gives better control at the expense
|
||||
of some thinking. The point of packet filtering is to
|
||||
take control, not to run catch-up with what the bad guys
|
||||
do. Marcus Ranum has written a very entertaining and
|
||||
informative article about this, <link
|
||||
xlink:href="http://www.ranum.com/security/computer_security/editorials/dumb/index.html">The
|
||||
Six Dumbest Ideas in Computer Security</link>, and
|
||||
it is well written too.</para></footnote>. This gives
|
||||
us the opportunity to introduce two of the features which
|
||||
make <application>PF</application> such a wonderful tool:
|
||||
<para>In addition to keeping state,
|
||||
<application>PF</application> provides
|
||||
<firstterm>lists</firstterm> and
|
||||
<firstterm>macros</firstterm>.</para>
|
||||
|
||||
<para>We will make some changes to
|
||||
<filename>/etc/pf.conf</filename>, starting with</para>
|
||||
|
||||
<programlisting>block all</programlisting>
|
||||
|
||||
<para>Then we back up a little. Macros need to be defined
|
||||
before use, so at the very top of the file, we add:</para>
|
||||
<firstterm>macros</firstterm> which can be defined for use
|
||||
when creating rules. Macros can include lists and need to be defined
|
||||
before use. As an example, insert these lines at the
|
||||
very top of the ruleset:</para>
|
||||
|
||||
<programlisting>tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"
|
||||
udp_services = "{ domain }"</programlisting>
|
||||
|
||||
<para>Now we have demonstrated several things at once - what
|
||||
macros look like, that macros may be lists, and that
|
||||
<application>PF</application> understands rules using port
|
||||
names equally well as it does port numbers. The names are
|
||||
the ones listed in <filename>/etc/services</filename>. This
|
||||
gives us something to put in our rules, which we edit
|
||||
slightly to look like this:</para>
|
||||
<para><application>PF</application> understands port
|
||||
names as well as port numbers, as long as the names are listed
|
||||
in <filename>/etc/services</filename>. This example
|
||||
creates two macros. The first is a list of seven
|
||||
<acronym>TCP</acronym> port names and the second is one
|
||||
<acronym>UDP</acronym> port name. Once defined, macros can
|
||||
be used in rules. In this example, all traffic is blocked
|
||||
except for the connections initiated by this system for the
|
||||
seven specified <acronym>TCP</acronym> services and the one
|
||||
specified <acronym>UDP</acronym> service:</para>
|
||||
|
||||
<programlisting>block all
|
||||
<programlisting>tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"
|
||||
udp_services = "{ domain }"
|
||||
block all
|
||||
pass out proto tcp to any port $tcp_services keep state
|
||||
pass proto udp to any port $udp_services keep state</programlisting>
|
||||
|
||||
<para>At this point some of us will point out that UDP is
|
||||
stateless, but <application>PF</application> actually
|
||||
manages to maintain state information despite this. Keeping
|
||||
state for a UDP connection means that for example when you
|
||||
ask a name server about a domain name, you will be able to
|
||||
receive its answer.</para>
|
||||
<para>Even though <acronym>UDP</acronym> is considered to be
|
||||
a stateless protocol, <application>PF</application>
|
||||
is able to track some state information. For example, when a
|
||||
<acronym>UDP</acronym> request is passed which
|
||||
asks a name server about a domain name, <application>PF</application>
|
||||
will watch for the response in order to pass it back.</para>
|
||||
|
||||
<para>Since we have made changes to our
|
||||
<filename>pf.conf</filename>, we load the new
|
||||
rules:</para>
|
||||
<para>Whenever an edit is made to a ruleset, the new rules
|
||||
must be loaded so they can be used:</para>
|
||||
|
||||
<screen>&prompt.root; <userinput>pfctl -f /etc/pf.conf</userinput></screen>
|
||||
|
||||
<para>and the new rules are applied. If there are no syntax
|
||||
<para>If there are no syntax
|
||||
errors, <command>pfctl</command> will not output any
|
||||
messages during the rule load. The <option>-v</option> flag
|
||||
will produce more verbose <command>pfctl</command>
|
||||
output.</para>
|
||||
|
||||
<para>If there have been extensive changes to the rule set,
|
||||
the rules can be tested before attempting to load them. The
|
||||
command to do this is</para>
|
||||
messages during the rule load. Rules can also be tested before attempting to load them:</para>
|
||||
|
||||
<screen>&prompt.root; <userinput>pfctl -nf /etc/pf.conf</userinput></screen>
|
||||
|
||||
<para><option>-n</option> causes the rules to be interpreted
|
||||
only, but does not load them. This provides an opportunity
|
||||
to correct any errors. Under any circumstances, the last
|
||||
valid rule set loaded will be in force until
|
||||
<application>PF</application> is disabled or a new rule set
|
||||
<para>Including <option>-n</option> causes the rules to be interpreted
|
||||
only, but not loaded. This provides an opportunity
|
||||
to correct any errors. At all times, the last
|
||||
valid ruleset loaded will be enforced until either
|
||||
<application>PF</application> is disabled or a new ruleset
|
||||
is loaded.</para>
|
||||
|
||||
<tip>
|
||||
<title>Use <command>pfctl -v</command> to Show the Parsed
|
||||
Rule Set</title>
|
||||
|
||||
<para>Adding the <option>-v</option> to a
|
||||
<command>pfctl</command> ruleset load (even a dry run with
|
||||
<option>-n</option>) will display the fully parsed rules
|
||||
<para>Adding <option>-v</option> to a
|
||||
<command>pfctl</command> ruleset verify or load will display the fully parsed rules
|
||||
exactly the way they will be loaded. This is extremely
|
||||
useful when debugging rules.</para>
|
||||
</tip>
|
||||
|
@ -699,10 +682,10 @@ pass proto udp to any port $udp_services keep state</programlisting>
|
|||
good these days, and we will get back to them later. For
|
||||
now we just accept the fact that for simple setups,
|
||||
interface-bound rules with in/out rules tend to add more
|
||||
clutter than they are worth to rule sets.</para>
|
||||
clutter than they are worth to rulesets.</para>
|
||||
|
||||
<para>For a busy network admin, a readable rule set is a
|
||||
safer rule set.</para>
|
||||
<para>For a busy network admin, a readable ruleset is a
|
||||
safer ruleset.</para>
|
||||
|
||||
<para>For the remainder of this section, with some
|
||||
exceptions, we will keep the rules as simple as possible
|
||||
|
@ -713,7 +696,7 @@ pass proto udp to any port $udp_services keep state</programlisting>
|
|||
|
||||
<para>Above, we introduced the
|
||||
<literal>interface:network</literal> notation. That is a
|
||||
nice piece of shorthand, but the rule set can be made even
|
||||
nice piece of shorthand, but the ruleset can be made even
|
||||
more readable and maintainable by taking the macro use a
|
||||
tiny bit further.</para>
|
||||
|
||||
|
@ -809,7 +792,7 @@ pass from { lo0, $localnet } to any keep state</programlisting>
|
|||
the last time during this tutorial we will find this of
|
||||
any interest whatsoever. In truly simple setups like this
|
||||
one, we may not gain very much by using macros like these,
|
||||
but once the rule sets grow somewhat larger, you will
|
||||
but once the rulesets grow somewhat larger, you will
|
||||
learn to appreciate the readability this provides.</para>
|
||||
|
||||
<para>Also note the <literal>nat</literal> rule. This is
|
||||
|
@ -825,7 +808,7 @@ pass from { lo0, $localnet } to any keep state</programlisting>
|
|||
interruptions even if the external IP address
|
||||
changes.</para>
|
||||
|
||||
<para>On the other hand, this rule set probably allows more
|
||||
<para>On the other hand, this ruleset probably allows more
|
||||
traffic to pass out of the network than actually desired.
|
||||
One reasonable setup could contain the macro</para>
|
||||
|
||||
|
@ -866,9 +849,9 @@ pass from { lo0, $localnet } to any keep state</programlisting>
|
|||
<programlisting>pass quick inet proto { tcp, udp } to any port $udp_services keep state</programlisting>
|
||||
|
||||
<para>Note the <literal>quick</literal> keyword in this
|
||||
rule. We have started writing rule sets which consist of
|
||||
rule. We have started writing rulesets which consist of
|
||||
several rules, and it is time to take a look at the
|
||||
relationships between the rules in a rule set. The rules
|
||||
relationships between the rules in a ruleset. The rules
|
||||
are evaluated from top to bottom, in the sequence they are
|
||||
written in the configuration file. For each packet or
|
||||
connection evaluated by <application>PF</application>,
|
||||
|
@ -1083,7 +1066,7 @@ rdr-anchor "ftp-proxy/*"</programlisting>
|
|||
<para>One of the early workarounds was to simply block either
|
||||
all <acronym>ICMP</acronym> traffic or at least
|
||||
<acronym>ICMP</acronym> ECHO, which is what ping uses. Now
|
||||
these rule sets have been around for roughly fifteen years,
|
||||
these rulesets have been around for roughly fifteen years,
|
||||
and the people who put them there are still scared.</para>
|
||||
|
||||
<sect4 xml:id="pftut-dowepass">
|
||||
|
@ -1128,7 +1111,7 @@ pass inet proto icmp from any to $ext_if keep state</programlisting>
|
|||
<sect4 xml:id="pftut-letpingthru">
|
||||
<title>Letting <command>ping</command> Through</title>
|
||||
|
||||
<para>The rule set we have developed so far has one clear
|
||||
<para>The ruleset we have developed so far has one clear
|
||||
disadvantage: common troubleshooting commands such as
|
||||
&man.ping.8; and &man.traceroute.8; will not work. That
|
||||
may not matter too much to end users, and since it was
|
||||
|
@ -1138,9 +1121,9 @@ pass inet proto icmp from any to $ext_if keep state</programlisting>
|
|||
we are better off without it. If you are in my perceived
|
||||
target audience, you will be rather fond of having those
|
||||
troubleshooting tools avalable. With a couple of small
|
||||
additions to the rule set, they will be. &man.ping.8;
|
||||
additions to the ruleset, they will be. &man.ping.8;
|
||||
uses <acronym>ICMP</acronym>, and in order to keep our
|
||||
rule set tidy, we start by defining another macro:</para>
|
||||
ruleset tidy, we start by defining another macro:</para>
|
||||
|
||||
<programlisting>icmp_types = "echoreq"</programlisting>
|
||||
|
||||
|
@ -1261,7 +1244,7 @@ pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 kee
|
|||
Quite right, and <application>PF</application> offers
|
||||
mechanisms for handling these situations as well. Tables
|
||||
are one such feature, mainly useful as lists which can be
|
||||
manipulated without needing to reload the entire rule set,
|
||||
manipulated without needing to reload the entire ruleset,
|
||||
and where fast lookups are desirable. Table names are
|
||||
always enclosed in <literal>< ></literal>, like
|
||||
this:</para>
|
||||
|
@ -1361,7 +1344,7 @@ Sep 26 03:12:44 skapet sshd[24703]: Failed password for invalid user admin from
|
|||
|
||||
<programlisting>table <bruteforce> persist</programlisting>
|
||||
|
||||
<para>Then somewhere fairly early in the rule set, add a rule
|
||||
<para>Then somewhere fairly early in the ruleset, add a rule
|
||||
to block the bruteforcers:</para>
|
||||
|
||||
<programlisting>block quick from <bruteforce></programlisting>
|
||||
|
@ -1598,7 +1581,7 @@ Sep 26 03:12:44 skapet sshd[24703]: Failed password for invalid user admin from
|
|||
</step>
|
||||
|
||||
<step>
|
||||
<para>Next, edit the rule set to include</para>
|
||||
<para>Next, edit the ruleset to include</para>
|
||||
|
||||
<programlisting>table <spamd> persist
|
||||
table <spamd-white> persist
|
||||
|
@ -1698,7 +1681,7 @@ rdr pass on $ext_if inet proto tcp from !<spamd-white> to \
|
|||
<programlisting>spamd_flags="-v" # for normal use: "" and see spamd-setup(8)</programlisting>
|
||||
|
||||
<para>When done with editing the setup,
|
||||
reload the rule set, start
|
||||
reload the ruleset, start
|
||||
<application>spamd</application> with the options
|
||||
desired using the
|
||||
<filename>/usr/local/etc/rc.d/obspamd</filename>
|
||||
|
|
Loading…
Reference in a new issue