LINUX.IE, website of the Irish Linux Users' Group
Tux rules!

   
Home
New Users
Articles
Download
Projects
Community
Vendors

  Print Version
Email to...
 
Archives:


planetILUG

Recent News

News Archive


Join the
ILUG
on FaceBook


Join the
ILUG
on LinkedIn


Join the
ILUG SETI
Group



















 
 :: Mailing Lists

[CLUG] *DSL, Firewalls, IPTables & more - a simple discussion.

[CLUG] *DSL, Firewalls, IPTables & more - a simple discussion.

Ronan Kirby ronan at kirby.ie
Wed Oct 22 08:58:16 IST 2003


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/




More information about the Cork mailing list
Read this without the formatting.
                                                                                                    

 

Hosted by HEAnet


Maintained by the ILUG website team. The aim of Linux.ie is to support and help commercial and private users of Linux in Ireland. You can display ILUG news in your own webpages, read backend information to find out how. Networking services kindly provided by HEAnet, server kindly donated by Dell. Linux is a trademark of Linus Torvalds, used with permission. No penguins were harmed in the production or maintenance of this highly praised website. Looking for the Indian Linux Users' Group? Try here. If you've read all this and aren't a lawyer: you should be!
RSS Version
Powered by Dell