Home > Articles/Tutorials > Iptables - An Introduction

Iptables - An Introduction

by Robert Spotswood 02/20/2005


Part 1 - Background and Firewall Basics


Why bother with security? No one is interested in me.

There are at least 5 types of people that would be interested in breaking into the system of a home user:

There are even more types interested in business computers!


Why bother? My ISP will protect me.

WRONG! In fact, most ISP's don't care at all if your machine is compromised, except if your using excessive bandwidth. Very few will do anything to protect you.


Why bother? No one will find me.


Why do I want a firewall?


What does a firewall NOT protect against?


Why do I want to learn about how to setup my own firewall?

To quote Shannon Dealy:

Frankly, I would love to be able to just buy a firewall and forget it, but so far every one I've looked at either doesn't have the flexibility I need for configuring my Internet connections, or has been breached in the six months prior to when I looked it over, usually both. I don't bother to look at anything that hasn't been on the market for at least nine months, since it takes time for the hackers and crackers of the world to look these things over and demonstrate how insecure they really are. It could be argued that since pretty much any firewall system is vulnerable, it would be better to leave it in the hands of the experts rather than doing it yourself, but how do you determine which firewall vendor is truly "expert"? Many breaches of commercial firewall products that I've looked over, were not due to some new form of attack and did not use any novel holes in the system, rather the vendor simply forgot (or worse, wasn't aware of) a well documented existing security hole. Some of the other cases were down right stupid in that the vendor's wonderful point and click user interface or some other aspect of their non-security related custom software was the source of the security hole. Other breaches, while not technically the vendor's fault, were due to the fact that the user was allowed to configure the product in a manner which was inherently insecure, which means that anyone using the product must completely understand firewalls in order to use it properly, in which case they might as well roll their own!


Packet Filtering Firewall

Iptables is a packet filtering firewall. Most packet filtering firewalls filter based on at least the following four criteria:

In addition to the criteria above, iptables also allows you to filter based on another criteria: state. This means iptables is a stateful firewall.


Stateful firewalling

What is it and why do I want it?


Stateful firewalling

What is it and why do I want it? Example

Here is an example to help make things clearer. (This example does have some flaws in it, but they are intentional. I did not want to publish a blueprint for breaking through firewalls.) Let's start with a stateless firewall example.

  1. You want to surf the web. This means your firewall must allow incoming packets from any IP address and port 80 to your ip address and an unprivledged port.
  2. Attackers know this by the way.
  3. An attacker could craft a packet with a spoofed IP address and send it from port 80 to an unprivledged port on your system.
  4. Stateless would allow this through.
  5. How would this be an attack, well HTTP traffic is usually allowed through firewalls and other network traffic barriers, and numerous non-HTTP protocols are tunneled via HTTP in order to ease their passage. They can be attacked.
  6. Now suppose your computer was vulnerable to crash if a special packet was sent (think ping-of-death). A stateless firewall wouldn't stop it.
  7. Unless you want to give up the ability to surf the web, an attacker could take your computer down at will.

Now the stateful example

  1. You want to surf the web. However, you are using the stateful property of your firewall. This means you only allow incoming packets from any IP address and port 80 to your ip address and unprivledged port where you have started a conversation.
  2. An attacker could craft a packet with a spoofed IP address and send it from port 80 to an unprivledged port on your system.
  3. Unless the attacker got lucky and spoofed a current connection correctly (web site address you are currently talking to and guessing the correct unprivledged port - good luck!), your firewall would block it.
  4. The attacker is out of luck!

Stateful Firewalling - Drawbacks

If stateful firewalling is superior, why isn't it used everywhere?

  1. It's more complicated to setup. It doesn't matter how many nice features your firewall software has, if it's misconfigured, it's not doing it's job.
  2. It requires more memory. The software has to keep track of every "stateful" connection until the connection is over. On lightly loaded machines with plenty of memory, this isn't a problem. But, on heavily loaded and/or low memory machines, this can become a real issue. Older connections can be dropped early, resulting in communication problems. Intermittent problems.


Part 2 - General Firewall Design Guidelines


Basic Types of Firewall Design

There are two basic firewall design types:


Mostly Open Firewalls

Mostly open means that the default action is to accept packets. Packets are denied only by specific rules.

Advantages:

Disadvantages:


Mostly Closed Firewalls

Mostly closed means that the default action is not to accept any packets. The packets can be either dropped or rejected (more on this in a moment).

Advantages:

Disadvantages:


To Drop or To Reject, that is the question

Without an ICMP error message, the sender of the packet doesn't know what happened. It will likely wait a while and/or send 3 more packets. This makes it look like there is no computer at the other end. This is great for hiding from probes, and slows scanning down. However, there is an attack that uses this behavior against you.

With an ICMP error message, the sender of the packet is told that sending any more packets is useless. However, it does let anyone scanning know there is an active system at that IP address. Also, anything that causes your computer to respond could be used as a denial of service attack..

Between the two, dropping is generally recommended for packets that are not from your network (or system) and rejecting is generally recommended for packets coming from your network.


What can be safely blocked?

There are a number of things you can block and lose almost no functionality. These things should be blocked unless you have a very good reason for not doing so.


Things you should give consideration to blocking.

The following are things that you should give heavy consideration to blocking, although they may cause problems.

Most people would say the private address ranges should be in the automatic blocking category, rather than this category. After all, you should never see any of these addresses on the Internet and if you do, it's a spoofed address. While it's true that you should never see these addresses, you sometimes will, and it is not always a spoofed address. From Marc Slemko:

On many routers, a separate IP address in the same subnet is required for each end of a point to point link. This can use [a lot of] address space if there are a large number of such links. Since the actual address of the links doesn't appear to impact much, many people use RFC 1918 private address space for such links...If [the router is] using such addresses, then ICMP messages (including "can't fragment" errors) will normally be generated using such addresses. Since many networks filter incoming traffic from such reserved addresses, the net result is the same as if all ICMP were being filtered and can cause the same problems.

Of course, this is not a problem with your firewall, but with the admin responsible for the router.


Do I need my Internet address in my firewall?

Short answer, no. Longer answer: If you have a static ip address, having it in the firewall won't hurt anything. However, in my opinion, it won't help much either. If you have a DHCP address, it could very well cause lots of problems, and, in my opinion, won't improve your security much. To understand the answer, some background into network cards (real or virtual) is needed.

A network card will automatically ignore any packets based on destination, regardless of firewall, OS, etc., except for:

So, in other words, the only thing your card is even going to listen to other than it's own address is the broadcast addresses. Since you want your network card to listen for it's address, this leaves only two possible "bad" addresses to "worry" about. This is before the firewall comes into play at all. The firewall can easily block the global broadcast address (255.255.255.255), so now we are down to a single "bad" address. All without having our ip address anywhere in the firewall.

So this brings up the question of whether to and how to block the local network broadcast address. Well, If you're not running any public servers (intentional or otherwise), and are intelligently filtering your packets (a stateful firewall REALLY helps here), then you're not going to respond to an arbitrary packet anyway. The normal firewall rules will pretty effectively block this address anyway. If you are running a public server, then you'll respond to any address anyway, so blocking this doesn't give you any real increased security. So the answer to the question is no, don't bother trying to block the local broadcast address directly.

Further, depending on various factors, you might not "have" a local broadcast address. For DHCP on Southwestern Bell's network, GNU/Linux machines I've seen take a local broadcast address of 255.255.255.255 . Makes blocking it easy, because you're already blocking that address (see above).

If you do try to add your ip address to your filter rules and you're using DHCP, then this can cause problems. Whenever you get a new address, you MUST re-run your firewall script or you just cut yourself off. What a pain! It is easier, although still not recommended, to pick out the local broadcast address and filter that. That is far less likely to change as often as your ip address.


