7. Network Security Strategies

Why network security? Why is the majority of this FAQ concerned with security issues? Unlike a simple personal computer system, Unix is a full-fledged, powerful operating system. It's what runs things such as our national phone network. It's founding purpose and philosophy was to promote information sharing in a research development lab environment. As such, it's large, cryptic, non-intuitive, and not for the inexperienced or unprotected.

Putting a Unix system on the internet is much like advertising an open house to the public, leaving your front door wide open, and going on an extended vacation. Without precautions, the results will be similar in both cases, and it will happen sooner than later. It's not a question of "if". It's a question of "when". Guaranteed.

7.1 Packet-Level Filtering

Overview

Firewall rules make more sense (maybe) if you think of them as sets of 4, an I/O pair on the external interface to the world, and an I/O pair on the internal interfaces to your private/trusted machines.

In addition, there's a rule that says to masquerade anything coming from your internal machines to look like your externally connected machine to the rest of the world. That is, the external world will only see one address from you, regardless of how many internal machines are accessing the internet through your firewall.

Source Address Filtering

The only means of identification under the Internet Protocol (IP) is the source address in the IP packet header. This fact opens the door to source address spoofing. This can allow unsavory types to break into your system or appear as you while attacking other sites.

Without packet level filtering, higher level filtering and proxy security measures are either crippled or useless.

Your firewall will filter source addresses in four areas. The filtering in each of the four cases can have completely different rules. On the external interface to the internet, you can filter what's coming in from outside, and what's going out from your machine. On the internal interface to your private, local network, again, you can filter what's coming into your firewall from your other computers, and what's going out (ie. back) to them from the firewall.

Presumably, most people have no reason to filter packets within their local network. I'll assume you won't do source address filtering between your firewall and internal machines. The only source address related action you'll take will be to enable your own form of spoofing to masquerade outgoing packets from your internal machines to identify themselves as coming from the IP address assigned to you external interface, and to translate incoming packets back into the target addresses of your internal computers.

That leaves two remaining areas to filter, what comes in and what goes out on the external interface.

There are six sets of addresses you should refuse on your external interface in all cases. These are incoming packets claiming to be from, and outgoing packets claiming to be to,

  1. your external IP address,
  2. Class A private IP addresses,
  3. Class B private IP addresses,
  4. Class C private IP addresses,
  5. reserved network addresses, and
  6. the loopback interface.

Other than this, you might be comfortable allowing all other outgoing traffic. A home LAN doesn't usually have the kinds of internal security issues that a large organization would have, where any number of user accounts exist internally.

Simple Walk Through

The following is an explanation of a few of the rules which will be used in the Firewalling & IP Masquerading Example below.

Constants Used in the Examples

Constants are used for most values. The most basic constants are:

EXTERNAL_INTERFACE

This is the name of the external network interface to the internet. It's defined as eth0 in the examples.

LOCAL_INTERFACE

This is the name of the internal network interface to the LAN, if any. It's defined as eth1 in the examples.

LOOPBACK_INTERFACE

This is the name of the loopback interface. It's defined as lo in the examples.

IPADDR

This is the IP address of your external interface. It's either a static IP address registered with InterNIC, or else a dynamically assigned address from your ISP (usually via DHCP).

LOCAL_IPADDR

This is the IP address of your internal interface, if any. In these examples, it is assumed to be 192.168.1.1, a Class C private network address, although it isn't referenced specifically in these particular firewall rules.

LOOPBACK

The loopback address range is 127.0.0.0/8. The interface itself is addressed as 127.0.0.1 (in /etc/hosts).

LOCALNET

This is the entire range of IP addresses used by the machines on your LAN, if any. These may be statically assigned, or you might run a local DHCP server to assign them. In these examples, the range is 192.168.1.0/24, part of the Class C private address range.

ANYWHERE

Anywhere is a label for an address used by ipfwadm and ipchains to match any (non-broadcast) address. Both programs provide any/0 as a label for this address, which is 0.0.0.0/0.

UNPRIVPORTS

The unprivileged ports, 1024 through 65535, are usually referenced in total. They are addresses dynamically assigned to the client side of a connection.

Default Policy


# Set the default policy of the filter to deny.
  ipfwadm -I -p deny
  ipfwadm -O -p reject
  ipfwadm -F -p deny

A firewall has a default policy and a collection of actions to take in response to specfic message types. This means that if a given packet has not been selected by any other rule, then the default policy rule will be applied.

There are two basic approaches to an IPFW firewall, deny everything by default and explicitly allow selected accesses, or accept everything by default and explicitly deny selected accesses. The deny everything policy is usually the recommended approach, because it's easier to set up a more secure firewall.

Using the deny everything policy makes it much easier to set up a secure firewall, but each service and related transaction you want must be enabled explicitly. Using the accept everything policy makes it much easier to get up and running right away, but forces you to anticipate every conceivable possible access type you might wish to disable. The danger is that you won't anticipate a dangerous access type until it's too late.

