Link to home
Start Free TrialLog in
Avatar of tagish
tagish

asked on

Simple iptables ruleset with port 80 forwarding to internal lan.

Hello,

I am trying to setup an iptables firewall on a slackware 9 box, running the 2.6.4. kernel. I want to upgrade from ipchains on slack 2, running on my old 486 :)
I would like to allow internal traffic out, allow for ssh, ping and ftp on both interfaces, and I would like to my web, ftp and e-mail servers behind the firewall. The firewall will also be doing dhcp for the inside, and nat from the inside to the outside. I am also running dns on the firewall (secondary dns at another location) that needs to be visible to the outside. I have a second web server inside that I would like to be able to make certain areas available to the outside, what do I need in my firewall rules to do this? (I know I will have to configure apache for specific access, and reconfigure my dns once the server is moved inside the firewall)

eth0 is the outside interface, and is connected to dsl (216.126.xxx.xxx) and is using dhcp.
eth1 is the indise interface and is fixed to 192.168.3.60

192.168.3.19 will be webserver/email server 1
192.168.3.17 is webserver 2

Here is what I currently have, I know it is not complete, and does not do any port forwarding, and it does not allow me to connect anything on the internet :(

#- Flush all the rules in filter and nat tables
   iptables --flush
   iptables --table nat --flush
#- Delete all chains that are not in default filter and nat table
   iptables --delete-chain
   iptables --table nat --delete-chain

# Set up IP FORWARDing and Masquerading
   iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
   iptables --append FORWARD --in-interface eth1 -j ACCEPT

#- Enables packet forwarding by kernel
   echo 1 > /proc/sys/net/ipv4/ip_forward

   iptables -P INPUT DROP
   iptables -P FORWARD ACCEPT
   iptables -P OUTPUT ACCEPT

#- Allow self access by loopback interface
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A OUTPUT -o lo -p all -j ACCEPT

#- Accept established connections
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --tcp-option ! 2 -j REJECT --reject-with tcp-reset

# Allow ping replies on BOTH interface
iptables -A INPUT -p ICMP -i eth0 -j ACCEPT
iptables -A INPUT -p ICMP -i eth1 -j ACCEPT

#- Open ftp port OUTSIDE interface
iptables -A INPUT -p tcp -i eth0 --dport 21 -j ACCEPT
iptables -A INPUT -p udp -i eth0 --dport 21 -j ACCEPT
iptables -A INPUT -p tcp -i eth1 --dport 21 -j ACCEPT
iptables -A INPUT -p udp -i eth1 --dport 21 -j ACCEPT

#- Open secure shell port BOTH Interfaces
iptables -A INPUT -p tcp -i eth0 --dport 22 -j ACCEPT
iptables -A INPUT -p udp -i eth0 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -i eth1 --dport 22 -j ACCEPT
iptables -A INPUT -p udp -i eth1 --dport 22 -j ACCEPT

#- Open HTTP port BOTH Interface
iptables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
iptables -A INPUT -p udp -i eth0 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -i eth1 --dport 80 -j ACCEPT
iptables -A INPUT -p udp -i eth1 --dport 80 -j ACCEPT

# webmin both interfaces
iptables -A INPUT -p tcp -i eth1 --dport 10000 -j ACCEPT
iptables -A INPUT -p udp -i eth1 --dport 10000 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 10000 -j ACCEPT
iptables -A INPUT -p udp -i eth0 --dport 10000 -j ACCEPT

#OUTPUT ruleset

any suggestions would be great.
Thanks
Avatar of ahoffmann
ahoffmann
Flag of Germany image

# port forwarding for a webserver goes like this (don't forget correspondig FORWARD rule):
iptables -A PREROUTING -t nat -p tcp --dport 80 -j DNAT -i eth0 --to 192.168.3.19 :80

other services or hosts work the same way
You might consider shortening the list by not always specifying the interface. If you do not specify the interface, then it is implicity set to all interfaces. So you could shorten the ftp,http, ssh and webmin rule-sections.

However I would reconsider publishing this much services to the outside world. Basically if you open up ssh, you can connect to all these services through ssh-tunnels, no need to make them known to the world (what you can't see, you can't attack).

Next is that you don't specify destination hosts, please DO, if only to make it explicit to yourself. I realize that it is some extra work to check if your address changed after a dhcp refresh and potentially reloading the ruleset, but it is worthwile. (Boiing, brain lights up, you say that you run a nameserver, so your ip address  is fixed.. (I hope), no need to check for changing addresses)  

For the DNS stuff you are going to have to accept dns-udp from the world:

iptables -A INPUT -p udp -d $ROUTER --dport dns -j ACCEPT

Then there is the secondary your mentioned, that will do zone-transfers using dns-tcp:

iptables -A INPUT -p tcp -s $SECONDARY -d $ROUTER --dport dns -j ACCEPT

I hope this gets you a bit further along the way to the ultimate firewall :-)
>  So you could shorten  ..
The nature/purpose of a firewall is exactly the oposite, isn't it?
Nope, readability and clarity are really important, if you stick in a whole bunch of redundant lines feore you know it you skip lines expecting them to be "just like the previous one". That is the way our mind works...
Avatar of tagish
tagish

