mail us  |  mail this page

contact us
training  | 
tech stuff  | 

Tech Stuff - FreeBSD Firewall + NAT + DNS + DHCP

Dates from 2006. The app stuff is probably still pretty relevant though not the version numbers.

We just migrated (2006) to a FreeBSD 5 base for all our standard Firewall + NAT + DNS + DHCP (client and server) configurations used to support DSL/Cable connections. The software implementation we currently use is :

  1. FreeBSD 5.4
  2. BIND 9.3.1 - Forwarding (a.k.a. Proxy) Server configuration
  3. IPFilter Firewall (installed with FBSD)
  4. DHCP client (3.0.3) (sometimes) on the External Network depending on the service provider. Sometimes static IPs with fixed routes.
  5. DHCP server (3.0.3) (always) on the Internal Network.
  6. We mail the FreeBSD periodic reports externally to ourselves and if we have on on-site mail requirement we use Postfix, otherwise we just leave the default sendmail (habit really no other reason).
  7. SSH for secure access including root to allow full control over the system - can be tricky with constantly changing dynamic IP addresses.

The hardware we use is normally pensioned-off servers or desktop PCs that still have lots of life for this kind of application. The following represents a reasonable minimum configuration:

  1. PC >= 300mhz for a typical 1 - 3 Mpbs DSL connection
  2. >= 128M RAM
  3. PC >= 10GB Disc (while the PC can be old, using old discs is a very bad idea)
  4. 2 LAN cards

The configuration is shown below:

Secure Perimeter

Contents

  1. FreeBSD base install notes
  2. Network Configuration
  3. Post Install
  4. DHCP
  5. Forwarding DNS
  6. Postfix
  7. Periodic Reports
  8. Security and SSH
  9. rc.conf Summary edits
  10. Test
  11. Firewall (IPF)
  12. NAT

As always the FreeBSD handbook is very good on many of these topics.

FreeBSD base install notes

The FreeBSD install process is very simple and well packaged - it may look a bit like a 1990 DOS graphical app - totally lacking the snazzy Ananconda style GUI - but that's not why we use FreeBSD. We simply want a rock-solid working system and IOHO nothing beats FreeBSD. The following notes explain some of our install choices only and are not intended to be a step-by-step guide to install FreeBSD - the handbook and many other sources provide excellant resources - though the first time we ever installed FreeBSD we booted the CD and it all worked. It really is that simple - and the default installation is pretty safe and secure.

  1. The machine is mostly dedicated to the firewall function so partitioning covers the whole disk. We occasionally run a modest web, mail and/or ftp server on this machine depending on needs - so on a 10GB disk system we would partition like this:

    1. / (root) = 500m
    2. swap (2 x memory) = 250m
    3. /tmp = 250m
    4. /usr = 8g
    5. /var = 1g (we move web doc root to /var/www unlike the FreeBSD default of /usr/local/www)
  2. We select the kernel developer option only since we will build a debug kernel as part of the post install process. Security conscious folks would delete all this stuff after building a kernel.

  3. If your DSL connection is dynamic, select DHCP client during the install connection - otherwise configure for the relevant static IP. The network section shows how to change this if you get it wrong or have to subsequently reconfigure.

  4. We always enable inetd during the install - since by default everything is turned off in the inetd.conf file (yeah including telnet) we regard it as benign and if we ever want to add something we only have to edit inetd.conf. Many admins prefer to keep inetd disabled since it is not necessary in most instances.

Return to contents

Network Configuration

All the subsequent steps require fully functional external network access as a minimum - so we configure all networking at this stage before moving to the next phases.

Find the Right Interface