Something you shouldn't block

All computers with a working TCP/IP stack will have special network adapter called the loopback adapter. This is a virtual network card and is always assigned the address of 127.0.0.1 . This is the loopback address. Some programs (especially on Unix) use this address for internal communication. You should never try to block this address. If an attacker can get bad packets on this address, they've already got control of your machine.



Part 3 - Linux Stuff Not Iptables Related

This part deals with some Linux configuration tweaks that are not iptables commands, but are useful security measures none the less. Many put these commands in the sysctl.conf file instead of the iptables script. I prefer the iptables script for reasons which will be explained in a few slides. Most of the thing listed here also apply to the 2.2 kernel, but not all. Also, the iptables description below applies to iptables version 1.2.4 or higher.


Local Port Range

Whenever you connect to server, say for web browsing, your computer "randomly" picks an unused port from the unprivledged range (1024-65535) for your end of the connection. In GNU/Linux, this choice is less random than you would think. The "available" range of unprivledged ports is actually controlled by the values in /proc/sys/net/ipv4/ip_local_port_range . By default Mandrake uses 32768 to 61000. Other GNU/Linux systems probably use the same range.

This comes into play in writing the iptables rules. Most rules I find in other's scripts allow outgoing connections from the entire unprivledged range, and most allow incoming to the unprivledged range. However, there are some services that run in the unprivledged range you usually don't want anyone to have any chance to connect to, such as Xwindows, NFS, NIS, Squid, etc.

Since responses to your web browsing requests should use the port number you used (for your side of the connection), you don't need to allow incoming packets access to the entire unprivledged port range. You can limit them to the "local port range". While the "local port range" can be set in sysctl.conf, it can also be set in your iptables script. This means you don't have do any fancy parsing to make sure the actual port range and the one you use in your iptables rules are the same range. Strange problems can occur if they differ.

Here is a code snippet I use for syncing the ranges.

LOCALPORTS="32768:61001"
LOCAL_PORTS="32768   61001"
if [ -e /proc/sys/net/ipv4/ip_local_port_range ] ; then
        echo -n "Setting local port range to $LOCALPORTS "
        echo $LOCAL_PORTS > /proc/sys/net/ipv4/ip_local_port_range
        echo "done."
else
        echo "Problem setting local port range.  Be worried."
fi
Note that the iptables syntax and the ip_local_port_range syntax are different. That's why I use two different variables.


TCP syncookie protection

It is possible to conduct denial-of-service attacks by creating TCP "half-open" connections. Any system connected to the Internet and providing TCP-based network services (such as a Web server, FTP server, mail server, ssh server, etc.) is potentially subject to this attack. TCP syncookies protection is the GNU/Linux answer to this attack.

The following code snippet shows you how to enable this defense:

# TCP syncookie protection
if [ -e /proc/sys/net/ipv4/tcp_syncookies ]; then
  echo -n "Enabling TCP syncookie protection..."
  echo 1 > /proc/sys/net/ipv4/tcp_syncookies
  echo "done."
else
  echo "Problem enabling TCP syncookie protection.  Be worried."
fi


Source Routed Packets

Source routing is a debugging technique which allows packets to explicitly state the route they wish to follow to their destination rather than following normal routing rules. However source routed packets can also be used to defeat some access control mechanisms. They can fool your machine into thinking it's talking to a local machine, or other trusted host. There is rarely a legitimate need to use source routed packets, so they are best blocked. The following code snippet will do it:

# Disable source routed packets
if [ -e /proc/sys/net/ipv4/conf/all/accept_source_route ]; then
   echo -n "Disabling source routed packets...."
   for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $f
   done
   echo "done."
else
   echo "Problems disabling source routed packets, be worried."
fi


ICMP Redirect Acceptance

When hosts use a non-optimal or defunct route to a particular destination, an ICMP redirect packet (type 5) is used by routers to inform the hosts what the correct route should be. If an attacker is able to forge ICMP redirect packets (they can!), and you run routed or gated, he can alter the routing tables on your computer and fool your system into thinking the attacker is local, or even forward all traffic to the attacker's machine. Therefore, it's recommended that ICMP Redirect Acceptance be disabled. The following code snippet will do it:

# Disable ICMP Redirect Acceptance
if [ -e /proc/sys/net/ipv4/conf/all/accept_redirects ]; then
   echo -n "Disabling ICMP Redirect Acceptance..."
   for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 > $f
   done
   echo "done."
else
   echo "Problems disabling ICMP Redirect Acceptance, be worried."
fi


RP Filter

The rp_filter subsystem is related to IP spoofing protection. Basically, does an incoming packet have a source address associated with the network interface it came in on? If not, discard the packet. However, there are occasions when this happens legitimately. FreeSwan is one example. Enabling rp_filter does make some legal multihoming configurations impossible. It's your choice whether to enable it or not. The following code snippet enables it:

if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]; then
   echo -n "Setting up IP spoofing protection..."
   for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f
   done
   echo "done."
else
   echo PROBLEMS SETTING UP IP SPOOFING PROTECTION.  BE WORRIED.
fi


Smurf Attacks

The "smurf" attack, named after its exploit program, is one of the most recent in the category of network-level attacks against hosts. A perpetrator sends a large amount of ICMP echo (ping) traffic at IP broadcast addresses, all of it having a spoofed source address of a victim. If the routing device delivering traffic to those broadcast addresses performs the IP broadcast to layer 2 broadcast function noted below, most hosts on that IP network will take the ICMP echo request and reply to it with an echo reply each, multiplying the traffic by the number of hosts responding. On a multi-access broadcast network, there could potentially be hundreds of machines to reply to each packet.

The GNU/Linux answer to this is to totally ignore such packets if set up to do so. The following code snippet does just that:

# Don't respond to broadcast pings.
if [ -e /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts ]; then
  echo -n "Stopping broadcast pings..."
  echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
  echo "done."
else
  echo "Problem stopping broadcast pings.  Be worried."
fi

There is a similar attack based on the UDP echo called fraggle. I do not believe the above would protect against such attacks. However, UDP echo uses port 7, so it is relatively easy to drop in iptables. Also, disable the echo command in inetd.conf .


Forwarding

If you want your GNU/Linux box to route packets, then you must enable forwarding. The most common use for routing packets I see is if the GNU/Linux box is the Internet gateway. However, it you don't need the routing, don't turn it on. Forwarding is simple to enable. Here is the code to do it:

# Activate the forwarding!
if [ -e /proc/sys/net/ipv4/ip_forward ]; then
  echo -n "Turning on forwarding..."
  echo 1 >/proc/sys/net/ipv4/ip_forward
  echo "done."
else
  echo "Forwarding not turned on!  Be worried."
fi



Part 4 - Rule Creation for Iptables


How to right an Iptables firewall rule

A typical iptables firewall rule is, in theory, quite simple, and composed of 4 sections. They are:

  1. A call to the iptables to add the rule, usually "/sbin/iptables -A"
  2. Where to look for the packet
  3. A description of the packet you are looking for. This is probably the most complicated part of an iptables rule.
  4. What to do with the packet once you have found it.

Adding the rule

There are a number of ways to manipulate rules in iptables. They are:

Of course, you must specify a chain. For instance, to append a rule to the input chain (discussed in a moment), the syntax would be: /sbin/iptables -A INPUT...

It is important to realize that other than -A, the rest of the ways to manipulate the rules should not be used except with extreme caution, if at all. They are more likely to introduce problems than to solve them.


Where to look for the Packet: A Packet flow diagram