ASKER

Thanks, so now I have shortened and cleaned, this is what I have now:
#- Flush all the rules in filter and nat tables
   iptables --flush
   iptables --table nat --flush
#- Delete all chains that are not in default filter and nat table
   iptables --delete-chain
   iptables --table nat --delete-chain
# Set up IP FORWARDing and Masquerading
   iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
   iptables --append FORWARD --in-interface eth1 -j ACCEPT
#- Enables packet forwarding by kernel
   echo 1 > /proc/sys/net/ipv4/ip_forward
# port forwarding for a webserver goes like this (don't forget correspondig FORWARD rule):
iptables -A PREROUTING -t nat -p tcp --dport 80 -j DNAT -i eth0 --to 192.168.3.19 :80  ###IS THIS THE CORRECT LOCATION FOR THIS?###
#Set policy
   iptables -P INPUT DROP
   iptables -P FORWARD ACCEPT
   iptables -P OUTPUT ACCEPT
#- Allow self access by loopback interface
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A OUTPUT -o lo -p all -j ACCEPT
#- Accept established connections
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --tcp-option ! 2 -j REJECT --reject-with tcp-reset

# Allow ping replies on BOTH interface
iptables -A INPUT -p ICMP -i eth0 -j ACCEPT
iptables -A INPUT -p ICMP -i eth1 -j ACCEPT

#- Open ftp port INSIDE interface
iptables -A INPUT -p tcp  -i eth1 --dport 21 -j ACCEPT
iptables -A INPUT -p udp  -i eth1 --dport 21 -j ACCEPT

#- Open secure shell port BOTH Interfaces
iptables -A INPUT -p tcp  --dport 22 -j ACCEPT
iptables -A INPUT -p udp  --dport 22 -j ACCEPT

#- Open HTTP port BOTH Interface (will my port forward work if this left closed on both interfaces?)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p udp --dport 80 -j ACCEPT

# webmin Inside interfaces only
iptables -A INPUT -p tcp -i eth1 --dport 10000 -j ACCEPT
iptables -A INPUT -p udp -i eth1 --dport 10000 -j ACCEPT

#For the DNS stuff you are going to have to accept dns-udp from the world:
iptables -A INPUT -p udp -d $ROUTER --dport dns -j ACCEPT
#Then there is the secondary your mentioned, that will do zone-transfers using dns-tcp:
iptables -A INPUT -p tcp -s $SECONDARY -d $ROUTER --dport dns -j ACCEPT
#OUTPUT ruleset


AHoffmann: Thanks, did I put the pre-routing rule in the correct place? What would the corresponding forward rule look like? I have played with it a bit this morning but did not get the forward to work.