The classic dual LAN Firewall configuration is multi-homed - it has more than one network (LAN) interface each of which has one (or more IPs). Where an interface has more that one IP this is known as aliasing or masquerading. The first, seemingly trivial, task is to find which interface FreeBSD configured for which purpose during its installation process. We proceed like this:

  1. Make sure your DSL or cable modem is switched on and connect an ethernet cable to any ethernet port on the PC (make sure the other ethernet cable is disconnected). Then issue:

    # ifconfig
    rl0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    	inet 10.0.10.1 netmask 0xffffff00 broadcast 10.0.10.1
    	ether 00:40:63:ca:9a:20
    	media: Ethernet autoselect (10baseT/UTP)
    	status: active
    rl1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    	inet 192.168.10.1 netmask 0xffffff00 broadcast 192.168.10.255
    	ether 00:40:63:ca:9a:21
    	media: Ethernet autoselect
    	status: no carrier
    lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    	inet 127.0.0.1 netmask 0xff000000 
    

    Note: We are using private IPs on both rl0 and rl1 in the examples only to protect the innocent. rl0 (the external/DSL/Cable modem interface) would normally be a public IP.

  2. This display indicates which interface is active (status: active on rl0 above) and which has the DHCP client or external static IP as shown above. If the connection is both active and has the DHCP client (or the right static IP configuration) you got lucky, otherwise plug the DSL ethernet cable into the other ethernet port and don't buy a lottery ticket. Plug your internal hub/switch ethernet cable into the other port and the physical configuration is complete.

Note all the interface names. You will need then for rc.conf and IPF configuration later. In our case the interfaces were named rl0 (to DSL modem), rl1 (to the internal LAN) and lo0 (standard loopback interface name) and we will use these values in subsequent commands - substitute your own values as appropriate.

We will use the IP addresses 192.168.10.0/24 for the internal network (rl1 above) which gives 254 effective addresses - if this not enough you could use any of the reserved IP addresses with any appropriate netmask e.g. 192.168.0.0/16 will give 65k IP addresses as will 172.30.0.0/16 as will 10.1.0.0/16. Take your pick. Finally we will configure the Firewall to use 192.168.10.1/24 for the internal network (if all this is a bit confusing you may want to read about CIDR and all that wonderful stuff).

Note: You might want to test that the external interface is working by pinging a well know external location or using some similar diagostic.

To bring up the interfaces at boot time edit /etc/rc.conf and add, or change if present, the following lines:

# forces DHCP client onto this (DSL modem) interface
ifconfig_rl0="DHCP"
# if the DSL modem or router has a static address configure as below
# ifconfig_rl0="inet xxx.xxx.xxx.xxx netmask 255.255.255.xxx"
# internal LAN network
ifconfig_rl1="inet 192.168.10.1 netmask 255.255.255.0"

To add IP aliases (additional IP address on a specific interface) to either the internal or external network use a command like the following:

ifconfig rl1 [inet] 192.168.222.1 netmask 255.255.255.255 alias

To delete the alias:

ifconfig rl1 inet 192.168.222.1 -alias

To make the alias permanent, add to /etc/rc.conf the following line:

ifconfig_rl1_alias0="inet 192.168.222.1 netmask 255.255.255.255"

Note: Multiple aliases can be added using the form ifconfig_rl1_alias1= etc.

The alias above is a host address (it defines a single IP address signified by the netmask 255.255.255.255) and no routing command is required.

If the alias will route more than one IP such as:

ifconfig rl1 [inet] 192.168.222.1 netmask 255.255.255.192 alias

In this case it routes the 64 addresses from 192.168.222.0 to 192.168.222.63 and is a network address not a host address and may require one or more routes which are added using the route command.

Note: We note that many howtos insist on adding a route for network address aliases, in practise it is not necessary.

To display the route table use:

netstat -nr

If a route is required the route add command format is used as shown:

route add -net 192.168.222.1/24 192.168.10.1

Which indicates that to get to 192.168.222.x we use this router (the IP of the rl1 interface = 192.168.10.1). To make this change permanent add to /etc/rc.conf:

static_routes="routename"
# to add multiple routes use "name1 name2" format e.g.
# static_routes="routename1 routename2"
route_routename="-net 192.168.222.1/24 192.168.10.1"

Finally in this section the issue of default gateway needs to be addressed. FreeBSD tries to discover the default gateway and in the case of DHCP almost invariably finds it. However if there are static addresses some DSL/Cable modems respond to the router discovery messages many do not. If a ping to an external IP adddress generates "no route" or "no host" responses you may have to add a defaultrouter to the /etc/rc.conf file:

defaultrouter="xxx.xxx.xxx.xxx"
# point to the static IP address of the DSL/Cable modem

Return to contents

Post Install

We add a fair bit of stuff here. The standard security adage is - add only what is strictly necessary - so you may want to evaluate this stuff carefully and only add what you need/want.

