Linux - SecurityThis forum is for all security related questions.
Questions, tips, system compromises, firewalls, etc. are all included here.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Heh, I had forgotten that you were using dedicated IPs (not shared) when I made my previous post - sorry about that.
Your FORWARD rules for SSH shouldn't be using my example port numbers then, you can make them all 22 (the DNAT won't change the port numbers in what you've posted). For saving your iptables configuration, see post #7, which also shows how to make the configuration survive a reboot. The PREROUTING command which is failing for you is doing so because specifying an outbound interface at that point doesn't make sense. I'm not sure why I included that match, I suspect I was sleepy at the time.
I'll edit my post to correct it in order to prevent confusing anyone running into this thread down the road.
Thanks! That makes it easier and your correction addressed that error message. Here is my final set of iptables rules, which I tested upon reboot so it is starting up correctly. If you notice anything off please let me know. Also, do you know if the order of the rules makes any difference?
Code:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT tcp -- anywhere 192.168.50.45 tcp dpt:www state NEW
ACCEPT tcp -- anywhere 192.168.50.45 tcp dpt:https state NEW
ACCEPT tcp -- anywhere 192.168.50.46 tcp dpt:www state NEW
ACCEPT tcp -- anywhere 192.168.50.46 tcp dpt:https state NEW
ACCEPT tcp -- anywhere 192.168.50.46 tcp dpt:smtp state NEW
ACCEPT tcp -- anywhere 192.168.50.46 tcp dpt:imap2 state NEW
ACCEPT tcp -- anywhere 192.168.50.46 tcp dpt:ssmtp state NEW
ACCEPT tcp -- anywhere 192.168.50.46 tcp dpt:585 state NEW
ACCEPT tcp -- anywhere 192.168.50.46 tcp dpt:imaps state NEW
ACCEPT udp -- anywhere 192.168.50.47 udp dpt:domain state NEW
ACCEPT udp -- anywhere 192.168.50.48 udp dpt:domain state NEW
ACCEPT tcp -- anywhere 192.168.50.45 tcp dpt:ssh state NEW
ACCEPT tcp -- anywhere 192.168.50.46 tcp dpt:ssh state NEW
ACCEPT tcp -- anywhere 192.168.50.47 tcp dpt:ssh state NEW
ACCEPT tcp -- anywhere 192.168.50.48 tcp dpt:ssh state NEW
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
And one of my final questions, what is the best way to now test my firewall rules? Should I begin setting up the internal DNS server and see if I can get out to the network and into it through ssh? Other methods? This is my planned network config for it, let me know if anything is off or if the broadcast or network are needed:
It's a bit awkward to read the output of this without the verbosity enabled. Could you kindly repost with the verbose option? While we're at it, let's get straight numbers by using the -n option. Show us the nat table too please (what you've got above is only the filter table). These commands would do just fine:
Code:
iptables -nvL
Code:
iptables -nvL -t nat
Oh, and yes, the order is extremely important. Packets traverse the chains from top to bottom. As for basic tools to test the firewall, you could use something like Firewalk for the LAN side and maybe Nmap for the WAN. Keep in mind that your firewall box is still lacking any rules for itself. At the very least, you should have a couple INPUT rules like this:
Code:
iptables -P INPUT DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
From there, you'd add exceptions (such as for SSH, for example).
I'd also recommend installing host-based firewalls on all the servers, with logging enabled, and a log checker. If any filtered packet is detected which shouldn't have made it through (such as a TCP packet with destination port 3456 reaching a server which is only supposed to be receiving TCP packets with destination port 80) you should receive an automatic alert (email, etc.) because such a thing is symptomatic of a misbehaving firewall and would require careful investigation.
One other suggestion: Create a shell script for this instead of typing commands.
Last edited by win32sux; 03-10-2010 at 05:11 AM.
Reason: Spelling.
That is very good to know about the significance of order, could you let me know if this order is good. Basically, does it matter that I entered the forwarding rules then the input rules? And does it matter that I entered the postrouting then snat then prerouting rules in that order during configuration, followed by the ssh rules for the internal machines?
As for the host machines firewall, that is very good advice. I am assuming I would follow the similar patterns for the internal machines to only allow the needed ports, but how would I enable the logging? And as that brings up a good point, what is the best way to view the log files i.e. where are they located?
If there are any other settings I should look into please let me know, such as certain output rules or forwarding and input rules I am lacking. On another note, I know that I can't do deep packet inspection but have heard l7 might be good if I wanted to set up application level rules. Not sure if I need that at this stage, but wanted to get your opinion on the value?
Also, from my understanding the current firewall rules will not affect the internal servers from communicating between each other, is that correct?
Thanks again for all your help.
Last edited by debianfan; 03-16-2010 at 11:14 AM.
Reason: Added CODE tags for readability.
That is very good to know about the significance of order, could you let me know if this order is good. Basically, does it matter that I entered the forwarding rules then the input rules? And does it matter that I entered the postrouting then snat then prerouting rules in that order during configuration, followed by the ssh rules for the internal machines?
No, you can enter rules in different chains in any order you want. What you need to be careful with is rules within the same chain. What you've got looks good to me. You're missing the PREROUTING rules for the port 22/TCP packets, though. BTW, I'd suggest using a script in order to make it easier to make tweaks and stuff. A script would also let you better organize your rules, which makes it easier to spot mistakes. I've written such a script for you, based on the information I could observe above. Please give a shot and see if you like it.
Quote:
As for the host machines firewall, that is very good advice. I am assuming I would follow the similar patterns for the internal machines to only allow the needed ports, but how would I enable the logging? And as that brings up a good point, what is the best way to view the log files i.e. where are they located?
Yeah, for the servers you'd be using INPUT and OUTPUT (not FORWARD), as IP forwarding should be disabled on them. Logging is done by using the LOG target. For example, say you have a rule to filter packets with destination port 666/TCP like this:
Code:
iptables -A INPUT -p TCP --dport 666 -j DROP
To generate a log entry every time such a packet is filtered, you could stick a LOG rule on top, like:
Code:
iptables -A INPUT -p TCP --dport 666 -j LOG
iptables -A INPUT -p TCP --dport 666 -j DROP
The packet hits the first rule and gets sent to LOG (which is a non-terminating target), then it hits the following rule and is filtered. On Ubuntu, this gets logged in the /var/log/messages file. You can also make a convenient label appear with each log entry, making them easier to locate both by you and any automated log checker (and you have several nice options to choose from as far as those applications are concerned). Example:
Code:
iptables -A INPUT -p TCP --dport 666 -j LOG --log-prefix "INPUT DROP: "
iptables -A INPUT -p TCP --dport 666 -j DROP
Quote:
If there are any other settings I should look into please let me know, such as certain output rules or forwarding and input rules I am lacking. On another note, I know that I can't do deep packet inspection but have heard l7 might be good if I wanted to set up application level rules. Not sure if I need that at this stage, but wanted to get your opinion on the value?
Application layer scanning is extremely valuable, as that's where most attacks happen nowadays. You might want to consider using an application layer scanner specifically designed for the service you're looking to protect. For example, there's ModSecurity for your Web servers. It might not be a bad idea to deploy an IDS such as Snort too, so you can get alerted when suspicious traffic in general is spotted in your LAN. Oh, and yes, tightening the OUTPUT chain is a very good idea, and something you most definitely want to look into when you're a bit more familiar with iptables.
Quote:
Also, from my understanding the current firewall rules will not affect the internal servers from communicating between each other, is that correct?
Yes, that is correct — dedicated firewalls will only filter traffic between networks, not within them.
Quote:
Thanks again for all your help.
You're very welcome. Here's that script I wrote for you:
Ahhh, thanks for catching the missing prerouting for ssh, I think I accidentally left the SMTP port in by mistake (which definitely speaks to the need to use scripts). I am just getting into programming and the concepts of scripting so I will do my best to implement your example.
So the first part of my plan to implement this firewall configuration cleanly is to flush my current iptables config and remove the pre-up rule from the network interfaces file. Once I have run your script and viewed my rules are correct, should I use the same method as post #7, to save it upon reboot?
As for the logging, should I just do that separate from the script or is it easily incorporated into the script?
The second part of my plan will be to start looking into the application layer software you recommended. I may try to make some headway on my DNS server to begin testing my setup and will then continue refining it.
And that iptables tutorial looks excellent, thank you for passing it along as I have already started to read through it. This process has been extremely enlightening and is really helping me to understand my network not only at a granular level but at a conceptual level as well.
I will post back if I run into any problems, and likely down the road with questions on the application layer stuff.
This has just proven to me the real value in Linux is its community. Much appreciated.
Ahhh, thanks for catching the missing prerouting for ssh, I think I accidentally left the SMTP port in by mistake (which definitely speaks to the need to use scripts). I am just getting into programming and the concepts of scripting so I will do my best to implement your example.
Cool. In the script I posted you just basically have to set the missing variables at the top (the ones for your NAT IPs) and you should be good to go (if I didn't make any typos, of course).
Quote:
So the first part of my plan to implement this firewall configuration cleanly is to flush my current iptables config and remove the pre-up rule from the network interfaces file. Once I have run your script and viewed my rules are correct, should I use the same method as post #7, to save it upon reboot?
Yeah, notice how the first section of the script is dedicated purely to putting everything back into a clean and pristine state before getting started: chain policies are set (-P); all chains are flushed (-F); and user-built chains are deleted (-X). As for saving the active configuration, the process from post #7 remains unchanged, so don't remove the pre-up line. You're basically just using a script instead of typing in commands one at a time. The way the sequence goes is: Make any tweaks you need to your script; execute the script; verify that everything looks good (-nvL) and works as intended (Firewalk, Nmap, etc.); then dump the verified configuration into the file you're referencing from the pre-up line (/etc/firewall.txt in my examples).
BTW, I like to zero all my counters before saving a configuration, and if you want to do that too it's just a matter of using the -Z option on each of the tables. For example, this is the command I use to save:
Of course, you could stick those commands into a script instead of typing them out. That said, saving an iptables configuration isn't something I do often (my current one's been doing just fine for over a year), so it's not a big deal either way IMO.
Please note that I never edit the /etc/firewall.txt file by hand, and I recommend you don't either (only edit your active configuration via script or manual commands). Others will say they've been editing their iptables configuration file by hand without any problems, but I still feel it's not a good idea — it's quite error-prone and not as straightforward as using a script (especially if you need to do something a bit more involved than tiny tweaks).
Quote:
As for the logging, should I just do that separate from the script or is it easily incorporated into the script?
It's up to you, but yeah, incorporating it is a piece of cake. Just slap a line like this onto the end of the FORWARD section in the script (for example):
Code:
iptables -A FORWARD -j LOG --log-prefix "FORWARD DROP: "
Note that it must be at the end of the chain, as the idea is to send the packets to LOG right before they are sent to DROP (which will happen as soon as they run into the chain's policy, which would come right after that rule). When you read the relevant sections in the tutorial, you'll see that there's more options you can use with your LOG rule. For example, there's rate limiting options which can help prevent log floods (see documentation about the limit match module for more information, and look around LQ for plenty of examples).
Quote:
The second part of my plan will be to start looking into the application layer software you recommended. I may try to make some headway on my DNS server to begin testing my setup and will then continue refining it.
Sounds good!
Quote:
And that iptables tutorial looks excellent, thank you for passing it along as I have already started to read through it. This process has been extremely enlightening and is really helping me to understand my network not only at a granular level but at a conceptual level as well.
I'm happy to hear that. I find that tutorial to be excellent too, BTW.
Quote:
I will post back if I run into any problems, and likely down the road with questions on the application layer stuff.
We look forward to hearing from you.
Quote:
This has just proven to me the real value in Linux is its community. Much appreciated.
Thanks to you for becoming a part of the LQ community!
Ok, so I believe I have set up the firewall rules correctly, but in my testing I am running into problems reaching the internal DNS server and reaching the internet from the internal DNS server.
Here are my network settings on the firewall server:
Code:
# The loopback network interface
auto lo
iface lo inet loopback
pre-up iptables-restore < /etc/firewall.txt
# The primary network interface
auto eth0
iface eth0 inet static
address xx.xx.xx.34
netmask 255.255.255.248
network xx.xx.xx.32
broadcast xx.xx.xx.39
gateway xx.xx.xx.33
# dns-* options are implemented by the resolvconf package, if installed
dns-nameservers xx.xx.xx.12 xx.xx.xx.13
dns-search xxxx.com
auto eth0:0
iface eth0:0 inet static
address xx.xx.xx.35
netmask 255.255.255.248
broadcast xx.xx.xx.39
auto eth0:1
iface eth0:1 inet static
address xx.xx.xx.36
netmask 255.255.255.248
broadcast xx.xx.xx.39
auto eth0:2
iface eth0:2 inet static
address xx.xx.xx.37
netmask 255.255.255.248
broadcast xx.xx.xx.39
auto eth0:3
iface eth0:3 inet static
address xx.xx.xx.38
netmask 255.255.255.248
broadcast xx.xx.xx.39
# The secondary network interface
auto eth1
iface eth1 inet static
address 192.168.21.1
netmask 255.255.255.0
network 192.168.21.0
broadcast 192.168.21.255
And here are my network settings on my internal server:
Chain INPUT (policy DROP 999 packets, 304K bytes)
pkts bytes target prot opt in out source destination
669 68586 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
3 176 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 state NEW
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 414 packets, 63642 bytes)
pkts bytes target prot opt in out source destination
Do any of these settings appear incorrect? Am I missing some network information in my firewall or nameserver network settings? For example, do I need a network IP address for each of the network aliases on the firewall machine? How could I or should I change my LAN settings for my firewall and internal nameserver?
I have tried pinging www.google.com out of my internal nameserver while logged in, as well as the gateway address of my firewall. Unfortunately, neither went through.
I also tried using SSH to get into the internal nameserver remotely, but no luck either.
Any ideas on good troubleshooting methods or possible solutions?
What does /sbin/ifconfig and /sbin/route -n look like? That's what we'd need to see in order to make sure the network configuration on the firewall is sane. As for outbound connections (or even a simple ping) from the LAN side, you'd need to make FORWARD rules for that, as the script I wrote has none. The failure to establish inbound connections to the SSH daemon on the DNS server, on the other hand, is unexpected. To troubleshoot this, first post the output of the previously mentioned commands, then append a LOG rule to your FORWARD chain and see if a message shows up when you attempt to connect to the DNS box's SSH daemon from the WAN side. You don't need to edit the script (unless you want to), just do it from the command line:
Code:
iptables -A FORWARD -j LOG --log-prefix "FORWARD DROP: "
And yeah, what you've posted so far looks okay to me, at least in the context of 192.168.21.47, which is what we're troubleshooting right now.
BTW, we'd need a packet capture to know exactly what this was about, but it does indicate that three TCP packets with destination port 22 were in fact received by this box — and sent to ACCEPT.
Quote:
Originally Posted by debianfan
3 176 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW
Oh on the last one, I believe I accidentally pasted results from the firewall box, so I think those SSH connections were to the firewall. I will include an accurate capture of the internal server when I send that other output as well. Thanks again, I will do my best to shoot you an update soon.
and the output from the /sbin/route -n command is:
Code:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
xx.xx.xx.32 0.0.0.0 255.255.255.248 U 0 0 0 eth0
192.168.21.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
0.0.0.0 xx.xx.xx.33 0.0.0.0 UG 100 0 0 eth0
I have a sneaking suspicion my problems might be related to my route tables, perhaps I am missing something there.
Also, here is the real output for my internal nameserver:
Code:
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
35 3392 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
state RELATED,ESTABLISHED
2 120 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0
tcp dpt:22 state NEW
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0
udp dpt:53 state NEW
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 77 packets, 6376 bytes)
pkts bytes target prot opt in out source destination
and here is my internal machines default nat in iptables:
Code:
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 22 packets, 1552 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 22 packets, 1552 bytes)
pkts bytes target prot opt in out source destination
Thanks for taking a look, let me know what looks off to you. Also, is it normal to have packets and bytes appearing on a machine not reaching the internet?
Also, on my firewall if I am connected through the SSH daemon should that only show up as 1 packet or can it be multiple. The reason I ask was when I saw 3 packets accepted to the firewall I was wondering if that could mean someone else was connected.
auto eth0
iface eth0 inet static
address xx.xx.xx.44
netmask 255.255.255.248
network xx.xx.xx.42
broadcast xx.xx.xx.49
gateway xx.xx.xx.43
# dns-* options are implemented by the resolvconf package, if installed
dns-nameservers xx.xx.xx.xx xx.xx.xx.xx
dns-search example.com
auto eth0:0
iface eth0:0 inet static
address xx.xx.xx.45
netmask 255.255.255.248
broadcast xx.xx.xx.49
auto eth0:1
iface eth0:1 inet static
address xx.xx.xx.46
netmask 255.255.255.248
broadcast xx.xx.xx.49
auto eth0:2
iface eth0:2 inet static
address xx.xx.xx.47
netmask 255.255.255.248
broadcast xx.xx.xx.49
auto eth0:3
iface eth0:3 inet static
address xx.xx.xx.48
netmask 255.255.255.248
broadcast xx.xx.xx.49
Could you double-check this configuration please? My IP calculator says this doesn't look right. Specifically, it's telling me that (assuming the netmask is correct) the network should be xx.xx.xx.40 and the broadcast xx.xx.xx.47.
Also note that this would mean that xx.xx.xx.48 is actually the start of another network.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.