Source Address Spoofing


# Refuse spoofed packets pretending to be to or from the external address.
  ipfwadm -I -a deny -o -W $EXTERNAL_INTERFACE -S $IPADDR
  ipfwadm -O -a deny -o -W $EXTERNAL_INTERFACE -D $IPADDR

The first sets of rules are set up to protect against some blatant cases of IP address spoofing. There's little you can do to protect yourself against spoofing in general, because the possibility is inherent in the IP protocol. But at the least, an incoming packet claiming to be from your machine is not a legitimate packet. Likewise, you would not be sending a packet addressed to yourself out unto the external internet. The same is true for the private network address classes, the loopback interface, and misconfigured broadcast addresses. (Seeing the latter address types is not necessarily an indication of deliberate spoofing. It's most likely an indication of a misconfigured system somewhere. Nevertheless, you don't want someone connecting to an internal machine directly.)

Opening Up Internal Traffic

Since the default policies are to deny everything, some of this must be undone once we've put in the few protections against spoofing.


# Allow all other outgoing traffic
  ipfwadm -O -a accept -W $EXTERNAL_INTERFACE -S $IPADDR

The example firewall is built on the assumption that no one in your home represents a potential security risk. All messages are allowed out, with the exception of a few service types which would be a mistake to allow out.

The way the firewall example is set up, the default outgoing policy could just as well be to accept everything outgoing by default, since only a limited number of outgoing messages are disabled. But I like the orthagonalism. And a household with numerous users might have reason to control additional outgoing message types.


# Unlimited traffic on the loopback interface.
  ipfwadm -I -a accept -W $LOOPBACK_INTERFACE
  ipfwadm -O -a accept -W $LOOPBACK_INTERFACE

# All internal machines have access to the fireall machine and each other.
  ipfwadm -I -a accept -W $LOCAL_INTERFACE -S $LOCALNET
  ipfwadm -O -a accept -W $LOCAL_INTERFACE -D $LOCALNET

# Allow forwarding of local network traffic - more than 1 internal machine
  ipfwadm -F -a accept -W $LOCAL_INTERFACE -S $LOCALNET -D $LOCALNET

The same goes for all local traffic.

Masquerading the Internal Machines as your ISP-Assigned IP Address

If you have multiple machines on an intranet, what you really want, probably, is to be able to access the web, mail, news, etc. from some internal machine (eg. a Windows machine, a Macintosh, another Linux machine) rather than from your Linux firewall machine. To do this, you need another rule to allow both IP forwarding and masquerading.


ipfwadm -F -a masquerade -W $EXTERNAL_INTERFACE -S $LOCALNET 

