Simplifing IPTABLES rule set

Support for security such as Firewalls and securing linux
gtinet
Posts: 4
Joined: 2022/03/28 23:56:36

Simplifing IPTABLES rule set

Post by gtinet » 2022/03/29 00:06:23

I would like to simplify the current IPTABLES rule set for my email server. I am using IPSET to create an extensive list of CIDR blocks then referencing that list in iptables to block all traffic from those IPs. However, in my case there are only 5 subnets that need to communicate with the email server, so I thought it might be easier to block all access and then explicitly allow just the subnets that are needed. Let's assume the 5 subnets are 1.1.1.0/24, 2.2.2.0/24, 3.3.3.0/24, 4.4.4.0/24 and 5.5.50/24. I'm not worried about nailing traffic down to specific ports because I control the devices on these subnets. Will the following accomplish that?


-A INPUT -s 1.1.1.0/24 -j ACCEPT
-A INPUT -s 2.2.2.0/24 -j ACCEPT
-A INPUT -s 3.3.3.0/24 -j ACCEPT
-A INPUT -s 4.4.4.0/24 -j ACCEPT
-A INPUT -s 5.5.5.0/24 -j ACCEPT
-A INPUT -j DROP


I apologize for what is probably very basic question, but I'm doing this on a very busy live server and I want to be very careful.

Thanks, Kevin

User avatar
TrevorH
Site Admin
Posts: 33219
Joined: 2009/09/24 10:40:56
Location: Brighton, UK

Re: Simplifing IPTABLES rule set

Post by TrevorH » 2022/03/29 01:10:27

Well, yes it will do what you want but it does a whole lot more than what you want too. And probably a whole lot less which might be more problematic.

First off, you are missing the standard rules that CentOS sets up out of the box:

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT

The first one is important as it says "allow any packets that are in reply to packets that I've sent out". Without that, you may never get responses back to things you've attempted to talk to outside. For example, I would very much suspect that yum won't work any more...

The second one allows ICMP packets from anywhere. There are two schools of thought on this, one that says that the RFCs say you should respond to ICMP as a matter of good netiquette, the other that you should hide yourself as much as possible and never reply to them.

The third is also important as it allows all traffic on the localhost interface and there are many things that use this to talk to themselves or to other things on the same host. Without this rule or something equivalent you can expect weird stuff to fail with not much idea of why.

So those are the things you are missing and might cause you problems. The next thing is that you allow all of those subnets to talk to all ports on your server, databases, mail servers, everything that listens on your server that doesn't just listen on localhost in fact. That could be quite a lot and you are opening that up to 5 separate blocks of 256 hosts each.

Using an ipset is pretty easy, you just need a rule like this one

-A INPUT -p tcp -m set --match-set MY_IPS src -m state --state NEW -m tcp --dport 22 -j ACCEPT

and that allows all subnets/ips listed in the MY_IPS subnet to have access to port 22.
The future appears to be RHEL or Debian. I think I'm going Debian.
Info for USB installs on http://wiki.centos.org/HowTos/InstallFromUSBkey
CentOS 5 and 6 are deadest, do not use them.
Use the FAQ Luke

User avatar
jlehtone
Posts: 4530
Joined: 2007/12/11 08:17:33
Location: Finland

Re: Simplifing IPTABLES rule set

Post by jlehtone » 2022/03/29 07:52:12

Building on what TrevorH said,

Code: Select all

-N friends

-P INPUT DROP
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -s 1.1.1.42 -j friends
-A INPUT -m set --match-set MY_IPS src -j friends
-A INPUT -j DROP

-A friends -p tcp  -m state --state NEW -m tcp --dport  22 -m comment --comment "SSH"   -j ACCEPT
-A friends -p tcp  -m state --state NEW -m tcp --dport 443 -m comment --comment "HTTPS" -j ACCEPT
-A friends -p icmp -j ACCEPT
-A friends -m conntrack --ctstate INVALID -j DROP
-A friends -j REJECT --reject-with icmp-host-prohibited
Now the policy of INPUT is DROP. Nothing is accepted without explicit rules.
The first rule in INPUT handles most of packets.
We ensure that at least 1.1.1.42 can connect even when MY_IPS is empty.

What we do with traffic from "friends" is in separate chain. You could have plain ACCEPT there as last rule if you really want.