Ports

  1. CVSUP

    cd /usr/ports/net/cvsup-without-gui
    make install clean
    

    This a brutal port with 6 gazillion dependencies. We once got caught with FBSD 4.something which could not find cvsup so we keep this handy to do a manual fetch for cvsup if necessary - since without it you are in a bit of trouble:

    fetch -4 -p -o /usr/ports/distfiles/cvsup-snap-16.1h.tar.gz \
      ftp://ftp.freebsd.org/pub/FreeBsd/development/CVSup/snapshots/ \
      cvsup-snap-16.1h.tar.gz
    

    Note: The \ indicates the line has been split for presentation reasons only and would not be present.

  2. Update Ports

    Update all the ports (edit /usr/share/examples/cvsup/ports-supfile to use your favorite FreeBSD FTP server e.g. cvsup9 or whatever) then update the required port collections using:

    cd /usr/share/examples/cvsup
    /usr/local/sbin/cvsup -g -L 2 ports-supfile
    

    Note: The default setting for the installed ports-supfile is 'ports-all' which can take some time to run depending on the link speed.

  3. DHCP Client

    Only required if using client on external network.

    cd /usr/ports/net/isc-dhcp3-client
    make install clean
    
  4. DHCP Server

    cd /usr/ports/net/isc-dhcp3-server
    make install clean
    
  5. DNS

    We are going to replace the base BIND system in FreeBSD so we use this sequence (from Bind 9.3.1 - previous releases used PORT_REPLACES_BASE_BIN9=yes)

    cd /usr/ports/dns/bind9
    make WITH_PORT_REPLACES_BASE_BIND9=yes install clean
    
  6. Portupgrade

    cd /usr/ports/sysutils/portugrade
    make install clean
    

    Not strictly necessary but since it also installs Ruby, our script language of choice, we always add it.

  7. Postfix

    We want to send the periodic FreeBSD reports to our external email address and since most service suppliers block port 25 we will have to use the submission (a.k.a. messaging) port. Since we are not sendmail users we have no idea how to configure this with the default (on FreeBSD) Sendmail installation so we use Postfix for this purpose. If you know how to do if for Sendmail send us an email and save us some work!.

    cd /usr/ports/mail/postfix
    make install clean
    

Odds and Ends

Various other odds and ends.

  1. We close the syslog port by adding the following line to /etc/rc.conf:

    syslogd_flags="-ss"
    
  2. Since this is a remote machine that may be tampered with we want to see all console traffic so edit /etc/syslog.conf:

    console.*					/var/log/console.log
    

    File needs to exist - so create an empty file:

    touch /var/log/console.log
    

    Either wait for the next reboot or refresh syslog using:

    # killall syslogd -HUP
    

Build a debug kernel

Having been caught once with kernel panics all over the place and unable to build a debug kernel due to the kernel panics (!) we now build the debug kernel before we have chance to really screw things up. To build a debug kernel use the following steps:

  1. Copy /usr/src/sys/i386/conf/Generic and save as, say, debug:

    # cd /usr/src/sys/i386/conf
    cp Generic debug
    

    edit /usr/src/sys/i386/conf/debug adding:

    makeoptions DEBUG=-g
    options DDB (not absolutely required)
    option DDB_UNATTENDED (lets system reboot automatically)
    
  2. cp current kernel cp /kernel kernel.previous (or whatever). Make install copies to kernel.old but better safe than sorry.

  3. build and install kernel. This method works:

    # cd /usr/src/sys/i386/conf
    # /usr/sbin/config debug (or whatever name)
    # cd ../../compile/debug (or whatever config file name is being used)
    # make depend
    # make
    # make install
    

    Builds kernel in /usr/src/sys/compile.

    Alternate (new) method:

    #cd /usr/src
    #make buildkernel KERNCONF=name (e.g. debug)
    #make installkernel KERNCONF=name
    

    kernels are built (and compiled into) /usr/obj/usr/src/sys/kernel-name (kernel.debug)

  4. By default the bootloader always loads /kernel. Either copy new (debug) version to /kernel and boot normally or to to boot at load time from another (debug) kernel press any key at load prompt then:

    # unload kernel
    # load kernel.name
    # boot
    

    Must replace kernel with following sequence:

    # cd /
    # chflags noschg kernel
    # cp kernel.old kernel
    # chflags schg kernel
    

Return to contents

DHCP Configuration

