Folks, Adam's mail regarding which front-end to use for a firewall raises a topic which I'm sure we will see again and again on the list, especially as DSL becomes more widespread in Cork. So, what options are available to us Linux junkies? Well, there are many many front ends to the Linux firewalling system. Really all most of these do is try and make "iptables" (the front end to the Kernel's "netfilter") a little more friendly. Unfortunately its a slight catch 22 situation though - the more simple the interface usually is, the more functionality you tend to loose[1]. In light of this, I discuss below the basics of setting up your own firewall on a gateway using iptables its self. It is by no means as advanced as some of us would use or as technically accurate as it could be, but it is a definite starting point, explaining in simple English what iptables means and does. It is also my little way of demonstrating that iptables is not the scary monster that some people[2] may tell you it is. In fact, it is a lot easier to use than its predecessors ipchains and ipfwadm[3], with one reason being that it is a stateful firewall (i.e. it can track connections properly). This makes rules a lot easier to write for services which you wish to allow. This is of course intended as a starting point and comes with no guarantees etcetera etcetera waffle waffle. It does however come with a desire to see this expanded on. So, first thing we want to do: Enable source address verification in the kernel. This goes a long way toward protecting you from spoofed packets, smurf attacks and other such fun things. So add the following line... net.ipv4.conf.default.rp_filter = 1 ...in to /etc/sysctl.conf. This will make the change permanent and active after you reboot. This can be done on a boot by boot basis by echoing directly in to the underlying subsystem - but this much is easier. Now we want to enable forwarding, permanently. So in the same file as before, /etc/sysctl.conf, add the following line... net.ipv4.ip_forward = 1 ...you can save and close the file for now. We will add more to it later. Lets start by clearing any rules that might be in memory already... # iptables -F ...and setting some defaults we will come back to later... # iptables --policy INPUT DROP # iptables --policy OUTPUT ACCEPT # iptables --policy FORWARD ACCEPT Now to the firewall itself. Being paranoid bunnies, by default we drop all traffic. It is important to note that I said "drop" and not reject. When you drop a packet, it literally does just that. No message or acknowledgment of any kind is sent back to the originator. Where as a reject will send back an error message to the originator. Now, while it might seem a little rude not to reply, if someone is flooding you with lots of traffic, you can use a lot of precious bandwidth by sending back errors. Better just to ignore it all. Also, this is part of being invisible to the world (so to speak). If someone is scanning your IP address, which does not reply in any way shape or form, people will generally assume there is simply nothing there. Thus not drawing any unwanted attention to one's self. So, in light of this, lets start by dropping ALL incoming traffic... # iptables -A INPUT -i eth0 -j DROP ...this discussion assumes that "eth0" is your connection to the Internet or outside world and that "eth1" is your internal facing interface. The internal network is assumed as being 192.168.1.0/24 a.k.a. 192.168.1.0/255.255.255.0 a.k.a 192.168.1.0 -> 192.168.1.255. For the sake of paranoia, lets drop all traffic from what should be loopback addresses on all interfaces except local... # iptables -A INPUT -s 127.0.0.0/255.0.0.0 -i ! lo -j DROP ...and while we're at it, lets drop ICMP traffic too, this means people won't be able to ping you (plus a little bit more)... # iptables -A INPUT -i eth0 -p icmp -j DROP At this stage, it should be becoming clear what the various flags mean. "-A" specifies the chain we're using. For the most part, we will deal with the INPUT chain, which is built in to iptables by default and deals with incoming traffic. "-i" specifies the incoming interface we're talking about. This could be anything - eth0 as above, or ppp0 if its a dialup or PPP based connection etcetera. "-p" specifies the protocol. You don't always have to specify this. But when you do it can be tcp, udp, icmp and so on. "-j" for all intents and purposes means "do what comes after me", i.e. the action comes next. The action we will mainly be dealing with is DROP. But it could be accept, log, reject - the list goes on. See the iptables man page for a full list. As it stands now, traffic from the Internet cannot get in to your network. Unfortunately at the moment, this also means that your requested information cannot get back in to you. i.e. if you try and check your mail, it can't get in. For this to work, we must enable whats called connection tracking, which put simply, watches any requests you make to the Internet (like for mail or a web page) and allows the replies back in to you. Thus greatly enhancing your Internet experience :o) This is done by the following... # iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT ...this is fairly self explanatory. Now is also a good time to do some protection from the common tactics of a creature known as "El Script Kiddy"... # iptables -A INPUT -i eth0 -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -j ACCEPT ...the use of "!" is quite interesting and allows you a lot of flexibility. For all intents and purposes it means "the opposite of what comes after me". So in the case above its almost like inserting the words "ARE NOT" between "--tcp-flags" and "SYN,R...". To put it one final way, the "!" argument inverts the test or condition which it comes before. We are assuming here that all outbound traffic is allowed (actually, we set it to be so at the beginning), i.e. that there are no restrictions on what you can send to the Internet. That makes this an ingress firewall but not an egress. This may not necessarily be desirable in a corporate situation or on a sensitive network, but for this home scenario its fine. Now, while you don't need to explicitly tell the kernel that its ok to allow outbound traffic, lets do it anyway so we can see what it looks like... # iptables -A OUTPUT -o eth0 -j ACCEPT ...as you can see, we are now dealing with the OUTPUT chain which obviously is for outbound traffic. Now instead of "-i" which earlier meant "coming in on interface xyz" we now have "-o" which means "going out on interface xyz". I'll state the obvious and say that with the OUTPUT chain you couldn't use "-i" because the output chain will never have incoming traffic to deal with, its simply not possible. The visa versa also applies. Of course what we also don't want is any nasty broadcast traffic getting from your network to the gateway or outside world. Nor do we want it to activate a dialup or dial-on-demand (if you are using ISDN or PSTN instead of DSL). You may for some strange reason have a Windows workstation sitting on your network, which often blast out broadcast traffic and trigger dialups on gateways. So lets cater for this in a simple basic way... # iptables -A INPUT -i eth1 -d 192.168.1.255 -j DROP ...what we're doing here is dropping broadcast traffic. There are a few important things to note. First of all note the interface used in the rule, eth1 (the internal facing interface) not eth0 (the Internet facing interface). The reason for this is we don't want the gateway PC to ever see this evil broadcast traffic in case it brings up the line (if applicable). The IP address used is the broadcast address of the IP range used in this example. Right then, if this were just a workstation and not and gateway/firewall, we'd have an almost workable (albeit basic) firewall at this stage. But this is a gateway, more over, it probably has to do NAT (Network Address Translation) too. Most people will only have 1 public IP address given to them by their ISP, so NAT is pretty handy. Having just the 1 public IP does not mean you can't run publicly accessible servers - we'll come back to that later. For now, lets get NAT and forwarding going... # iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE ...here "-t" tells iptables we are using the "nat" table, which here we are using for "postrouting". We can also do "prerouting", in fact we will use this toward the end. Basically postrouting is a chain (part of the nat table) which is for adjusting packets as they are about to go out or leave the network. No prizes for guessing that prerouting is for adjusting packets are they enter a network. If you like, you could leave it there. The above should work, but its still a bit lacking, even for a basic firewall. We could however go a little further and gain a lot more. So, lets continue with some likely scenarios. Lets say you want to be able to SSH back to your gateway from the outside world. Maybe so you can access your personal mail... # iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT ...having said that, you really only want to collect it from work. So there is no point in risking leaving SSH open to the world, when you know the IP address your work network comes from. So instead of the above rule, lets use this one... # iptables -A INPUT -i eth0 -s 123.123.123.123 -p tcp --dport 22 -j ACCEPT ...what we're saying here is that any traffic coming in on eth0, who's source IP address ("-s") is 123.123.123.123 coming in on TCP port 22 (which is SSH's port) should be allowed. Obviously you should change the IP address to the appropriate one or network. In the same way the above rule uses "-s" to specify source address or network, we can also use "-d" to specify destination address if we needed to. The same applies to "--dport" which represents destination port, you can specify "--sport" which, you guessed it, means source port. The only point to note when specifying source or destination ports is that you have to state which protocol you mean. Thats why we have used "-p tcp", i.e. protocol tcp. Now, we still haven't discussed that clunky old 486 in the corner you want to use as your web server. Obviously if people are going to be able to browse to your sites, the box has to be accessible to the public Internet, or to be more precise, port 80 on it must be accessible to the public Internet. The simple way we do it in a nat situation like this is to forward port 80 from your gateway's external IP to port 80 on your internal clunky old 486. In other words, your website will be on the IP your ISP gave you at port 80 (where web servers normally listen, or 443 for HTTPS). This is done with the following, where 192.168.1.3 is the IP private address you've given to the 486 and you will remember that we are calling 121.121.121.121 is real public IP that your ISP assigned you... # iptables -t nat -A PREROUTING -p tcp -d 121.121.121.121 --dport 80 -j DNAT --to 192.168.1.3:80 ...the most interesting thing to note above this rule is that in fact, we can change the port we send it in to internally. As you can see, we specify the destination port "--dport" is 80, as that is where web requests will come in. But would could forward that to any port on the internal server if you wanted, just change the port which comes after the IP address, like ":80" in this case. A little food for though: you could take this rule a step further by specifying a source IP address too ("-s"), so the rule would only apply if traffic was coming from that address. This could be handy if you only wanted the web server to be available to your college network and not the whole Internet for example. You could reverse that and make it available to everyone except your college network by using "! -s" as mentioned earlier. Its time for one last iptables rule, just to make sure you have complete access to your gateway PC from your local network without restrictions. This is obviously not suitable for all situations. # iptables -A INPUT -i eth1 -s 192.168.1.0/24 -j ACCEPT Now, lets reopen /etc/sysctl.conf and add a little more protection. First of all add the following line... net.ipv4.conf.default.send_redirects = 0 ...which will make sure we don't send any ICMP redirect messages. On that note, lets also make sure we don't act on any we receive either... net.ipv4.conf.default.accept_redirects = 0 For pure pig iron, lets turn on the kernel's inbuilt syn cookie protection. This simply put affords you some protection against syn floods... net.ipv4.tcp_syncookies = 1 The last thing we will add to this file as a little trick to make sure we ignore ICMP broadcast requests. If left enabled it is a way people could discover your existence. Block this by adding... net.ipv4.icmp_echo_ignore_broadcasts = 1 ...now save and close the file. While we're at it, lets save the iptables rules too. We will do this in such a way that they will reload when the computer reboots... # iptables-save > /etc/sysconfig/iptables ...if you want to edit the rules in the future, you can do so using your favorite editor and attacking the file /etc/sysconfig/iptables, which is quite simple when you think it all through. When these rules are put in memory / active, your system should automatically load any related modules like ip_conntrack. This is quite a basic firewall, but it involves enough flags and attributes to allow you to make it in to something a lot more functional. Don't be afraid to play around. For example where we have used the INPUT and OUTPUT chains, you can apply many of the same rules to the FORWARD chain, i.e. the chain which passes the traffic back and forth for your network. A few things won't work so well, like FTP and Voice Over IP. They can be made to function properly though. You need to look in to ip_conntract_ftp (tldp.org and google.ie are your friends). You can also examine the state of traffic in considerably more detail than just ESTABLISHED or RELATED like we have used above. In fact its incredibly powerful. have a look in to the man page (man iptables) for more information. Depending on your kernel, you can mirror ports too! Also, using the "type of service" field in the packet headers, you can assign priority to packets and services as they go out (see TOS in iptables). This is great for giving priority to interactive traffic like web, ssh and so on. Once your comfortable with all this, you can start using logging too. Basically you would repeat each rule you want to log, but with the action set to log ("-j LOG ..."). Then someday when you have nothing to do, you can play with using Intrusion Detection Systems (IDS) like wonderfully named services such as SNORT :o) Anyway, the point of this is to try and demonstrate that IPTables is not some mean nasty beast thats hard to use and write rules for. Once you think things through logically, you can do pretty much anything you want! So don't bother with your fancy front-end. They can often be more confusing still! Linux is natively an incredibly powerful firewall system. You'd be amazed how many of the big commercial firewall appliances are actually just running embedded Linux! I have yet to come across anything more flexible and powerful. (I acknowledge and accept that there are probably mistakes in the above. This was done on a laptop, offline, in a lovely place called the Squirrel Inn[4]. A lot of it the descriptions given for various functions have been purposely simplified - so no grief please :o) If you have questions, just ask! We're a Linux User Group. We're here to help each other with Linux! Y'all take care now. - Ronan [1] I know, I know. You don't have to say it. But for the most part, alright? [2] ...daaa da daaa da Uber Alles... ;o) [3] Dear God, how did we survive having to use that? [4] Fantastic place to stay if your in Surrey - http://www.thesquirrelinn.co.uk/ _______________________________________________ Cork mailing list Cork@linux.ie http://www.linux.ie/mailman/listinfo/cork