PS.
Red Hat has backported nftables into the kernel of EL7. It is possible to run nftables.service, rather than iptables.service.
The command-line tool for nftables is nft. Nftables has "named sets" that seems to be equivalent of ipsets.
It is worthwhile to learn the syntax of nftables, because iptables is deprecated in RHEL.

gtinet
Posts: 4
Joined: 2022/03/28 23:56:36

Re: Simplifing IPTABLES rule set

Post by gtinet » 2022/03/30 19:31:59

TrevorH and jlehtone, I sincerely appreciate your insightful responses. Below is the current iptables script that I inherited when I took over the mail server. As I understand it, this blocks everything in the set named Block_CIDR then accepts all other traffic with the correct dport. It also allows two specific hosts to access the server via ssh. I am always modifying Block_CIDR by adding additional CIDR blocks, or removing one that has an IP in it that needs access.

At this point I would guess it's best to continue to use ipset, but for allowed addresses instead of blocked addresses. Can you suggest what that would look like? Many Thanks!


#!/bin/bash

# iptables configuration script

# Flush all current rules from iptables
iptables -F

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -N LOG_AND_DROP
iptables -A LOG_AND_DROP -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
iptables -A LOG_AND_DROP -j DROP

iptables -A INPUT -m set --match-set Block_CIDR src -j LOG_AND_DROP

iptables -A INPUT -p tcp --dport 22 --source x.x.x.x/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 --source x.x.x.x/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 993 -j ACCEPT
iptables -A INPUT -p tcp --dport 25 -j ACCEPT
iptables -A INPUT -p tcp --dport 465 -j ACCEPT
iptables -A INPUT -p tcp --dport 8443 -j ACCEPT
iptables -A INPUT -p tcp --dport 587 -j ACCEPT
iptables -A INPUT -p tcp --dport 995 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport 7071 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 10000 -j ACCEPT
iptables -A INPUT -p tcp --dport 110 -j ACCEPT
iptables -A INPUT -p tcp --dport 143 -j ACCEPT
iptables -A INPUT -p tcp --dport 8008 -j ACCEPT

iptables -P INPUT DROP

# Save settings
/sbin/service iptables save

User avatar
jlehtone
Posts: 4530
Joined: 2007/12/11 08:17:33
Location: Finland

Re: Simplifing IPTABLES rule set

Post by jlehtone » 2022/03/31 07:43:11

I basically did show in my previous comment.

Note that x.x.x.x/24 looks like subnet, not one address. One host would be x.x.x.x

User avatar
TrevorH
Site Admin
Posts: 33219
Joined: 2009/09/24 10:40:56
Location: Brighton, UK

Re: Simplifing IPTABLES rule set

Post by TrevorH » 2022/03/31 07:56:06

You might also look at something like fail2ban to monitor your logs and add/remove ip addresses dynamically from the block list based on their curretn activity. I'd use that in addition to your current ipset and tweak that to just ban those things that really are persistent offenders.
The future appears to be RHEL or Debian. I think I'm going Debian.
Info for USB installs on http://wiki.centos.org/HowTos/InstallFromUSBkey
CentOS 5 and 6 are deadest, do not use them.
Use the FAQ Luke

gtinet
Posts: 4
Joined: 2022/03/28 23:56:36

Re: Simplifing IPTABLES rule set

Post by gtinet » 2022/04/01 15:33:05

jlehtone wrote:
2022/03/31 07:43:11
I basically did show in my previous comment.

Note that x.x.x.x/24 looks like subnet, not one address. One host would be x.x.x.x
Thank you jlehtone. So, taking your example I added what I think are the important bits from my config and came up with the following. To summarize, I will be using IPSET to create MY_IPS which will be used for friendly IPs. The friendly IPs and the two subnets that are explicitly stated are the only ones that can communicate with the server and only on the ports specified. Do I understand this correctly? Thanks again, Kevin.

#!/bin/bash

# iptables configuration script

# Flush all current rules from iptables
iptables -F

-N friends

-P INPUT DROP
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -s x.x.x.0/24 -j friends
-A INPUT -s x.x.x.0/24 -j friends
-A INPUT -m set --match-set MY_IPS src -j friends
-A INPUT -j DROP

-A friends -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 993 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 465 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 8443 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 587 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 995 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 7071 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 10000 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 110 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 143 -j ACCEPT
-A friends -p tcp -m state --state NEW -m tcp --dport 8008 -j ACCEPT
-A friends -p icmp -j ACCEPT
-A friends -m conntrack --ctstate INVALID -j DROP
-A friends -j REJECT --reject-with icmp-host-prohibited