We typically run a DHCP client on the DSL side and always a DHCP server on the internal LAN side. The DHCP client is driven entirely from rc.conf - there is no other configuration required - so forget it. There is a /etc/dhcpclient.conf but it is always empty of parameter values and everything works - so leave it alone! The dhcp-server install adds /usr/local/etc/dhcpd.conf.sample. Copy to dhcpd.conf and edit to create something like the following:

# dhcpd.conf
# change log:
# 1. oct 23 2005 
# a. changed global values
# b. added subnet
#
# option definitions common to all supported networks...
# or you can add them within the subnet statement below if 
# they only apply to the subnet
option domain-name "example.com";
# points all users at this server which is configured 
# as a forwarding DNS server
option domain-name-servers 192.168.10.1;

# matter of taste for these values the longer the lease the 
# less volume of requests on the server 
# but the longer it takes to change something
default-lease-time 7200;
max-lease-time 7200;

# This DHCP server is the official DHCP server for the local
# network, if not comment it out.
authoritative;

# we don't currently use this service but should!
ddns-update-style none;

# This is our internal network declaration.

subnet 192.168.10.0 netmask 255.255.255.0 {
  range 192.168.10.2 192.168.10.254;
  option routers 192.168.10.1;
}

To startup dhcp edit /etc/rc.conf as shown below:

dhcpd_enable="YES"
# force DHCP server use on the internal network
dhcpd_ifaces="rl1"

To stop and start DHCP use the following commands:

# killall dhcpd
# dhcpd -cf /path/to/dhcpd.conf rl1

Return to contents

Forwarding DNS

The DNS is configured as a forwarding (or Proxy) DNS to both speed up responses to local users and to reduce the use of external bandwidth. The configuration used is defined here.

To startup named edit /etc/rc.conf as shown below:

named_enable="YES"
named_flags="-u bind"
named_chrootdir="" # inhibits chroot

Note: We run named with a user name (-u bind) but never, as a matter of course, in a chroot jail. It is not worth the additional effort in our view.

Return to contents

Postfix

We only use postfix to send mail to ourselves (admin alerts etc.). Arguably this is serious overkill. But we have never wanted to understand sendmail since we never use it - so configuring postfix is the cost. Edit the following parameters only in /usr/local/etc/postfix/main.cf with appropriate values:

# only change the value below if the default username (nobody) does not exist
default_privs = nobody
# these next two can be omitted 
# since they will default to your fully qualified hostname
myhostname = hostname.example.com
mydomain = example.com
# added to unqualified mailbox addresses 
myorigin = $mydomain
# substitution
mydestination = $myhostname, localhost.$mydomain
# this is the normal default value
alias_maps = hash:/usr/local/etc/postfix/aliases

Since SMTP (port 25) is blocked by most service providers we use the submission port (a.k.a SMTP_AUTH or messaging) port 587 to send mail to our host (clearly our mail server must also be listening on this port). Edit the following lines in master.cf

# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
# by default this port is enabled
#smtp      inet  n       -       n       -       -       smtpd
# by default this port is disabled
submission inet n      -       n       -       -       smtpd

Note: Our mail server has both smtp and submission enabled which has the effect of sending on port 25 and listening on port 25 and 587.

Edit the /usr/local/etc/postfix/alias file to look something like that below which streams traffic to various mailboxes:

# Operational alias file for POSTFIX 
#
# this file should be in usr/local/etc/postfix (FBSD)
#
# Modify as necessary all example.com names with a real mailbox@domain.name
# postmaster gets all the postfix messages - rejected mail etc

postmaster: postmaster@example.com

# Many mailers use this address to represent the empty SMTP return
# path
MAILER-DAEMON:	postmaster


# Common aliases for system accounts.
bin:		ops
daemon:		ops
games:		ops
ingres:		ops
nobody:		ops
system:		ops
toor:		root
foo:		ops
falken:		ops

# Well-known aliases.
admin:		ops
manager:	ops
dumper:		ops
operator:	ops

# traps to catch security attacks
decode:		postmaster
moof:		postmaster
moog:		postmaster

# The following aliases are required by RFC 2142
info:		info@example.com
marketing:	info
sales:		info
support:	support@example.com

