Chinaunix首页 | 论坛 | 博客
  • 博客访问: 730768
  • 博文数量: 140
  • 博客积分: 5097
  • 博客等级: 大校
  • 技术积分: 991
  • 用 户 组: 普通用户
  • 注册时间: 2006-01-05 19:13
文章分类

全部博文(140)

文章存档

2018年(1)

2015年(5)

2014年(5)

2013年(2)

2011年(16)

2010年(6)

2009年(9)

2008年(45)

2007年(26)

2006年(25)

分类: BSD

2006-01-16 13:49:06

FreeBSD firewall using IP Filter
from unixcircle

by

It is really simple to build a FreeBSD gateway for a private network. You only need to do several tasks. Details are given below.

Lock down the box

The first step in setting up a firewall is to disable all running services that are not necessary. This helps minimize local and remote exploits. Edit /etc/rc.conf and make sure inetd, portmap, sendmail daemons are all disabled.

inetd_enable="NO"
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
check_quotas="NO"

Also comment out each service line in /etc/inetd.conf for extra precaution. If you need to remote logon, use ssh and add sshd_enable="YES" to /etc/rc.conf.

Once you disabled unnecessary services, go to to remotely port scan your own box
from the outside. Be careful when you do this behind a NAT/firewall box as the port scan script will scan the
NAT/firewall instead. If you have another box, use
nmap to scan the box from the inside.

Get the latest FreeBSD security patches manually and apply them from here:

ftp://ftp.FreeBSD.org/pub/FreeBSD/CERT/patches/

or use CVSup to to stable release and build from source.

For more information on security vulnerabilities, read SANS The Twenty Most Critical Internet Security Vulnerabilities (Updated)

Setup network interfaces

Assume this box has 2 3com 509B network cards and their FreeBSD driver are named as ep0 and
ep1 for first and second card. First network card will use the non-routable private address according to rfc1918.
The second will be assigned either static or dynamic via DHCP IP address.

Non-routable IP addresses for private networks:

10.0.0.1 - 10.255.255.254      netmask 255.0.0.0
172.16.0.1 - 172.31.255.254    netmask 255.240.0.0
192.168.0.1 - 192.168.255.254  netmask 255.255.0.0

Assume you choose 192.168.0.1 range, enable the first network interface in /etc/rc.conf:

ifconfig_ep0="inet 192.168.1.1 netmask 255.255.255.0"

If the second network card has static IP, enable it in /etc/rc.conf also:

ifconfig_ep1="inet xxx.xxx.xxx.xxx netmask xxx.xxx.xxx.xxx"

where xxx denotes your IP address and netmask provided by your ISP.

Be sure to indicate a correct IP address and netmask for both interfaces. Once you have chosen
a private network address range for your inside machines, stay with that same range. The first network
card will be the default FreeBSD gateway IP address.

Customize the kernel

To compile the new kernel you need the kernel source (part of kernel developer distribution).
If you haven't done that, run /stand/sysinstall and make sure to install the kernel source.

# cd /sys/i386/conf
# cp GENERIC firewall

I usually name the kernel to the machine hostname, but you can give it any name. Edit the kernel config file:

# vi firewall

In the options section, add these lines:

options     IPFILTER                  # IPFilter support
options     IPFILTER_LOG              # IPFilter logging support
options     IPFILTER_DEFAULT_BLOCK    # Block all packets by default
options     RANDOM_IP_ID              # RANDOM_IP_ID causes the ID field in IP packets to be randomized
                                      # instead of incremented by 1 with each packet generated.

Remove any hardware related ``options'' that are not relevant to your machine. One way to find out what to keep is to consult
the dmesg output and remove all the rest. For all available kernel options, refer to LINT in the same directory as the kernel
file. Save the kernel config file and then compile and install it:

# cd /usr/src
# make buildkernel KERNCONF=firewall
( kernel building output... )
...
# make installkernel KERNCONF=firewall
# reboot

This will retain the old kernel as /kernel.old just in case something has gone awry with the new one and the box
doesn't boot. If that happens you can type 'kernel.old' at the boot: prompt to boot the old kernel.

Enable packet forwarding, dhcp, firewall and network address translation

To enable packet forwarding, add to /etc/sysctl.conf:

net.inet.ip.forwarding=1

Hardening features:

Add to /etc/sysctl.conf:

To verify that an incoming packet arrives on an interface that has an address matching the packet's destination address:

net.inet.ip.check_interface=1
To drop SYN packets destine to non-listening tcp/udp port. This will create a blackhole and protect against stealth port scans:
net.inet.tcp.blackhole=2
net.inet.udp.blackhole=1
Improve performance features:

To enable high performance data transfers on hosts according to ,
add the following in addition to ip forwarding to /etc/sysctl.conf:

# 1. Path MTU discovery: enabled by default
# 2. TCP Extension (RFC1323): enabled by default
# 3. Increase TCP Window size for increase in network performance
net.inet.tcp.recvspace=65535
net.inet.tcp.sendspace=65535
# 4. SACK (RFC2018): FreeBSD doesn't have a SACK implementation
DHCP client:

