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:
- The Curious
- The Vandal
- The Leapfrogger
- The Harraser
- The Pirate
- (Optional) The Competition
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.
- Wrong! You will be found, quickly! Lance Spitzner reports: "I personally witnessed a system hacked by a script kiddie within 15 minutes of connecting to the Internet."
- Relatively few people actually have the skill to break into systems.
- However, some of the few who have the skills now put their knowledge into automated programs and shell scripts which can be used to scan for security holes and attack many computers simultaneously. These programs are then distributed.
- Thus are born "script kiddies", who are basically thousands of bored children (or childish adults) who lack the expertise to be any kind of a real threat, using software downloaded from the Internet to implement broad scale attacks against anyone and everyone on the net.
- If your system only gets probed once a week, you're lucky! No one is safe.
Why do I want a firewall?
- A firewall is a very good, perhaps essential, tool (but not the only one!) for stopping attacks on your system(s).
- A firewall helps to protect sensitive information, provide traffic analysis, and increase network availability.
- A firewall (iptables at least) can provide Internet connection sharing for your network. This makes direct attacks on those client machines more difficult.
- A properly configured firewall can not only block some incoming attacks, and it can also block some outgoing attacks.
- A firewall (iptables at least) can also do port redirection and transparent proxying.
- Logging - It is usually a good idea to know what's going on in the network.
What does a firewall NOT protect against?
- Installing a firewall does not make your computer or network secure, it just makes it less insecure, maybe.
- Installing a firewall does not make your computer or network secure, it just makes it less insecure, maybe.
- A firewall will not protect you from a virus you receive through email, or through files you download from floppy or off the net. However, if that virus or trojan horse turns your computer into a server, or if it turns on features that allow others to fully control your computer remotely, the a firewall might offer you some protection from your computer from being abused by people on the Internet and stop your computer from abusing others.
- Having insecure hosts. Every service you allow through the firewall is a potential risk.
- Not having proper backups.
- Defective hardware (if only!)
- Power problems.
- Getting an anthrax tainted letter in the mail, etc.
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:
- Protocol Type - TCP, UDP, ICMP. Many will allow you filter other protocols types too.
- Source Address - The computer that supposedly originated the packet, but note this could be falsified.
- Destination Address -- The computer the packet is addressed to.
- Protocol sub-type -- Some protocol specific sub-type such as TCP's "SYN" packet used to initiate a connection or ICMP type (i.e. echo-request, echo-reply, etc.)
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?
- A stateful firewall provides more control over which packets are allowed through and which aren't than a stateless firewall.
- A stateless firewall (such as ipchains) is an all or nothing deal. Either the packets are allowed through or they aren't.
- It is fairly easy to get "bad" packets by a stateless firewall, but not as easy to get "bad" packets past a stateful firewall.
- A stateful firewall keeps track of connections in addition to the normal filtering by port, protocol, and IP address(s).
- A connection can either be NEW, ESTABLISHED, RELATED, or INVALID. These are discussed in more detail later.
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.
- 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.
- Attackers know this by the way.
- An attacker could craft a packet with a spoofed IP address and send it from port 80 to an unprivledged port on your system.
- Stateless would allow this through.
- 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.
- 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.
- 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
- 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.
- An attacker could craft a packet with a spoofed IP address and send it from port 80 to an unprivledged port on your system.
- 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.
- The attacker is out of luck!
Stateful Firewalling - Drawbacks
If stateful firewalling is superior, why isn't it used everywhere?
- 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.
- 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
- Mostly Closed
Mostly Open Firewalls
Mostly open means that the default action is to accept packets. Packets are denied only by specific rules.
Advantages:
- Appears simple and easy to setup compared to mostly closed.
- Very low chance of breaking some application.
Disadvantages:
- You must think of every possible bad packet and block all of them.
- You must keep a constant watch for new insecure services popping up on your computer/network and update the firewall appropriately.
- Your computer is vulnerable to being used by trojan horses.
- Your firewall rules can be pretty easily discovered if you use DROP instead of REJECT.
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:
- Tends to be less insecure than mostly open
- Lower maintenance than mostly open
Disadvantages:
- Likely to (temporarily) break some applications
- More work to initially set up
- Requires a greater understanding of the application protocols and routing than mostly open
To Drop or To Reject, that is the question
- Dropping a packet does not send an ICMP error message. The original packet is not sent on.
- Rejecting a packet does send an ICMP error message. The original packet is not sent on either.
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.
- The private address ranges going out to the Internet.
- The loopback address range coming from anywhere except the loopback adapter.
- Class D IP addresses (224.0.0.0 to 239.255.255.255) when used as a source address. They may be ok as destination addresses.
- Class E IP addresses (240.0.0.0 to 247.255.255.255) when used as a source address. It's highly unlikely someone will be transmitting to these address, so it's probably a good idea to block them when used as a destination address.
- Broadcast address unless you are using DHCP. The addresses are 0.0.0.0 for source and 255.255.255.255 for destination. Block these after you allow for DHCP.
- Any packets coming from your network that don't have your network address as a source, unless you are doing routing, maybe.
- If your firewall allows you to filter on arbitrary tcp flags (iptables does), drop any tcp packets that have either no flags set (null packets) or all the flags set (SYN,ACK,FIN,RST,URG,PSH - an Xmas packet).
Things you should give consideration to blocking.
The following are things that you should give heavy consideration to blocking, although they may cause problems.
- IANA reserved addresses. These are "legitimate" IP addresses that have not been allocated. Therefore, no one should be using them. The downside to this is the addresses do change every so often, so you will get mysterious problems is you don't check on this address space every so often. One place to find the current list is http://www.iana.org/assignments/ipv4-address-space
- Any protocols you are using internally that you want to be sure don't leak out into the Internet (or vice-versa). Examples of this would be SMB, NFS, NIS, etc. In theory, if you use portwalling and your firewall is perfectly configured, this would never be an issue.
- The private address ranges coming from the Internet.
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:
- The packet is specifically addressed to it, or
- A broadcast address, which is either 255.255.255.255, which can be blocked (and should be, see above), and local network broadcasts.
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:
- A call to the iptables to add the rule, usually "/sbin/iptables -A"
- Where to look for the packet
- A description of the packet you are looking for. This is probably the most complicated part of an iptables rule.
- 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:
- Append a new rule to a chain (-A)
- Insert a new rule at some position in a chain (-I)
- Replace a rule at some position in a chain (-R)
- Delete a rule at some position in a chain (-D)
- Delete the first rule that matches in a chain (-D)
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:
- ACCEPT
- DROP
- MASQUERADE
- QUEUE
- RETURN
- REJECT
- The name of a user defined chain
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:
- Web browsers connect, then hang with no data received.
- Small mail works fine, but large emails hang.
- 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.
- Procotol Type - TCP, UDP, ICMP, etc.
- Source Port(s) - With the multiport module, you can match several different ranges of ports.
- Destination Port(s) - With the multiport module, you can match several different ranges of ports.
- Source IP address
- Destination IP address
- Interface - eth0, ppp0, etc.
- Inversion - Taking any above criteria and turning it around, i.e. Not this source ip address
- limit - It is used to restrict the rate of matches, such as for suppressing log messages.
- TCP Packet Flags - i.e. SYN, ACK, etc.
- State
- Fragmentation - If a packet is broken up (due to size problems), then it is fragmented. All fragments except the first will never match any other criteria except this.
- MAC address
- Mark - This "marks" a packet that can later be matched against.
- Owner - This works only for locally generated packets of course, and then only under certain circumstances.
- TOS - Type of Service
- Packet Length (aka size)
- TTL - Time to Live
- MSS value of TCP SYN packets - This controls the maximum packet size for a connection.
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:
- Use the UDP or TCP extensions
- 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.
| Name | Number |
| source-quench | 4 |
| parameter-problem | 12 |
| destination-unreachable | 3 |
| time-exceeded | 11 |
| echo-request | 8 |
| echo-reply | 0 |
/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:
- --limit followed by a number; specifies the maximum average number of matches to allow per second. The number can specify units explicitly, using `/second', `/minute', `/hour' or `/day', or parts of them (so `5/second' is the same as `5/s').
- --limit-burst followed by a number, indicating the maximum burst before the above limit kicks in.
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
- A NEW connection is one where the packet is attempting to start a connection or is otherwise not associated with a connection which has not seen packets in both directions. For TCP connections, this may noted by the incoming packet having the SYN flag set, but not the ACK. There are other possibilities. UDP for instance, is connectionless, so there is no SYN flag, and ICMP packets don't have flags. Basically, NEW means the first packet to start traveling, and usually only the first.
- ESTABLISHED means a packet which belongs to an existing connection. The term connection is used very loosely and does not take on the same meaning as a TCP connection. For instance, an echo reply to a ping you send out is considered an existing connection and therefore is an ESTABLISHED packet. NEW and ESTABLISHED often, but not always, go together.
- RELATED packets are similar to ESTABLISHED packets, but something is different. These are packets that are related to an established connection, but are not part of the connection. So far, the only confirmed use of RELATED I've seen has to do with FTP and ICMP, and then only in conjunction with ESTABLISHED for FTP.
- INVALID are packets that can't otherwise be classified. As a general rule, they should be dropped if you encounter any. However, so far, the only use I've found for INVALID is with inversion, i.e. ! INVALID as shorthand for NEW,ESTABLISHED,RELATED.
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
- Flushing the rules does not change the default policies like it did in ipchains.
- Each built-in table must be flushed separately.
- Packets send from your machine to your machine always go through the loopback interface. In other words, if you ping yourself, those packets go through the loopback interface, not the one you would think.
- There are two rpms for iptables. One is for IPv4, the other is for IPv6. If you load the one for IPv6 and you don't have IPv6 in your kernel, iptables won't work.
- You can only use reject in the filter table. You can't use it in the NAT table.
- The INPUT table onlymatches packets heading for your firewall itself. You have to use the FORWARD table to match packets heading for your network.
- The only chain an incoming packet is guaranteed to go through is PREROUTING.
- The only chain an outgoing packet is guaranteed to go through is POSTROUTING.
- Remember PREROUTING deals with incoming packets (like INPUT), whereas POSTROUTING deals with outgoing packets (like OUTPUT). Watch your source ports and destination ports when dealing with these rules.
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.
- Download the iptables code from http://netfilter.samba.org/iptables-1.2.4.tar.bz2 or the nearest mirror.
- Unpack it somewhere: tar jxvf iptables-1.2.4.tar.bz2 and cd into the iptables-1.2.4 directory.
- 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.
- 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.
- Compile the user-space code and the libraries: make KERNEL_DIR=[full path to kernel source].
- Install the programs, code and libraries: make install KERNEL_DIR=[full path to kernel source].
- 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:
- 10.0.0.0-10.255.255.255
- 172.16.0.0-172.31.255.255
- 192.168.0.0-192.168.255.255
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."