de2Zotjes: Thanks, I have removed the interface for most. I did decide to reduce the services showing outside. Now only ssh, http, and ping. Do I need to open port 80 if I am using a forward? The firewall does not run a web server. I agree that the more lines I have, the more difficult it will be to read this thing....-d $ROUTER  is the destination ip? should this then be my firewall ip? For the secondary -s $seconday -d $router...should this  be -s source ip (ip of secondary dns) and -d as my firewall ip again?
###############
Next is that you don't specify destination hosts, please DO, if only to make it explicit to yourself. I realize that it is some extra work to check if your address changed after a dhcp refresh and potentially reloading the ruleset, but it is worthwile. (Boiing, brain lights up, you say that you run a nameserver, so your ip address  is fixed.. (I hope), no need to check for changing addresses)
###############
What do you mean by specify destination hosts? Please explain this a bit...I would like a good firewall but simplicity is the key...my ip address is fixed....sort of...it has changed only 2x in the last 4 years(both times after my firewall was down for a week in the first 6 months)..Not bad for a dynamic dhcp address eh!! If they fix this feature then I will purchase a true fixed ip :)

For bonus points (100) what would my script look like (.sh to be called by cron at a specific time) to block internet access for the kids computers, and the opposite one for re-starting their internet access. Access to internal is fine as they have homework stuff stored inside. I have assigned them reserved ip's on the internal lan so they will always be the same.

Thanks again for all your help!!
> iptables -A PREROUTING -t nat -p tcp --dport 80 -j DNAT -i eth0 --to 192.168.3.19 :80  ###IS THIS THE CORRECT

no. The location within your script doesn't matter (as long as it is not prepended by other DROP rules).
But the syntax is incorrect: remove the space before  :80, must be: 192.168.3.19:80

for cron to disable routing (blocking anything), simply do:
iptables -P FORWARD DROP # assuming kids are not sitting at the firewall itself ;-)
Avatar of tagish

ASKER

Thanks ahoffmann,

I have corrected my script and will be testing it shortly...for the disable, how would I do it on a per ip or mac basis? I would like to restrict just the kids pc's.

thanks.
iptables -I FORWARD 1 -s ip-of-your-kids-pc -j DROP
SOLUTION
Avatar of de2Zotjes
de2Zotjes
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of tagish

ASKER

Thanks!
the forward rule in my firewall script for port 80...should it be the following?
#FORWARD ruleset
iptables -A FORWARD -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -p udp --dport 80 -j ACCEPT

What is your thought on specifying destination hosts as de2Zotjes mentioned? If you think they are not nessesary I will not worry about them, if you think they are a good idea and can answer my questions to de2Zotjes I will give you most of the points...

Thanks again.
> iptables -A FORWARD -p udp --dport 80 -j ACCEPT
not needed, usually

BTW, DENY is ipchains, DROP iptables
Yep the DROP should be a DENY, that's what you get for not actually testing your commands. Sorry about that.
Avatar of tagish

ASKER

Thanks!!  Sorry de2Zotjes, your response was not visible to me when I posted my reply...

One more question regarding the port forwarding....
I have set my dns for hostname.domain.com of my internal machine, ip pointing at my firewall's external interface.
My httpd.conf  has the entry "servername hostname.domain.com" but when I go to  hostname.domain.com I get "the operation timed out when attempting to conatct hostname.domain.com" What have I done wrong?

the dns is resolving the hostname to the firewall's ip address.

I also get an error "Bad argument `dns'"...what port number can I sub? or is my syntax bad? Sorry, I did not have that rule enabled in script before now...it is not affecting  my dns resolution as this server is still a test one so my dns is currently resolving from a different server.

Here is my script now:
#- Flush all the rules in filter and nat tables
   iptables --flush
   iptables --table nat --flush
#- Delete all chains that are not in default filter and nat table
   iptables --delete-chain
   iptables --table nat --delete-chain
# Set up IP FORWARDing and Masquerading
   iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
   iptables --append FORWARD --in-interface eth1 -j ACCEPT
#- Enables packet forwarding by kernel
   echo 1 > /proc/sys/net/ipv4/ip_forward