And if you receive your public address assignment dynamically through DHCP, edit /etc/rc.conf and add:

ifconfig_ep1="DHCP"
and edit /etc/dhclient.conf so that the dhcp client can query the dhcp server for appropriate information
in order to connect. Here's my /etc/dhclient.conf
send host-name "crxxxxxx-a"; # Put your client IP here
request subnet-mask, broadcast-address, routers, domain-name-servers;
Filter rule:

Since you don't know what to block yet, you need to open up ingress and outgress traffic to flow through. Edit /etc/ipf.rules and add:

pass in all
pass out all
An example of a working

Network Address Translation rule:

For NAT and ftp clients behind NAT to work, add the following to /etc/ipnat.rules:

# Use ipfilter ftp proxy for ftp client transfers mode: active
map ep1 192.168.1.0/24 -> 0.0.0.0/32 proxy port ftp ftp/tcp

# Map all tcp and udp connections from 192.168.1.0/24 to external IP address,
# changing the source port number to something between 40,000 and 60,000 inclusive
map ep1 192.168.1.0/24 -> 0.0.0.0/32 portmap tcp/udp 40000:60000

# For all other IP packets, map to the external IP address
map ep1 192.168.1.0/24 -> 0.0.0.0/32

Make sure all the `proxy' lines are before any generic `portmap' lines, as the first match always wins.

An example of a working

Now, turn on NAT/firewall feature in /etc/rc.conf:

ipfilter_enable="YES"       #Stateful firewall
ipfilter_flags=""           #IPFilter is enabled in the kernel and not module
ipnat_enable="YES"          #Network Address Translation
ipmon_enable="YES"          #Firewall logging
ipmon_flags="-Dsn"

-D: Cause ipmon to turn itself into  a  daemon.
-n: IP addresses and port numbers will be mapped, where possible, back into hostnames and service names.
-s: Packet information read in  will  be  sent  through syslogd  rather  than saved to a file.

Some other interesting features with IPFilter you might find useful:

1. Transparent proxying

If there's a mail server as 192.168.1.2 inside the private network , use ``rdr'' statement to transparent proxying.
Since NAT happens before ``rdr'', a ``pass in'' is required in /etc/ipf.conf for the translated packets to flow into the mail server.

/etc/ipnat.rules:

# Redirect incoming smtp traffic to mail server behind NAT
rdr ep1 0.0.0.0/0 port 25 -> 192.168.1.2 port 25

/etc/ipf.rules:

# Allow the translated packets with fragment and SYN flag to flow in. Keep state the connection.
pass in quick on ep1 proto tcp from any to any port = 25 flags S keep state keep frags
2. Load balancing

To load balancing a farm of 6 web servers behind NAT with address 192.168.1.1-192.168.1.6, use ``round-robin'' statement.
IPFilter will distribute the load using round robin method. IPFilter will distribute the load even if one of the web servers is
down. l4check which is part of IPFilter and can deal with this scenario.

rdr ep1 0.0.0.0/0 port 80 -> 192.168.1.1,192.168.1.2 port 80 tcp round-robin
rdr ep1 0.0.0.0/0 port 80 -> 192.168.1.3,192.168.1.4 port 80 tcp round-robin
rdr ep1 0.0.0.0/0 port 80 -> 192.168.1.5,192.168.1.6 port 80 tcp round-robin

Log filtering rules to a dedicated log host:

A nice way to backup log messages and rely on if the NAT/firewall is rooted is to use a dedicated log server. Here is how you setup:

1. On the NAT/firewall, send log messages to a dedicated log server called e.g. ``loghost''

Edit /etc/syslog.conf and uncomment out the following line:

# uncomment this to enable logging to a remote loghost named loghost
*.*                                             @loghost
Restart syslogd:
# kill -1 `cat /var/run/syslog.pid`
2. On the dedicated FreeBSD log server Kill the current running syslogd which does not log messages from remote machines
# kill -9 `cat /var/run/syslog.pid`
Invoke it with -a to turn on remote logging for log messages from NAT/firewall
# syslogd -a 192.168.1.1
The check out the /var/log files on the loghost for new log entries from the NAT/firewall.
Caveat: The communication link between loghost and the firewall is not encrypted and therefore potentially vulnerable to eavedrop.
Use IPsec to encrypt the channel.

Configure machines behind NAT

All the machines on the private network should be configured to use the address of the private interface of the FreeBSD box as the default gateway.

To set the internal boxes to the default FreeBSD gateway on various operating systems:

Assume the FreeBSD box NAT/firewall has IP address: 192.168.1.1

AIX: edit /etc/rc.net and add /usr/sbin/route add 192.168.1.1 gateway >>$LOGFILE 2>&1
FreeBSD: edit /etc/rc.conf and add defaultrouter="192.168.1.1"

HP-UX: edit /etc/rc.config.d/netconf and add ROUTE_GATEWAY[0]="192.168.1.1"
Linux Redhat: edit /etc/sysconfig/network and add GATEWAY=192.168.1.1
NetBSD:  echo "192.168.1.1" > /etc/mygate
OpenBSD: echo "192.168.1.1" > /etc/mygate
Solaris: echo "192.168.1.1" > /etc/defaultrouter