Iptables has, by default, three different tables. This presentation will only talk about 2 of them: filter and nat. Each table has several "chains". A chain is a list of rules. Each rule says `if the packet header looks like this, then here's what to do with the packet'. If the rule doesn't match the packet, then the next rule in the chain is consulted. Finally, if there are no more rules to consult, then the kernel looks at the chain (default) policy to decide what to do. You can create your own chains, but that won't be covered here.

The filter table has three chains: INPUT, OUTPUT, and FORWARD. The nat table also has three chains: PREROUTING, OUTPUT, and POSTROUTING. The following ASCII art tries to include both the filter table and the nat table in the same diagram and show where the individual chains come into play. Note that only packets that are ACCEPTed continue on to the next stop in the diagram.

Packets not generated by the iptables computer

incoming --> PREROUTING (nat) --> routing --> FORWARD (filter) --> POSTROUTING (nat) --> out
                                    |	
                                    V
                                 INPUT (filter) --> computer

Packets generated by the iptables computer (Note, I'm not sure I have the order of the two OUTPUTS correct. They may be reversed, but it doesn't matter, since the path is linear.)

computer --> OUTPUT (nat) --> OUTPUT (filter) --> POSTROUTING (nat)--> out

Important: Note that all packets go through both the nat and the filter tables at some point before reaching a computer.

By default, the iptables rule applies to the filter table. If you want to apply it to another table, use the syntax "-t [table name]". For example, to append a rule on the PREROUTING chain in the nat table, a rule would be /sbin/iptables -t nat -A PREROUTING....


What to do with a packet once you found it (aka targets)?

The names of the targets, in no particular order, are capitalized because they must appear in all caps in the actual rules.

ACCEPT
This means pass the packet on to the next point in the diagram
DROP
Quietly discard the packet. Do not send an error message. This is the best target for non-local packets you don't want to accept.
LOG
This is the logging mechanism of iptables. Note that anything with LOG as a target is passed on to the next rule even if it matches.
REJECT
This target has the same effect as DROP, except that the sender is sent an ICMP port unreachable error message in all but a few instances (see the manual). This is a better target than DROP for your lan. This way you get an error message instead of waiting for the timeout.
RETURN
This target has the same effect as falling off the end of the chain: The default policy is applied.
QUEUE
This special target queues the packet for userspace processing. It will not be discussed further.
The name of a user defined chain
Listing the name of a user defined chain jumps to the first rule in that chain.
MASQUERADE
This is used for Internet connection sharing.
REDIRECT
This rewrites the packet header. It is useful in transparent proxying.
TCPMSS
This allows you to alter the MSS value of TCP SYN packets.
SNAT
Changes the source address of connections to something different. Very similar to MASQUERADE.
DNAT
Similar to SNAT, this changes the destination of the packet to something different.

How do I use a target? - General

For some of the targets, the syntax is simple: "-j target name". This applies to the following targets:


How do I use a target? - LOG

--log-level : Allows you specify the level of logging just like syslog.conf does. I recommend the info level.

--log-prefix: This allows you to prefix the messages in your log files with a string up to 29 characters. This makes it easier to pick out the messages.

Example:: /sbin/iptables -A INPUT -i $EXTINT -p TCP --sport 80 \ -m limit -j LOG --log-level info --log-prefix "Port 80 dropped.." which produces a line in the syslog like

Dec 27 19:07:18 linux kernel: Port 80 dropped..IN=eth0 OUT= MAC=00:c0:f0:58:d9:53:00:10:67:00:9a:4e:08:00 SRC=216.105.165.68 DST=208.191.XXX.XXX LEN=40 TOS=0x00 PREC=0x00 TTL=48 ID=15862 DF PROTO=TCP SPT=80 DPT=34711 WINDOW=8760 RES=0x00 ACK RST URGP=0


How do I use a target? - TCPMSS

This option needs and deserves a little explanation. In theory, you should never need to use it. The TCPMSS target allows you to alter the MSS value of TCP SYN packets, which controls the maximum size for that connection (usually limiting it to your outgoing interface's MTU minus 40).

Some criminally braindead ISPs or servers block ICMP Fragmentation Needed packets. These are a very important type of ICMP packets. The symptoms of this blocking problem are that everything works fine from your Linux firewall/router, but machines behind it can never exchange large packets:

  1. Web browsers connect, then hang with no data received.
  2. Small mail works fine, but large emails hang.
  3. Ssh (or openssh) works fine, but scp hangs after initial handshaking.

This target provides the workaround to the problem. To activate this option, add the following rule to your firewall configuration:

iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu


How do I use a target? - REDIRECT, SNAT, DNAT

Both SNAT and DNAT have similar functions. SNAT allows you to change the packet's source address and/or port, while DNAT allows you to change the packet's destination address and/or port. SNAT is used in the POSTROUTING chain, which means the iptables box will see the packet as it was originally sent out in the other chains. DNAT is used in the PREROUTING chain, which means all the other chains on the iptables box will see only the altered packet. Remember this when writing the rules! Also note that ports can only be used for UDP or TCP packets.

The basic syntax of a SNAT or DNAT rule is: -j (SNAT or DNAT) --to [IP address]:[port] where [IP address] can be either a single ip address or a range of ip addresses and [port] is a port number from 1-65535 or a range of port numbers. Ranges are separated by a hypen (-). Multiple, non-overlapping --to statements are allowed. Port numbers are optional. If given a range of ip addresses, the one chosen is based on the least currently used IP for connections the machine knows about. This gives primitive load-balancing.

Example: iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j DNAT --to 5.6.7.8-5.6.7.10:3128 Here, web requests are redirected to another set of servers (probably proxy servers).

Example: iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 5.6.7.8 Here, all incoming traffic is sent to another machine, 5.6.7.8 .

REDIRECT is just a special case of DNAT, where the ip address is changed to that of the interface the packet came in on. Ports can still be altered though with the "--to-port [port number]". For example: iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 3128. Here, we are doing some transparent proxying (The proxy must know about this though!).


A description of the packet you are looking for

Iptables allows you to describe or match packets based on any of the following (non-experimental) criteria, listed in no particular order.

Some of these target are extension modules, and depending on your kernel configuration, may not be available. In addition, an experimental match module allows the matching of strings inside a packet. Instructions for this are in Appendix A. I won't discuss all of these here, only the more important (IMHO) ones.


Protocol Type

The protocol of the packet can be specified with the `-p' (or `--protocol') flag. Protocol can be a number (if you know the numeric protocol values for IP) or a name for the special cases of `TCP', `UDP' or `ICMP'. Case doesn't matter, so `tcp' works as well as `TCP'. A list of names and numbers can be found in /etc/protocols on most linux machines. Further. the protocol name can be prefixed by a `!', to invert it, such as `-p ! TCP' to specify packets which are not TCP.

Most people will only use the TCP, UDP, or ICMP protocols. However, some of the others come into play with VPNS.

