Date: Fri, 11 Oct 2019 19:21:19 +0000 (UTC) From: Benedict Reuschling <bcr@FreeBSD.org> To: doc-committers@freebsd.org, svn-doc-all@freebsd.org, svn-doc-head@freebsd.org Subject: svn commit: r53486 - head/en_US.ISO8859-1/books/handbook/firewalls Message-ID: <201910111921.x9BJLJ4b076111@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bcr Date: Fri Oct 11 19:21:19 2019 New Revision: 53486 URL: https://svnweb.freebsd.org/changeset/doc/53486 Log: Rewrite the NAT chapter to focus on in-kernel NAT, with a small section about natd at the end. Submitted by: driesm.michiels@gmail.com Approved by: bcr@ Differential Revision: https://reviews.freebsd.org/D21306 Modified: head/en_US.ISO8859-1/books/handbook/firewalls/chapter.xml Modified: head/en_US.ISO8859-1/books/handbook/firewalls/chapter.xml ============================================================================== --- head/en_US.ISO8859-1/books/handbook/firewalls/chapter.xml Fri Oct 11 12:35:28 2019 (r53485) +++ head/en_US.ISO8859-1/books/handbook/firewalls/chapter.xml Fri Oct 11 19:21:19 2019 (r53486) @@ -1698,7 +1698,7 @@ options ALTQ_PRIQ # Priority Queuing (PR <warning> <para>Only firewall rules with the <option>log</option> option will be logged. The default rules do not include this option and it - must be manually added. Therefor it is advisable that the default + must be manually added. Therefore it is advisable that the default ruleset is edited for logging. In addition, log rotation may be desired if the logs are stored in a separate file.</para> </warning> @@ -2121,9 +2121,9 @@ pif="dc0" # interface name of NIC attached to Inte $cmd 00999 deny log all from any to any</programlisting> </sect2> - <sect2 xml:id="network-natd"> + <sect2 xml:id="in-kernel-nat"> <info> - <title>Configuring <acronym>NAT</acronym></title> + <title>In-kernel <acronym>NAT</acronym></title> <authorgroup> <author> @@ -2134,19 +2134,34 @@ pif="dc0" # interface name of NIC attached to Inte <contrib>Contributed by </contrib> </author> </authorgroup> + + <authorgroup> + <author> + <personname> + <firstname>Dries</firstname> + <surname>Michiels</surname> + </personname> + <contrib>Rewritten and updated by </contrib> + </author> + </authorgroup> </info> + <indexterm> <primary>NAT</primary> <secondary>and <application>IPFW</application></secondary> </indexterm> - <para>&os;'s built-in <acronym>NAT</acronym> daemon, - &man.natd.8;, works in conjunction with + <para>&os;'s <application>IPFW</application> firewall has two + implementations of <acronym>NAT</acronym>: one being the + userland &man.natd.8; daemon, and the more recent + <application>IPFW</application>'s built-in + <acronym>NAT</acronym> facility also known as in-kernel + <acronym>NAT</acronym>. Both work in conjunction with <application>IPFW</application> to provide network address translation. This can be used to provide an Internet Connection Sharing solution so that several internal computers - can connect to the Internet using a single + can connect to the Internet using a single public <acronym>IP</acronym> address.</para> <para>To do this, the &os; machine connected to the Internet @@ -2157,92 +2172,143 @@ pif="dc0" # interface name of NIC attached to Inte <acronym>LAN</acronym> should be assigned an <acronym>IP</acronym> address in the private network space, as defined by <link - xlink:href="https://www.ietf.org/rfc/rfc1918.txt">RFC - 1918</link>, and have the default gateway set to the - &man.natd.8; system's internal <acronym>IP</acronym> - address.</para> + xlink:href="https://www.ietf.org/rfc/rfc1918.txt">RFC + 1918</link>.</para> - <para>Some additional configuration is needed in order to - activate the <acronym>NAT</acronym> function of - <application>IPFW</application>. If the system has a custom - kernel, the kernel configuration file needs to include - <literal>option IPDIVERT</literal> along with the other - <literal>IPFIREWALL</literal> options described in <xref - linkend="firewalls-ipfw-enable"/>.</para> + <para>Some additional configuration is needed in order to enable + the in-kernel <acronym>NAT</acronym> function of + <application>IPFW</application>. To enable in-kernel + <acronym>NAT</acronym> support at boot time, the following + must be set in <filename>/etc/rc.conf</filename>:</para> - <para>To enable <acronym>NAT</acronym> support at boot time, the - following must be in <filename>/etc/rc.conf</filename>:</para> + <programlisting>gateway_enable="YES" +firewall_enable="YES" +firewall_nat_enable="YES"</programlisting> - <programlisting>gateway_enable="YES" # enables the gateway -natd_enable="YES" # enables <acronym>NAT</acronym> -natd_interface="rl0" # specify interface name of NIC attached to Internet -natd_flags="-dynamic -m" # -m = preserve port numbers; additional options are listed in &man.natd.8;</programlisting> - <note> - <para>It is also possible to specify a configuration file - which contains the options to pass to &man.natd.8;:</para> + <para>When <literal>firewall_enable</literal> is not set, + but <literal>firewall_nat_enable</literal> is, it will have + no effect and do nothing, because the in-kernel + <acronym>NAT</acronym> implementation is only compatible + with <application>IPFW</application>.</para></note> - <programlisting>natd_flags="-f /etc/natd.conf"</programlisting> - - <para>The specified file must contain a list of configuration - options, one per line. For example:</para> - - <programlisting>redirect_port tcp 192.168.0.2:6667 6667 -redirect_port tcp 192.168.0.3:80 80</programlisting> - - <para>For more information about this configuration file, - consult &man.natd.8;.</para> - </note> - - <para>Next, add the <acronym>NAT</acronym> rules to the firewall - ruleset. When the rulest contains stateful rules, the - positioning of the <acronym>NAT</acronym> rules is critical - and the <literal>skipto</literal> action is used. The + <para>When the ruleset contains stateful rules, the positioning + of the <acronym>NAT</acronym> rule is critical and the + <literal>skipto</literal> action is used. The <literal>skipto</literal> action requires a rule number so - that it knows which rule to jump to.</para> + that it knows which rule to jump to. Furthermore, because + of the architecture of &man.libalias.3;, a library implemented + as a kernel module used for the in-kernel + <acronym>NAT</acronym> facility of + <application>IPFW</application>, it is necessary to disable + TCP segmentation offloading, or in short + <acronym>TSO</acronym>. <acronym>TSO</acronym> can be + disabled on a per network interface basis by using + &man.ifconfig.8; or on a system wide basis using + &man.sysctl.8;. To disable <acronym>TSO</acronym> system + wide, the following must be set in + <filename>/etc/sysctl.conf</filename>:</para> - <para>The following example builds upon the firewall ruleset + <programlisting>net.inet.tcp.tso="0"</programlisting> + + <para>The example below builds upon the firewall ruleset shown in the previous section. It adds some additional entries and modifies some existing rules in order to configure - the firewall for <acronym>NAT</acronym>. It starts by adding - some additional variables which represent the rule number to - skip to, the <literal>keep-state</literal> option, and a list - of <acronym>TCP</acronym> ports which will be used to reduce - the number of rules:</para> + the firewall for in-kernel <acronym>NAT</acronym>. It starts + by adding some additional variables which represent the rule + number to skip to, the <literal>keep-state</literal> option, + and a list of <acronym>TCP</acronym> ports which will be used + to reduce the number of rules.</para> <programlisting>#!/bin/sh ipfw -q -f flush cmd="ipfw -q add" -skip="skipto 500" +skip="skipto 1000" pif=dc0 ks="keep-state" good_tcpo="22,25,37,53,80,443,110"</programlisting> + <para>A <acronym>NAT</acronym> instance will also be + configured. With in-kernel <acronym>NAT</acronym> it is + possible to have multiple <acronym>NAT</acronym> instances + each with their own configuration. Although, for this example + only one <acronym>NAT</acronym> instance is needed; + <acronym>NAT</acronym> instance number 1. The configuration + takes a few arguments and flags such as: <option>if</option> + which indicates the public interface, + <option>same_ports</option> which takes care that alliased + ports and local port numbers are mapped the same, + <option>unreg_only</option> will result in only unregistered + (private) address spaces to be processed by the + <acronym>NAT</acronym> instance, and <option>reset</option> + which will help to keep a functioning <acronym>NAT</acronym> + instance even when the public <acronym>IP</acronym> address of + the <application>IPFW</application> machine changes. For all + possible options that can be passed to a single + <acronym>NAT</acronym> instance configuration consult + &man.ipfw.8;. Furthermore, because of the nature of a + stateful <acronym>NAT</acronym>ing firewall, it is neseccary + to allow translated packets to be reinjected in the firewall + for further processing, this can be achieved by disabling + <option>one_pass</option> behavior at the start of the + firewall script.</para> + + <programlisting>ipfw disable one_pass +ipfw -q nat 1 config if $pif same_ports unreg_only reset</programlisting> + <para>The inbound <acronym>NAT</acronym> rule is inserted <emphasis>after</emphasis> the two rules which allow all - traffic on the trusted internal interface and on the loopback - interface and <emphasis>before</emphasis> the + traffic on the trusted and loopback interfaces and after the + reassamble rule but <emphasis>before</emphasis> the <literal>check-state</literal> rule. It is important that the rule number selected for this <acronym>NAT</acronym> rule, in this example <literal>100</literal>, is higher than the first - two rules and lower than the <literal>check-state</literal> - rule:</para> + three rules and lower than the <literal>check-state</literal> + rule. Furthermore, because of the behavior of in-kernel + <acronym>NAT</acronym> it is advised to place a reassamble + rule just before the first <acronym>NAT</acronym> rule and + after the rules that allow traffic on trusted interface. + Normally, <acronym>IP</acronym> fragmentation should not + happen, but when dealing with <acronym>IPSEC/ESP/GRE</acronym> + tunneling traffic it might and the reassmabling of fragments + is necessary before handing the complete packet over to the + in-kernel <acronym>NAT</acronym> engine.</para> + <note> + <para>The reassemble rule was not needed with userland + &man.natd.8; because the internal workings of the + <application>IPFW</application> <literal>divert</literal> + action already takes care of this automatically as also + stated in &man.ipfw.8;.</para> + + <para>The current <acronym>NAT</acronym> instance number and + <acronym>NAT</acronym> rule number does not match with the + default <acronym>NAT</acronym> instance number and rule + number created by <filename>rc.firewall</filename> which is + a script to set up the baked-in default firewall rulesets + present in &os;.</para></note> + <programlisting>$cmd 005 allow all from any to any via xl0 # exclude LAN traffic $cmd 010 allow all from any to any via lo0 # exclude loopback traffic -$cmd 100 divert natd ip from any to any in via $pif # NAT any inbound packets +$cmd 099 reass all from any to any in # reassamble inbound packets +$cmd 100 nat 1 ip from any to any in via $pif # NAT any inbound packets # Allow the packet through if it has an existing entry in the dynamic rules table $cmd 101 check-state</programlisting> <para>The outbound rules are modified to replace the <literal>allow</literal> action with the <literal>$skip</literal> variable, indicating that rule - processing will continue at rule <literal>500</literal>. The + processing will continue at rule <literal>1000</literal>. The seven <literal>tcp</literal> rules have been replaced by rule <literal>125</literal> as the <literal>$good_tcpo</literal> variable contains the seven allowed outbound ports.</para> + <note> + <para>Remember that <application>IPFW</application>'s + firewall performance is largely determined by the number of + rules present in the ruleset.</para></note> + <programlisting># Authorized outbound packets $cmd 120 $skip udp from any to x.x.x.x 53 out via $pif $ks $cmd 121 $skip udp from any to x.x.x.x 67 out via $pif $ks @@ -2256,20 +2322,19 @@ good_tcpo="22,25,37,53,80,443,110"</programlisting> rule, must have a higher number than that last rule, and the rule number must be referenced by the <literal>skipto</literal> action. In this ruleset, rule - number <literal>500</literal> diverts all packets which match - the outbound rules to &man.natd.8; for - <acronym>NAT</acronym> processing. The next rule allows any - packet which has undergone <acronym>NAT</acronym> processing - to pass.</para> + number <literal>1000</literal> handles passing all packets to + our configured instance for <acronym>NAT</acronym> processing. + The next rule allows any packet which has undergone + <acronym>NAT</acronym> processing to pass.</para> - <programlisting>$cmd 499 deny log all from any to any -$cmd 500 divert natd ip from any to any out via $pif # skipto location for outbound stateful rules -$cmd 510 allow ip from any to any</programlisting> + <programlisting>$cmd 999 deny log all from any to any +$cmd 1000 nat 1 ip from any to any out via $pif # skipto location for outbound stateful rules +$cmd 1001 allow ip from any to any</programlisting> <para>In this example, rules <literal>100</literal>, <literal>101</literal>, <literal>125</literal>, - <literal>500</literal>, and <literal>510</literal> control the - address translation of the outbound and inbound packets so + <literal>1000</literal>, and <literal>1001</literal> control + the address translation of the outbound and inbound packets so that the entries in the dynamic state table always register the private <acronym>LAN</acronym> <acronym>IP</acronym> address.</para> @@ -2286,7 +2351,7 @@ good_tcpo="22,25,37,53,80,443,110"</programlisting> internal <acronym>LAN</acronym>. On matching this rule, two actions take place. First, the <literal>keep-state</literal> action adds an entry to the dynamic state table and the - specified action, <literal>skipto rule 500</literal>, is + specified action, <literal>skipto rule 1000</literal>, is executed. Next, the packet undergoes <acronym>NAT</acronym> and is sent out to the Internet. This packet makes its way to the destination web server, where a response packet is @@ -2305,22 +2370,50 @@ good_tcpo="22,25,37,53,80,443,110"</programlisting> generated as a response is recognized by the <literal>check-state</literal> rule as belonging to an existing session. It is then sent to rule - <literal>500</literal> to undergo + <literal>1000</literal> to undergo <acronym>NAT</acronym> before being released to the outbound interface.</para> + <note> + <para>Transition from userland &man.natd.8; to in-kernel + <acronym>NAT</acronym> might seem seamless at first but + there is small catch. When using the GENERIC kernel, + <application>IPFW</application> will load the + <filename>libalias.ko</filename> + kernel module, when <literal>firewall_nat_enable</literal> + is enabled in <filename>rc.conf</filename>. Although, the + loaded module only provides basic <acronym>NAT</acronym> + functionality, whereas the userland implementation + &man.natd.8; has all functionality available without any + extra configuration from its userland library. All + functionality refers to the following kernel modules that + can additionally be loaded when needed besides the standard + <filename>libalias.ko</filename> kernel module: + <filename>alias_cuseeme.ko</filename>, + <filename>alias_ftp.ko</filename>, + <filename>alias_bbt.ko</filename>, + <filename>skinny.ko</filename>, <filename>irc.ko</filename>, + <filename>alias_pptp.ko</filename> and + <filename>alias_smedia.ko</filename> using the + <literal>kld_list</literal> directive in + <filename>rc.conf</filename> to mimic the full functionality + of the userland implementation. If a custom kernel is used, + the full functionality of the userland library can be + compiled in, in the kernel, using the <option>option + LIBALIAS</option>.</para></note> + <sect3> <title>Port Redirection</title> - <para>The drawback with &man.natd.8; is that the - <acronym>LAN</acronym> clients are not accessible from the - Internet. Clients on the <acronym>LAN</acronym> can make - outgoing connections to the world but cannot receive - incoming ones. This presents a problem if trying to run - Internet services on one of the <acronym>LAN</acronym> + <para>The drawback with <acronym>NAT</acronym> in general is + that the <acronym>LAN</acronym> clients are not accessible + from the Internet. Clients on the <acronym>LAN</acronym> + can make outgoing connections to the world but cannot + receive incoming ones. This presents a problem if trying to + run Internet services on one of the <acronym>LAN</acronym> client machines. A simple way around this is to redirect - selected Internet ports on the &man.natd.8; machine to a - <acronym>LAN</acronym> client.</para> + selected Internet ports on the <acronym>NAT</acronym> + providing machine to a <acronym>LAN</acronym> client.</para> <para>For example, an <acronym>IRC</acronym> server runs on client <systemitem>A</systemitem> and a web server runs on @@ -2329,49 +2422,51 @@ good_tcpo="22,25,37,53,80,443,110"</programlisting> (<acronym>IRC</acronym>) and 80 (<acronym>HTTP</acronym>) must be redirected to the respective machines.</para> - <para>The syntax for <option>-redirect_port</option> is as + <para>With in-kernel <acronym>NAT</acronym> all configuration + is done in the <acronym>NAT</acronym> instance + configuration. For a full list of options that an in-kernel + <acronym>NAT</acronym> instance can use, consult + &man.ipfw.8;. The <application>IPFW</application> syntax + follows the syntax of <application>natd</application>. The + syntax for <option>redirect_port</option> is as follows:</para> - <programlisting> -redirect_port proto targetIP:targetPORT[-targetPORT] - [aliasIP:]aliasPORT[-aliasPORT] - [remoteIP[:remotePORT[-remotePORT]]]</programlisting> + <programlisting>redirect_port proto targetIP:targetPORT[-targetPORT] + [aliasIP:]aliasPORT[-aliasPORT] + [remoteIP[:remotePORT[-remotePORT]]]</programlisting> - <para>In the above example, the argument should be:</para> + <para>To configure the above example setup, the arguments + should be:</para> - <programlisting> -redirect_port tcp 192.168.0.2:6667 6667 - -redirect_port tcp 192.168.0.3:80 80</programlisting> + <programlisting>redirect_port tcp 192.168.0.2:6667 6667 +redirect_port tcp 192.168.0.3:80 80</programlisting> - <para>This redirects the proper <acronym>TCP</acronym> ports - to the <acronym>LAN</acronym> client machines.</para> + <para>After adding these arguments to the configuration of + <acronym>NAT</acronym> instance 1 in the above ruleset, the + <acronym>TCP</acronym> ports will be port forwarded to the + <acronym>LAN</acronym> client machines running the + <acronym>IRC</acronym> and <acronym>HTTP</acronym> + services.</para> + <programlisting>ipfw -q nat 1 config if $pif same_ports unreg_only reset \ + redirect_port tcp 192.168.0.2:6667 6667 \ + redirect_port tcp 192.1683.0.3:80 80</programlisting> + <para>Port ranges over individual ports can be indicated with - <option>-redirect_port</option>. For example, + <option>redirect_port</option>. For example, <replaceable>tcp 192.168.0.2:2000-3000 - 2000-3000</replaceable> would redirect all connections + 2000-3000</replaceable> would redirect all connections received on ports 2000 to 3000 to ports 2000 to 3000 on client <systemitem>A</systemitem>.</para> - - <para>These options can be used when directly running - &man.natd.8;, placed within the - <literal>natd_flags=""</literal> option in - <filename>/etc/rc.conf</filename>, or passed via a - configuration file.</para> - - <para>For further configuration options, consult - &man.natd.8;.</para> </sect3> <sect3> <title>Address Redirection</title> - <indexterm> - <primary>address redirection</primary> - </indexterm> - <para>Address redirection is useful if more than one <acronym>IP</acronym> address is available. Each <acronym>LAN</acronym> client can be assigned its own - external <acronym>IP</acronym> address by &man.natd.8;, + external <acronym>IP</acronym> address by &man.ipfw.8;, which will then rewrite outgoing packets from the <acronym>LAN</acronym> clients with the proper external <acronym>IP</acronym> address and redirects all traffic @@ -2383,7 +2478,7 @@ good_tcpo="22,25,37,53,80,443,110"</programlisting> class="ipaddress">128.1.1.2</systemitem>, and <systemitem class="ipaddress">128.1.1.3</systemitem> are available, <systemitem class="ipaddress">128.1.1.1</systemitem> can be - used as the &man.natd.8; machine's external + used as the &man.ipfw.8; machine's external <acronym>IP</acronym> address, while <systemitem class="ipaddress">128.1.1.2</systemitem> and <systemitem class="ipaddress">128.1.1.3</systemitem> are forwarded @@ -2391,48 +2486,90 @@ good_tcpo="22,25,37,53,80,443,110"</programlisting> <systemitem>A</systemitem> and <systemitem>B</systemitem>.</para> - <para>The <option>-redirect_address</option> syntax is as - follows:</para> + <para>The <option>redirect_address</option> syntax is as + below, where <literal>localIP</literal> is the internal + <acronym>IP</acronym> address of the <acronym>LAN</acronym> + client, and <literal>publicIP</literal> the external + <acronym>IP</acronym> address corresponding to the + <acronym>LAN</acronym> client.</para> - <programlisting>-redirect_address localIP publicIP</programlisting> + <programlisting>redirect_address localIP publicIP</programlisting> + <para>In the example, the arguments would read:</para> - <informaltable frame="none" pgwide="1"> - <tgroup cols="2"> - <tbody> - <row> - <entry>localIP</entry> - <entry>The internal <acronym>IP</acronym> address of - the <acronym>LAN</acronym> client.</entry> - </row> + <programlisting>redirect_address 192.168.0.2 128.1.1.2 +redirect_address 192.168.0.3 128.1.1.3</programlisting> - <row> - <entry>publicIP</entry> - <entry>The external <acronym>IP</acronym> address - corresponding to the <acronym>LAN</acronym> - client.</entry> - </row> - </tbody> - </tgroup> - </informaltable> - - <para>In the example, this argument would read:</para> - - <programlisting>-redirect_address 192.168.0.2 128.1.1.2 --redirect_address 192.168.0.3 128.1.1.3</programlisting> - - <para>Like <option>-redirect_port</option>, these arguments - are placed within the <literal>natd_flags=""</literal> - option of <filename>/etc/rc.conf</filename>, or passed via a - configuration file. With address redirection, there is no - need for port redirection since all data received on a + <para>Like <option>redirect_port</option>, these arguments + are placed in a <acronym>NAT</acronym> instance + configuration. With address redirection, there is no + need for port redirection, as all data received on a particular <acronym>IP</acronym> address is redirected.</para> <para>The external <acronym>IP</acronym> addresses on the - &man.natd.8; machine must be active and aliased to the + &man.ipfw.8; machine must be active and aliased to the external interface. Refer to &man.rc.conf.5; for details.</para> + </sect3> + + <sect3> + <title>Userspace <acronym>NAT</acronym></title> + + <para>Let us start with a statement: the userspace + <acronym>NAT</acronym> implementation: &man.natd.8;, has + more overhead than in-kernel <acronym>NAT</acronym>. For + &man.natd.8; to translate packets, the packets have to be + copied from the kernel to userspace and back which brings in + extra overhead that is not present with in-kernel + <acronym>NAT</acronym>.</para> + + <para>To enable the userpace <acronym>NAT</acronym> daemon + &man.natd.8; at boot time, the following is a minimum + configuration in <filename>/etc/rc.conf</filename>. Where + <option>natd_interface</option> is set to the name of the + <acronym>NIC</acronym> attached to the Internet. The + &man.rc.8; script of &man.natd.8; will automatically check + if a dynamic <acronym>IP</acronym> address is used and + configure itself to handle that.</para> + + <programlisting>gateway_enable="YES" +natd_enable="YES" +natd_interface="rl0"</programlisting> + + <para>In general, the above ruleset as explained for in-kernel + <acronym>NAT</acronym> can also be used together with + &man.natd.8;. The only exceptions are the configuration of + the in-kernel <acronym>NAT</acronym> instance <literal>(ipfw + -q nat 1 config ...)</literal> not being applicable any + more, rule number 100 and 1000 will have to change sligthly + as below, and reassemble rule 99 is not needed anymore + as the <option>divert</option> action is used which covers + fragmentation.</para> + + <programlisting>$cmd 100 divert natd ip from any to any in via $pif +$cmd 1000 divert natd ip from any to any out via $pif</programlisting> + + <para>To configure port or address redirection, a similar + syntax as with in-kernel <acronym>NAT</acronym> is used. + Although, now, instead of specifying the configuration in + our ruleset script like with in-kernel + <acronym>NAT</acronym>, configuration of &man.natd.8; is + best done in a configuration file. To do this, an extra + flag must be passed via <filename>/etc/rc.conf</filename> + which specifies the path of the configuration file.</para> + + <programlisting>natd_flags="-f /etc/natd.conf"</programlisting> + + <note> + <para>The specified file must contain a list of + configuration options, one per line. For more information + about the configuration file and possible variables, + consult &man.natd.8;. Below are two example + entries, one per line:</para> + + <programlisting>redirect_port tcp 192.168.0.2:6667 6667 +redirect_address 192.168.0.3 128.1.1.3</programlisting></note> </sect3> </sect2>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201910111921.x9BJLJ4b076111>