# Standard aliases also defined by RFC 2142
abuse:		abuse@example.com
# reports of network infrastructure difficulties
noc:		root
# address to report security problems
security:	support
# DNS administrator (DNS soa records should use this)

hostmaster:	dnsadmin@example.com

# Usenet news service administrator
news:		postmaster
usenet:		postmaster
# http/web service administrator
www:		webmaster@example.com
# UUCP service administrator
uucp:		postmaster
# FTP administrator (especially anonymous FTP)
ftp:		root

# Commonly used group aliases:
#
staff:		ops
office:		ops
all:		postmaster
tech:		ops
ops:		mailops@example.com

# Person who should get root's mail.  This alias
# must exist.
# this gets all the FreeBSD system mail such as periodic reports
root:		admin@example.com

To build the alias file:

cd /usr/local/etc/postfix
/usr/local/sbin/postalias aliases

To startup postfix and completeley disable sendmail edit /etc/rc.conf as shown below:

sendmail_enable="NONE"

Then ensure there is a startup script in /local/etc/rc.d by the following:

cd /usr/local/etc/rc.d
ln -s /usr/local/sbin/postfix postfix.sh

Alternative Mail Configuration:

If port 25 is not blocked you could use sendamil and simply edit /etc/mail/aliases:

root: localuser, external@example.com
postmaster: localuser, external@example.com

Apparently this does not need any smtp daemon to be active but will send directly via port 25.

Return to contents

Periodic Reports

Periodic reports (daily, weekly, monthly etc.) are defined by /etc/defaults/periodic.conf. As always when changes are required create or edit /etc/periodic.conf to override them. To send the /var/log/security.log add a task to /etc/periodic/security e.g. 810.sshloginfail

#!/bin/sh -
#
# Show ssh login failures
#

# If there is a global system configuration file, suck it in.
#
if [ -r /etc/defaults/periodic.conf ]
then
    . /etc/defaults/periodic.conf
    source_periodic_confs
fi

LOG="${daily_status_security_logdir}"

yesterday=`date -v-1d "+%b %e "`

catmsgs() {
	find ${LOG} -name 'security.log.*' -mtime -2 |
	    sort -t. -r -n +1 -2 |
	    xargs zcat -f
	[ -f ${LOG}/auth.log ] && cat $LOG/auth.log
}

case "$daily_status_security_loginfail_enable" in
    [Yy][Ee][Ss])
	echo ""
	echo "${host} ssh login failures:"
	n=$(catmsgs | grep -ia "^$yesterday.*fail" |
	    tee /dev/stderr | wc -l)
	[ $n -gt 0 ] && rc=1 || rc=0;;
    *)	rc=0;;
esac

exit $rc

Return to contents

Security and SSH Access

SSH Access

We want remote login access for this machine so we configure SSH to force use of SSH2. Add in /etc/ssh/ssh_config:

Protocol 2

To allow root access (disabled by default) add in /etc/ssh/sshd_config (watch the sshd_conf):

PermitRootLogin yes
# PermitRootLogin nopwd [only allow authenticated RSA/DSA login]

This simple configuration forces use of the password to login. Using RSA or DSA based access - which does not need explicit use of a password - is a lengthier (but more secure) process and can be added at any subsequent stage and can be done remotely via ssh. This keeps the initial on-site configuration as quick and simple as possible.

SSH Paranoid Configuration

Whether this alternate configuration is paranoid or sensible is for you the reader to decide. The above configuration means that a dictionary attack, weak pasword or luck will allow root access. An alternative method is to provide dual access. Root logins are not permitted, instead a relatively limited account account is used to login. This account is defined to be a member of the wheel group so that an su root can be issued (requiring a second password). The membership of the wheel group can still give the basic account considerable access unless you use absolutely consistent permission masks of 755 everywhere (which corresponds to the default umask of 022). To make things a little more awkward for any would be attacker you can also change the default port number from 22 to something else. Look at /etc/services for a list of used ports and pick something suitably obscure - we'll use port 244 (daya service) for no particularly good reason simply as an example.

edit /etc/ssh/ssh_config:

# uncomment the following line and change
# to selected port number
Port 244

edit /etc/ssh/sshd_config:

# uncomment the following line and change
# to selected port number
Port 244
# inhibit root login (default)
PermitRootLogin no
# security advisory FreeBSD-SA-06:09.openssh
UsePAM no