# Save settings
/sbin/service iptables save

User avatar
TrevorH
Site Admin
Posts: 33219
Joined: 2009/09/24 10:40:56
Location: Brighton, UK

Re: Simplifing IPTABLES rule set

Post by TrevorH » 2022/04/01 16:28:04

If this is a mail server that needs to accept mail from outside sources then you will not be able to lock down port 25 to just your "friends". Anyone and everyone that sends you mail needs to be able to talk to port 25 or the mail will never be delivered.
The future appears to be RHEL or Debian. I think I'm going Debian.
Info for USB installs on http://wiki.centos.org/HowTos/InstallFromUSBkey
CentOS 5 and 6 are deadest, do not use them.
Use the FAQ Luke

User avatar
jlehtone
Posts: 4530
Joined: 2007/12/11 08:17:33
Location: Finland

Re: Simplifing IPTABLES rule set

Post by jlehtone » 2022/04/01 16:47:30

You obviously need to insert the "iptables " into those rule lines.
Bash will not undertand commands, like "-N friends". It should be "iptables -N friends".

Are the x.x.x and x.x.x different obfuscated subnets in the:

Code: Select all

iptables -A INPUT -s x.x.x.0/24 -j friends
iptabels -A INPUT -s x.x.x.0/24 -j friends
gtinet wrote:It also allows two specific hosts to access the server via ssh.
Your new ruleset allows all "friends" to connect with ssh. That is different from your old.

Code: Select all

iptables -A INPUT -s a.b.c.d -p tcp -m state --state NEW -m tcp --dport  22 -m comment --comment "Admin SSH" -j ACCEPT
iptables -A INPUT -m set --match-set MY_IPS src -j friends

# no ssh-rule in friends
Now (only) host "a.b.c.d" can access with SSH. It can access other services too, if it is in MY_IPS.

You have 14 ports in your rules. Do you know why each of them is there?
Adding comments into the rules documents the purpose of each port and keeps that documentation "near" the rules.

gtinet
Posts: 4
Joined: 2022/03/28 23:56:36

Re: Simplifing IPTABLES rule set

Post by gtinet » 2022/04/04 21:56:58

Thanks again for your response jlehtone. I understand that the script will require the iptables command so I have added it here for clarification.

I removed the following two lines because those subnets will be in MY_IPS.
iptables -A INPUT -s x.x.x.0/24 -j friends
iptables -A INPUT -s x.x.x.0/24 -j friends

The remaining ports are needed by my installation of ZIMBRA Mail Server.

Can you explain the following two lines? The first one appears to accept icmp from 'friends'. The second seems to reject icmp.
iptables -A friends -p icmp -j ACCEPT
iptables -A friends -j REJECT --reject-with icmp-host-prohibited



#!/bin/bash

# iptables configuration script

# Flush all current rules from iptables
iptables -F

iptables -N friends

iptables -P INPUT DROP
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -s 12.34.56.78 -m comment --comment "Access from Office Public IP" -j ACCEPT
iptables -A INPUT -m set --match-set MY_IPS src -j friends
iptables -A INPUT -j DROP

iptables -A friends -p tcp -m state --state NEW -m tcp --dport 22 -m comment --comment "SSH Access" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 443 -m comment --comment "HTTPS Webmail" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 993 -m comment --comment "SSL IMAP" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 25 -m comment --comment "SMTP" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 465 -m comment --comment "SSL SMTP" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 8443 -m comment --comment "HTTPS Webmail" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 587 -m comment --comment "TLS SMTP" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 995 -m comment --comment "SSL POP3" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 7071 -m comment --comment "Mgmt GUI" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 80 -m comment --comment "HTTP Webmail" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 10000 -m comment --comment "Mgmt GUI" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 110 -m comment --comment "POP3" -j ACCEPT
iptables -A friends -p tcp -m state --state NEW -m tcp --dport 143 -m comment --comment "IMAP" -j ACCEPT
iptables -A friends -p icmp -j ACCEPT
iptables -A friends -m conntrack --ctstate INVALID -j DROP
iptables -A friends -j REJECT --reject-with icmp-host-prohibited

# Save settings
/sbin/service iptables save

Post Reply