What this rule does is enable masquerading and forwarding of all allowed traffic between your internal machines and the external world. Any traffic from your internal machines (ie. any machine on your $LOCALNET) to an outside destination (ie. accessible through the firewall's $EXTERNAL_INTERFACE) is passed through, but in the process, the internal IP address is replaced with the address of your firewall machine (ie. the address your ISP knows you as). The process is reversed for incoming responses, where your firewall's destination IP address is replaced with the real, internal address of the machine participating in the connection, and the packet is forwarded on to the internal machine.

Offering a Service to the Outside World

Whether or not you plan on offering services to the rest of the world, a very few system services must be offered, or at least appear to be offered as a special case. Both the familiar services, such as hosting a web server, and a few system services, such as identd, have similar firewall rules.

As an example of enabling outside access to one of your servers, let's use a web server as an example and assume that you're running the Apache web server. Most services work this way.


# allow www (80)
  ipfwadm -I -a accept -P tcp -W $EXTERNAL_INTERFACE \ 
          -S $ANYWHERE $UNPRIVPORTS -D $IPADDR 80

HTTP is a TCP-based service. What this rule does is allow incoming TCP connections from anywhere, using an unprivileged port, to connect to your port 80, which is the default web server port. The web server will communicate with the client browser at the client's IP address on the given unprivileged port. Incoming connections are limited to coming from the unprivileged ports because an incoming connection from a privileged port would be a protocol violation representing either an attempted security breach, or more likely, a misconfigured client system.

Accessing a Service from the Outside World

As an example of accessing an external service, let's use an external web server. Again, most services work this way.


# allow www
  ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
          -S $ANYWHERE 80 \
          -D $IPADDR $UNPRIVPORTS

# allow https www-cache
#        443    8080
  ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
          -S $ANYWHERE 443 8080 \
          -D $IPADDR $UNPRIVPORTS

This example is broken into 2 seperate rules as a point of clarification. The second rule is a special case related to a web server, and might not be necessary for all people.

The first rule is the inverse, client-side version of the earlier web server rule. It says to allow responses (ie. the -k option) from external web servers (ie. from ANYWHERE using port 80) to the unprivileged port you used to contact the server from. The ACK bit (-k option) will only be legitimately set in incoming packets arriving in response to a connection you have initiated.

The second rule addresses special cases related to web servers. Port 443 is the server port for secure HTTP servers. Port 8080 is one of the standard ports often used for web proxy servers.

7.2 Port-Level Filtering

In terms of incoming traffic, the approach exampled here denies all incoming traffic by default. Connections to specific ports are then enabled explicitly.

There are two classes of port numbers.

The range from 0 through 1023 are reserved ports. These ports represent a particular service. An incoming connection to one of these ports is routed to the appropriate service by inetd, portmap, or some other server listening on that port, for example, sshd or your web server. The ports are defined in /etc/services/. Don't change these values.

The range from 1024 through 65535 are unprivileged ports. When a client program initiates a connection to a server, a port is selected from the unprivileged pool on the client's end. The combination of the client machine's IP address and port number defines the client's socket. On the server side, the combination of host IP address and the server's famous port number form the server's socket. The connection between client and server is uniquely defined by this socket pair.

For example, someone might connect to your web server by connecting to TCP port 80, the port reserved for http connections. On their end, the client side, an unused port from the unprivileged pool has been assigned. Your web server and their browser continue the connection defined by this socket pair.

Another way of saying this is that each individual connection between a given client and server, possibly just one in a set of simultaneus connections to that server, is uniquely identified by the both the source address and port number of the client in conjunction with the server's IP address and famous port number.

Therefore, the firewall must not only allow access to the reserved ports you are offering services on, but must also allow access to the unprivileged ports as part of the ongoing connection between the client and server.

Allow incoming connections on only those reserved ports representing services you are providing to the outside world. Again, these services have either been enabled in /etc/inetd.conf/ or by a server package you have installed which is started by a control script in the /etc/rc.d/ directories. In the example below, ftp (20 and 21), secure shell (22) and web server (80) services are offered from the local machine.

Allow unprivileged port connections only on behalf of the services you are providing to the outside world, plus whatever external services you connect to, such as sending and receiving mail, news, telnet, finger, and your web proxy server.

Use the -k option for TCP connections on the unprivileged ports, which means to only accept packets sent in response to your service request. (Note that SSH is an exception, and seems to talk to the client on a port between 1023 and 513 instead of using an unprivileged port.)

Some services represent known security holes if they are accessible from the outside world. Regardless of the default policies you choose, be sure to disable external access to the following services unless you have a specific need for them. (Refer to the AUSCERT UNIX Computer Security Checklist for more information.)

By convention, a few of the unprivileged ports are used by specific services, including OpenWindows (TCP on 2000), NFS (TCP and UDP on 2049), and X Windows (TCP on 6000+). If any of these servers are running on your machine, but you aren't using these services from a remote machine, filter external access to these ports. It's recommended that you not allow outside access to these services, as they all represent serious security holes. Refer to the Packet Filtering document for more information.

Conservative sources recommend that you disable ICMP altogether. Otherwise, your machine is vulnerable to denial of service attacks. Other sources recommend enabling some of the message types.

NOTE: The less conservative approach is used in the example below because ICMP messages are also used to negotiate and regulate connection parameters, and some services depend on underlying ICMP messages.

For a more complete list, see Commonly Probed Ports. Some of ports listed represent famous services, some known security holes.

7.3 Firewalling & IP Masquerading Example

Refer to the Firewall HOWTO for more information. There is additional information at the Linux Documentation Project.

Note: This example is based on ipfwadm (ipfw4). Future RedHat Linux releases will be based on ipchains (ipfw6). For feature and syntax differences, see the IPCHAINS-HOWTO.

In this example, the firewall configuration file is /etc/rc.d/rc.firewall/. For people with static IP addresses, the firewall script can be executed from /etc/rc.d/rc.local. Nothing else is needed. For DHCP users, the script can be executed automatically from /etc/sysconfig/network-scripts/ifdhcpc-done. This ensures that the firewall is enabled as soon as the network interfaces are brought up, and whenever the IP address changes. - Remember to add . etc/rc.d/rc.firewall/ to the end of /etc/sysconfig/network-scripts/ifdhcpc-done/.

The goal is to enable IP masquerading for the machines on the local LAN, to allow complete local access within the private intranet, to allow complete access to whatever external services you want, and to tightly restrict access from the outside.

Remember that the order of the rules is important. The list of rules is applied in order. The first matching rule is applied. If no matching rule is found, the default policy is applied.

You can download a copy of the firewall example in either ipfwadm format or ipchains format (for both RedHat 5.1 and 5.2). However, the example here allows anything out to make the examples clearer and because writing firewall rules by hand is error-prone. For a more complete firewall, use the Firewall Design Tool.

The following example is the ipfwadm version.


#!/bin/sh
#
#  /etc/rc.d/rc.firewall
#  Invoked from /etc/sysconfig/network-scripts/ifdhcpc-done.

echo "Starting firewalling... "

# Some definitions for easy maintenance.

ANYWHERE="any/0"

# ----------------------------------------------------------------------------
#  EDIT THESE TO SUIT YOUR SYSTEM AND ISP.

EXTERNAL_INTERFACE="eth0"               # whichever you use
LOCAL_INTERFACE="eth1"                  # whichever you use
LOCALNET="192.168.1.0/24"               # whatever private range you use

DHCP_SERVERS="24.128.0.0/16"
SMTP_SERVER="smtp.ne.mediaone.net/31"   # $ANYWHERE if running your own server
#SMTP_SERVER="any/0"                    # $ANYWHERE if running your own server
POP_SERVER="pop.ne.mediaone.net"        # $ANYWHERE if running your own server
NEWS_SERVER="news.ne.mediaone.net"
WEB_PROXY_SERVER="www.ne.mediaone.net"

# ----------------------------------------------------------------------------

#  The IP address, $IPADDR, is defined by dhcpc

if [ -f /etc/dhcpc/hostinfo-$EXTERNAL_INTERFACE ]; then
    . /etc/dhcpc/hostinfo-$EXTERNAL_INTERFACE
elif [ -f /etc/dhcpc/dhcpcd-$EXTERNAL_INTERFACE.info ]; then
    . /etc/dhcpc/dhcpcd-$EXTERNAL_INTERFACE.info
else
    echo "rc.firewall:  dhcp is not configured." 
    exit 1
fi

# nameservers are originally from /etc/dhcpc/resolv.conf.
# The example ifdhcpc-done script updates these automatically and
# appends them to /etc/dhcpc/hostinfo-$EXTERNAL_INTERFACE or
# /etc/dhcpc/dhcpcd-$EXTERNAL_INTERFACE.info.

# Edit and uncomment these if NOT using the example ifdhcpc-done script.

#NAMESERVER_1="24.128.60.8"
#NAMESERVER_2="24.128.60.7"
#NAMESERVER_3="24.128.1.81"

# ----------------------------------------------------------------------------

LOOPBACK_INTERFACE="lo"
LOOPBACK="127.0.0.0/8"
CLASS_A="10.0.0.0/8"
CLASS_B="172.16.0.0/12"
CLASS_C="192.168.0.0/16"
MULTICAST="240.0.0.0/3"
BROADCAST_0="0.0.0.0"
BROADCAST_1="255.255.255.255"
PRIVPORTS="0:1023"
UNPRIVPORTS="1024:65535"
RESTRICTED_PORTS="2049"                 # (TCP/UDP) NFS
RESTRICTED_OPENWINDOWS="2000"           # (TCP) openwindows

# X Windows port allocation begins at 6000 and increments
# for each additional server running.
RESTRICTED_XWINDOWS="6000:6001"         # (TCP) X windows

# Note, SSH starts at 1023 and works down to 513 
# for each additional simultaneous incoming connection.
SSH_PORTS="1020:1023"                   # range for SSH privileged ports

# ----------------------------------------------------------------------------
# Default policy is DENY
# Explicitly accept desired INCOMING connections
# ----------------------------------------------------------------------------
# Flush and set default policy of DENY.

    # Remove all existing rules belonging to this filter
    ipfwadm -I -f
    ipfwadm -O -f
    ipfwadm -F -f

    # Set the default policy of the filter to deny.
    ipfwadm -I -p deny
    ipfwadm -O -p accept
    ipfwadm -F -p deny

# ----------------------------------------------------------------------------
# Network Ghouls
# Deny access to jerks

    # /etc/rc.d/rc.firewall.blocked contains a list of
    # ipfwadm -I -a deny -W $EXTERNAL_INTERFACE -S address
    # rules to block from any access.

    # Refuse any connection from problem sites
    if [ -f /etc/rc.d/rc.firewall.blocked ]; then
        . /etc/rc.d/rc.firewall.blocked
    fi

# ----------------------------------------------------------------------------
# SPOOFING & BAD ADDRESSES
# Refuse spoofed packets.
# Ignore blatantly illegal source addresses.
# Protect yourself from sending to bad addresses.

    # Refuse spoofed packets pretending to be to or from the external address.
    ipfwadm -I -a deny -o -W $EXTERNAL_INTERFACE -S $IPADDR
    ipfwadm -O -a reject -o -W $EXTERNAL_INTERFACE -D $IPADDR

    # Refuse packets claiming to be to or from a Class A private network
    ipfwadm -I -a deny -W $EXTERNAL_INTERFACE -S $CLASS_A
    ipfwadm -I -a deny -W $EXTERNAL_INTERFACE -D $CLASS_A
    ipfwadm -O -a reject -W $EXTERNAL_INTERFACE -S $CLASS_A
    ipfwadm -O -a reject -W $EXTERNAL_INTERFACE -D $CLASS_A

    # Refuse packets claiming to be to or from a Class B private network
    ipfwadm -I -a deny -W $EXTERNAL_INTERFACE -S $CLASS_B
    ipfwadm -I -a deny -W $EXTERNAL_INTERFACE -D $CLASS_B
    ipfwadm -O -a reject -W $EXTERNAL_INTERFACE -S $CLASS_B
    ipfwadm -O -a reject -W $EXTERNAL_INTERFACE -D $CLASS_B

    # Refuse packets claiming to be to or from a Class C private network
    ipfwadm -I -a deny -W $EXTERNAL_INTERFACE -S $CLASS_C
    ipfwadm -I -a deny -W $EXTERNAL_INTERFACE -D $CLASS_C
    ipfwadm -O -a reject -W $EXTERNAL_INTERFACE -S $CLASS_C
    ipfwadm -O -a reject -W $EXTERNAL_INTERFACE -D $CLASS_C

    # Refuse packets claiming to be to or from the loopback interface
    ipfwadm -I -a deny -o -W $EXTERNAL_INTERFACE -S $LOOPBACK
    ipfwadm -I -a deny -o -W $EXTERNAL_INTERFACE -D $LOOPBACK
    ipfwadm -O -a reject -o -W $EXTERNAL_INTERFACE -S $LOOPBACK
    ipfwadm -O -a reject -o -W $EXTERNAL_INTERFACE -D $LOOPBACK

    # Refuse broadcast address SOURCE packets
    ipfwadm -I -a deny -W $EXTERNAL_INTERFACE -S $BROADCAST_1
    ipfwadm -I -a deny -W $EXTERNAL_INTERFACE -D $BROADCAST_0

    # Refuse multicast/anycast/broadcast addresses (in.h) (NET-3-HOWTO)
    ipfwadm -I -a deny -o -W $EXTERNAL_INTERFACE -S $MULTICAST

# ----------------------------------------------------------------------------
# ICMP

    #    To prevent denial of service attacks based on ICMP bombs, filter
    #    incoming Redirect (5) and outgoing Destination Unreachable (3).
    #    Note, however, disabling Destination Unreachable (3) is not
    #    advisable, as it is used to negotiate packet fragment size.

    # For bi-directional ping.
    #     Message Types:  Echo_Reply (0),  Echo_Request (8)
    #     To prevent attacks, limit the src addresses to your ISP range.
    # 
    # For outgoing traceroute.
    #     Message Types:  INCOMING Dest_Unreachable (3), Time_Exceeded (11)
    #     default UDP base: 33434 to base+nhops-1
    # 
    # For incoming traceroute.
    #     Message Types:  OUTGOING Dest_Unreachable (3), Time_Exceeded (11)
    #     To block this, deny OUTGOING 3 and 11
    # 
    # Other control messages.
    #     Message Types:  Source_Quench (4),  Parameter_Problem (12)

    #  0: Echo_Reply
    #  3: Dest_Unreachable, Network_Unavailable, Service_Unavailable, etc.
    #  4: Source_Quench
    #  5: Redirect
    #  8: Echo_Request
    # 11: Time_Exceeded
    # 12: Parameter_Problem
    
     ipfwadm -I -a accept -P icmp -W $EXTERNAL_INTERFACE \
             -S $ANYWHERE 0 3 4 11 12 -D $IPADDR

     ipfwadm -I -a accept -P icmp -W $EXTERNAL_INTERFACE \
             -S $DHCP_SERVERS 8 -D $IPADDR

     ipfwadm -O -a accept -P icmp -W $EXTERNAL_INTERFACE \
             -S $IPADDR 3 4 8 12  -D $ANYWHERE

     ipfwadm -O -a accept -P icmp -W $EXTERNAL_INTERFACE \
             -S $IPADDR  0 11 -D $DHCP_SERVERS

# ----------------------------------------------------------------------------
# Disallow certain outgoing traffic to protect yourself from mistakes.

    # reserved link sunrpc exec login shell printer uucp
    ipfwadm -O -a reject -P tcp -W $EXTERNAL_INTERFACE \
            -S $IPADDR \
            -D $ANYWHERE 0 87 111 512 513 514 515 540

    # reserved link sunrpc exec login shell printer uucp
    ipfwadm -O -a reject -P tcp -W $EXTERNAL_INTERFACE \
            -S $IPADDR 0 87 111 512 513 514 515 540 \
            -D $ANYWHERE 

    # openwindows: establishing a connection
    ipfwadm -O -a reject -P tcp -y -W $EXTERNAL_INTERFACE \
            -S $IPADDR \
            -D $ANYWHERE $RESTRICTED_OPENWINDOWS 

    # Xwindows: establishing a connection
    ipfwadm -O -a reject -P tcp -y -W $EXTERNAL_INTERFACE \
            -S $IPADDR \
            -D $ANYWHERE $RESTRICTED_XWINDOWS 

    # SOCKS: establishing a connection
    ipfwadm -O -a reject -P tcp -y -W $EXTERNAL_INTERFACE \
            -S $IPADDR \
            -D $ANYWHERE 1080

    # reserved dhcp tftp sunrpc snmp snmp-trap 
    ipfwadm -O -a reject -P udp -W $EXTERNAL_INTERFACE \
            -S $IPADDR \
            -D $ANYWHERE 0 68 69 111 161 162 

    # biff who syslog route
    ipfwadm -O -a reject -P udp -W $EXTERNAL_INTERFACE \
            -S $IPADDR \
            -D $ANYWHERE 512 513 514 520 521 

    # reserved dhcp tftp sunrpc snmp snmp-trap 
    ipfwadm -O -a reject -P udp -W $EXTERNAL_INTERFACE \
            -S $IPADDR 0 67 69 111 161 162 \
            -D $ANYWHERE 

    # biff who syslog route
    ipfwadm -O -a reject -P udp -W $EXTERNAL_INTERFACE \
            -S $IPADDR \
            -D $ANYWHERE 512 513 514 520 521

# ----------------------------------------------------------------------------
# Unlimited traffic within the local network.

    # All internal machines have access to the fireall machine.

    ipfwadm -I -a accept -W $LOCAL_INTERFACE -S $LOCALNET
    ipfwadm -O -a accept -W $LOCAL_INTERFACE -D $LOCALNET

# ----------------------------------------------------------------------------
# LOOPBACK

    # Unlimited traffic on the loopback interface.
    ipfwadm -I -a accept -W $LOOPBACK_INTERFACE
    ipfwadm -O -a accept -W $LOOPBACK_INTERFACE

# ----------------------------------------------------------------------------
# NOTE:
#      The symbolic names used in /etc/services for the port numbers vary by
#      supplier.  Using them is less error prone and more meaningful, though.

# ----------------------------------------------------------------------------
# TCP UNPRIVILEGED PORTS
# Avoid ports subject to protocol & system administration problems.
# FTP can use the unprivileged ports without the "-k" flag.

    # Deny access to the NFS, openwindows and X windows unpriveleged ports
    ipfwadm -I -a deny -o -P tcp -y -W $EXTERNAL_INTERFACE \
            -D $IPADDR $RESTRICTED_PORTS 

    ipfwadm -I -a deny -o -P tcp -y -W $EXTERNAL_INTERFACE \
            -D $IPADDR $RESTRICTED_OPENWINDOWS 

    ipfwadm -I -a deny -o -P tcp -y -W $EXTERNAL_INTERFACE \
            -D $IPADDR $RESTRICTED_XWINDOWS 

    # SOCKS: incoming connection
    ipfwadm -I -a deny -P tcp -y -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE \
            -D $IPADDR 1080

# ----------------------------------------------------------------------------
# UDP UNPRIVILEGED PORTS
# Avoid ports subject to protocol & system administration problems.

    ipfwadm -I -a deny -o -P udp -W $EXTERNAL_INTERFACE \
            -D $IPADDR $RESTRICTED_PORTS 

# UDP INCOMING TRACEROUTE
# traceroute usually uses -S 32769:65535 -D 33434:33523

    ipfwadm -I -a accept -o -P udp -W $EXTERNAL_INTERFACE \
            -S 24.128.0.0/16 32769:65535 \
            -D $IPADDR 33434:33523

    ipfwadm -I -a deny -o -P udp -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 32769:65535 \
            -D $IPADDR 33434:33523

# ----------------------------------------------------------------------------
# DNS
# The nameserver must be configured before any rule which uses
# a host name instead of an IP address.
#
# 1-19-99:  in RedHat 5.2 with the new bind-8.1.2-5, see /etc/named.conf.
#           "query-source address * port 53;" must be uncommented.

    # DNS server
    # ----------

    # DNS forwarding, caching only nameserver (53)
    # --------------------------------------------

    # server to server query or response
    # Caching only name server only requires UDP, not TCP
    # 1-19-99:  in RedHat 5.2 with the new bind-8.1.2-5,
    #           a caching-only nameserver seems to need these rules
    #           and the following client-mode rules.

#     ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
#             -S $NAMESERVER_1 53 \
#             -D $IPADDR 53

#     ipfwadm -O -a accept -W $EXTERNAL_INTERFACE \
#             -S $IPADDR 53 \
#             -D $NAMESERVER_1 53

#     ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
#             -S $NAMESERVER_2 53 \
#             -D $IPADDR 53

#     ipfwadm -O -a accept -W $EXTERNAL_INTERFACE \
#             -S $IPADDR 53 \
#             -D $NAMESERVER_2 53

#     ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
#             -S $NAMESERVER_3 53 \
#             -D $IPADDR 53

#     ipfwadm -O -a accept -W $EXTERNAL_INTERFACE \
#             -S $IPADDR 53 \
#             -D $NAMESERVER_3 53

    # DNS client (53)
    # ---------------

     ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
             -S $NAMESERVER_1 53 \
             -D $IPADDR $UNPRIVPORTS

     ipfwadm -O -a accept -P udp -W $EXTERNAL_INTERFACE \
             -S $IPADDR $UNPRIVPORTS \
             -D $NAMESERVER_1 53 

     ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
             -S $NAMESERVER_1 53 \
             -D $IPADDR $UNPRIVPORTS

     ipfwadm -O -a accept -P tcp -W $EXTERNAL_INTERFACE \
             -S $IPADDR $UNPRIVPORTS \
             -D $NAMESERVER_1 53 

     ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
             -S $NAMESERVER_2 53 \
             -D $IPADDR $UNPRIVPORTS

     ipfwadm -O -a accept -P udp -W $EXTERNAL_INTERFACE \
             -S $IPADDR $UNPRIVPORTS \
             -D $NAMESERVER_2 53 

     ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
             -S $NAMESERVER_2 53 \
             -D $IPADDR $UNPRIVPORTS

     ipfwadm -O -a accept -P tcp -W $EXTERNAL_INTERFACE \
             -S $IPADDR $UNPRIVPORTS \
             -D $NAMESERVER_2 53 

     ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
             -S $NAMESERVER_3 53 \
             -D $IPADDR $UNPRIVPORTS

     ipfwadm -O -a accept -P udp -W $EXTERNAL_INTERFACE \
             -S $IPADDR $UNPRIVPORTS \
             -D $NAMESERVER_3 53 

     ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
             -S $NAMESERVER_3 53 \
             -D $IPADDR $UNPRIVPORTS

     ipfwadm -O -a accept -P tcp -W $EXTERNAL_INTERFACE \
             -S $IPADDR $UNPRIVPORTS \
             -D $NAMESERVER_3 53 

# ----------------------------------------------------------------------------
# TCP accept only on selected ports

    # SSH server (22)
    # ---------------

#    ipfwadm -I -a accept -P tcp -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $UNPRIVPORTS -D $IPADDR 22

#    ipfwadm -I -a accept -P tcp -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $SSH_PORTS -D $IPADDR 22

    # SSH client (22)
    # ---------------

#    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE 22 -D $IPADDR $UNPRIVPORTS

#    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE 22 -D $IPADDR $SSH_PORTS

    # ------------------------------------------------------------------

    # TELNET server (23)
    # ------------------

#    ipfwadm -I -a accept -P tcp -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $UNPRIVPORTS -D $IPADDR 23

    # TELNET client (23)
    # ------------------

#    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE 23 -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # HTTP server (80)
    # ----------------

#    ipfwadm -I -a accept -P tcp -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $UNPRIVPORTS -D $IPADDR 80

    # HTTP client (80)
    # ----------------

    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 80 \
            -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # HTTPS client (443)
    # ------------------

    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 443 \
            -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # WWW-CACHE client (typical ports are 8000 or 8080)
    # -------------------------------------------------

#    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
#            -S $WEB_PROXY_SERVER \
#            -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # POP client (110)
    # ----------------

    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $POP_SERVER 110 \
            -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # NNTP NEWS client (119)
    # ----------------------

    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $NEWS_SERVER 119 \
            -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # FINGER client (79)
    # ------------------

    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 79 \
            -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # AUTH server (113)
    # -----------------

    # Reject, rather than deny, the incoming auth port. (NET-3-HOWTO)

    ipfwadm -I -a reject -P tcp -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE -D $IPADDR 113

    # AUTH client (113)
    # -----------------

    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 113 -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # SMTP server (25)
    # ----------------

#    ipfwadm -I -a accept -P tcp -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $UNPRIVPORTS \
#            -D $IPADDR 25

    # SMTP client (25)
    # ----------------

    # Note: The server should be $ANYWHERE if you aren't relaying through
    # your ISP's SMTP server.

    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $SMTP_SERVER 25 \
            -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # IRC client (6667)
    # -----------------

#    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE 6667 \
#            -D $IPADDR $UNPRIVPORTS

    # ------------------------------------------------------------------

    # RealAudio client
    # ----------------

#    ipfwadm -I -a accept -P tcp  -k -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $UNPRIVPORTS \
#            -D $IPADDR 554 7070 7071

    # UDP is the preferred method
#    ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $UNPRIVPORTS \
#            -D $IPADDR 6970:7170

    # ------------------------------------------------------------------

    # FTP server (20, 21)
    # -------------------

    # incoming request

#    ipfwadm -I -a accept -P tcp -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $UNPRIVPORTS \
#            -D $IPADDR 21

    # PORT MODE data channel responses

#    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $UNPRIVPORTS \
#            -D $IPADDR 20

    # PASSIVE MODE data channel responses

#    ipfwadm -I -a accept -P tcp -W $EXTERNAL_INTERFACE \
#            -S $ANYWHERE $UNPRIVPORTS \
#            -D $IPADDR $UNPRIVPORTS

    # FTP client (20, 21)
    # -------------------

    # response to outgoing request
    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 21 \
            -D $IPADDR $UNPRIVPORTS

    # NORMAL mode data channel
    ipfwadm -I -a accept -P tcp -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 20 \
            -D $IPADDR $UNPRIVPORTS

    # PASSIVE mode data channel responses
    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE $UNPRIVPORTS \
            -D $IPADDR $UNPRIVPORTS

# ----------------------------------------------------------------------------

    # WHOIS client (43)
    # -----------------

    ipfwadm -I -a accept -P tcp -k -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 43 \
            -D $IPADDR $UNPRIVPORTS

# ----------------------------------------------------------------------------
# UDP  accept only on selected ports

    # DHCP client (67, 68)
    # --------------------

    # allow dhcp server (67) to connect to dhcp client (68)
    # Note: the DHCP server is the only externel source of broadcast
    #       messages we should see, ever.

    ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
            -S $DHCP_SERVERS 67 \
            -D $IPADDR 68

    ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
            -S $DHCP_SERVERS 67 \
            -D $BROADCAST_1 68

    ipfwadm -O -a accept -P udp -o -W $EXTERNAL_INTERFACE \
            -S $BROADCAST_0 68 \
            -D $DHCP_SERVERS 67

    # Getting renumbered
    ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
            -S $BROADCAST_0 67 \
            -D $BROADCAST_1 68

    # REBINDING: Lease time expired. Fall back to INIT.
    ipfwadm -O -a accept -P udp -W $EXTERNAL_INTERFACE \
            -S $BROADCAST_0 68 \
            -D $BROADCAST_1 67

    # As a result of the above, we're supposed to change our IP address with
    # this message, which is addressed to our new address before the dhcp
    # client has received the update.

    ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
            -S $DHCP_SERVERS 67 \
            -D $ANYWHERE 68

    # log any other dhcp server (67) to connect to dhcp client (68)
    ipfwadm -I -a deny -P udp -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 67 \
            -D $IPADDR 68

    # ------------------------------------------------------------------

    # NTP TIME clients (123)
    # ----------------------

    # ONLY IF USING NTP time service!!!
    # Allow access to and from selected NTP servers.
    # Add one rule for each server selected.
    # Example:

#   ipfwadm -I -a accept -P udp -W $EXTERNAL_INTERFACE \
#           -S dominator.eecs.harvard.edu 123 \
#           -D $IPADDR $UNPRIVPORTS

# ----------------------------------------------------------------------------
# Enable logging for selected denied packets

    ipfwadm -I -a deny -o -P tcp -W $EXTERNAL_INTERFACE -D $IPADDR 
    ipfwadm -I -a deny -o -P udp -W $EXTERNAL_INTERFACE -D $IPADDR $PRIVPORTS

    ipfwadm -O -a deny -o -P icmp -W $EXTERNAL_INTERFACE -S $IPADDR 5 
    ipfwadm -I -a deny -o -P icmp -W $EXTERNAL_INTERFACE \
            -S $ANYWHERE 5 13 14 15 16 17 18 -D $IPADDR

# ----------------------------------------------------------------------------
# Allow all other outgoing traffic

     ipfwadm -O -a accept -W $EXTERNAL_INTERFACE -S $IPADDR

# ----------------------------------------------------------------------------
# Masquerade internal traffic.

    # ALL internal machines have outside access.
    # Machines can be added without specifying them here.

    ipfwadm -F -a masquerade -W $EXTERNAL_INTERFACE -S $LOCALNET

# ----------------------------------------------------------------------------

echo "done"

7.4 Service-Level Filtering

Defining Your inetd Services

/etc/inetd.conf/ defines the services your machine will make available to both the rest of the world and your local network. It does not affect the services you can take advantage of from outside sources.

As shipped, /etc/inetd.conf/ is not set up so securely anymore. Check out your copy to make sure it reflects only the services you want to offer.

Practically, you should not enable anything you don't understand, need, or use.

For myself, I disabled all services except for ftp and telnet. (Most people will recommend against enabling telnet, but I use it regularily within the local network. The firewall and tcp_wrappers disable access from the outside. For outside access, SSH is a much safer choice.)

Linux comes preconfigured to use tcp_wrappers for additional security. You'll notice that most services in /etc/inetd.conf/ are explicitly managed by /usr/sbin/tcpd/. See the man page, TCPD(8), for more information. /etc/hosts.allow and /etc/hosts.deny are the configuration files for tcpd.

Note: The new portmap daemon also uses these files for its RPC connection configuration.

Set up /etc/hosts.allow and /etc/hosts.deny to match what you want.

/etc/hosts.allow should reflect the services you've enabled in /etc/inetd.conf. The file for this example is:


ALL: LOCAL
in.ftpd sshd : ALL

The example of an /etc/hosts.deny file is:


ALL: PARANOID
ALL EXCEPT in.ftpd sshd : ALL

Note, if you installed the anonymous ftp package during installation, be sure to disable the ftp service until you've configured it properly. Otherwise, anonymous ftp access will be available in its default setting after you reboot. The defaults look fine, but still...