Use adduser to create a normal password based user account (for ssh login) and make sure to add the wheel group to enable su root functionality.

Note: When an ssh login uses root, logout will terminate the ssh connection. When using this technique either use exit then logout or terminate the ssh session using ~..

Restart ssh using:

# /etc/rc.d/sshd restart

A normal login sequence will be:

ssh -p 244 -l useraccount host-name-or-ip
Response:xxxxxxx (pasword)
# when logged in
su root
Password:xxxx (root password)
~. (terminate ssh session)

Log Attempts

Log illegal port access commands (poor mans SNORT), edit rc.conf

log_in_vain="YES"

Return to contents

rc.conf Summary Edits

At this stage we are going to activate a basic configuration to test the whole process before we start adding firewall rules. This stabilises the configuration and means that subsequent problems are IPF related which is likely to be the most error prone process. The following edits both summarize all the edits to date and add the basic ipfilter and ipnat definitions

# network edits
# forces DHCP client onto this (DSL modem) interface
ifconfig_rl0="DHCP"
# if the DSL modem or router has a static address configure as below
# ifconfig_rl0="inet xxx.xxx.xxx.xxx netmask 255.255.255.xxx"
# internal LAN network
ifconfig_rl1="inet 192.168.10.1 netmask 255.255.255.0"
# add any network aliases - single hosts - more than /32 may need route command
# ifconfig_rl1_alias0="inet 10.50.3.10 netmask 255.255.255.255"
# logs attempts to log into ports
log_in_vain="YES"
# forces routing from one interface to another
gateway_enable="YES"
# DHCP server edits
dhcpd_enable="YES"
# force use on the internal network
dhcpd_ifaces="rl1"
named_enable="YES"
named_flags="-u bind"
named_chrootdir="" # inhibits chroot
# postfix edits
postfix_enable="YES"
# IPFilter edits
ipfilter_enable="YES"
ipfilter_rules="/etc/ipf.rules.temp"
ipmon_enable="YES"
ipmon_flags="-Ds"
# NAT edits
ipnat_enable="YES"
ipnat_rules="/etc/ipnat.rules.temp"

Create a dummy /etc/ipf.rules.temp file to pass all traffic:

# internal traffic on rl1 is never impeded
pass out quick on rl1 all
pass in quick on rl1 all
# loopback traffic is never impeded
pass out quick on lo0 all
pass in quick on lo0 all
# temp external interface pass all traffic
pass out quick on rl0 all
pass in quick on rl0 all

Create the /etc/ipnat.rules.temp file with a basic rule set:

# all internal traffic on rl1 mapped to external IP
map rl1 192.168.10.0/24 -> 0/32

Return to contents

Test

We test the configuration at this point on the grounds that we can isolate any problems without messing around with Firewall and NAT rules.

We always do a reboot at this point and then confirm that all still works - from here on adding revised IPF and NAT rules can all be done without a reboot and can be done remotely - as long as you don't get port 22 (ssh) access rules wrong!

If it does not work at this point - we recommend ritual suicide or at least checking the logs if you find the former a little drastic.

Return to contents

Firewall (IPF)

You have a choice of three firewalls in FreeBSD IPF, ipfw and OpenBSDs PF. We chose IPF for no very good reasons except that the rule set, IOHO, is slightly clearer - if a tad verbose.

Create the real IPF rules in /etc/ipf.rules file to pass only required traffic (this a slightly modified version of that shown in the FreeBSD Handbook Chapter 25.5 to suit local taste):

#################################################################
# No restrictions on Inside LAN Interface for private network
# Not needed unless you have LAN
#################################################################

pass out quick on rl1 all
pass in quick on rl1 all

#################################################################
# No restrictions on Loopback Interface
#################################################################
pass in quick on lo0 all
pass out quick on lo0 all

#################################################################
# Interface facing Public Internet (Outbound Section)
# Interrogate session start requests originating from behind the
# firewall on the private network
# or from this gateway server destine for the public Internet.
#################################################################

# Allow DNS traffic
# xxx must be the IP address of ISP's DNS.
# Get the IP addresses from /etc/resolv.conf file
pass out quick on rl0 proto tcp from any to xxx port = 53 flags S keep state
# if dual DNS server at ISP uncomment line
#pass out quick on rl0 proto udp from any to xxx port = 53 keep state

