######################################################################### # getting the most out of iptables # # (c) spender 2001 # # greets: just my girlfriend, sharon, i love you baby ;) # ######################################################################### Ok it's been a while since i've written a doc, but this should be relatively easy. I've been using iptables for quite some time now, actually ever since it was merged into the 2.4.x kernel tree. It has many more new features compared to ipchains. My goal in this doc is to tell you about some of the new features in iptables and to explain how you can use them, as well as show you how to create rulesets, and i'll even throw in a script for a tightly secured firewall for general use. TOC I. New Features II. How they can be used III. Ruleset basics IV. Advanced firewalling V. Sample ruleset script I. New features iptables comes with a lot of new features. It is modularized, so you can plug in which features you want to use. It has "connection tracking", which makes it a stateful firewalling system (like ipfilter for bsd). This is the first of its kind for linux, and allows it to accept/deny/route packets based on whether or not they are found in certain stages of a tcp session. iptables includes full NAT support, and a neat feature that allows you to "mangle" packets (i'll discuss this later). It also allows packets to be passed to the userspace where it can be handled and reinjected into the stream. it also includes rate-limiting, which can both be used to keep logs from being flooded and limit the amount of packets/types of packets that can be received in a certain time interval. i'm sure there's other features i can't think of right now, but just check out the different stuff when you compile your kernel. II. How they can be used here's just a few things i would do with the new iptables. First off the more exciting things....like being able your os on a timed interval. ok, not really, but you can make it look that way. look into a kernel patch called ippersonality...unless there was a new version developed recently, it was made for 2.4.0-test4 kernels, though i had it working on kernels up to test9...though i haven't tried it on any newer ones...it probably still works, if not it wouldn't be hard fixing it. anywayz, what it does is uses the "mangling" feature of iptables and upon receiving certain packets like the ones used in os fingerprint detection by nmap and queso, it sends back artificially crafted packets, fooling the program into thinking your system has a different os. If done well enough, and if you hide/fake information about your services well enough, you can fool most kiddies. another nice feature, the userspace queuing, allows you to pass packets that match your rules to the userspace where your program can handle then and reinject them. there's so many things you can do with just that...like more intelligent and secure "portsentry" type programs...rate limiting makes sure that your services are not abused, and can also be used in a routing environment to enforce bandwidth usage, not only by ip but types of services used, etc. and lastly, the "connection tracking" can be used to further enhance network security, since you can make sure that the temporary ports on your system (generally 32768-61000 for linux) are used only for connecting to other hosts and not for connections into your system. i would assume this would keep your box from being attacked with ack floods, since the firewall would recognize there is no real session there and drop it. III. Ruleset basics writing rules in iptables, you'll find, is very similar to ipchains in most respects....though citing all the differences between the two is beyond the scope of this, there's an exhaustive list at the projects homepage, http://netfilter.kernelnotes.org. here's the flags and targets, etc you should know for most usage; iptables --help if you need help with syntax. -A appends a rule to a chain -F flushes all rules from a chain -P sets default target for a chain -L lists rules in chain -D deletes a rule that matches its argument -j specifies target (default targets are ACCEPT,DROP,REJECT) -p specifies ip protocol (tcp,udp,icmp....you can use their names, or if you just got done programming and remember their numerical equivalents, go ahead and use that if u want ;) -s specifies source host/subnet in x.x.x.x/[0-32] format..ip with bitmask -d specifies destination host/subnet....same format -i specifies the interface the rule applies to -f matches packet fragments tcp options ( to be used with -p tcp ): --sport (can also use --source-port) specifies source port number or range, by using LOW:HIGH syntax...or LOW: to specify all ports including and above that port and :HIGH to specify all ports including and below that port. --dport (can also use --destination-port) same thing, just the destination port. --tcp-flags matches when its second argument is flagged, and the rest of the flags specified in its first argument are cleared. (note that using "ALL" as an argument is the same as using "SYN,ACK,RST,PSH,URG,FIN") ex: iptables -A INPUT -p tcp --tcp-flags SYN,ACK,RST SYN --dport 21 -j ACCEPT this rule will match any incoming packets with the SYN flag set, but the ACK and RST flags cleared coming to port 21 on your end. the reason why you have to specify which flags to check if a certain flag/flags are set in it is because flags can be set at the same time, so it's for a point of precision...if this wasn't the case, any packets with SYN set on it would match, even if it was a SYN/ACK combination or even with the URG flag set as well. by the way, you can also just use --syn to replace the entire "--tcp-flags SYN,ACK,RST SYN" string. udp options (to be used with -p udp) --sport same as with tcp --dport same as with tcp icmp options (to be used with -p icmp) --icmp-type this option specifies the icmp type of the packet to be matched. you can use the type's name (names can be found by running "iptables -p icmp --help", or the type's numerical equivalent. limit match (used with -m limit) --limit set the number of times rule can be matched in a time interval... syntax is num/interval interval can be "s"(for second),"m"(minute) ,"h"(hour),"d"(day) ex: iptables -A INPUT -p tcp --syn -m limit --limit 1/s --dport 21 -j ACCEPT this rate-limits syns (incoming connections) to port 21 on your end to 1 per second...severely restricting the effect syn floods can have on your resources, though i'd think unless there was some type of priority queuing, your box would be blocking legitimate requests. state match (used with -m state) --state arguments can be one of NEW,ESTABLISHED,RELATED,INVALID NEW matches connection initiation, ESTABLISHED matches packets involved in an active session, RELATED matches packets that are related to an existing connection, like ftp data connections, and INVALID matches packets that can't be identified for some reason or another. (which means they're not something you need and should be dropped) IV. Advanced firewalling Ok, what i recommend doing, all of which i've done in my sample ruleset, is to restrict incoming connections to only the services running on your system. block all fragments, rate-limit syns, a certain type of portscan, and try to restrict access to your services from only temporary port ranges 1024-5000 and 32768-61000, which will cover windows and *nix boxes.....while making it more difficult for you to be dos'd...basically they'd have to simulate actual traffic, which most kiddies would overlook. take a look at the sample firewall (which includes a short snippet to enable anti-spoof protection in the linux kernel....which is kind of weak, so i added some domains to block out....if you use mcast, or bootp, you might want to change those.) and adapt it to your own. it's an extremly anal ruleset for incoming connections...etc but does nothing for outgoing packets....personally i don't see the reasons behind doing anything to keep kiddies from ddosing on your box, since they can remove(or edit) the firewall once they have root unless you're using lids or something, but if you still feel like you need to protect the world from the users on your system, go on ahead. Also note that in my forward rules i'm blocking aim, icq, msn messenger, and yahoo pager services by their ip. take out all that if you don't want it. V. Sample ruleset script #!/bin/sh echo "Initializing modules..." cd /lib/modules/2.4.1/kernel/net/ipv4/netfilter insmod ip_tables insmod ip_conntrack insmod ipt_state insmod ipt_limit #insmod iptable_mangle #insmod ipt_PERS echo "Flushing rules.." #iptables -F PREROUTING #iptables -t mangle -F OUTPUT iptables -F INPUT iptables -F FORWARD iptables -F OUTPUT iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT if [ "$1" == "start" ]; then echo "Setting up spoof protection..." for blah in /proc/sys/net/ipv4/conf/*/rp_filter; do echo "1" > $blah done echo "Setting default routes..." iptables -P INPUT DROP iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT echo "Configuring external interface rulesets..." #iptables -t mangle -A PREROUTING -j PERS --local --tweak dst --conf /etc/win9x.conf #iptables -t mangle -A OUTPUT -j PERS --local --tweak src --conf /etc/win9x.conf iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP iptables -A INPUT -i eth0 -s 255.255.255.255/32 -j DROP iptables -A INPUT -i eth0 -s 0.0.0.0/8 -j DROP iptables -A INPUT -i eth0 -s 169.254.0.0/16 -j DROP iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP iptables -A INPUT -i eth0 -s 192.0.2.0/24 -j DROP iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP iptables -A INPUT -i eth0 -s 224.0.0.0/4 -j DROP iptables -A INPUT -i eth0 -s 240.0.0.0/5 -j DROP iptables -A INPUT -i eth0 -s 248.0.0.0/5 -j DROP iptables -A INPUT -i eth0 -f -j DROP iptables -A INPUT -i eth0 -p TCP -m state --state INVALID -j DROP iptables -A INPUT -i eth0 -p TCP --syn -m limit --limit 1/s -j ACCEPT iptables -A INPUT -i eth0 -p TCP --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 1024:5000 --dport 20 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 1024:5000 --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 1024:5000 --dport 23 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 1024:5000 --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 1024:5000 --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 1024:5000 --dport 110 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 1024:5000 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 1024:5000 --dport 113 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 1024:5000 --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT #iptables -A INPUT -i eth0 -p TCP -s 0/0 --sport 1024:5000 -d 0/0 --dport 1998 -j ACCEPT #iptables -A INPUT -i eth0 -p TCP -s 0/0 --sport 1024:5000 -d 0/0 --dport 1999 -j ACCEPT iptables -A INPUT -i eth0 -p TCP --dport 32768:61000 -m state --state ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 20 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 23 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 110 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 113 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT #iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 1998 -j ACCEPT #iptables -A INPUT -i eth0 -p TCP --sport 32768:61000 --dport 1999 -j ACCEPT #iptables -A INPUT -i eth0 -p UDP -j DENY iptables -A INPUT -i eth0 -p UDP -s 0/0 --sport 53 -j ACCEPT #iptables -A INPUT -i eth0 -p UDP -s 0/0 --dport 53 -j ACCEPT #iptables -A INPUT -i eth0 -p UDP -s 0/0 --sport 161 -j ACCEPT iptables -A INPUT -i eth0 -p UDP -s 0/0 --sport ntp -j ACCEPT iptables -A INPUT -i eth0 -p UDP -s 0/0 --dport ntp -j ACCEPT iptables -A INPUT -i eth0 -p ICMP --icmp-type echo-reply -j ACCEPT echo "Configuring routing rulesets..." iptables -A FORWARD -i eth0 -d 205.188.153.139/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.153.140/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.153.141/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.7.168/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.7.164/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.7.178/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.7.172/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.7.176/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.5.208/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.4.159/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.3.160/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.3.176/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.5.204/32 -j DROP iptables -A FORWARD -i eth0 -d 205.188.153.139/32 -j DROP iptables -A FORWARD -i eth0 -d 209.185.128.132/32 -j DROP iptables -A FORWARD -i eth0 -d 152.163.241.128/32 -j DROP iptables -A FORWARD -i eth0 -d 152.163.242.24/32 -j DROP iptables -A FORWARD -i eth0 -d 152.163.242.28/32 -j DROP iptables -A FORWARD -i eth0 -d 152.163.241.120/32 -j DROP iptables -A FORWARD -i eth0 -p TCP --sport 1024: --dport 9898 -j DROP iptables -A FORWARD -i eth0 -d 10.0.0.0/8 -j DROP iptables -A FORWARD -i eth0 -d 127.0.0.0/8 -j DROP iptables -A FORWARD -i eth0 -p igmp -j DROP iptables -A FORWARD -i eth0 -p TCP --syn -m limit --limit 10/s -j ACCEPT iptables -A FORWARD -i eth0 -p TCP --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 10/s -j ACCEPT echo "Configuring internal interface rulesets..." iptables -A INPUT -i lo -j ACCEPT echo "IPtables firewall configuration completed." fi