# port forwarding for a webserver goes like this (don't forget correspondig FORWARD rule):
iptables -A PREROUTING -t nat -p tcp --dport 80 -j DNAT -i eth0 --to 192.168.3.17:80

#Set policy
   iptables -P INPUT DROP
   iptables -P FORWARD ACCEPT
   iptables -P OUTPUT ACCEPT

#- Allow self access by loopback interface
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A OUTPUT -o lo -p all -j ACCEPT

#- Accept established connections
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --tcp-option ! 2 -j REJECT --reject-with tcp-reset

# Allow ping replies on BOTH interface
iptables -A INPUT -p ICMP -i eth0 -j ACCEPT
iptables -A INPUT -p ICMP -i eth1 -j ACCEPT

#- Open ftp port INSIDE interface
iptables -A INPUT -p tcp  -i eth1 --dport 21 -j ACCEPT
iptables -A INPUT -p udp  -i eth1 --dport 21 -j ACCEPT

#- Open secure shell port BOTH Interfaces
iptables -A INPUT -p tcp  --dport 22 -j ACCEPT
iptables -A INPUT -p udp  --dport 22 -j ACCEPT

# webmin Inside interfaces only
iptables -A INPUT -p tcp -i eth1 --dport 10000 -j ACCEPT
iptables -A INPUT -p udp -i eth1 --dport 10000 -j ACCEPT

#For the DNS stuff you are going to have to accept dns-udp from the world:
iptables -A INPUT -p udp --dport dns -j ACCEPT
#Then there is the secondary your mentioned, that will do zone-transfers using dns-tcp:-not enabling yet..
#iptables -A INPUT -p tcp -s $SECONDARY -d $ROUTER --dport dns -j ACCEPT
#FORWARD ruleset
iptables -A FORWARD -p tcp --dport 80 -j ACCEPT

Thanks again.
Avatar of tagish

ASKER

I think the trouble is my web sever config. I see packets hitting the forward rule, and I can also see rxpackets increasing on the internal web server......

Thanks.
Avatar of tagish

ASKER