# Allow DHCP server for cable or DSL networks.
# Use the following rule and check log for IP address.
# Then put IP address in commented out rule & delete first rule
pass out log quick on rl0 proto udp from any to any port = 67 keep state
#pass out quick on rl0 proto udp from any to z.z.z.z port = 67 keep state


# Allow out non-secure standard www function
pass out quick on rl0 proto tcp from any to any port = 80 flags S keep state

# Allow out secure www function https over TLS SSL
pass out quick on rl0 proto tcp from any to any port = 443 flags S keep state

# Allow out send & get email function
# pop3
pass out quick on rl0 proto tcp from any to any port = 110 flags S keep state
# smtp
pass out quick on rl0 proto tcp from any to any port = 25 flags S keep state
# imap - if required
pass out quick on rl0 proto tcp from any to any port = 143 flags S keep state
# message/submission/SMTP_AUTH port
pass out quick on rl0 proto tcp from any to any port = 587 flags S keep state

# Allow out Time - if required
pass out quick on rl0 proto tcp from any to any port = 37 flags S keep state

# Allow out nntp news - if required
pass out quick on rl0 proto tcp from any to any port = 119 flags S keep state

# Allow out gateway & LAN users non-secure FTP ( both passive & active modes)
# This function uses the IPNAT built in FTP proxy function coded in
# the nat rules file to make this single rule function correctly.
# If you want to use the pkg_add command to install application packages
# on your gateway system you need this rule.
pass out quick on rl0 proto tcp from any to any port = 21 flags S keep state

# Allow out secure FTP, Telnet, and SCP
# This function is using SSH (secure shell)
pass out quick on rl0 proto tcp from any to any port = 22 flags S keep state

# Allow out non-secure Telnet - if required
pass out quick on rl0 proto tcp from any to any port = 23 flags S keep state

# Allow out FBSD CVSUP function
pass out quick on rl0 proto tcp from any to any port = 5999 flags S keep state

# Allow out ping to public Internet
pass out quick on rl0 proto icmp from any to any icmp-type 8 keep state

# Allow out whois for LAN PC to public Internet
pass out quick on rl0 proto tcp from any to any port = 43 flags S keep state

# Block and log only the first occurrence of everything
# else that's trying to get out.
# This rule enforces the block all by default logic.
block out log first quick on rl0 all

#################################################################
# Interface facing Public Internet (Inbound Section)
# Interrogate packets originating from the public Internet
# destined for this gateway server or the private network.
#################################################################

# Block all inbound traffic from non-routable or reserved address spaces
block in quick on rl0 from 192.168.0.0/16 to any    #RFC 1918 private IP
block in quick on rl0 from 172.16.0.0/12 to any     #RFC 1918 private IP
block in quick on rl0 from 10.0.0.0/8 to any        #RFC 1918 private IP
block in quick on rl0 from 127.0.0.0/8 to any       #loopback
block in quick on rl0 from 0.0.0.0/8 to any         #loopback
block in quick on rl0 from 169.254.0.0/16 to any    #DHCP auto-config
block in quick on rl0 from 192.0.2.0/24 to any      #reserved for docs
block in quick on rl0 from 204.152.64.0/23 to any   #Sun cluster interconnect
block in quick on rl0 from 224.0.0.0/3 to any       #Class D & E multicast

##### Block a bunch of different nasty things. ############

# Block frags
block in quick on rl0 all with frags

# Block short tcp packets
block in quick on dc0 proto tcp all with short

# block source routed packets
block in quick on rl0 all with opt lsrr
block in quick on rl0 all with opt ssrr

# Block nmap OS fingerprint attempts
# Log first occurrence of these so I can get their IP address
block in log first quick on rl0 proto tcp from any to any flags FUP

# Block anything with special options
block in quick on rl0 all with ipopts
        
# Block public pings
# as a matter of policy we do not do this
# means we are vulnerable to ping floods but
# the incoming traffic alone is the killer 
# and we would lose a useful diagnostic
# block in quick on rl0 proto icmp all icmp-type 8

# Block ident
block in quick on rl0 proto tcp from any to any port = 113

