Make the section on PF NAT clearer.

Sponsored by: iXsystems
This commit is contained in:
Dru Lavigne 2014-02-18 17:03:47 +00:00
parent 03011be15e
commit 828f628631
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=43977

View file

@ -628,57 +628,64 @@ pass proto udp to any port $udp_services keep state</programlisting>
<title>A Simple Gateway with NAT</title>
<para>This section demonstrates how to configure a &os; system
which is running <application>PF</application> and also acts
running <application>PF</application> to act
as a gateway for at least one other machine. The gateway
has at least two network interfaces, each connected to a
separate network. For example, one connection is to the
Internet and the other is to the internal network.</para>
needs at least two network interfaces, each connected to a
separate network. In this example, <filename>xl1</filename> is connected to the
Internet and <filename>xl0</filename> is connected to the internal network.</para>
<para>It is reasonable to think that for stateful traffic to
pass from the network connected to <filename>xl1</filename>
to hosts on the network connected to
<filename>xl0</filename>, a rule like this is needed:</para>
<para>First, enable the gateway in order to let the
machine forward the network traffic it receives on one
interface to another interface. This <application>sysctl</application>
setting will forward <acronym>IPv4</acronym> packets:</para>
<screen>&prompt.root; <userinput>sysctl net.inet.ip.forwarding=1</userinput></screen>
<para>To forward <acronym>IPv6</acronym> traffic, use:</para>
<screen>&prompt.root; <userinput>sysctl net.inet6.ip6.forwarding=1</userinput></screen>
<para>To enable these settings at system boot, add the following
to
<filename>/etc/rc.conf</filename>:</para>
<programlisting>gateway_enable="YES" #for ipv4
ipv6_gateway_enable="YES" #for ipv6</programlisting>
<para>Verify with <command>ifconfig</command> that
both of the interfaces are up and
running.</para>
<para>Next, create the <application>PF</application> rules to
allow the gateway to pass traffic. While the following rule allows stateful traffic to
pass from the Internet
to hosts on the network, the <literal>to</literal> keyword does not
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>
<para>However, the <quote>to</quote> keyword does not
guarantee passage all the way from source to destination.
This rule only lets the traffic pass in to the gateway on
<para>That rule only lets the traffic pass in to the gateway on
the internal interface. To let the packets go further, a
matching rule is needed:</para>
<programlisting>pass out on xl0 from xl1:network to xl0:network port $ports keep state</programlisting>
<para>These rules will work, but they will not necessarily
achieve the desired effect.</para>
<para>Rules this specific are rarely needed. A better rule
says:</para>
<para>While these two rules will work, rules this specific are
rarely needed. For a busy network admin, a readable ruleset is a safer
ruleset. The remainder of this section demonstrates how to
keep the rules as simple as possible
for readability. For example, those two rules could be
replaced with one rule:</para>
<programlisting>pass from xl1:network to any port $ports keep state</programlisting>
<para>This provides local network access to the Internet and
leaves the detective work to the
<firstterm>antispoof</firstterm> and
<firstterm>scrub</firstterm> code.</para>
<para>For a busy network admin, a readable ruleset is a safer
ruleset. For the remainder of this section, with some
exceptions, we will keep the rules as simple as possible
for readability.</para>
<para>Above, we introduced the
<literal>interface:network</literal> notation. That is a
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>
<para>For example, a <literal>$localnet</literal> macro could
be defined as the network directly attached to your
internal interface (<literal>$xl1:network</literal> in the
examples above).</para>
<para>Alternatively, the definition of
<para>The
<literal>interface:network</literal> notation can be
replaced with a macro to make the ruleset even
more readable. For example, a <literal>$localnet</literal> macro could
be defined as the network directly attached to the
internal interface (<literal>$xl1:network</literal>).
Alternatively, the definition of
<literal>$localnet</literal> could be changed to an
<emphasis>IP address/netmask</emphasis> notation to denote
a network, such as <literal>192.168.100.1/24</literal> for
@ -686,55 +693,26 @@ pass proto udp to any port $udp_services keep state</programlisting>
<para>If required, <literal>$localnet</literal> could even be
defined as a list of networks. Whatever the specific needs,
a sensible <literal>$localnet</literal> definition and a
typical pass rule of the type</para>
a sensible <literal>$localnet</literal> definition could be
used in a
typical pass rule as follows:</para>
<programlisting>pass from $localnet to any port $ports keep state</programlisting>
<para>could end up saving you a few headaches. We will stick
to that convention from here on.</para>
<para>First, we need to turn on gatewaying in order to let the
machine forward the network traffic it receives on one
interface to other networks via a separate interface.
Initially we will do this on the command line with
&man.sysctl.8;, for traditional <emphasis>IP version
four</emphasis>.</para>
<screen>&prompt.root; <userinput>sysctl net.inet.ip.forwarding=1</userinput></screen>
<para>If we need to forward <emphasis>IP version
six</emphasis> traffic, the command is</para>
<screen>&prompt.root; <userinput>sysctl net.inet6.ip6.forwarding=1</userinput></screen>
<para>In order for this to continue working after the
computer has been restarted at some time in the future,
enter these settings into
<filename>/etc/rc.conf</filename>:</para>
<programlisting>gateway_enable="YES" #for ipv4
ipv6_gateway_enable="YES" #for ipv6</programlisting>
<para>Use <command>ifconfig -a</command>, or
<command>ifconfig interface_name</command> to find out if
both of the interfaces to be used are up and
running.</para>
<para>If all traffic initiated by machines on the inside is to
be allowed, <filename>/etc/pf.conf</filename> could look
roughly like this
<footnote>
<para>For dialup users, the external interface is the
<filename>tun0</filename> pseudo-device. Broadband
users such as ADSL subscribers tend to have an
Ethernet interface to play with, however for a
significant subset of ADSL users, specifically those
using PPP over Ethernet (PPPoE), the correct external
interface will be the <filename>tun0</filename>
pseudo-device, not the physical Ethernet
<para>The following sample ruleset allows all traffic initiated by
machines on the internal network. It first defines two
macros to represent the external and internal 3COM interfaces of
the gateway.</para>
<note>
<para>For dialup users, the external interface will use
<filename>tun0</filename>. For an
<acronym>ADSL</acronym> connection, specifically those
using <acronym>PPP</acronym> over Ethernet (<acronym>PPPoE</acronym>), the correct external
interface is <filename>tun0</filename>,
not the physical Ethernet
interface.</para>
</footnote>:</para>
</note>
<programlisting>ext_if = "xl0" # macro for external interface - use tun0 for PPPoE
int_if = "xl1" # macro for internal interface
@ -744,77 +722,56 @@ nat on $ext_if from $localnet to any -&gt; ($ext_if)
block all
pass from { lo0, $localnet } to any keep state</programlisting>
<para>Note the use of macros to assign logical names to the
network interfaces. Here 3Com cards are used, but this is
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 rulesets grow somewhat larger, you will
learn to appreciate the readability this provides.</para>
<para>Also note the <literal>nat</literal> rule. This is
where we handle the network address translation from the
non-routable address inside the local net to the sole
official address we assume has been assigned.</para>
<para>The parentheses surrounding the last part of the nat
rule <literal>($ext_if)</literal> are there to compensate
for the possibility that the IP address of the external
interface may be dynamically assigned. This detail will
ensure that network traffic runs without serious
interruptions even if the external IP address
<para>This ruleset introduces the <literal>nat</literal> rule which is used to
handle the network address translation from the
non-routable addresses inside the internal network to the <acronym>IP</acronym> address
assigned to the external interface. The parentheses surrounding the last part of the nat
rule <literal>($ext_if)</literal> is included
when the <acronym>IP</acronym> address of the external
interface is dynamically assigned. It
ensures that network traffic runs without serious
interruptions even if the external <acronym>IP</acronym> address
changes.</para>
<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>
<para>Note that this ruleset probably allows more
traffic to pass out of the network than is needed.
One reasonable setup could create this macro:</para>
<programlisting>client_out = "{ ftp-data, ftp, ssh, domain, pop3, auth, nntp, http, \
https, cvspserver, 2628, 5999, 8000, 8080 }"</programlisting>
<para>and the main pass rule</para>
<para>to use in the main pass rule:</para>
<programlisting>pass inet proto tcp from $localnet to any port $client_out \
flags S/SA keep state</programlisting>
<para>In addition, we have a few other pass rules. One pass
rule which is useful for administering machines remotely
is:</para>
<para>A few other pass rules may be needed. This one enables
<acronym>SSH</acronym> on the external interface::</para>
<programlisting>pass in inet proto tcp to $ext_if port ssh</programlisting>
<para>Lastly we need to make the name service work for our
<para>This macro definition and rule allows
<acronym>DNS</acronym> and <acronym>NTP</acronym> for internal
clients:</para>
<programlisting>udp_services = "{ domain, ntp }"</programlisting>
<para>This is supplemented with a rule which passes the
traffic we want through our firewall:</para>
<programlisting>pass quick inet proto { tcp, udp } to any port $udp_services keep state</programlisting>
<programlisting>udp_services = "{ domain, ntp }"
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 rulesets which consist of
several rules, and it is time to take a look at the
relationships between the rules in a ruleset. The rules
rule. Since the ruleset consists of
several rules, it is important to understand the
relationships between the rules in a ruleset. Rules
are evaluated from top to bottom, in the sequence they are
written in the configuration file. For each packet or
written. For each packet or
connection evaluated by <application>PF</application>,
<emphasis>the last matching rule</emphasis> in the rule
set is the one which is applied. The
<literal>quick</literal> keyword offers an escape from the
ordinary sequence. When a packet matches a quick rule,
the packet is treated according to the present rule. The
rule processing stops without considering any further
rules which might have matched the packet. This is very
useful when a few isolated exceptions to the general rules
are needed.</para>
<para>This rule also takes care of <acronym>NTP</acronym>,
which is used for time synchronization. One thing common
to both protocols is that they may under certain
circumstances communicate alternately over TCP and
UDP.</para>
<emphasis>the last matching rule</emphasis> in the ruleset
is the one which is applied. However,
when a packet matches a rule which
contains the <literal>quick</literal> keyword,
the rule processing stops and the packet is treated
according to that rule. This is very
useful when an exception to the general rules
is needed.</para>
</sect3>
<sect3 xml:id="pftut-ftp">