Hmmm,
Ok, I commented out the servername line in httpd.conf so the web server is the same as it used to be. It now responds when I open a web browser inside the network and point it to 192.168.3.17...But when I use webserver.domain.com I still get  "the operation timed out when attempting to conatact hostname.domain.com"
When I do an nslookup for webserver.domain.com it resolves to my firewall. Is this correct?
stop!
don't change more than one configuration.
Either setup you webserver, or iptables. I'd suggest the webserver first, then if it is up and accessable from internet, configure firewall.
You still did not test what has been recommended. I'don't want to fix more and more problems just 'cause you "play" with something you're not used too :-(
Take a look at this why reinvent the wheel http://monmotha.mplug.org/firewall/index.php
Avatar of tagish

ASKER

Thanks,
I have stopped changing things....the webserver is available from my internal lan via ip address http:\\192.168.3.17. (I don't wish to connect this box to the internet, just port 80). I did test what was suggested, but things did not seem to work. How can I verify that the packets destined for my internal server are being forwarded? My earllier comment that I see packets hitting the forward rule may not be correct....If I can verify the forward is working correctly I will close the question, assign points, and if nessesary open a new one for my apache config.
Please note, that while I am new to iptables, I am not new to linux or apache...yes, I do know better than to change everything at once, I just got impatient :(

Thanks for the link paranoidcookie, I will go and read up on it now....

Thanks.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of tagish

ASKER

IT WORKS!!!!

I had a couple minor issues to fix up...It seems I did not flush something, after I ran your flush commands from the top of your script and re-applied my firewall script all worked...I appreciate your help, and concern for security, I now have the knowledge I need to get at it and learn more!! :)

This is not yet the most secure as my forward and output rules need to changed to DENY(and appropiate rules put in place to allow what I want)....but the port forward and the script for the kids pc are both working. This firewall is not yet in "production" as it still my learining box...Thanks for your help, and now for the points. I am going to assign 25 points to de2Zotjes for his input, and all the rest to AHoffmann. Thanks for the link paranoidcookie, it looks good but removes all the learning from the process which is what I need.

Here is the final script I am using as of today....

# Delete and flush. Default table is "filter". Others like "nat" must be explicitly stated.
#- Flush all the rules in filter and nat tables
   iptables --flush
   iptables --table nat --flush
#- Delete all chains that are not in default filter and nat table
   iptables --delete-chain
   iptables --table nat --delete-chain
# Set up IP FORWARDing and Masquerading
   iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
   iptables --append FORWARD --in-interface eth1 -j ACCEPT
#- Enables packet forwarding by kernel
   echo 1 > /proc/sys/net/ipv4/ip_forward
.
# port forwarding for webserver. DINO
   iptables -A PREROUTING -i eth0 -t nat -p tcp --dport 80 -j DNAT --to 192.168.3.17:80

#Set policy
   iptables -P INPUT DROP
   iptables -P FORWARD ACCEPT
   iptables -P OUTPUT ACCEPT

####################################################
#- Internet interface is eth0 LAN interface is eth1#
####################################################

#- Allow self access by loopback interface
   iptables -A INPUT -i lo -p all -j ACCEPT
   iptables -A OUTPUT -o lo -p all -j ACCEPT

#- Accept established connections
   iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
   iptables -A INPUT -p tcp --tcp-option ! 2 -j REJECT --reject-with tcp-reset

###############
# *** PING ***# replies on BOTH interface
###############
   iptables -A INPUT -p ICMP -i eth0 -j ACCEPT
   iptables -A INPUT -p ICMP -i eth1 -j ACCEPT

###############
#- *** SSH ***# port BOTH Interfaces
###############
   iptables -A INPUT -p tcp  --dport 22 -j ACCEPT
   iptables -A INPUT -p udp  --dport 22 -j ACCEPT

################
#*** WEBMIN ***#  -both interfaces
################
   iptables -A INPUT -p tcp -i eth1 --dport 10000 -j ACCEPT
   iptables -A INPUT -p udp -i eth1 --dport 10000 -j ACCEPT
   iptables -A INPUT -p tcp -i eth0 --dport 10000 -j ACCEPT
   iptables -A INPUT -p udp -i eth0 --dport 10000 -j ACCEPT

##############
# *** DNS ***# stuff you are going to have to accept dns-udp from the world:
##############
iptables -A INPUT -p udp --dport 53 -j ACCEPT

################
# secondary DNS         # not in use today
################
#iptables -A INPUT -p tcp -s $SECONDARY -d $ROUTER --dport dns -j ACCEPT

#################
#*** FORWARD ***     # this should forward port 80 requests to
################# firewall to internal machine 192.168.3.17.
iptables -A FORWARD -p tcp -i eth0 -d 192.168.3.17 --dport 80 -j ACCEPT
you got it, a working firewall and the idea that you need to get used to it. Congrats.

About your script: please see my comments in particular the graded one.
Avatar of tagish

ASKER

Hi ahoffmann,

Thanks you, I did look at your comments again., I think you must be meaning the "2. a firewall script should not set the kernel's routing, if it does then please at the end *after* setting iptables rules correctly." I noticed that comment (after re-reading) and investigated things on my box. I am actually setting the kernels routing in my boot process (one of the rc.inet files)...so I have removed it from my script. If I notice that my investigaton was incorrect (damn learning curve :) ) I will put that line at the bottom of my script instead of the top. Thanks for all your help!!

BTW: All 3 of my Policies are now set to DENY and I have the correct rule sets in place to allow me to connect to most places I need to now....I am feeling better about this script every day now, as well as my understanding of iptables.....I sure reccomend a test box for learing this stuff however....It much more comfortable to know that blowing it and leaving wide open holes, or closing things to tight and not being able to get out the network has no impacts...
good learning curve !

> I am feeling better about this script every day now
hint: start tcpdump on internal interface leaving out legal traffic
start tcpdump on external interface leaving out legal traffic too, then compare results ;-)
Or simply log anything before it gets droped, and monitor logfile ...