# Block all Netbios service. 137=name, 138=datagram, 139=session
# Netbios is MS/Windows sharing services.
# Block MS/Windows hosts2 name server requests 81
block in log first quick on rl0 proto tcp/udp from any to any port = 137
block in log first quick on rl0 proto tcp/udp from any to any port = 138
block in log first quick on rl0 proto tcp/udp from any to any port = 139
block in log first quick on rl0 proto tcp/udp from any to any port = 81

# Allow traffic in from ISP's DHCP server. This rule must contain
# the IP address of your ISP's DHCP server as it's the only
# authorized source to send this packet type. Only necessary for
# cable or DSL configurations.
# This is the same IP address you captured and
# used in the outbound section.
pass in quick on rl0 proto udp from z.z.z.z to any port = 68 keep state

# Allow in standard www function if web server active 
# pass in quick on rl0 proto tcp from any to any port = 80 flags S keep state

# Allow in non-secure Telnet session from public Internet
# never enabled
#pass in quick on rl0 proto tcp from any to any port = 23 flags S keep state

# Allow in secure FTP, Telnet, and SCP from public Internet
# This function is using SSH (secure shell)
# get this wrong and remote ssh login will not work
pass in quick on rl0 proto tcp from any to any port = 22 flags S keep state

# Block and log only first occurrence of all remaining traffic
# coming into the firewall. The logging of only the first
# occurrence stops a .denial of service. attack targeted
# at filling up your log file space.
# This rule enforces the block all by default logic.
block in log first quick on rl0 all
################### End of rules file #####################################

Restart Firewall (update rules)

Use the following commands:

# ipf -Fa -f /etc/ipf.rules

Display Firewall Information

Use the following commands:

# display incoming numbered rules
# ipfstat -in
# display outgoing numbered rules
# ipfstat -on

To view current firewall state table use:

# display current process table and states
# ipfstat -t

Command works like top and lets you watch the dumped traffic in real time e.g. DDoS attack - it there is any bandwidth left!

Firewall Logging

Edit syslog.conf

# freebsd 5.x
security.* /var/log/ipf.log
# freebsd 4.x
local0.* /var/log/ipf.log

File must exist so use:

touch /var/log/ipf.log
chmod 0640 /var/log/ipf.log

Return to contents

NAT

Create the real version of the /etc/ipnat.rules file by adding any port mapping to the file ipnat.rules.temp shown above.

Note: When we map ports for non-public services such as telnet, or whatever, we usually use an obscure external port number rather than the normal port 23 and then map it with an ipnat rule to the real port on the serving host. While its not secure it stops the quick scans and lets us spot the bad guys more easily.

Port mapping (PAT):

# maps incoming port 5555 to port 23 (telnet) of specified server
rdr rl1 192.168.10.0 port 5555 -> 192.168.50.3 port 23 tcp

You must add a firewall rule for each mapped port. In the above example an in and out rule would be required:

pass out quick on rl0 proto tcp from any to any port = 5555 flags S keep state
pass in quick on rl0 proto tcp from any to any port = 5555 flags S keep state

To reload NAT rules:

# ipnat -CF -f /etc/ipnat.rules

Return to contents



Problems, comments, suggestions, corrections (including broken links) or something to add? Please take the time from a busy life to 'mail us' (at top of screen), the webmaster (below) or info-support at zytrax. You will have a warm inner glow for the rest of the day.

Tech Stuff

RSS Feed Icon

If you are happy it's OK - but your browser is giving a less than optimal experience on our site. You could, at no charge, upgrade to a W3C standards compliant browser such as Firefox

Search

web zytrax.com

Share

Icons made by Icomoon from www.flaticon.com is licensed by CC 3.0 BY
share page via facebook tweet this page

Page

email us Send to a friend feature print this page Display full width page Decrease font size Increase font size

Standards

ISO (International)
IEC (International)
ANSI (US)
DIN (Germany)
ETSI (EU)
BSI (UK)
AFNOR (France)

Telecom

TIA (US)
ECIA (US)
ITU (International)
IEEE (US)
ETSI (EU)
OFCOM (UK)

Internet

IETF
IETF-RFCs
IANA
ICANN
W3C

Electronics

JEDEC
ECIA (US)

Site

CSS Technology SPF Record Conformant Domain
Copyright © 1994 - 2024 ZyTrax, Inc.
All rights reserved. Legal and Privacy
site by zytrax
hosted by javapipe.com
web-master at zytrax
Page modified: January 20 2022.