![]() | ![]() |
|
Linux IPCHAINS-HOWTORusty Russellv1.0.8, Tue Jul 4 14:20:53 EST 2000This document aims to describe how to obtain, install and configure the enhanced IP firewalling chains software for Linux, and some ideas on how you might use them.
1. Introduction
2. Packet Filtering Basics
3. I'm confused! Routing, masquerading, portforwarding, ipautofw...
4. IP Firewalling Chains
5. Miscellaneous.
6. Common Problems
7. A Serious Example.
8. Appendix: Differences between ipchains and ipfwadm.
9. Appendix: Using the ipfwadm-wrapper script.
10. Appendix: Thanks.1. IntroductionThis is the Linux IPCHAINS-HOWTO; see Where? for the master site, which contains the latest copy. You should read the Linux NET-3-HOWTO as well. The IP-Masquerading HOWTO, the PPP-HOWTO, the Ethernet-HOWTO and the Firewall HOWTO might make interesting reading. (Then again, so might the alt.fan.bigfoot FAQ).
If packet filtering is passe to you, read Section Why?, Section How?, and scan through the titles in Section IP Firewalling Chains.
If you are converting from
1.1 What?Linux
1.2 Why?The older Linux firewalling code doesn't deal with fragments, has 32-bit counters (on Intel at least), doesn't allow specification of protocols other than TCP, UDP or ICMP, can't make large changes atomically, can't specify inverse rules, has some quirks, and can be tough to manage (making it prone to user error).
1.3 How?Currently the code is in the mainstream kernel from 2.1.102. For the 2.0 kernel series, you will need to download a kernel patch from the web page. If your 2.0 kernel is more recent than the supplied patch, the older patch should be OK; this part of the 2.0 kernels is fairly stable (eg. the 2.0.34 kernel patch works just fine on the 2.0.35 kernel). Since the 2.0 patch is incompatible with the ipportfw and ipautofw patches, I don't recommend applying it unless you really need some functionality that ipchains offers.
1.4 Where?The official page is in three places: Thanks to Penguin Computing Thanks to the SAMBA Team Thanks to Jim Pick
There is a mailing list for bug reports, discussion, development and usage. Join the mailing list by sending a message containing the word ``subscribe ipchains-list'' to subscribe at east.balius.com. To mail to everyone on the list use ipchains-list at east.balius.com.
2. Packet Filtering Basics2.1 What?All traffic through a network is sent in the form of packets. For example, downloading this package (say it's 50k long) might cause you to receive 36 or so packets of 1460 bytes each, (to pull numbers at random).
The start of each packet says where it's going, where it came from, the type of the packet, and other administrative details. This start of the packet is called the header. The rest of the packet, containing the actual data being transmitted, is usually called the body.
Some protocols, such TCP, which is used for web traffic, mail, and remote logins, use the concept of a `connection' -- before any packets with actual data are sent, various setup packets (with special headers) are exchanged saying `I want to connect', `OK' and `Thanks'. Then normal packets are exchanged.
A packet filter is a piece of software which looks at the header of packets as they pass through, and decides the fate of the entire packet. It might decide to deny the packet (ie. discard the packet as if it had never received it), accept the packet (ie. let the packet go through), or reject the packet (like deny, but tell the source of the packet that it has done so).
Under Linux, packet filtering is built into the kernel, and there are a few trickier things we can do with packets, but the general principle of looking at the headers and deciding the fate of the packet is still there.
2.2 Why?Control. Security. Watchfulness.
2.3 How?A Kernel With Packet FilteringYou need a kernel which has the new IP firewall chains in it. You can tell if the kernel you are running right now has this installed by looking for the file `/proc/net/ip_fwchains'. If it exists, you're in.
If not, you need to make a kernel that has IP firewall chains. First, download the source to the kernel you want. If you have a kernel numbered 2.1.102 or higher, you won't need to patch it (it's in the mainstream kernel now). Otherwise, apply the patch from the web page listed above, and set the configuration as detailed below. If you don't know how to do this, don't panic -- read the Kernel-HOWTO.
The configuration options you will need to set for the 2.0-series kernel are:
CONFIG_EXPERIMENTAL=y CONFIG_FIREWALL=y CONFIG_IP_FIREWALL=y CONFIG_IP_FIREWALL_CHAINS=y For the 2.1 or 2.2 series kernels: CONFIG_FIREWALL=y CONFIG_IP_FIREWALL=y
The tool
ipchainsThe
http://netfilter.filewatcher.org/ipchains/ipchains-scripts-1.1.2.tar.gz
This contains a shell script called See Appendix
Differences between ipchains and ipfwadm
and Appendix
Using the `ipfwadm-wrapper' script
for more details on
Making Rules PermanentYour current firewall setup is stored in the kernel, and thus will be lost on reboot. I recommend using the `ipchains-save' and `ipchains-restore' scripts to make your rules permanent. To do this, set up your rules, then run (as root):
Create a script like the following:
Make sure this is run early in the bootup procedure. In my case (Debian 2.1), I make a symbolic link called `S39packetfilter' in the `/etc/rcS.d' directory (this will be run before S40network).
3. I'm confused! Routing, masquerading, portforwarding, ipautofw...This HOWTO is about packet filtering. This means deciding whether a packet should be allowed to pass or not. However, Linux being the hacker's playground that it is, you probably want to do more than that.
One problem is that the same tool (``ipchains'') is used to control both masquerading and transparent proxying, although these are notionally separate from packet filtering (the current Linux implementation blurs these together unnaturally, leaving the impression that they are closely related).
Masquerading and proxying are covered by separate HOWTOs, and the auto forwarding and port forwarding features are controlled by separate tools, but since so many people keep asking me about it, I'll include a set of common scenarios and indicate when each one should be applied. The security merits of each setup will not be discussed here.
3.1 Rusty's Three-Line Guide To MasqueradingThis assumes that your external interface is called `ppp0'. Use ifconfig to find out, and adjust to taste.
3.2 Gratuitous Promotion: WatchGuard RulesYou can buy off-the-shelf firewalls. An excellent one is WatchGuard's FireBox. It's excellent because I like it, it's secure, it's Linux-based, and because they funded the maintenance of ipchains as well as the new firewalling code (for 2.4). In short, WatchGuard were paying for me to eat while I work for you. So please consider their stuff.
3.3 Common Firewall-like SetupsYou run littlecorp.com. You have an internal network, and a single dialup (PPP) connection to the Internet (firewall.littlecorp.com which is 1.2.3.4). You run Ethernet on your local network, and your personal machine is called "myhost".
This section will illustrate the different arrangement which are common. Read carefully, because they are each subtly different.
Private Network: Traditional ProxiesIn this scenario, packets from the private network never traverse the Internet, and vice versa. The IP addresses of the private network should be assigned from the RFC1918 Address Allocation for Private Internets (ie. 10.*.*.*, 172.16.*.*-172.31.*.* or 192.168.*.*).
The only way things ever connect to the Internet is by connecting to the firewall, which is the only machine on both networks which connects onwards. You run a program (on the firewall) called a proxy to do this (there are proxies for FTP, web access, telnet, RealAudio, Usenet News and other services). See the Firewall HOWTO.
Any services you wish the Internet to access must be on the firewall. (But see Limited Internal Services below).
Example: Allowing web access from private network to the Internet.
Netscape on myhost reads http://slashdot.org.
ie. From slashdot.org's point of view, the connection is made from 1.2.3.4 (firewall's PPP interface) port 1025 to 207.218.152.131 (slashdot.org) port 80. From myhost's point of view, the connection is made from 192.168.1.100 (myhost) port 1050, to 192.168.1.1 (firewall's Ethernet interface) port 8080.
Private Network: Transparent ProxiesIn this scenario, packets from the private network never traverse the Internet, and vice versa. The IP addresses of the private network should be assigned from the RFC1918 Address Allocation for Private Internets (ie. 10.*.*.*, 172.16.*.*-172.31.*.* or 192.168.*.*).
The only way things ever connect to the Internet is by connecting to the firewall, which is the only machine on both networks, which connects onwards. You run a program (on the firewall) called a transparent proxy to do this; the kernel sends outgoing packets to the transparent proxy instead of sending them onwards (ie. it bastardizes routing).
Transparent proxying means that the clients don't need to know there is a proxy involved.
Any services you wish the Internet to access must be on the firewall. (But see Limited Internal Services below).
Example: Allowing web access from private network to the Internet.
Netscape on myhost reads http://slashdot.org.
ie. From slashdot.org's point of view, the connection is made from 1.2.3.4 (firewall's PPP interface) port 1025 to 207.218.152.131 (slashdot.org) port 80. From myhost's point of view, the connection is made from 192.168.1.100 (myhost) port 1050, to 207.218.152.131 (slashdot.org) port 80, but it's actually talking to the transparent proxy.
Private Network: MasqueradingIn this scenario, packets from the private network never traverse the Internet without special treatment, and vice versa. The IP addresses of the private network should be assigned from the RFC1918 Address Allocation for Private Internets (ie. 10.*.*.*, 172.16.*.*-172.31.*.* or 192.168.*.*).
Instead of using a proxy, we use a special kernel facility called "masquerading". Masquerading rewrites packets as they pass through the firewall, so that they always seem to come from the firewall itself. It then rewrites the responses so that they look like they are going to the original recipient.
Masquerading has separate modules to handle "tricky" protocols, such as FTP, RealAudio, Quake, etc. For really hard-to-handle protocols, the "auto forwarding" facility can handle some of them by automatically setting up port forwarding for related sets of ports: look for ``ipportfw'' (2.0 kernels) or ``ipmasqadm'' (2.1 kernels).
Any services you wish the Internet to access must be on the firewall. (But see Limited Internal Services below).
Example: Allowing web access from private network to the Internet.
Netscape on myhost reads http://slashdot.org.
ie. From the slashdot.org's point of view, the connection is made from 1.2.3.4 (firewall's PPP interface) port 65000 to 207.218.152.131 (slashdot.org) port 80. From the myhost's point of view, the connection is made from 192.168.1.100 (myhost) port 1050, to 207.218.152.131 (slashdot.org) port 80.
Public NetworkIn this scenario, your personal network is a part of the Internet: packets can flow without change across both networks. The IP addresses of the internal network must be assigned by applying for a block of IP addresses, so the rest of the network will know how to get packets to you. This implies a permanent connection.
In this role, packet filtering is used to restrict which packets can be forwarded between your network and the rest of the Internet, eg. to restrict the rest of the Internet to only accessing your internal web servers.
Example: Allowing web access from private network to the Internet.
Netscape on myhost reads http://slashdot.org.
ie. There is only one connection: from 1.2.3.100 (myhost) port 1050, to 207.218.152.131 (slashdot.org) port 80.
Limited Internal ServicesThere are a few tricks you can pull to allow the Internet to access your internal services, rather than running the services on the firewall. These will work with either a proxy or masquerading based approach for external connections.
The simplest approach is to run a "redirector", which is a poor-man's proxy which waits for a connection on a given port, and then open a connection a fixed internal host and port, and copies data between the two connections. An example of this is the "redir" program. From the Internet point of view, the connection is made to your firewall. From your internal server's point of view, the connection is made from the internal interface of the firewall to the server.
Another approach (which requires a 2.0 kernel patched for ipportfw, or a 2.1 or later kernel) is to use port forwarding in the kernel. This does the same job as "redir" in a different way: the kernel rewrites packets as they pass through, changing their destination address and ports to point them at an internal host and port. From the Internet's point of view, the connection is made to your firewall. From your internal server's point of view, a direct connection is made from the Internet host to the server.
3.4 More Information on MasqueradingDavid Ranch has written an excellent new HOWTO on Masquerading, which has a large amount of overlap with this HOWTO. You can currently find that HOWTO at http://www.linuxdoc.org/HOWTO/IP-Masquerade-HOWTO.html
The official Masquerading home page is at
4. IP Firewalling ChainsThis section describes all you really need to know to build a packet filter that meets your needs.
4.1 How Packets Traverse The FiltersThe kernel starts with three lists of rules; these lists are called
firewall chains or just chains. The three chains are
called input, output and forward. When a packet comes
in (say, through the Ethernet card) the kernel uses the
A chain is a checklist 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 policy to decide what to do. In a security-conscious system, this policy usually tells the kernel to reject or deny the packet.
For ASCII-art fans, this shown the complete path of a packet coming into a machine.
---------------------------------------------------------------- | ACCEPT/ lo interface | v REDIRECT _______ | --> C --> S --> ______ --> D --> ~~~~~~~~ -->|forward|----> _______ --> h a |input | e {Routing } |Chain | |output |ACCEPT e n |Chain | m {Decision} |_______| --->|Chain | c i |______| a ~~~~~~~~ | | ->|_______| k t | s | | | | | s y | q | v | | | u | v e v DENY/ | | v m | DENY/ r Local Process REJECT | | DENY/ | v REJECT a | | | REJECT | DENY d --------------------- | v e ----------------------------- DENYHere is a blow-by-blow description of each stage:
Using ipchainsFirst, check that you have the version of ipchains that this document refers to:
Note that I recommend 1.3.4 (which has no long options, like `--sport'), or 1.3.8 or above; these are very stable.
ipchains has a fairly detailed manual page (
There is also an excellent quick reference card by Scott Bronson in the source package, in both A4 and US Letter PostScript(TM).
There are several different things you can do with
There are several ways to manipulate rules inside a chain:
There are a few operations for masquerading, which are in
The final (and perhaps the most useful) function allows you to check what would happen to a given packet if it were to traverse a given chain.
What You'll See When Your Computer Starts UpBefore any ipchains commands have been run (be careful: some distributions run ipchains in their initialization scripts), there will be no rules in any of the built-in chains (`input', `forward' and `output'), and each of the chains will have a policy of ACCEPT. This is as wide-open as you can get.
Operations on a Single RuleThis is the bread-and-butter of ipchains; manipulating rules. Most commonly, you will probably use the append (-A) and delete (-D) commands. The others (-I for insert and -R for replace) are simple extensions of these concepts.
Each rule specifies a set of conditions the packet must meet, and what to do if it meets them (a `target'). For example, you might want to deny all ICMP packets coming from the IP address 127.0.0.1. So in this case our conditions are that the protocol must be ICMP and that the source address must be 127.0.0.1. Our target is `DENY'.
127.0.0.1 is the `loopback' interface, which you will have even if you have no real network connection. You can use the `ping' program to generate such packets (it simply sends an ICMP type 8 (echo request) which all cooperative hosts should obligingly respond to with an ICMP type 0 (echo reply) packet). This makes it useful for testing.
You can see here that the first ping succeeds (the `-c 1' tells ping to only send a single packet).
Then we append (-A) to the `input' chain, a rule specifying that for packets from 127.0.0.1 (`-s 127.0.0.1') with protocol ICMP (`-p ICMP') we should jump to DENY (`-j DENY').
Then we test our rule, using the second ping. There will be a pause before the program gives up waiting for a response that will never come.
We can delete the rule in one of two ways. Firstly, since we know that it is the only rule in the input chain, we can use a numbered delete, as in:
To delete rule number 1 in the input chain.
The second way is to mirror the -A command, but replacing the -A with -D. This is useful when you have a complex chain of rules and you don't want to have to count them to figure out that it's rule 37 that you want to get rid of. In this case, we would use:
The syntax of -D must have exactly the same options as the -A (or -I
or -R) command. If there are multiple identical rules in the same
chain, only the first will be deleted.
Filtering SpecificationsWe have seen the use of `-p' to specify protocol, and `-s' to specify source address, but there are other options we can use to specify packet characteristics. What follows is an exhaustive compendium.
Specifying Source and Destination IP AddressesSource (-s) and destination (-d) IP addresses can be specified in four ways. The most common way is to use the full 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, such as `199.95.207.0/24' or `199.95.207.0/255.255.255.0'. These both specify any IP address from 199.95.207.0 to 199.95.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 (match all of the IP address). To specify any IP address at all `/0' can be used, like so:
This is rarely used, as the effect above is the same as not specifying the `-s' option at all.
Specifying InversionMany flags, including the `-s' and `-d' flags 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.
Don't forget the spaces around the `!': they really are needed.
Specifying ProtocolThe protocol can be specified with the `-p' 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'.
The protocol name can be prefixed by a `!', to invert it, such as `-p ! TCP'.
Specifying UDP and TCP PortsFor the special case where a protocol of TCP or UDP is specified, there can be an extra argument indicating the TCP or UDP port, or an (inclusive) range of ports (but see Handling Fragments below). A range is represented using a `:' character, such as `6000:6010', which covers 11 port numbers, from 6000 to 6010 inclusive. If the lower bound is omitted, it defaults to 0. If the upper bound is omitted, it defaults to 65535. So to specify TCP connections coming from ports under 1024, the syntax would be as `-p TCP -s 0.0.0.0/0 :1023'. Port numbers can be specified by name, eg. `www'.
Note that the port specification can be preceded by a `!', which inverts it. So to specify every TCP packet BUT a WWW packet, you would specify -p TCP -d 0.0.0.0/0 ! www It is important to realize that the specification
-p TCP -d ! 192.168.1.1 www is very different from -p TCP -d 192.168.1.1 ! www The first specifies any TCP packet to the WWW port on any machine but 192.168.1.1. The second specifies any TCP connection to any port on 192.168.1.1 but the WWW port.
Finally, this case means not the WWW port and not 192.168.1.1: -p TCP -d ! 192.168.1.1 ! www
Specifying ICMP Type and CodeICMP also allows an optional argument, but as ICMP doesn't have ports, (ICMP has a type and a code) they have a different meaning.
You can specify them as ICMP names (use
The ICMP names are fairly long: you only need use enough letters to make the name distinct from any other.
Here is a small table of some of the most common ICMP packets:
Note that the ICMP names cannot be preceeded by `!' at the moment.
DO NOT DO NOT DO NOT block all ICMP type 3 messages! (See ICMP Packets below).
Specifying an InterfaceThe `-i' option specifies the name of an interface to match. An
interface is the physical device the packet came in on, or is going
out on. You can use the
The interface for incoming packets (ie. packets traversing the
It is perfectly legal to specify an interface that currently does not
exist; the rule will not match anything until the interface comes up.
This is extremely useful for dial-up PPP links (usually interface
As a special case, an interface name ending with a `+' will match all
interfaces (whether they currently exist or not) which begin with that
string. For example, to specify a rule which matches all PPP
interfaces, the
The interface name can be preceded by a `!' to match a packet which does NOT match the specified interface(s).
Specifying TCP SYN Packets OnlyIt is sometimes useful to allow TCP connections in one direction, but not the other. For example, you might want to allow connections to an external WWW server, but not connections from that server.
The naive approach would be to block TCP packets coming from the server. Unfortunately, TCP connections require packets going in both directions to work at all.
The solution is to block only the packets used to request a connection. These packets are called SYN packets (ok, technically they're packets with the SYN flag set, and the FIN and ACK flags cleared, but we call them SYN packets). By disallowing only these packets, we can stop attempted connections in their tracks.
The `-y' flag is used for this: it is only valid for rules which specify TCP as their protocol. For example, to specify TCP connection attempts from 192.168.1.1: -p TCP -s 192.168.1.1 -y
Once again, this flag can be inverted by preceding it with a `!', which means every packet other than the connection initiation.
Handling FragmentsSometimes a packet is too large to fit down a wire all at once. When this happens, the packet is divided into fragments, and sent as multiple packets. The other end reassembles the fragments to reconstruct the whole packet.
The problem with fragments is that some of the specifications listed above (in particular, source port, destinations port, ICMP type, ICMP code, or TCP SYN flag) require the kernel to peek at the start of the packet, which is only contained in the first fragment.
If your machine is the only connection to an external network, then
you can tell the Linux kernel to reassemble all fragments which pass
through it, by compiling the kernel with
Otherwise, it is important to understand how fragments get treated by
the filtering rules. Any filtering rule that asks for information we
don't have will not match. This means that the first fragment is
treated like any other packet. Second and further fragments won't be.
Thus a rule
However, you can specify a rule specifically for second and further fragments, using the `-f' flag. Obviously, it is illegal to specify a TCP or UDP port, ICMP type, ICMP code or TCP SYN flag in such a fragment rule.
It is also legal to specify that a rule does not apply to second and further fragments, by preceding the `-f' with `!'.
Usually it is regarded as safe to let second and further fragments through, since filtering will effect the first fragment, and thus prevent reassembly on the target host, however, bugs have been known to allow crashing of machines simply by sending fragments. Your call.
Note for network-heads: malformed packets (TCP, UDP and ICMP packets too short for the firewalling code to read the ports or ICMP code and type) are treated as fragments as well. Only TCP fragments starting at position 8 are explicitly dropped by the firewall code (a message should appear in the syslog if this occurs).
As an example, the following rule will drop any fragments going to 192.168.1.1:
Filtering Side EffectsOK, so now we know all the ways we can match a packet using a rule. If a packet matches a rule, the following things happen:
For variety, I'll address these in order of importance.
Specifying a TargetA target tells the kernel what to do with a packet that matches a rule. ipchains uses `-j' (think `jump-to') for the target specification. The target name must be less than 8 letters, and case matters: "RETURN" and "return" are completely different.
The simplest case is when there is no target specified. This type of rule (often called an `accounting' rule) is useful for simply counting a certain type of packet. Whether this rule matches or not, the kernel simply examines the next rule in the chain. For example, to count the number of packets from 192.168.1.1, we could do this:
(Using `ipchains -L -v' we can see the byte and packet counters associated with each rule).
There are six special targets. The first three,
The next one,
The other major special target is
The final special target is
Any other target indicates a user-defined chain (as described in Operations on an Entire Chain below). The packet will begin traversing the rules in that chain. If that chain doesn't decide the fate of the packet, then once traversal on that chain has finished, traversal resumes on the next rule in the current chain.
Time for more ASCII art. Consider two (silly) chains:
`input' `Test' ---------------------------- ---------------------------- | Rule1: -p ICMP -j REJECT | | Rule1: -s 192.168.1.1 | |--------------------------| |--------------------------| | Rule2: -p TCP -j Test | | Rule2: -d 192.168.1.1 | |--------------------------| ---------------------------- | Rule3: -p UDP -j DENY | ----------------------------
Consider a TCP packet coming from 192.168.1.1, going to 1.2.3.4. It
enters the
So the packet path is: v __________________________ `input' | / `Test' v ------------------------|--/ -----------------------|---- | Rule1 | /| | Rule1 | | |-----------------------|/-| |----------------------|---| | Rule2 / | | Rule2 | | |--------------------------| -----------------------v---- | Rule3 /--+___________________________/ ------------------------|--- v
See the section How to Organise Your Firewall Rules for ways to use user-defined chains effectively.
Logging PacketsThis is a side effect that matching a rule can have; you can have the matching packet logged using the `-l' flag. You will usually not want this for routine packets, but it is a useful feature if you want to look for exceptional events.
The kernel logs this information looking like:
This log message is designed to be terse, and contain technical information useful only to networking gurus, but it can be useful to the rest of us. It breaks down like so:
On standard Linux systems, this kernel output is captured by klogd (the kernel logging daemon) which hands it to syslogd (the system logging daemon). The `/etc/syslog.conf' controls the behaviour of syslogd, by specifying a destination for each `facility' (in our case, the facility is "kernel") and `level' (for ipchains, the level used is "info").
For example, my (Debian) /etc/syslog.conf contains two lines which match `kern.info':
These mean that the messags are duplicated in `/var/log/kern.log' and `/var/log/messages'. For more details, see `man syslog.conf'.
Manipulating the Type Of ServiceThere are four seldom-used bits in the IP header, called the Type of Service (TOS) bits. They effect the way packets are treated; the four bits are "Minimum Delay", "Maximum Throughput", "Maximum Reliability" and "Minimum Cost". Only one of these bits is allowed to be set. Rob van Nieuwkerk, the author of the TOS-mangling code, puts it as follows:
Especially the "Minimum Delay" is important for me. I switch it on for "interactive" packets in my upstream (Linux) router. I'm behind a 33k6 modem link. Linux prioritizes packets in 3 queues. This way I get acceptable interactive performance while doing bulk downloads at the same time. (It could even be better if there wasn't such a big queue in the serial driver, but latency is kept down 1.5 seconds now).
Note: obviously, you have no control over incoming packets; you can only control the priority of packets leaving your box. To negotiate priorities with the other end, a protocol like RSVP (which I know nothing about, so don't ask me) must be used.
The most common use is to set telnet & ftp control connections to "Minimum Delay" and FTP data to "Maximum Throughput". This would be done as follows:
The `-t' flag takes two extra parameters, both in hexadecimal. These allow complex twiddling of the TOS bits: the first mask is ANDed with the packet's current TOS, and then the second mask is XORed with it. If this is too confusing, just use the following table:
Andi Kleen goes on to point out the following (mildly edited for posterity): Maybe it would be useful to add an reference to the txqueuelen parameter of ifconfig to the discussion of TOS bits. The default device queue length is tuned for ethernet cards, on modems it is too long and makes the 3 band scheduler (which queues based on TOS) work suboptimally. It is a good idea to set it to a value between 4-10 on modem or single b channel ISDN links: on bundled devices a longer queue is needed. This is a 2.0 and 2.1 problem, but in 2.1 it is a ifconfig flag (with recent nettools), while in 2.0 it requires source patches in the device drivers to change. So, to see maximal benifits of TOS manipulation for modem PPP links, do `ifconfig $1 txqueuelen' in your /etc/ppp/ip-up script. The number to use depends on the modem speed and the amount of buffering in the modem; here's Andi setting me straight again:
The best value for a given configuration needs experiment. If the queues are too short on a router then packets will get dropped. Also of course one gets benefits even without TOS rewriting, just that TOS rewriting helps to give the benefits to non cooperating programs (but all standard linux programs are cooperating).
Marking a PacketThis allows complex and powerful interactions with Alexey Kuznetsov's new Quality of Service implementation, as well as the mark-based forwarding in later 2.1 series kernels. More news as it comes to hand. This option is ignored altogether in the 2.0 kernel series.
Operations on an Entire ChainA very useful feature of ipchains is the ability to group related
rules into chains. You can call the chains whatever you want, as long
as the names don't clash with the built-in chains (
Creating a New ChainLet's create a new chain. Because I am such an imaginative fellow,
I'll call it
It's that simple. Now you can put rules in it as detailed above.
Deleting a ChainDeleting a chain is simple as well.
Why `-X'? Well, all the good letters were taken.
There are a couple of restrictions to deleting chains: they must be empty (see Flushing a Chain below) and they must not be the target of any rule. You can't delete any of the three built-in chains.
Flushing a ChainThere is a simple way of emptying all rules out of a chain, using the `-F' command.
If you don't specify a chain, then all chains will be flushed.
Listing a ChainYou can list all the rules in a chain by using the `-L' command.
The `refcnt' listed for
If the chain name is omitted, all chains are listed, even empty ones.
There are three options which can accompany `-L'. The `-n' (numeric)
option is very useful as it prevents
The `-v' options shows you all the details of the rules, such as the the packet and byte counters, the TOS masks, the interface, and the packet mark. Otherwise these values are omitted. For example:
Note that the packet and byte counters are printed out using the suffixes `K', `M' or `G' for 1000, 1,000,000 and 1,000,000,000 respectively. Using the `-x' (expand numbers) flag as well prints the full numbers, no matter how large they are.
Resetting (Zeroing) CountersIt is useful to be able to reset the counters. This can be done with the `-Z' (zero counters) option. For example:
The problem with this approach is that sometimes you need to know the counter values immediately before they are reset. In the above example, some packets could pass through between the `-L' and `-Z' commands. For this reason, you can use the `-L' and `-Z' together, to reset the counters while reading them. Unfortunately, if you do this, you can't operate on a single chain: you have to list and zero all the chains at once.
Setting PolicyWe glossed over what happens when a packet hits the end of a built-in
chain when we discussed how a packet walks through chains in
Specifying a Target above. In this case,
the policy of the chain determines the fate of the packet. Only
built-in chains (
The policy can be any of the first four special targets:
It is also important to note that a
Operations on MasqueradingThere are several parameters you can tweak for IP Masquerading. They
are bundled with
The IP Masquerading command is `-M', and it can be combined with `-L' to list currently masqueraded connections, or `-S' to set the masquerading parameters.
The `-L' command can be accompanied by `-n' (show numbers instead of hostnames and port names) or `-v' (show deltas in sequence numbers for masqueraded connection, just in case you care).
The `-S' command should be followed by three timeout values, each in seconds: for TCP sessions, for TCP sessions after a FIN packet, and for UDP packets. If you don't want to change one of these values, simply give a value of `0'.
The default values are listed in `/usr/src/linux/include/net/ip_masq.h', currently 15 minutes, 2 minutes and 5 minutes respectively.
The most common value to change is the first one, for FTP (see FTP Nightmares below).
Note the problems with setting timeouts listed in I can't set masquerading timeouts!.
Checking a PacketSometimes you want to see what happens when a certain packet enters
your machine, such as for debugging your firewall chains.
You specify which chain to test the packet on by following the `-C'
argument with its name. Whereas the kernel always starts traversing
on the
The details of the `packet' are specified using the same syntax used to specify firewall rules. In particular, a protocol (`-p'), source address (`-s'), destination address (`-d') and interface (`-i') are compulsory. If the protocol is TCP or UDP, then a single source and a single destination port must be specified, and a ICMP type and code must be specified for the ICMP protocol (unless the `-f' flag is specified to indicate a fragment rule, in which case these options are illegal).
If the protocol is TCP (and the `-f' flag is not specified), the `-y' flag may be specified, to indicate that the test packet should have the SYN bit set.
Here is an example of testing a TCP SYN packet from 192.168.1.1 port 60000 to 192.168.1.2 port www, coming in the eth0 interface, entering the `input' chain. (This is a classic incoming WWW connection initiation):
Multiple Rules at Once and Watching What HappensSometimes a single command line can result in multiple rules being
effected. This is done in two ways. Firstly, if you specify a
hostname which resolves (using DNS) to multiple IP addresses,
So if the hostname `www.foo.com' resolves to three IP addresses, and
the hostname `www.bar.com' resolves to two IP addresses, then the
command `ipchains -A input -j reject -s www.bar.com -d www.foo.com'
would append six rules to the
The other way to have
Personally, I don't like the `-b' option much; if you want convenience, see Using ipchains-save below.
The -b option can be used with the insert (`-I'), delete (`-D') (but not the variation which takes a rule number), append (`-A') and check (`-C') commands.
Another useful flag is `-v' (verbose) which prints out exactly what
4.2 Useful ExamplesI have a dialup PPP connection (
I don't mind people trying to ftp to my machine while I'm online
(
This setup is fairly simple, because there are currently no other boxes on my internal network.
I don't want any local process (ie. Netscape, lynx etc.) to connect to doubleclick.net:
Now I want to set priorities on various outgoing packets (there isn't
much point in doing it on incoming packets). Since I have a fair
number of these rules, it makes sense to put them all in a single
chain, called
Minimum delay for web traffic & telnet.
Low cost for ftp data, nntp, pop-3:
There are a few restrictions on packets coming in the ppp0 interface: let's create a chain called `ppp-in':
Now, no packets coming in
I allow UDP packets in for DNS (I run a caching nameserver which forwards all requests to 203.29.16.1, so I expect DNS replies from them only), incoming ftp, and return ftp-data only (which should only be going to a port above 1023, and not the X11 ports around 6000).
I allow TCP reply packets back in
Finally, local-to-local packets are OK:
Now, my default policy on the
NOTE: I wouldn't set up my chains in this order, as packets might get through while I'm setting up. Safest is usually to set the policy to DENY first, then insert the rules. Of course, if your rules require DNS lookups to resolve hostnames, you could be in trouble.
Using ipchains-saveSetting up firewall chains just the way you want them, and then trying to remember the commands you used so you can do them next time is a pain.
So,
Using ipchains-restore
If a user-defined chain is found in the input,
For example:
5. Miscellaneous.This section contains all the information and FAQs that I couldn't fit inside the structure above.
5.1 How to Organize Your Firewall RulesThis question requires some thought. You can try to organize them to optimize speed (minimize the number of rule-checks for the most common packets) or to increase manageability.
If you have an intermittent link, say a PPP link, you might want to
set the first rule in the input chain to be set to `-i ppp0 -j DENY' at
boot time, then have something like this in your
Your
5.2 What Not To Filter OutThere are some things you should be aware of before you start filtering out everything you don't want.
ICMP packetsICMP packets are used (among other things) to indicate failure for other protocols (such as TCP and UDP). `destination-unreachable' packets in particular. Blocking these packets means that you will never get `Host unreachable' or `No route to host' errors; any connections will just wait for a reply that never comes. This is irritating, but rarely fatal.
A worse problem is the role of ICMP packets in MTU discovery. All good TCP implementations (Linux included) use MTU discovery to try to figure out what the largest packet that can get to a destination without being fragmented (fragmentation slows performance, especially when occasional fragments are lost). MTU discovery works by sending packets with the "Don't Fragment" bit set, and then sending smaller packets if it gets an ICMP packet indicating "Fragmentation needed but DF set" (`fragmentation-needed'). This is a type of `destination-unreachable' packet, and if it is never received, the local host will not reduce MTU, and performance will be abysmal or non-existent.
Note that it is common to block all ICMP redirect messages (type 5); these can be used to manipulate routing (although good IP stacks have safeguards), and so are often seen as slightly risky.
TCP Connections to DNS (nameservers)If you're trying to block outgoing TCP connections, remember that DNS doesn't always use UDP; if the reply from the server exceeds 512 bytes, the client uses a TCP connection (still going to port number 53) to get the data.
This can be a trap because DNS will `mostly work' if you disallow such TCP transfers; you may experience strange long delays and other occasional DNS problems if you do.
If your DNS queries are always directed at the same external source
(either directly by using the
FTP NightmaresThe classic packet filtering problem is FTP. FTP has two modes; the traditional one is called active mode and the more recent one is called passive mode. Web browsers usually default to passive mode, but command-line FTP programs usually default to active mode.
In active mode, when the remote end wants to send a file (or even the
results of an
If you have the option of using passive mode, then fine; passive mode makes data connections from client to server, even for incoming data. Otherwise, it is recommended that you only allow TCP connections to ports above 1024 and not between 6000 and 6010 (6000 is used for X-Windows).
5.3 Filtering out Ping of DeathLinux boxes are now immune to the famous Ping of Death, which involves sending an illegally-large ICMP packet which overflows buffers in the TCP stack on the receiver and causes havoc.
If you are protecting boxes which might be vulnerable, you could simply block ICMP fragments. Normal ICMP packets aren't large enough to require fragmentation, so you won't break anything except big pings. I have heard (unconfirmed) reports that some systems required only the last fragment of an oversize ICMP packet to corrupt them, so blocking only the first fragment is not recommended.
While the exploit programs I have seen all use ICMP, there is no reasons that TCP or UDP fragments (or an unknown protocol) could not be used for this attack, so blocking ICMP fragments is only a temporary solution.
5.4 Filtering out Teardrop and BonkTeardrop and Bonk are two attacks (mainly against Microsoft Windows NT machines) which rely on overlapping fragments. Having your Linux router do defragmentation, or disallowing all fragments to your vulnerable machines are the other options.
5.5 Filtering out Fragment BombsSome less-reliable TCP stacks are said to have problems dealing with large numbers of fragments of packets when they don't receive all the fragments. Linux does not have this problem. You can filter out fragments (which might break legitimate uses) or compile your kernel with `IP: always defragment' set to `Y' (only if your Linux box is the only possible route for these packets).
5.6 Changing Firewall RulesThere are some timing issues involved in altering firewall rules. If you are not careful, you can let packets through while you are half-way through your changes. A simplistic approach is to do the following:
This drops all packets for the duration of the changes.
If your changes are restricted to a single chain, you might want to create a new chain with the new rules, and then replace (`-R') the rule that pointed to the old chain with one that points to the new chain: then you can delete the old chain. This replacement will occur atomically.
5.7 How Do I Set Up IP Spoof Protection?IP spoofing is a technique where a host sends out packets which claim to be from another host. Since packet filtering makes decisions based on this source address, IP spoofing is uses to fool packet filters. It is also used to hide the identity of attackers using SYN attacks, Teardrop, Ping of Death and the like (don't worry if you don't know what they are).
The best way to protect from IP spoofing is called Source Address
Verification, and it is done by the routing code, and not firewalling
at all. Look for a file called
If you cannot do this, you can manually insert rules to protect every
interface. This requires knowledge of each interface. The 2.1
kernels automatically reject packets claiming to come from the 127.*
addresses (reserved for the local loopback interface,
For example, say we have three interfaces,
This approach is not as good as the Source Address Verification approach, because if your network changes, you have to change your firewalling rules to keep up.
If you are running a 2.0 series kernel, you might want to protect the loopback interface as well, using a rule like this:
5.8 Advanced ProjectsThere is a userspace library I have written which is included with the source distribution called `libfw'. It uses the ability of IP Chains 1.3 and above to copy a packet to userspace (using the IP_FIREWALL_NETLINK config option).
The mark value can be used to specify the Quality of Service parameters for packets, or to specify how packets should be port-forwarded. I've never used either, but if you want to write about it, please contact me.
Things such as stateful inspection (I prefer the term dynamic firewalling) can be implemented in userspace using this library. Other nifty ideas include controlling packets on a per-user basis by doing a lookup in a userspace daemon. This should be pretty easy.
SPF: Stateful Packet Filteringftp://ftp.interlinx.bc.ca/pub/spf is the site of Brian Murrell's SPF project, which does connection tracking in userspace. It adds significant security for low-bandwidth sites.
There's little documentation at present, but here's a post to the mailing list in which Brian answered some questions:
Michael Hasenstein's ftp-data hackMichael Hasenstein of SuSE has written a kernel patch which adds ftp connection tracking to ipchains. It can currently be found at http://www.suse.de/~mha/patch.ftp-data-2.gz
5.9 Future EnhancementsFirewalling and NAT have being redesigned for 2.4. Plans and discussions are available on the netfilter list (see http://lists.samba.org). These enhancements should clear up many outstanding usability issues (really, firewalling and masquerading shouldn't be this hard), and allow growth for far more flexible firewalling.
6. Common Problems
6.1 ipchains -L Freezes!You're probably blocking DNS lookups; it will eventually time out. Try using the `-n' (numeric) flag to ipchains, which suppresses the lookup of names.
6.2 Inverse doesn't work!You must put the `!' option by itself, with spaces either side. A classic mistake (warned about in 1.3.10) is:
There will never be an interface called `!eth0', but ipchains doesn't know that.
6.3 Masquerading/Forwarding Doesn't Work!Make sure that packet forwarding is enabled (in recent kernels it is disabled by default, meaning that packets never even try to traverse the `forward' chain). You can override this (as root) by typing
If this works for you, you can put this somewhere in your bootup scripts so it is enabled every time; you'll want to set up your firewalling before this command runs though, otherwise there's an opportunity for packets to slip through.
6.4 -j REDIR doesn't work!You must allow forwarding packets (see above) for redirect to work; otherwise the routing code drops the packet. So if you are just using redirect, and don't have any forwarding at all, you should be aware of that.
Note that REDIR (being in the input chain) doesn't effect connections from a local process.
6.5 Wildcard Interfaces Don't Work!There was a bug in versions 2.1.102 and 2.1.103 of the kernel (and
some old patches I produced) which made ipchains commands which
specified a wildcard interface (such as
This is fixed in recent kernels, and in the 2.0.34 patch on the web site. You can also fix it by hand in the kernel source by changing line 63 or so in include/linux/ip_fw.h:
This should read ``0x003F''. Fix this and recompile the kernel.
6.6 TOS Doesn't Work!This was my mistake: setting the Type of Service field did not actually set the Type of Service in kernel versions 2.1.102 through 2.1.111. This problem was fixed in 2.1.112.
6.7 ipautofw and ipportfw Don't Work!For 2.0.x, this is true; I haven't time to create and maintain a jumbo patch for ipchains and ipautofw/ipportfw.
For 2.1.x, download Juan Ciarlante's ipmasqadm from <url url="http://juanjox.linuxhq.com/" name="http://juanjox.linuxhq.com/">and use it exactly as you would have used ipautofw or
ipportfw , except instead of ipportfw you type ipmasqadm
portfw , and instead of ipautofw you type ipmasqadm autofw .
6.8 xosview is Broken!Upgrade to version 1.6.0 or above, which doesn't require any firewall rules at all for 2.1.x kernels. This seems to have broken again in the 1.6.1 release; please bug the author (it's not my fault!).
6.9 Segmentation Fault With `-j REDIRECT'!This was a bug in ipchains version 1.3.3. Please upgrade.
6.10 I Can't Set Masquerading Timeouts!True (for 2.1.x kernels) up to 2.1.123. In 2.1.124, trying to set the
masquerading timeouts causes a kernel lockup (change
6.11 I Want to Firewall IPX!So do a number of others, it seems. My code only covers IP, unfortunately. On the good side, all the hooks are there to firewall IPX! You just need to write the code; I will happily help where possible.
7. A Serious Example.This example was extracted from Michael Neuling and my March 1999 LinuxWorld Tutorial; this is not the only way to solve the given problem, but it is probably the simplest. I hope you will find it informative.
7.1 The Arrangement
7.2 Goals
Packet Filter box:
Within the DMZ:
Mail server
Name Server
Web server
Internal:
7.3 Before Packet Filtering
7.4 Packet Filtering for Through PacketsWith masquerading, it's best to filter in the forward chain.
Split forward chain into various user chains depending on source/dest interfaces; this breaks the problem down into managable chunks.
ACCEPTing standard error ICMPs is a common thing to do, so we create a chain for it.
Set Up Jumps From forward ChainUnfortunately, we only know (in the forward chain) the outgoing interface. Thus, to figure out what interface the packet came in on, we use the source address (the anti-spoofing prevents address faking).
Note that we log anything which doesn't match any of these (obviously, this should never happen).
Define the icmp-acc ChainPackets which are one of the error ICMPs get ACCEPTed, otherwise, control will pass back to the calling chain.
Good (Internal) to DMZ (Servers)Internal restrictions:
Could do masquerading from internal network into DMZ, but here we don't. Since noone in the internal network should be trying to do evil things, we log any packets that get denied.
Note that old versions of Debian called `pop3' `pop-3' in /etc/services, which disagrees with RFC1700.
Bad (external) to DMZ (servers).
Good (internal) to Bad (external).
DMZ to Good (internal).
DMZ to bad (external).
Bad (external) to Good (internal).
Packet Filtering for the Linux Box Itself
Bad (external) interface.
DMZ interface.
Good (internal) interface.
7.5 Finally
8. Appendix: Differences between ipchains and ipfwadm.Some of these changes are a result of kernel changes, and some a
result of
8.1 Quick-Reference table.[ Mainly, command arguments are UPPER CASE, and option arguments are lower case ]
One thing to note, masquerading is specified by `-j MASQ'; it is
completely different from `-j ACCEPT', and not treated as merely a
side-effect, unlike
================================================================ | ipfwadm | ipchains | Notes ---------------------------------------------------------------- | -A [both] | -N acct | Create an `acct' chain | |& -I 1 input -j acct | and have output and input | |& -I 1 output -j acct | packets traverse it. | |& acct | ---------------------------------------------------------------- | -A in | input | A rule with no target ---------------------------------------------------------------- | -A out | output | A rule with no target ---------------------------------------------------------------- | -F | forward | Use this as [chain]. ---------------------------------------------------------------- | -I | input | Use this as [chain]. ---------------------------------------------------------------- | -O | output | Use this as [chain]. ---------------------------------------------------------------- | -M -l | -M -L | ---------------------------------------------------------------- | -M -s | -M -S | ---------------------------------------------------------------- | -a policy | -A [chain] -j POLICY | (but see -r and -m). ---------------------------------------------------------------- | -d policy | -D [chain] -j POLICY | (but see -r and -m). ---------------------------------------------------------------- | -i policy | -I 1 [chain] -j POLICY| (but see -r and -m). ---------------------------------------------------------------- | -l | -L | ---------------------------------------------------------------- | -z | -Z | ---------------------------------------------------------------- | -f | -F | ---------------------------------------------------------------- | -p | -P | ---------------------------------------------------------------- | -c | -C | ---------------------------------------------------------------- | -P | -p | ---------------------------------------------------------------- | -S | -s | Only takes one port or | | | range, not multiples. ---------------------------------------------------------------- | -D | -d | Only takes one port or | | | range, not multiples. ---------------------------------------------------------------- | -V | <none> | Use -i [name]. ---------------------------------------------------------------- | -W | -i | ---------------------------------------------------------------- | -b | -b | Now actually makes 2 rules. ---------------------------------------------------------------- | -e | -v | ---------------------------------------------------------------- | -k | ! -y | Doesn't work unless | | | -p tcp also specified. ---------------------------------------------------------------- | -m | -j MASQ | ---------------------------------------------------------------- | -n | -n | ---------------------------------------------------------------- | -o | -l | ---------------------------------------------------------------- | -r [redirpt] | -j REDIRECT [redirpt] | ---------------------------------------------------------------- | -t | -t | ---------------------------------------------------------------- | -v | -v | ---------------------------------------------------------------- | -x | -x | ---------------------------------------------------------------- | -y | -y | Doesn't work unless | | | -p tcp also specified. ----------------------------------------------------------------
8.2 Examples of translated ipfwadm commandsOld command: ipfwadm -F -p deny New command: ipchains -P forward DENY
Old command: ipfwadm -F -a m -S 192.168.0.0/24 -D 0.0.0.0/0 New command: ipchains -A forward -j MASQ -s 192.168.0.0/24 -d 0.0.0.0/0
Old command: ipfwadm -I -a accept -V 10.1.2.1 -S 10.0.0.0/8 -D 0.0.0.0/0 New command: ipchains -A input -j ACCEPT -i eth0 -s 10.0.0.0/8 -d 0.0.0.0/0 (Note that there is no equivalent for specifying interfaces by address: use the interface name. On this machine, 10.1.2.1 corresponds to eth0).
9. Appendix: Using the ipfwadm-wrapper script.The
The only feature it can't really handle is the `-V' option. When this
is used, a warning is given. If the `-W' option is also used, the
`-V' option is ignored. Otherwise, the script tries to find the
interface name associated with that address, using
This warning can be suppressed by either changing the `-V' to a `-W', or directing the standard output of the script to /dev/null.
If you should find any mistakes in this script, or any changes between
the real ipfwadm and this script, please report a bug to me: send
an EMail to rusty@linuxcare.com with "BUG-REPORT" in the subject.
Please list your old version of
Mix
10. Appendix: Thanks.Many thanks have to go to Michael Neuling, who wrote the first releasable cut of the IP chains code while working for me. Public apologies for nixing his result-caching idea, which Alan Cox later proposed and I have finally begun implementing, having seen the error of my ways.
Thanks to Alan Cox for his 24-hour EMail tech support, and encouragement.
Thanks to all the authors of the ipfw and ipfwadm code, especially Jos Vos. Standing on the shoulders of giants and all that... This applies to Linus Torvalds and all the kernel and userspace hackers as well.
Thanks to the diligent beta testers and bughunters, especially Jordan Mendelson, Shaw Carruthers, Kevin Moule, Dr. Liviu Daia, Helmut Adams, Franck Sicard, Kevin Littlejohn, Matt Kemner, John D. Hardin, Alexey Kuznetsov, Leos Bitto, Jim Kunzman, Gerard Gerritsen, Serge Sivkov, Andrew Burgess, Steve Schmidtke, Richard Offer, Bernhard Weisshuhn, Larry Auton, Ambrose Li, Pavel Krauz, Steve Chadsey, Francesco Potorti`, Alain Knaff, Casper Boden-Cummins and Henry Hollenberg.
10.1 TranslationsPeople who do translations should put themselves at the top of the Thanks page, like so: `Special thanks to XXX, for translating everything exactly from my English.'. Then tell me about your translation so I can include it here.
Arnaud Launay, asl@launay.org: http://www.freenix.fr/unix/linux/HOWTO/IPCHAINS-HOWTO.html
Giovanni Bortolozzo, borto@pluto.linux.it: http://www.pluto.linux.it/ildp/HOWTO/IPCHAINS-HOWTO.html
Herman Rodríguez, herman@maristas.dhis.org: http://netfilter.kernelnotes.org/ipchains/spanish/HOWTO.html
|
![]() |