361 lines
14 KiB
Text
361 lines
14 KiB
Text
<!--
|
|
The FreeBSD Documentation Project
|
|
-->
|
|
|
|
<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook V4.1-Based Extension//EN" [
|
|
<!ENTITY % man PUBLIC "-//FreeBSD//ENTITIES DocBook Manual Page Entities//EN">
|
|
%man;
|
|
]>
|
|
|
|
<article>
|
|
<articleinfo>
|
|
<title>Dialup firewalling with FreeBSD</title>
|
|
|
|
<authorgroup>
|
|
<author>
|
|
<firstname>Marc</firstname>
|
|
<surname>Silver</surname>
|
|
|
|
<affiliation>
|
|
<address><email>marcs@draenor.org</email></address>
|
|
</affiliation>
|
|
</author>
|
|
</authorgroup>
|
|
|
|
<pubdate>$FreeBSD$</pubdate>
|
|
|
|
<abstract>
|
|
<para>This article documents how to setup a firewall using a PPP
|
|
dialup with FreeBSD and IPFW, and specifically with firewalling over
|
|
a dialup with a dynamically assigned IP address. This document does
|
|
not cover setting up your PPP connection in the first place.</para>
|
|
</abstract>
|
|
</articleinfo>
|
|
|
|
<sect1 id="preface">
|
|
<title>Preface</title>
|
|
|
|
<para>Dialup Firewalling with FreeBSD</para>
|
|
|
|
<para>This document covers the process that is required to setup
|
|
firewalling with FreeBSD when an IP address is assigned dynamically
|
|
by your ISP. While every effort has been made to make this document
|
|
as informative and correct as possible, you are welcome to mail your
|
|
comments/suggestions to the <email>marcs@draenor.org</email>.</para>
|
|
</sect1>
|
|
|
|
<sect1 id="kernel">
|
|
<title>Kernel Options</title>
|
|
|
|
<para>The first thing you'll need to do is recompile your kernel
|
|
If you need more information on how to recompile the kernel,
|
|
then the best place to start is the <ulink
|
|
URL="http://www.freebsd.org/handbook/kernelconfig.html">kernel
|
|
configuration section in the Handbook</ulink>. You need to add the
|
|
following options into your kernel configuration file:</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>options IPFIREWALL</literal></term>
|
|
|
|
<listitem>
|
|
<para>Enables the kernel's firewall code.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>options IPFIREWALL_VERBOSE</literal></term>
|
|
|
|
<listitem>
|
|
<para>Sends logged packets to the system logger.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>options
|
|
IPFIREWALL_VERBOSE_LIMIT=<replaceable>100</replaceable></literal></term>
|
|
|
|
<listitem>
|
|
<para>Limits the number of times a matching entry is logged. This
|
|
prevents your log file from filling up with lots of repetitive
|
|
entries.
|
|
<replaceable>100</replaceable> is a reasonable number to use, but
|
|
you can adjust it based on your requirements.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>options IPDIVERT</literal></term>
|
|
|
|
<listitem>
|
|
<para>Enables <emphasis>divert</emphasis> sockets, which will be
|
|
shown later.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>There are some other OPTIONAL items that you can compile
|
|
into the kernel for some added security. These are not required in
|
|
order to get firewalling to work, but some more paranoid users may
|
|
want to use them.</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>options TCP_DROP_SYNFIN</literal></term>
|
|
|
|
<listitem>
|
|
<para>This option ignores TCP packets with SYN and FIN. This
|
|
prevents tools such as nmap etc from identifying the TCP/IP
|
|
stack of the machine, but breaks support for RFC1644
|
|
extensions. This is NOT recommended if the machine will be
|
|
running a web server.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>Don't reboot once you have recompiled the kernel. Hopefully,
|
|
we will only need to reboot once to complete the installation of the
|
|
firewall.</para>
|
|
</sect1>
|
|
|
|
<sect1 id="rcconf">
|
|
<title>Changing <filename>/etc/rc.conf</filename> to load the
|
|
firewall</title>
|
|
|
|
<para>We now need to make some changes to
|
|
<filename>/etc/rc.conf</filename> in order to tell it about the
|
|
firewall. Simply add the following lines:</para>
|
|
|
|
<programlisting>firewall_enable="YES"
|
|
firewall_script="/etc/firewall/fwrules"
|
|
natd_enable="YES"
|
|
natd_interface="tun0"
|
|
natd_flags="-dynamic"</programlisting>
|
|
|
|
<para>For more information on the functions of these statements take
|
|
a look at <filename>/etc/defaults/rc.conf</filename> and read
|
|
&man.rc.conf.5;</para>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Disable PPP's network address translation</title>
|
|
|
|
<para>You may already be using PPP's built in network address
|
|
translation (NAT). If that is the case then you will have to disable
|
|
it, as these examples use &man.natd.8; to do the same.</para>
|
|
|
|
<para>If you already have a block of entries to
|
|
automatically start PPP, it probably looks like this:</para>
|
|
|
|
<programlisting>ppp_enable="YES"
|
|
ppp_mode="auto"
|
|
ppp_nat="YES"
|
|
ppp_profile="<replaceable>profile</replaceable>"</programlisting>
|
|
|
|
<para>If so, remove the <literal>ppp_nat="YES"</literal> line. You will
|
|
also need to remove any <literal>nat enable yes</literal> or
|
|
<literal>alias enable yes</literal> in
|
|
<filename>/etc/ppp/ppp.conf</filename>.</para>
|
|
</sect1>
|
|
|
|
<sect1 id="rules">
|
|
<title>The ruleset for the firewall</title>
|
|
|
|
<para>We're nearly done now. All that remains now is to define the
|
|
firewall rules and then we can reboot and the firewall should be up and
|
|
running. I realize that everyone will want something slightly different
|
|
when it comes to their rulebase. What I've tried to do is write a
|
|
rulebase that suits most dialup users. You can obviously modify it to
|
|
your needs by using the following rules as the foundation for
|
|
your own rulebase. First, let's start with the basics of closed
|
|
firewalling. What you want to do is deny everything by default and then
|
|
only open up for the things you really need. Rules should be in the
|
|
order of allow first and then deny. The premise is that you add the
|
|
rules for your allows, and then everything else is denied. :)</para>
|
|
|
|
<para>Now, let's make the dir /etc/firewall. Change into the directory and
|
|
edit the file <filename>fwrules</filename> as we specified in
|
|
<filename>rc.conf</filename>. Please note that you can change this
|
|
filename to anything you wish. This guide just gives an example of a
|
|
filename. </para>
|
|
|
|
<para>Now, let's look at a sample firewall file, that is commented
|
|
nicely.</para>
|
|
|
|
<programlisting># Firewall rules
|
|
# Written by Marc Silver (marcs@draenor.org)
|
|
# http://draenor.org/ipfw
|
|
# Freely distributable
|
|
|
|
|
|
# Define the firewall command (as in /etc/rc.firewall) for easy
|
|
# reference. Helps to make it easier to read.
|
|
fwcmd="/sbin/ipfw"
|
|
|
|
# Force a flushing of the current rules before we reload.
|
|
$fwcmd -f flush
|
|
|
|
# Divert all packets through the tunnel interface.
|
|
$fwcmd add divert natd all from any to any via tun0
|
|
|
|
# Allow all data from my network card and localhost. Make sure you
|
|
# change your network card (mine was fxp0) before you reboot. :)
|
|
$fwcmd add allow ip from any to any via lo0
|
|
$fwcmd add allow ip from any to any via fxp0
|
|
|
|
# Allow all connections that I initiate.
|
|
$fwcmd add allow tcp from any to any out xmit tun0 setup
|
|
|
|
# Once connections are made, allow them to stay open.
|
|
$fwcmd add allow tcp from any to any via tun0 established
|
|
|
|
# Everyone on the internet is allowed to connect to the following
|
|
# services on the machine. This example shows that people may connect
|
|
# to ssh and apache.
|
|
$fwcmd add allow tcp from any to any 80 setup
|
|
$fwcmd add allow tcp from any to any 22 setup
|
|
|
|
# This sends a RESET to all ident packets.
|
|
$fwcmd add reset log tcp from any to any 113 in recv tun0
|
|
|
|
# Allow outgoing DNS queries ONLY to the specified servers.
|
|
$fwcmd add allow udp from any to <replaceable>x.x.x.x</replaceable> 53 out xmit tun0
|
|
|
|
# Allow them back in with the answers... :)
|
|
$fwcmd add allow udp from <replaceable>x.x.x.x</replaceable> 53 to any in recv tun0
|
|
|
|
# Allow ICMP (for ping and traceroute to work). You may wish to
|
|
# disallow this, but I feel it suits my needs to keep them in.
|
|
$fwcmd add 65435 allow icmp from any to any
|
|
|
|
# Deny all the rest.
|
|
$fwcmd add 65435 deny log ip from any to any</programlisting>
|
|
|
|
<para>You now have a fully functional firewall that will allow on
|
|
connections to ports 80 and 22 and will log any other connection
|
|
attempts. Now, you should be able to safely reboot and your firewall
|
|
should come up fine. If you find this incorrect in anyway or experience
|
|
any problems, or have any suggestions to improve this page, please
|
|
email me.</para>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Questions</title>
|
|
|
|
<qandaset>
|
|
<qandaentry>
|
|
<question>
|
|
<para>Why are you using natd and ipfw when you could be using
|
|
the built in ppp-filters?</para>
|
|
</question>
|
|
|
|
<answer>
|
|
<para>I'll have to be honest and say there's no definitive reason
|
|
why I use ipfw and natd instead of the built in ppp filters. From
|
|
the discussions I've had with people the consensus seems to be
|
|
that while ipfw is certainly more powerful and more configurable
|
|
than the ppp filters, what it makes up for in functionality it
|
|
loses in being easy to customise. One of the reasons I use it is
|
|
because I prefer firewalling to be done at a kernel level rather
|
|
than by a userland program.</para>
|
|
</answer>
|
|
</qandaentry>
|
|
|
|
<qandaentry>
|
|
<question>
|
|
<para>I get messages like <errorname>limit 100 reached on entry
|
|
2800</errorname> and after that I never see more denies in my
|
|
logs. Is my firewall still working?</para>
|
|
</question>
|
|
|
|
<answer>
|
|
<para>This merely means that the maximum logging count for the
|
|
rule has been reached. The rule itself is still working,
|
|
but it will no longer log until such time as you reset the
|
|
logging counters. This can be done by simply prefixing the
|
|
ipfw command with the <literal>resetlog</literal> option.</para>
|
|
</answer>
|
|
</qandaentry>
|
|
|
|
<qandaentry>
|
|
<question>
|
|
<para>If I'm using private addresses internally, such as in the
|
|
192.168.0.0 range, could I add a command like <literal>$fwcmd add
|
|
deny all from any to 192.168.0.0:255.255.0.0 via tun0</literal>
|
|
to the firewall rules to prevent outside attempts to connect to
|
|
internal machines?</para>
|
|
</question>
|
|
|
|
<answer>
|
|
<para>The simple answer is no. The reason for this is that natd is
|
|
doing address translation for <emphasis>anything</emphasis> being
|
|
diverted through the tun0 device. As far as it's concerned
|
|
incoming packets will speak only to the dynamically assigned IP
|
|
address and NOT to the internal network. Note though that you can
|
|
add a rule like <literal>$fwcmd add deny all from
|
|
192.168.0.4:255.255.0.0 to any via tun0</literal> which would
|
|
limit a host on your internal network from going out via the
|
|
firewall.</para>
|
|
</answer>
|
|
</qandaentry>
|
|
|
|
<qandaentry>
|
|
<question>
|
|
<para>There must be something wrong. I followed your instructions
|
|
to the letter and now I am locked out.</para>
|
|
</question>
|
|
|
|
<answer>
|
|
<para>This tutorial assumes that you are running
|
|
<emphasis>userland-ppp</emphasis>, therefore the supplied ruleset
|
|
operates on the <devicename>tun0</devicename> interface, which
|
|
corresponds to the first connection made with &man.ppp.8; (a.k.a.
|
|
<emphasis>user-ppp</emphasis>). Additional connections would use
|
|
<devicename>tun1</devicename>, <devicename>tun2</devicename> and so
|
|
on.</para>
|
|
|
|
<para>You should also note that &man.pppd.8; uses the
|
|
<devicename>ppp0</devicename> interface instead, so if you start the
|
|
connection with &man.pppd.8; you must substitute
|
|
<devicename>tun0</devicename> for <devicename>ppp0</devicename>. A
|
|
quick way to edit the firewall rules to reflect this change is shown
|
|
below. The original ruleset is backed up as
|
|
<filename>fwrules_tun0</filename>.</para>
|
|
|
|
<screen> &prompt.user; <userinput>cd /etc/firewall</userinput>
|
|
/etc/firewall&prompt.user; <userinput>su</userinput>
|
|
<prompt>Password:</prompt>
|
|
/etc/firewall&prompt.root; <userinput>mv fwrules fwrules_tun0</userinput>
|
|
/etc/firewall&prompt.root; <userinput>cat fwrules_tun0 | sed s/tun0/ppp0/g > fwrules</userinput>
|
|
</screen>
|
|
|
|
<para>To know whether you are currently using &man.ppp.8; or
|
|
&man.pppd.8; you can examine the output of &man.ifconfig.8; once the
|
|
connection is up. E.g., for a connection made with &man.pppd.8; you
|
|
would see something like this (showing only the relevant lines):</para>
|
|
|
|
<screen> &prompt.user; <userinput>ifconfig</userinput>
|
|
<emphasis>(skipped...)</emphasis>
|
|
ppp0: flags=<replaceable>8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1524</replaceable>
|
|
inet <replaceable>xxx.xxx.xxx.xxx</replaceable> --> <replaceable>xxx.xxx.xxx.xxx</replaceable> netmask <replaceable>0xff000000</replaceable>
|
|
<emphasis>(skipped...)</emphasis>
|
|
</screen>
|
|
|
|
<para>On the other hand, for a connection made with &man.ppp.8;
|
|
(<emphasis>user-ppp</emphasis>) you should see something similar to
|
|
this:</para>
|
|
|
|
<screen> &prompt.user; <userinput>ifconfig</userinput>
|
|
<emphasis>(skipped...)</emphasis>
|
|
ppp0: flags=<replaceable>8010<POINTOPOINT,MULTICAST> mtu 1500</replaceable>
|
|
<emphasis>(skipped...)</emphasis>
|
|
tun0: flags=<replaceable>8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1524</replaceable>
|
|
<emphasis>(IPv6 stuff skipped...)</emphasis>
|
|
inet <replaceable>xxx.xxx.xxx.xxx</replaceable> --> <replaceable>xxx.xxx.xxx.xxx</replaceable> netmask <replaceable>0xffffff00</replaceable>
|
|
Opened by PID <replaceable>xxxxx</replaceable>
|
|
<emphasis>(skipped...)</emphasis></screen>
|
|
</answer>
|
|
</qandaentry>
|
|
</qandaset>
|
|
</sect1>
|
|
</article>
|