If no protocol is specified (i.e. -p isn't used), then the rule will match any and all protocols.


Source and Destination Ports

If you specify UDP or TCP for the protocol, a number of extensions, or additional things to match, become available. Probably the most used are the extensions that allow matching on the source port and destination port. Both support inversion. If no ports are specified, then the rule will match any port. There are two ways to do port matching:

  1. Use the UDP or TCP extensions
  2. Use the multiport module

There significant differences between the two options. The UDP/TCP extensions only allow for a single port or continuous range of ports (i.e. 20:25, but not 20:22 and 24:25) within the same rule. Also, you can specify different source and destination ranges. However, you can not specify noncontiguous port numbers. Inversion is allowed.

The multiport modules does allow up to 15 different port numbers. Order is not important. However, you can really only specify either source ports or destination ports, not both. (Technically you can have both, but the ranges must be the same.) Also, ranges of ports are not allowed.

In both cases, the syntax has some similarities. To specify a source port(s), use the syntax --source-port or the shorthand --sport. Destination ports are specified by either --destination-port or --dport. Here are a few examples:

Example1: Suppose you want to allow outgoing access to FTP (ports 20-21), email (ports 25 and 110), DNS (port 53), and newsgroups (port 119) in your POSTROUTING chain on the external interface($EXTINT here). Since you don't care about source ports here (at least in this example), and you want to use several non-continuous ranges, multiport is the answer. Therefore, the rule would look like:


/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -p TCP -m multiport --dport 20,21,25,53,110,119 -j ACCEPT

Example2: Suppose you want to allow on the INPUT chain packets from port 80 with a destination port somewhere in your local port range coming from the external interface ($EXTINT here). Since you want a range of ports that is larger than 15 and you want both a source and destination port, the TCP extensions are called for. Therefore, the rule would look like:


/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 80 --dport  32768:61001 -j ACCEPT

Since ICMP packets don't use port numbers, there's no way to specify them. However, there are various types of icmp packets, and you can specify those. The syntax to do is --icmp-type followed by either the name or numeric equivalent. Inversion is allowed. To get the full list of names, type the command iptables -p icmp --help. A few of the important ones to let through are listed here.

NameNumber
source-quench4
parameter-problem12
destination-unreachable3
time-exceeded11
echo-request8
echo-reply0
For example, to allow outgoing pings (and the replies of course), the following rules (filter table only listed) will do:
/sbin/iptables -A INPUT -i $EXTINT -p ICMP --icmp-type echo-reply -m state --state ESTABLISHED -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p ICMP --icmp-type echo-request -m state --state NEW -j ACCEPT


Source and destination addresses

Remember, source (and destination) addresses can be forged!

Source (`-s', `--source' or `--src') and destination (`-d', `--destination' or `--dst') IP addresses can be specified in four ways. The most common way is to use the fully qualified name, such as `localhost' or `www.linuxhq.com'. The second way is to specify the IP address such as `127.0.0.1'.

The third and fourth ways allow specification of a group of IP addresses by giving the network id and the appropriate subnetmask, such as `192.168.207.0/24' or `192.168.207.0/255.255.255.0'. These both specify any IP address from 192.168.207.0 to 192.168.207.255 inclusive; the digits after the `/' tell which parts of the IP address are significant. `/32' or `/255.255.255.255' is the default which matches that specific address and only that address. To specify any IP address at all `/0' can be used, but that is rare because the default is to match any address.

If the source and/or destination address(es) is not given, then the rule will match any and all addresses.

The most common use I've seen for this is to blocking certain IP addresses, such as the unassigned ip address ranges (See IANA reserved addresses) and private address ranges. However, if you're running a private server, these flags can be very helpful in limiting access.


The Interfaces

In addition to specifying a table and chain, you may, but don't have to, also specify an interface. If you don't specify an interface, the rule applies to all interfaces. Further, you if you do specify an interface, you indicate which direction you are looking for (incoming packets or outgoing packets). Obviously, the direction should match the chain. Here is a table of allowed direction matches.
Incoming Outgoing
PREROUTING Yes No
INPUT Yes No
FORWARD Yes Yes
POSTROUTING No Yes
OUTPUT (nat and filter) No Yes

Incoming is specified with -i and outgoing is specified with -o, followed by the interface name. Wildcards, in the form of a + are allowed. For instance, to specify all ppp interfaces, incoming on the input chain, it would be -A INPUT -i ppp+. Inversion (discussed later) is also allowed.

If you don't specify an interface, the rule applies to all interfaces.


Inversion

Many of the other criteria, including the `-s' (or `--source') and `-d' (`--destination') criteria can have their arguments preceded by `!' (pronounced `not') to match addresses NOT equal to the ones given. For example. `-s ! localhost' matches any packet not coming from localhost.

Inversion may also be used with the interfaces. For instance, to specify all interfaces EXCEPT the ppp interfaces, you could write something like -i ! ppp+.


Limit matches

The limit match limits the rate and number of matches. The main use I've seen so far is in conjunction with the LOG target, but it can also be useful in limiting traffic to or from your network. If I logged every system that tried to connect to me on port 80, I'd run out of disk space very quickly. I could chose not to log those packets at all, but I like knowing what's going on. The limit match has 2 optional arguments:

The default, BTW, is 3 matches per hour, with a burst of 5

The easiest way to understand this is to think of it as self-renewing battery. The limit-burst is the total capacity of the battery. Once you drain all the capacity, you can use (match) it again until the battery has recharged. The limit option is the recharge rate. With the defaults, the recharge rate is one unit (packet) every 20 minutes. However, the battery will never have a capacity of more that the limit-burst, no matter how long you let it sit without using any of the charge.


TCP Flags

In rules with the TCP protocol specified (-p TCP), you can also examine the TCP flags. The syntax is --tcp-flags followed by two strings. The first is the list of flags you want to examine, and the second is the list of flags that should be set. Overall, I feel that using the state modules will give better, easier security. State works on TCP, UDP and ICMP (and maybe other protocols), whereas the TCP flags only apply to TCP. However, some scans can be blocked by checking the flags. The code to block many such scans is here:


/sbin/iptables -t nat -A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
/sbin/iptables -t nat -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
/sbin/iptables -t nat -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
/sbin/iptables -t nat -A PREROUTING -p TCP --tcp-flags SYN,FIN SYN,FIN -j DROP
/sbin/iptables -t nat -A PREROUTING -p TCP --tcp-flags SYN,RST SYN,RST -j DROP


The States


The States - Examples

Here are a few examples of using the states:

This snippet allows me to connect freely to a web server (or something running on port 80), but tightly controls who can send packets back. For MOST services, this is all the statefulness you'll need provided your not running a server.

/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $PUBLICPORTS --dport 80 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 80 --dport $PUBLICPORTS -m state --state ESTABLISHED -j ACCEPT

Ok, I said most above, so lets show an exception, ftp. (Note: You also need a special module for ftp.)

/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $PUBLICPORTS --dport 20 -m state --state ESTABLISHED -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 20 --dport $PUBLICPORTS -m state --state ESTABLISHED,RELATED -j ACCEPT

Here is an example that allows outgoing pings (you can ping someone else, they can't ping you).

/sbin/iptables -A INPUT -i $EXTINT -p ICMP --icmp-type echo-reply -m state --state ESTABLISHED -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p ICMP --icmp-type echo-request -m state --state NEW -j ACCEPT

Ok, so what if you want to run a server. Well, here is an example for openssh.

/sbin/iptables -A INPUT -i $EXTINT -p TCP --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport 22 -j ACCEPT

Gotcha's for iptables



Appendix A - Matching Strings with Iptables

If you want to add the experimental ability to match strings in packets, do the following:

WARNING: If you use rpms, this will screw up things if you upgrade using rpms.

  1. Download the iptables code from http://netfilter.samba.org/iptables-1.2.4.tar.bz2 or the nearest mirror.
  2. Unpack it somewhere: tar jxvf iptables-1.2.4.tar.bz2 and cd into the iptables-1.2.4 directory.
  3. Run the following command: make pending-patches KERNEL_DIR=[the full path to your kernel source]. This will start an interactive patch session. Say yes to patches you want to try. You can say no to all of them if you wish.
  4. Run the following command: make patch-o-matic KERNEL_DIR=[full path to your kernel source]. Choose carefully if you say yes to any patches besides the string one. Also, the MAC patch has some bugs, so don't install that one.
  5. Compile the user-space code and the libraries: make KERNEL_DIR=[full path to kernel source].
  6. Install the programs, code and libraries: make install KERNEL_DIR=[full path to kernel source].
  7. Now do a normal kernel recompile. In the configuration part, be sure and select the string module.

To learn more about how to use the string match: iptables -m string -help. Here is a simple example where we will log packets with the string "test": iptables -A INPUT -m string --string "test" -j LOG --log-level info --log-prefix "TEST"


Appendix B - Private Address Ranges

The following IP addresses are reserved for private use, and should be used for internal networks:

The range 127.0.0.0-127.255.255.255 is also reserved for the loopback network and should not be used.

Despite the above addresses being reserved, this does not mean you will never see them on the Internet. IP addresses from crackers and script kiddies can be forged, and other instances are the result of misconfiguration. It is a good idea to block these addresses at your firewall or router if possible, both incoming and outgoing. Most ISP's don't filter these addresses very well, if at all.


Appendix C - Useful Links

http://www.robertgraham.com/pubs/firewall-pr0n.html
A firewall Admins Guide to Porn - Some advice on how to handle porn surfers at work.
http://www.robertgraham.com/pubs/firewall-seen.html
Firewall Forensics - A guide to what you're seeing on your firewall.
http://netfilter.samba.org/documentation/index.html#HOWTO
The Netfilter/Iptables howtos
http://www.linux-firewall-tools.com/linux/
A Linux Firewall and Security Site, with lots of reading materials.

Appendix D - Sample Script

#!/bin/sh
#Iptables Bastion firewall v0.92
#updated 02/15/02

# Copyright (C) 2002  Robert Spotswood 
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program or from the site that you downloaded it
# from; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA  02111-1307   USA

#Define some constants
echo "Seting up firewall....."
IPSEC="no" #The default
#IPSEC="yes" #Uncomment if you are using freeswan
LOCALNETWORK="192.168.1.0/24"
INTINT="eth1" #The internal interface
EXTINT="eth0" #The external interface
#INTIP="192.168.1.1" #The internal interface address - Not used
DHCPSERVER="0/0" #Enter DHCP server address
DHCPSERVER3="0/0" #Enter DHCP server address
DHCPSERVER4="0/0" #Enter DHCP server address
DHCPSERVER2="0/0" #Internal DHCP Server
FTPSERVER="no"
FRIENDIP="0/0"	#If you set FTPSERVER to yes, these are the IP's that are
		#allowed to connect to it.
SQUID="192.168.1.10:3128"
MYSQLPORT="3306"
LOCALPORTS="32768:61001" #This is the port range this computer will pick
			 #from for it's end of an unprivileged port.
			 #Also, if you change this, change the next line too.
LOCAL_PORTS="32768   61001"
LOGGER="/usr/bin/logger" #Path to the logger program
#---------------------------------------------------
# User should not have to change anything below here
#---------------------------------------------------
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="224.0.0.0/4"
CLASS_E="240.0.0.0/5"
ANYWHERE="any/0"
BROADCAST_SRC="0.0.0.0/32"
BROADCAST_DEST="255.255.255.255/32"
PRIVPORTS="0:1023"

PUBLICPORTS="1024:65535"
NFS_PORT="2049"
SOCKS_PORT="1080"
XWINDOW_PORTS="6000:6023"
# traceroute usually uses -S 32769:65535 -D 33434:33523
TRACEROUTE_SRC_PORTS="32769:65535"
TRACEROUTE_DEST_PORTS="33434:33523"

#=============================================
# Non iptables stuff
#=============================================
#Set the local port range so the variable above is always correct
#You can change the local unprivileged port range 
#with: echo 32768 61000 > /proc/sys/net/ipv4/ip_local_port_range
if [ -e /proc/sys/net/ipv4/ip_local_port_range ] ; then
	echo -n "Setting local port range to $LOCALPORTS "
	echo $LOCAL_PORTS > /proc/sys/net/ipv4/ip_local_port_range
	echo "done."
else
	echo "Problem setting local port range.  Be worried."
fi
# TCP syncookie protection
if [ -e /proc/sys/net/ipv4/tcp_syncookies ]; then
  echo -n "Enabling TCP syncookie protection..."
  echo 1 > /proc/sys/net/ipv4/tcp_syncookies
  echo "done."
else
  echo "Problem enabling TCP syncookie protection.  Be worried."
fi


# Disable source routed packets
if [ -e /proc/sys/net/ipv4/conf/all/accept_source_route ]; then
   echo -n "Disabling source routed packets...."
   for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $f
   done
   echo "done."
else
   echo "Problems disabling source routed packets, be worried."
fi


# Disable ICMP Redirect Acceptance
if [ -e /proc/sys/net/ipv4/conf/all/accept_redirects ]; then
   echo -n "Disabling ICMP Redirect Acceptance..."
   for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 > $f
   done
   echo "done."
else
   echo "Problems disabling ICMP Redirect Acceptance, be worried."
fi


# Turn on IP Spoof protection by using IP Source Address Verification
# This is from the IPChains-HOWTO, but it works for iptables too.
# However, this screws up free S/Wan, so turn it off if IPSEC = "yes"
if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]; then
   echo -n "Setting up IP spoofing protection..."
   for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f
   done
   echo "done."
else
   echo PROBLEMS SETTING UP IP SPOOFING PROTECTION.  BE WORRIED.
fi

if [ $IPSEC = "yes" ]; then
   echo -n "Turning off IP spoofing protection for free S/Wan..."
   for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f
   done
   echo "done."
fi

# Don't respond to broadcast pings.
if [ -e /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts ]; then
  echo -n "Stopping broadcast pings..."
  echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
  echo "done."
else
  echo "Problem stopping broadcast pings.  Be worried."
fi


# Activate the forwarding!
if [ -e /proc/sys/net/ipv4/ip_forward ]; then
  echo -n "Turning on forwarding..."
  echo 1 >/proc/sys/net/ipv4/ip_forward
  echo "done."
else
  echo "Forwarding not turned on!  Be worried."
fi


# Enable bad error message protection
if [ -e /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses ] ; then
  echo -n "Turning on bad error message protection..."
  echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
  echo "done."
else
  echo "Problem turing on bad error message protection.  Be worried."
fi

# Insert the required kernel modules
# Note if iptables is compiled in, this will
# generate error messages.  These can be safely
# ignored.
modprobe iptable_nat
modprobe ip_conntrack
modprobe ip_conntrack_ftp

#=============================================
# Flush the old rules and set default policies
#=============================================
echo "Setting defaults"
/sbin/iptables -F
/sbin/iptables -t nat -F #Yes, this is valid, and important!
/sbin/iptables -P INPUT DROP
/sbin/iptables -P OUTPUT DROP
/sbin/iptables -P FORWARD DROP
/sbin/iptables -t nat -P POSTROUTING ACCEPT
/sbin/iptables -t nat -P PREROUTING ACCEPT
/sbin/iptables -t nat -P OUTPUT ACCEPT

#=============================================
# Filter rules
#=============================================

#Test transparent proxying
# Uncomment if you want to use, but read the howto first!
#/sbin/iptables -t nat -A PREROUTING -i $INTINT -p tcp --dport 80 \
#	-j DNAT --to $SQUID

# In the NAT table (-t nat), Append a rule (-A) after routing
# (POSTROUTING) for all packets going out ppp0 (-o ppp0) which says to
# MASQUERADE the connection (-j MASQUERADE).
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -s $LOCALNETWORK \
	-j MASQUERADE
echo "Masquerading enabled"

#Allow all loopback interface traffic.  If there are bad
#packets here, a firewall won't protect you.
#BTW, traffic from an ip addresses on this machine to any
#ip address on this machine goes through lo, not the
#interface you would expect.
/sbin/iptables -A INPUT  -i lo -j ACCEPT
/sbin/iptables -A OUTPUT -o lo -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -o lo -j ACCEPT
#I don't think this one matters, but it doesn't hurt anything either.
/sbin/iptables -t nat -A POSTROUTING -o lo -j ACCEPT
echo "Unlimited traffic on Loopback setup"

#Allow unlimited LAN traffic
/sbin/iptables -A INPUT  -i $INTINT -s $LOCALNETWORK -j ACCEPT
/sbin/iptables -A OUTPUT -o $INTINT -s $LOCALNETWORK -j ACCEPT

#This next allows local broadcasts from this machine.
/sbin/iptables -t nat -A OUTPUT -s $LOCALNETWORK -j ACCEPT
/sbin/iptables -t nat -A POSTROUTING -o $INTINT -s $LOCALNETWORK \
	-j ACCEPT
/sbin/iptables -t nat -A PREROUTING -s $LOCALNETWORK -j ACCEPT
echo "LAN traffic allowed"

# Anything coming from our internal network should have only our 
# address
/sbin/iptables -A FORWARD -i $INTINT -s ! $LOCALNETWORK -j LOG \
        --log-level info --log-prefix "Forwarding problem..."
/sbin/iptables -A FORWARD -i $INTINT -s ! $LOCALNETWORK -j DROP

#Protect against fraggle attacks (UDP port 7).
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p UDP --dport 7 -j DROP
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p TCP --dport 7 -j DROP

#Allow forwarding from inside to out and vice versa
/sbin/iptables -A FORWARD -i $INTINT -s $LOCALNETWORK -j ACCEPT
/sbin/iptables -A FORWARD -o $INTINT -d $LOCALNETWORK -j ACCEPT

# remote inteface, claiming to be local machines gets dropped
/sbin/iptables -A INPUT -i $EXTINT -s $LOCALNETWORK -j DROP

# Drop incoming on remote interface from known bad IPs (probably
# an attempted spoof or misconfigured machine, just in case the rules above don't stop this.)
# Anything coming from the Internet should have a real Internet address
# Multicast is Class_D.
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -s $CLASS_E -j DROP
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -s $CLASS_C -j DROP
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -s $CLASS_B -j DROP
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -s $CLASS_A -j DROP
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -s $LOOPBACK -j DROP
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -s $MULTICAST -j DROP

#This is an exception to the reject from local rule I use.
#You can't reject in NAT, only in filter.  If I want to reject,
#the number of rules would double.
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -d $CLASS_E -j DROP
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -d $CLASS_C -j DROP
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -d $CLASS_B -j DROP
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -d $CLASS_A -j DROP
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -d $LOOPBACK -j DROP
#Multicast could be a valid destination, so that rule is missing on purpose.
echo "Done with private addresses"

# Kill malformed packets -- enhance this list yourself!
# Block XMAS packets
/sbin/iptables -t nat -A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
# Block NULL packets
/sbin/iptables -t nat -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
# Drop FIN packets that don't have ACKs. They are scans.
/sbin/iptables -t nat -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
#Some other "illegal" combination of TCP flags.  These are either
#scans or attacks.
#The following rule is slightly deceptive.  A TCP packet with both
#SYN and FIN set is a scan or attack.  However, since most firewalls
#are aware of this combo, you see other combos used, such as
#SYN/FIN/PSH, SYN/FIN/RST, SYN/FIN/RST/PSH, etc.  However, in all
#these combos, SYN and FIN are both set.  By limiting the first
#set of flags to look at only the SYN and FIN, we automatically
#catch all the other combos.
/sbin/iptables -t nat -A PREROUTING -p TCP \
	--tcp-flags SYN,FIN SYN,FIN -j DROP
/sbin/iptables -t nat -A PREROUTING -p TCP \
	--tcp-flags SYN,RST SYN,RST -j DROP
echo "Some malformed packets blocked"

#===============================================================
#Test Code
#Check to see if I actually see any local broadcast packets.
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -d 208.191.175.255 \
	-j LOG --log-level info --log-prefix "Broadcast packet..."
#===============================================================

# The IANA has defined some sets of addresses as reserved.  Therefore
# these addresses should never be a source address.  The reserved
# addresses are: 0-2.*.*.*, 5.*.*.*, 7.*.*.*, 23.*.*.* 27.*.*.*,
# 31.*.*.*, 36-37.*.*.* 39.*.*.* 41.*.*.*, 42.*.*.*, 58-60.*.*.*,
# 69-79.*.*.*, 82-127.*.*.*, 197.*.*.*, 201.*.*.*, 219-223.*.*.*, 
# 240-255.*.*.*
# One location of the current list as of 07/20/2001 is at
# http://www.iana.org/assignments/ipv4-address-space
#Note this one is different to allow for an internal DHCP server
/sbin/iptables -A INPUT -i $EXTINT -s 0.0.0.0/8  -j DROP
#Yes this is a little redundant
/sbin/iptables -A INPUT -s 1.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 2.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 5.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 7.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 23.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 27.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 31.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 36.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 37.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 39.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 41.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 42.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 58.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 59.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 60.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 69.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 70.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 71.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 72.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 73.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 74.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 75.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 76.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 77.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 78.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 79.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 82.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 83.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 84.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 85.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 86.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 87.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 88.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 89.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 90.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 91.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 92.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 93.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 94.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 95.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 96.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 97.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 98.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 99.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 100.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 101.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 102.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 103.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 104.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 105.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 106.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 107.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 108.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 109.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 110.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 110.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 111.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 112.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 113.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 114.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 115.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 116.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 117.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 118.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 119.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 120.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 121.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 122.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 123.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 124.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 125.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 126.0.0.0/8  -j DROP
#Redundent?
/sbin/iptables -A INPUT -i $EXTINT -s 127.0.0.0/8 -j DROP
/sbin/iptables -A INPUT -s 197.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 219.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 220.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 221.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 222.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 223.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 224.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 225.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 226.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 227.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 228.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 229.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 230.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 231.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 232.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 233.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 234.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 235.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 236.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 237.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 238.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 239.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 240.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 241.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 242.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 243.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 244.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 245.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 246.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 247.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 248.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 249.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 250.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 251.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 252.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 253.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 254.0.0.0/8  -j DROP
/sbin/iptables -A INPUT -s 255.0.0.0/8  -j DROP
echo "Done with reserved addresses"

# Block outgoing network filesharing protocols that aren't designed 
# to leave the LAN -- log the SMB ones
# SMB / Windows filesharing
#Uncomment if you want to log incoming SMB attempts.
#/sbin/iptables -t nat -A PREROUTING -p TCP --dport 137:139 \
#	-i $EXTINT -j LOG --log-level info \
#	--log-prefix "SMB tried to come in..."
#/sbin/iptables -t nat -A PREROUTING -p UDP --dport 137:139 \
#	-i $EXTINT -j LOG --log-level info \
#	--log-prefix "SMB tried to come in..."
#/sbin/iptables -A FORWARD -p tcp --sport 137:139 -j LOG \
#	--log-level info --log-prefix "SMB tried to cross."
#/sbin/iptables -A FORWARD -p udp --sport 137:139 -j LOG \
#	--log-level info --log-prefix "SMB tried to cross."
/sbin/iptables -t nat -A PREROUTING -p TCP --dport 137:139 \
	-i $EXTINT -j DROP
/sbin/iptables -t nat -A PREROUTING -p UDP --dport 137:139 \
	-i $EXTINT -j DROP
#Not needed.  It will get dropped either at PREROUTING or POSTROUTING
#/sbin/iptables -A FORWARD -p tcp --sport 137:139 -j DROP
#/sbin/iptables -A FORWARD -p udp --sport 137:139 -j DROP
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -p tcp --sport 137:139 -j DROP
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -p udp --sport 137:139 -j DROP
echo "SMB outgoing and incoming blocked"

#===========================================================
#Not needed.  $LOCALPORTS eliminates these problems.
#Block SQL ports until I figure out portwalling at least
#/sbin/iptables -A INPUT -i $EXTINT -p TCP --dport $MYSQLPORT -j DROP
#/sbin/iptables -A INPUT -i $EXTINT -p UDP --dport $MYSQLPORT -j DROP
echo "SQL blocked"
#Drop Xwindows connections
#/sbin/iptables -t nat -A PREROUTING -i $EXTINT \
#	-p TCP --dport $XWINDOW_PORTS -j DROP
#===========================================================
#Allow IPSEC (Free S/WAN)
# Note here the ipsec is on the $INTINT

if [ $IPSEC = "yes" ]; then
#Rules for IKE
/sbin/iptables -A INPUT -i $EXTINT -p UDP \
	--sport 500 --dport 500 -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p UDP \
	--sport 500 --dport 500 -j ACCEPT
#Rules for ESP (protocol 50)
/sbin/iptables -A INPUT -i $EXTINT -p 50 -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p 50 -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p 50 \
	-j ACCEPT
#Rules for AH (protocol 51)
#General ipsec rules (bare minimum)
/sbin/iptables -t nat -A PREROUTING -i ipsec+ -j ACCEPT
/sbin/iptables -t nat -A POSTROUTING -o ipsec+ -j ACCEPT
/sbin/iptables -A INPUT  -i ipsec+ -j ACCEPT
/sbin/iptables -A OUTPUT -o ipsec+ -j ACCEPT 

fi
#===========================================================

#Allow DHCP traffic
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p UDP -s $DHCPSERVER \
	--sport 67 --dport 68 -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p UDP -s $DHCPSERVER3 \
	--sport 67 --dport 68 -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p UDP -s $DHCPSERVER4 \
	--sport 67 --dport 68 -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p UDP -s $BROADCAST_SRC --sport 68 \
	-d $BROADCAST_DEST --dport 67 -m state --state NEW,ESTABLISHED \
	-j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p UDP -s $BROADCAST_SRC --sport 67 \
	-d $BROADCAST_DEST --dport 68 -m state --state ESTABLISHED -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p UDP -s $ANYWHERE --sport 68 \
	-d $DHCPSERVER --dport 67 -m state --state NEW,ESTABLISHED \
	-j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p UDP -s $ANYWHERE --sport 68 \
	-d $DHCPSERVER3 --dport 67 -m state --state NEW,ESTABLISHED \
	-j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p UDP -s $ANYWHERE --sport 68 \
	-d $DHCPSERVER4 --dport 67 -m state --state NEW,ESTABLISHED \
	-j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p UDP -s $DHCPSERVER --sport 67 \
	-d $ANYWHERE --dport 68 -m state --state NEW,ESTABLISHED -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p UDP -s $DHCPSERVER3 --sport 67 \
	-d $ANYWHERE --dport 68 -m state --state NEW,ESTABLISHED -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p UDP -s $DHCPSERVER4 --sport 67 \
	-d $ANYWHERE --dport 68 -m state --state NEW,ESTABLISHED -j ACCEPT
#Internal DHCP SERVER
/sbin/iptables -t nat -A PREROUTING -i $INTINT -p UDP -s $DHCPSERVER2 \
	--sport 68 --dport 67 -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -i $INTINT -p UDP -s $BROADCAST_SRC \
	--sport 68 -d $BROADCAST_DEST --dport 67 -j ACCEPT

#Don't need established - Tested
/sbin/iptables -A INPUT  -i $INTINT -p UDP -s $BROADCAST_SRC --sport 68 \
	-d $BROADCAST_DEST --dport 67 -m state --state NEW -j ACCEPT
/sbin/iptables -A OUTPUT -o $INTINT -p UDP -s $DHCPSERVER2 --sport 67 \
	-d $BROADCAST_DEST --dport 68 -m state --state NEW \
	-j ACCEPT
#Note rules to allow renewals for those clients who already have addresses is
#covered by unlimited LAN traffic rules
echo "DCHP allowed"

# Refuse all 0.0.0.0 source packets.  The only legitimate use is for DHCP (already covered).
/sbin/iptables -A INPUT -i $EXTINT -s $BROADCAST_SRC -j DROP

# Refuse all broadcasts (except DHCP which is already covered).
/sbin/iptables -A INPUT -i $EXTINT -d $BROADCAST_DEST -j DROP

#Multiport rule(s) for PREROUTING and POSTROUTING
#Since my default policy is to accept (in NAT), I can combine them for 
#rule reduction and simplication, with no real impact on security.
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -p UDP \
	-m multiport --dport 53 -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p UDP \
	-m multiport --sport 53 -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -o $EXTINT -p UDP \
	-m multiport --dport 53 -j ACCEPT
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -p TCP \
	-m multiport --dport 20,21,22,25,53,80,110,119,443,2064,5190 -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p TCP \
	-m multiport --sport 20,21,22,25,53,80,110,119,443,2064,5190 -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -o $EXTINT -p TCP \
	-m multiport --dport 20,21,22,25,53,80,110,119,443,2064,4000 -j ACCEPT
echo "Multiport NAT rules done"


#Allow DNS (port 53 TCP and UDP)
/sbin/iptables -A INPUT  -i $EXTINT -p UDP --sport 53 \
	-m state --state ESTABLISHED --dport $LOCALPORTS -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p UDP --sport $LOCALPORTS \
	-m state --state NEW,ESTABLISHED --dport 53 -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 53 \
	--dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT
echo "DNS queries allowed"

#*****************
# PCANYWHERE
#*****************
#uncomment this and change the address to the computer you want
#pcanywhere rerouted to.  This is only needed if you want to be a server.
#PCHOST="192.168.1.101"
#/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p UDP --dport 5632 \
#	-j DNAT --to $PCHOST:5632
#/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p TCP --dport 5631 \
#	-j DNAT --to $PCHOST:5631
#echo "Done with PCANYWHERE"


#Allow Web access (ports 80 and 443)
#First 80 then 443
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	-m state --state NEW,ESTABLISHED --dport 80 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 80 \
	--dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT

#Limit logging of incoming http packets.  Some seem to be cookie placement
#attempts, but many could be worms attempting to break in.
#Your web surfing isn't affected by these because of the state rules
#above.  Traffic where you established the connection is allowed through.
/sbin/iptables -A INPUT -i $EXTINT -p TCP --sport 80 \
	-m limit -j LOG --log-level info --log-prefix "Port 80 dropped.."
/sbin/iptables -A INPUT -i $EXTINT -p TCP --sport 80 -j DROP

/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport 443 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 443 \
	--dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT
echo "Web and Secure Web allowed"


#Allow FTP

#Filter Rules
#Active channels
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport 21 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 21 \
	--dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport 20 -j ACCEPT
#Tested - Both ESTABLISHED and RELATED are required for FTP
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 20 \
	--dport $LOCALPORTS -m state --state ESTABLISHED,RELATED \
	-j ACCEPT
#Passive channels
#Don't need related here because unlike port 20, the client
#establishes the connection, not the server
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport $PUBLICPORTS -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport $PUBLICPORTS \
	--dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT
#Passive NAT rules
/sbin/iptables -t nat -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport $PUBLICPORTS -j ACCEPT
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -p TCP \
	--sport $LOCALPORTS --dport $PUBLICPORTS -j ACCEPT

echo "FTP allowed"

#=================================================================
if [ $FTPSERVER = "yes" ]; then

#Doesn't support passive yet.
/sbin/iptables -A INPUT -i $EXTINT -p TCP -s $FRIENDIP \
	--sport $PUBLICPORTS --dport 21 -j ACCEPT
/sbin/iptables -A INPUT -i $EXTINT -p TCP -s $FRIENDIP \
	--sport $PUBLICPORTS --dport 20 -j ACCEPT

/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport 21 \
	-d $FRIENDIP --dport $PUBLICPORTS -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport 20 \
	-d $FRIENDIP --dport $PUBLICPORTS -j ACCEPT

echo "FTP server allowed"
fi
#=================================================================

#Allow Email (port 25 and 110)
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport 25 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 25 \
	--dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport 110 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 110 \
	--dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT
echo "Email allowed (except IMAP)"

#Allow ssh (port 22 - access as a client)
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP \
	--dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 22 \
	 -m state --state ESTABLISHED -j ACCEPT
echo "SSH client allowed"

#Allow SSH server access (Port 22)
#Uncomment the next few lines to enable
#/sbin/iptables -A INPUT -i $EXTINT -p TCP \
#	--dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
#/sbin/iptables -A OUTPUT -o $EXTINT -p TCP \
#	--sport 22 -j ACCEPT
#/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p TCP \
#	--dport 22 -j ACCEPT
#/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -p TCP \
#	--sport 22 -j ACCEPT
#echo "SSH server allowed"

#Allows usenet (port 119)
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP \
	--dport 119 --sport $LOCALPORTS -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 119 \
	 --dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT
echo "News allowed"

#Allow ICQ and AIM (TCP port 5190 and TCP public ports)
#Because of the passive FTP rules, these are unnecessary.
#/sbin/iptables -A OUTPUT -o $EXTINT -p UDP --sport $PUBLICPORTS \
#	--dport 5190 -j ACCEPT
#/sbin/iptables -A INPUT  -i $EXTINT -p UDP --sport 5190 \
#	--dport $PUBLICPORTS -j ACCEPT
#The public ports are covered by passive FTP, except for allowing
#connections to me.  Therefore, I need only one rule.
#/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport $PUBLICPORTS \
#	--dport $PUBLICPORTS -m state --state NEW -j ACCEPT
#echo "ICQ and AOL allowed"

#Allow distributed.net
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport 2064 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 2064 \
	--dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT
echo "Distributed.net allowed"

#Allow ntp
/sbin/iptables -A OUTPUT -o $EXTINT -p UDP --sport 123 \
	--dport 123 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p UDP --sport 123 \
	--dport 123 -m state --state ESTABLISHED -j ACCEPT
echo "ntp allowed"

#Allow outgoing whois(port 43)
/sbin/iptables -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport 43 -m state --state ESTABLISHED -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -o $EXTINT -p TCP --sport $LOCALPORTS \
	--dport 43 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport 43 \
	--dport $LOCALPORTS -m state --state ESTABLISHED -j ACCEPT
echo "whois allowed"

#Allow pptpd connections (port 1723)
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p TCP \
	--sport $PUBLICPORTS --dport 1723 -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -o $EXTINT -p 47 -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p 47 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p 47 -j ACCEPT
/sbin/iptables -A INPUT  -i ppp+ \
	-s $LOCALNETWORK -d $LOCALNETWORK -j ACCEPT 
/sbin/iptables -A OUTPUT -o ppp+ \
	-s $LOCALNETWORK -d $LOCALNETWORK -j ACCEPT 
/sbin/iptables -A FORWARD -i ppp+ -o $EXTINT -p 47 \
	-s $LOCALNETWORK -d $LOCALNETWORK -j ACCEPT
/sbin/iptables -A FORWARD -o ppp+ -i $EXTINT -p 47 \
	-s $LOCALNETWORK -d $LOCALNETWORK -j ACCEPT
#Rules to allow surfing
/sbin/iptables -A FORWARD -i ppp+ -o $EXTINT -s $LOCALNETWORK \
	-j ACCEPT
/sbin/iptables -A FORWARD -o ppp+ -i $EXTINT -d $LOCALNETWORK \
	-j ACCEPT
echo "PPTPD allowed"

#Reject port 113
#I can't reject in nat, so let it through.  The next rule will block.
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p TCP \
	--dport 113 -j ACCEPT
/sbin/iptables -A INPUT  -i $EXTINT -p TCP --sport $PUBLICPORTS \
	--dport 113 -j REJECT

#Allow some ICMP messages
# ICMP types which lack socially redeeming value.
# Be very careful about allowing these through
#  5     Redirect
#  9     Router Advertisement
# 10     Router Selection
# 15     Information Request
# 16     Information Reply
# 17     Address Mask Request
# 18     Address Mask Reply
# Now on to the rules.
#Allow source quench (type 4)
/sbin/iptables -A INPUT  -i $EXTINT -p ICMP --icmp-type source-quench \
	-m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p ICMP --icmp-type source-quench \
	-j ACCEPT
#Allow parameter problem status (type 12)
/sbin/iptables -A INPUT  -i $EXTINT -p ICMP --icmp-type parameter-problem \
	-m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p ICMP --icmp-type parameter-problem \
	-j ACCEPT
#Allow Destination unreachable (type 3)
#Checked
/sbin/iptables -A INPUT -i $EXTINT -p ICMP --icmp-type \
	destination-unreachable -m state --state RELATED \
	-j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p ICMP --icmp-type \
	destination-unreachable -j ACCEPT
#Allow time exceeded (type 11) messages
/sbin/iptables -A INPUT -i $EXTINT -p ICMP --icmp-type \
	time-exceeded -m state --state ESTABLISHED,RELATED \
	-j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p ICMP --icmp-type \
	time-exceeded -j ACCEPT
#Allow outgoing pings (type 8 and type 0)

/sbin/iptables -t nat -A OUTPUT -o $EXTINT -p ICMP --icmp-type \
	echo-request -j ACCEPT
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -p ICMP --icmp-type \
	echo-request -j ACCEPT

/sbin/iptables -A INPUT -i $EXTINT -p ICMP --icmp-type \
	echo-reply -m state --state ESTABLISHED \
	-j ACCEPT
/sbin/iptables -A OUTPUT -o $EXTINT -p ICMP --icmp-type \
	echo-request -m state --state NEW \
	-j ACCEPT

echo "Some ICMP allowed"

#Limit logging of pings.
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p ICMP --icmp-type \
	echo-request -m limit -j LOG --log-level info \
	--log-prefix "Ping dropped.."
/sbin/iptables -t nat -A PREROUTING -i $EXTINT -p ICMP --icmp-type \
	echo-request -j DROP

#Allow traceroute
#By default, it uses UDP packets, and tends (for Linux at least)
#to use source ports 32769-65536 and destination ports
# 33434:33523.  It can be made to any port, however.
# Note that the input is handles by the icmp type 3 above.
/sbin/iptables -A OUTPUT -o $EXTINT -p UDP --sport $TRACEROUTE_SRC_PORTS \
	--dport $TRACEROUTE_DEST_PORTS -m state --state NEW -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -o $EXTINT -p UDP \
	--sport $TRACEROUTE_SRC_PORTS \
	--dport $TRACEROUTE_DEST_PORTS -j ACCEPT
/sbin/iptables -t nat -A POSTROUTING -o $EXTINT -p UDP \
	--sport $TRACEROUTE_SRC_PORTS \
	--dport $TRACEROUTE_DEST_PORTS -j ACCEPT
echo "traceroute allowed"

#Log everything else (which would be dropped anyway)
/sbin/iptables -A INPUT -j LOG --log-level info \
	--log-prefix "Input packet dropped"
/sbin/iptables -A INPUT -j DROP
/sbin/iptables -A OUTPUT -j LOG --log-level info \
	--log-prefix "Output packet dropped"
/sbin/iptables -A OUTPUT -j REJECT
/sbin/iptables -A FORWARD -j LOG --log-level info \
	--log-prefix "Forward packet dropped"
/sbin/iptables -A FORWARD -j DROP
/sbin/iptables -t nat -A PREROUTING -j LOG --log-level info \
	--log-prefix "PreNat logging at end."
/sbin/iptables -t nat -A POSTROUTING -j LOG \
	--log-level info --log-prefix "PostNat logging at end."
/sbin/iptables -t nat -A OUTPUT -j LOG \
	--log-level info --log-prefix "Out NAT logging at end."

#Leave a record in syslog that the firewall is (re)started
$LOGGER "Firewall is (re)started and should be up now."