Win2k: Start-Settings->Control Panel->Network and Dial-up Connections->Local Area Network->
       Properties->Internet Protocol (TCP/IP)->Default Gateway->192.168.1.1
If you don't want to reboot to pick up the IP address for the default gateway, use ``route'' to manually add the default route.

AIX: route add 0 192.168.1.1

HP-UX: route add 192.168.1.1

FreeBSD,NetBSD,OpenBSD,Solaris: route add default 192.168.1.1

Linux Redhat: route add default gw 192.168.1.1

2. /etc/resolv.conf on unix client hosts need to edit/add to have nameserver statements in order to resolve hostnames.

UNIX clients:

$ cat /etc/resolv.conf
nameserver      
nameserver      
Win2k :
Start-Settings->Control Panel->Network and Dial-up Connections->Local Area Network->

       Properties->Internet Protocol (TCP/IP)->->Advanced TCP/IP Settings->DNS
and add the ISP DNS IPs.

Familiarize with IPFilter

Once your NAT/firewall is online, you should start to read the IPFILTER-HOWTO at
and add more blocking/passing rules to /etc/ipf.rules. Some other useful
links can be found on the home page. Each time /etc/ipf.rules or /etc/ipnat.rules is modified,
you have to them as follow. Reloading these rules will flush all current active connections.
# /sbin/ipf -Fa -f /etc/ipf.rules
# /sbin/ipnat -CF -f /etc/ipnat.rules
You can use ipfstat to display firewall statistics a la ``top" command:
# /sbin/ipfstat -t

           firewall.muine.org - IP Filter: v3.4.27 - state top           23:01:10

Src = 0.0.0.0  Dest = 0.0.0.0  Proto = any  Sorted by = # bytes

Source IP             Destination IP         ST   PR   #pkts    #bytes       ttl
192.168.1.200,1415    65.92.100.89,6699     4/4  tcp    8245   6923504  42:14:06
23.234.234.2,24064    208.31.160.30,22      4/4  tcp     576    199843 119:59:59
192.168.1.200,2091    64.124.41.191,8888    4/4  tcp     157    118770  51:36:40
192.168.1.200,1094    64.124.41.161,8888    4/4  tcp     125     94190  46:37:34
To find out the ipfilter version:
# /sbin/ipf -V
ipf: IP Filter: v3.4.27 (264)
Kernel: IP Filter: v3.4.27
Running: yes
Log Flags: 0 = none set
Default: block all, Logging: available
Active list: 0
Notice the ``block all" setting from our options IPFILTER_DEFAULT_BLOCK in the kernel.

To display the current list of active MAP/Redirect filters and active sessions:

# /sbin/ipnat -l
To find out the ``hit" statistic for each individual rule in /etc/ipf.rules:
# /sbin/ipfstat -hio
See also ipftest(1), mkfilters(1), ipf(4), ipl(4), ipf(8), ipfstat(8), ipmon(8), ipnat(8) for details.

Test the firewall

To test firewall, the following links are useful: Some useful tools to test firewall:
  • nmap
  • xprobe
  • hping2
  • firewalk
  • isic

QoS

Bandwidth limiting:

FreeBSD comes with a bandwidth management in dummynet. dummynet can be extremely useful to slow down
a potential fast link DoS another slower link. man dummynet(4) for other powerful features. Since dummynet is tied
with ipfw -- FreeBSD specific firewall, you will need to include 3 ipfw options in the kernel along with dummynet.

options         IPFIREWALL
options         IPFIREWALL_VERBOSE
options         IPFIREWALL_DEFAULT_TO_ACCEPT
options         DUMMYNET
Recompile the kernel and reboot.

Enable ipfw to work with dummynet in /etc/rc.conf:

firewall_enable="YES"
firewall_script="/etc/rc.dummynet"
firewall_type="open"
firewall_logging="YES"
Assume you have a fast ethernet pipe and need to bandwidth limiting it to ethernet speed:

Construct a pipe 1 on host 192.168.1.4 to any destination:

# /sbin/ipfw add 100 pipe 1 ip from 192.168.1.4 to any
Reduce the pipe to 10Mbits/s:
# /sbin/ipfw pipe 1 config bw 10Mbit/s
You can construct many pipes with different speeds, protocols.

To remove all pipes:

# /sbin/ipfw flush
To enable the above rules, add them to /etc/rc.dummynet

Reference

IPFilter home page:
   http://
IPFilter examples:
   ~avalon/examples.html
IPFilter how-to:
   
IPFilter mailing list archive:
   
Guido van Rooij has written some real nice IPFilter papers:
   
Address Allocation for Private Internets:
   
The IP Network Address Translator (NAT):
   
Traditional IP Network Address Translator (Traditional NAT)
   
Bandwidth management:
   ~luigi/ip_dummynet/
The Twenty Most Critical Internet Security Vulnerabilities (Updated)
  


last update: Oct 20, 2003

copyright © 2000-2003 unixcircle -->
Contact
阅读(1978) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~