Welcome to the TechSpot OpenBoards. Please read the FAQ if you have any questions. Login to participate.
|
|||||||
Setting up a firewall properly using Linux 2.4.x/2.6.x: a solution
![]() |
| Thread Tools |
|
#1
|
|||
|
|||
|
Setting up a firewall using Linux 2.4.x/2.6.x: a solution (and how iptables works)
Hello all,
Here is a solution using iptables in order to have a fully functional firewall. I'll first put in the commands themselves, and will explain in later posts why and how it works. The setup is the following: * the machine acts as a router for a local network with IP network/mask of 192.168.1.0/24, on eth0 ; * the interface is ppp0, its address is dynamic. Here goes, supposing that your iptables rules are blank: # # The central part of it - conntrack, ie stateful firewalling # iptables -N connstate iptables -A connstate -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A connstate -m state --state INVALID -j DROP iptables -A connstate -m state --state NEW -p tcp ! --syn -m limit --limit 2/sec -j LOG --log-prefix "NEWNOTSYN: " iptables -A connstate -m state --state NEW -p tcp ! --syn -j REJECT --reject-with tcp-reset iptables -A connstate -m state --state NEW -j RETURN iptables -A connstate -j LOG --log-level CRIT --log-prefix "CONNTRACK BARF: " iptables -A connstate -j DROP # # For all three filter chains: drop everything by default - first chain to go through is # connstate # for i in INPUT OUTPUT FORWARD; do iptables -P $i DROP iptables -A $i -j connstate done # # Deal with the loopback special case # iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT # # First, let's allow anything from the local machine to the local network # iptables -N local_to_eth0 iptables -A local_to_eth0 -j ACCEPT iptables -A OUTPUT -o eth0 -j local_to_eth0 # # Also allow anything from the local machine to the Internet # iptables -N local_to_ppp0 iptables -A local_to_ppp0 -j ACCEPT iptables -A OUTPUT -o ppp0 -j local_to_ppp0 # # Now, only allow some protocols (here, let's say SSH and ping only) from the local # network to the local machine # iptables -N eth0_to_local iptables -A eth0_to_local -p tcp --dport 22 -j ACCEPT iptables -A eth0_to_local -p icmp --icmp-type echo-request -j ACCEPT iptables -A INPUT -i eth0 -j eth0_to_local # # For the Internet, first thing is to masquerade our local network... Private IP # addresses cannot be routed on the Internet! # iptables -t nat -A POSTROUTING -o ppp+ -j MASQUERADE # # Now, packets that come from our local network and go to the Internet: accept # everything # iptables -N eth0_to_ppp0 iptables -A eth0_to_ppp0 -j ACCEPT iptables -A FORWARD -i eth0 -o ppp0 -j eth0_to_ppp0 # # END # Last edited by fgaliegue; 02-11-2006 at 01:35 PM. |
|
#2
|
|||
|
|||
|
Stateful firewalling, what it is
OK, how it works...
First of all, at the center of it all is the connstate table, which makes use of the ip_conntrack module. What this module does is stateful firewalling. What this means is that it keeps track of "connections" at large in a table, ie it knows whether a packet it receives belongs to an existing dialog. It puts packet in basically 4 categories:
Last edited by fgaliegue; 02-11-2006 at 02:54 PM. |
|
|
|
#3
|
|||
|
|||
|
Packet traversal
Now, it's time to delve a little in the core of the story, the netfilter architecture.
First of all, there are three tables defined as standard: the mangle table, the nat table and the filter table. When you don't specify which table to use (see option -t of iptables), the filter table is used by default. Each table has a number of chains associated with it. You can create new chains on the fly, however creating new tables requires a kernel module. The different chains traversed by a packet depends on where the packet comes from, and where it is supposed to go. There are three possible cases:
Note that the fact of being able to forward packets through interfaces is the act of routing. ARRIVAL OF A PACKET (I, F only) When a packet arrives through an interface, first of all it traverses these two chains: mangle/PREROUTING and nat/PREROUTING. After traversing these two chains, it reaches the point where the kernel has to decide where to route it. Hence the name (PREROUTING) of these two chains. This means that the nat/PREROUTING chain can influence the routing decision by modifying the destination address. We will see some uses of it. FIRST ROUTING DECISION (I, F only) From then on, the kernel looks at the destination address of the packet and determines one of two scenarios:
PACKETS ORIGINATING FROM THE MACHINE ITSELF (O only) For packets originating from the machine itself, three chains are traversed: filter/OUTPUT, nat/OUTPUT and mangle/OUTPUT. SECOND ROUTING DECISION (O, F only) From then on, and provided that the packet hasn't been dropped before, the kernel knows that this packet has to go outside. By looking at its routing table, it determines the correct interface and sends the packet there. AFTER SECOND ROUTING DECISION (O, F only) Nope, it's not ready to go yet. Before it reaches this point, it first has to go through the two last chains: nat/POSTROUTING and mangle/POSTROUTING. As their name says, these chains can alter packets just before they are actually sent to the wild and out of reach. The nat/POSTROUTING chain, in particular, can rewrite the source address of the packet before it is sent out. This is used in our basic firewall. We will see why. |
|
#4
|
|||
|
|||
|
How it really works
Now, let's see what happens when a machine from our local network, say 192.168.1.3, attempts a Web connection to www.google.com (66.102.9.147):
It is necessary to do so, as private IP addresses (defined in RFC 1918) CANNOT be routed on the Internet. OK, now the first packet is gone, let's see what happens when the response from www.google.com comes in:
Now you can see the power of stateful firewalling: provided you trigger the stateful functionality of your firewall BEFORE anything else, you only have to write the filtering rules ONE WAY. What's more, it's much, much more secure than writing the rules both ways, like ipchains required to do. Last edited by fgaliegue; 02-11-2006 at 02:57 PM. |
|
#5
|
|||
|
|||
|
Source NAT, destination NAT
Now let's explore a little more the NAT stuff.
We've seen one example of source NAT: the MASQUERADE target. There are others, however, such as SNAT for example. Provided you have a fixed IP address for your net connection and the interface used is eth1, you would use it like this: iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to x.y.z.t where x.y.z.t is the address of your eth1 interface. Why do both SNAT and MASQUERADE exist? Well, the MASQUERADE target has two fundamental differences: * it will look up each time the IP of the outgoing interface; * if the interface drops, it clears all connections using this interface from the conntrack table, unlike SNAT. In short, use MASQUERADE if your IP address on the Internet is dynamic, use SNAT otherwise. Now, an example of destination NAT. Say you want to play Diablo 2 from one of the machines in the LAN which has address 192.168.1.5. You want to be able to host games. Diablo 2 listens on port TCP/4000. Your net interface is ppp0. You'll need to do two things here:
Well, let's do it, starting with the filter table changes:
Done for the filter table changes. Now, the nat table changes: as written above, we want that any packet coming from interface ppp0 (our net interface), protocol TCP and destination port 4000, must see its destination address rewritten to 192.168.1.5. We have to use the PREROUTING table here, since this rewriting will influence the first kernel routing decision, and use the DNAT target, which does what we want (rewrite destination address): iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 4000 -j DNAT --to 192.168.1.5Done! Last edited by fgaliegue; 02-11-2006 at 09:08 AM. |
|
#6
|
||||
|
||||
|
Wow.. Someone actually bothers with this stuff in our days of point-and-click?
![]() A good read to anyone interested in the murky internals of iptables ![]() |
|
#7
|
|||
|
|||
|
Quote:
![]() This kind of firewall setup is used in production on all the servers I have to manage and it never failed on me. It failed ONCE however, at home, using [some kind of file sharing protocol], because the TCP connection lifespan is set to 5 days by default - my conntrack table was full (more than 120k entries!). Setting the lifespan to 12 hours instead cured the problem... But it's a limit to remember for very big systems. |
|
|
|
#8
|
|||
|
|||
|
Why the two last lines in the connstate table - and about fragments
You could very well ask, why on earth are these two last lines here in the connstate table:
After all, the rules above cover all the possible states, don't they? Well yes they do, but these two lines are here "just in case". The reason for them being logged with log level CRIT is so that the logged packet(s) be visible whatever way you're connected to the machine (distant or local connection). In case there is such a packet, you have found a bug in netfilter! These two rules actually never caught anything on any of the systems which have this kind of firewall in my case. But who knows, it may very well happen one day. In case there are, such packets are just dropped, you don't want them to reach anything, do you? Also, about fragments: a frequently used type of attack is sending packets in fragments - ie, the first packet contains only parts of the headers of the underlying protocol, the rest of the headers is in another; this kind of attack is frequently used to bypass firewalls. But you need not worry! The use of conntrack itself REQUIRES that packets be reassembled before they even get out of the interface from which they originate. Should a partial packet be seen and not completed in a delay determined at compile time (can't remember where it is defined though), it will be silently ignored by the kernel and removed from skbuffs (that's the structure holding network packets in Linux), therefore avoiding a memory DoS. Linux is actually very clever, come to think of it ![]() Last edited by fgaliegue; 02-11-2006 at 01:26 PM. |
|
#9
|
|||
|
|||
|
iptables command syntax: selecting the table, chain, position
Now, on to the syntax of the iptables command.
Note that this post only deals with how to select the correct table and chain you want to act upon. The way to define a rule (what packets should be matched and what to do with them) will be explained later. First: which table Theoretically, the first argument to iptables should be the table it is asked to act upon. This is the -t option. If not specified, it is the filter table by default. All arguments between brackets are optional. All arguments between <...> are MANDATORY. Hence the command: iptables -A OUTPUT blah blahis the equivalent of: iptables -t filter -A OUTPUT blah blahIf you want to act on ANOTHER table than filter (say, nat), then the -t argument becomes MANDATORY. Second: how to act on the table What to do on the table is determined by the following option. This can be:
Last edited by fgaliegue; 02-11-2006 at 06:22 PM. |
|
#10
|
|||
|
|||
|
iptables command syntax, continued: matching packets
So, we now know how to select the table and chain we want to alter. Let's see now all the <rule> stuff. It is in two parts, as the title of the post states:
How to match packets iptables has a pretty comprehensive set of rules in order to match packets. As a result, only some of them are described. Of course, you can combine several of the criteria mentioned here, in certain limits however - these will be explained too. Matching on incoming/outgoing interface At the lowest possible level, it is possible to match packets based on the incoming or outgoing interface. To match the incoming interface, use the option -i <interface> (for example, -i eth0). Note that if the number besides the interface class is replaced by a +, it will match all such interfaces (eth+ will match eth0, eth1, eth2 and so on). To match the outgoing interface, use the option -o <interface>. The same holds true wrt the + character. IMPORTANT!
The reason is pretty straightforward: at PREROUTING time, you cannot tell which interface a packet is going to (it's up to the kernel to determine this - and nat/PREROUTING can influence the routing decision, remember), and at INPUT time, the packet being destined to the local machine, there's just no outgoing interface. Similarly, the POSTROUTING chains cannot tell where a packet comes from (similarly, only the kernel knows that), and OUTPUT packets, having been initiated from the machine itself, don't have a source interface either. For */FORWARD chains, however, both options can be used. You can NEGATE this option by using ! before the interface name: for example, -i ! eth0 will match all packets NOT coming from interface eth0. Matching the source/destination address(es) You can match source addresses using the -s <address>[/netmask], and in a similar vein, match destination addresses using the -d <address>[/netmask] option. The mask is optional and can either follow the "classic" notation (255.255.255.0) or the CIDR notation (24). For instance:
Similarly, you can negate the argument by preceeding it with a !, for example, -s ! 192.168.1.0/24. You can also put machine names instead of IP addresses, but this is STRONGLY DISCOURAGED (try and imagine what happens if your current rules block DNS traffic...). Matching against the protocol You can match the protocol with the -p <protocol> [protocol-options] option (and negate the match with ! as well). We will see the three commonly used protocols here, which are TCP, UDP and ICMP, however others exist as well, you can see a non exhaustive list in file /etc/protocols on any Linux system. So, let's see what flags you can specify with protocols TCP (-p tcp) and UDP (-p udp):
With the ICMP protocol, you can specify the type of message you want with the --icmp-type <type> protocol - and negate it too (for instance --icmp-type ! timestamp-request). As a side note it should be noted that conntrack knows how to deal with ping request packets (ICMP type echo-request): it will expect ping answers (ICMP type echo-reply) as results... Smart, I tell you! Generally, you can see all available flags for a protocol by typing iptables -p <protocol> -h (for instance, iptables -p tcp -h). Extended matching Many, many extensions exist for iptables which are called with the -m option, and each of them has its specific option. An extensively used one in the sample firewall is of course the state extension. As a general rule, an extension is invoked with -m <extension_name> [extension arguments and options]. You can see all arguments of an extension by invoking iptables -m <extension_name> -h. Which you will want to do anyway, since I won't be mentioning all possible options :p Only some of them are listed here, but you will certainly find them useful ;)
__________________
"There are 10 sorts of people in this world: people who understand binary, and those who don't." (Anonymous)
Last edited by fgaliegue; 02-11-2006 at 06:26 PM. |
|
#11
|
|||
|
|||
|
iptables command syntax, the end: what to do with packets - targets
Now that we have specified what packets we want to match, we must decide what to do with them, and that is the goal of targets. You specify the target by using the -j option, which sould ALWAYS be the last one.
You can either jump to a user defined table (but you CANNOT jump to a built-in table!), or to one of the predefined targets. Like protocols and extensions, you can see all possible options of a target by invoking iptables -j <target> -h. Some targets are legal only in certain tables, some can be used in several tables but are preferably used in one of them in particular. Targets only legal in the nat table
Targets to be used in the filter table The targets below can be used in either table, however they are best used in the filter table since they decide on the fate of the packet. All of these targets are final, that is, when such a target is reached, the treatment stops there and the packet goes out of the filter table, and on to the next one (except for the DROP target).
The LOG target The LOG target will do just that, log packets using syslog. Where it will be logged will depend on the configuration of your sysklogd/syslog-ng daemon. The two most interesting options are these:
The LOG target is NOT a final target: the packet will keep going down the rules until either a final target or the default policy of the chain is reached. Last edited by fgaliegue; 02-11-2006 at 06:05 PM. |
|
#12
|
|||
|
|||
|
Putting it all together...
So now, for example, you can decrypt this line:
iptables -A connstate -m state --state NEW -p tcp ! --syn -m limit --limit 2/sec -j LOG --log-prefix "NEWNOTSYN: "Let's examine it in detail:
Last edited by fgaliegue; 02-11-2006 at 06:19 PM. |
|
#13
|
|||
|
|||
|
Nice tutorial on how iptables work :-)
For mere mortals, there are a few other choices, in order of complexity: 1) firestarter (UI based...kinda like typical Windows firewalls, but not very flexible) 2) firehol (text config, but more configurable and relatively simple to understand) 3) shorewall (text config, but more complicated and also has traffic shaping support) I'm only at the (2) level, but have gotten it to do what I need. It apparently generates 400 IP tables rules out of a 20-30 line config file, so it's a lot easier to read and understand how the firewall is configured, for this mere mortal... |
![]() |
| Thread Tools | |
|
| Similar Topics | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Linux bookmarks | Phantasm66 | The Alternative OS | 14 | 07-10-2008 10:36 AM |
| RH9 Unable to access internet after setting Firewall? posted Today 07:08 PM | novkhan | The Alternative OS | 2 | 02-11-2006 12:19 PM |
| Setting up n ad-hoc wireless network in Linux | Superczar | The Alternative OS | 3 | 07-13-2005 09:47 AM |
| Need some advice on setting up a dedicated firewall computer | Jay Jay | Security and the Web | 4 | 07-09-2005 05:05 PM |
| To Linux or not to Linux | Vehementi | The Alternative OS | 31 | 04-22-2005 02:02 PM |
All times are GMT -4. The time now is 04:39 PM.





