What is the difference between these 2 iptables rules?

Solution 1:

Both of those sets of rules have problems, and I wouldn't use either of them as-is.


In the first set, the first rule allows new incoming traffic to destination port 22 from anywhere. This isn't a problem.

The first problem is that the second rule allows new incoming traffic to destination port 22 from a specific subnet. This is completely redundant since the first rule has allowed traffic from anywhere.

My guess is that you read some tutorial which used these rules as (mutually exclusive) examples, advising you to select one or the other, but not both.

The second problem is that another rule is required before this rule to make the firewall fully stateful, and that rule is missing here. Without this rule, only the SYN packet would be allowed, and the connection would never complete.

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

The second set of rules has a similar problem. I don't know who originally wrote this ruleset, but it's been widely copied all over the Internet. It seems to have been written by someone who was unfamiliar with stateful firewalls in general, or iptables in particular.

In this ruleset, the input rule allows new and established incoming traffic to destination port 22 from anywhere. Then, the output rule allows established traffic from source port 22 to anywhere. This is essentially a mirror of the first rule and something like it is required if your default policy on outgoing traffic is to drop or reject it.

The problem is that these outbound rules become redundant very fast, which leads to performance issues as well as comprehension problems for any humans who have to read the rules later. If you are dropping outgoing traffic, only one rule is needed for established outgoing traffic (matching allowed incoming traffic) on any port, regardless of how many incoming ports you allow.

-A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

For a host firewall where the default input policy is to deny trafic and the default output policy is to permit traffic, most all of your rules will be in the INPUT table. It's sufficient to have the stateful rule and then rules to open ports for any incoming traffic you need.

For example, to allow ssh and http connections:

-P INPUT DROP
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT

If you're also denying output traffic by default, then you need to allow the return traffic for these allowed inbound connections as well.

-P OUTPUT DROP
-A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

And that is a firewall that's about as simple and effective as iptables can be.

Solution 2:

The top one seems a little confused about what it's trying to do, it only seems to be allowing ssh packets in if iptables hasn't seen traffic in both directions, very strange.

The bottom one is much more sensible but the 2nd line is redundant unless you have a policy of other than ACCEPT on your OUTPUT chain. (iptables -L and look for "Chain OUTPUT (policy XXXXXX)").

You probably just want the first line of the bottom set.

Solution 3:

line 1 of First Set will allow INBOUND port 22 traffic if connection = NEW CONNECTION. Line 2 of First set seems to be not necessary due to only allows port 22 traffic for a set network range also must be a new connections. Howver the previous rule on line 2 has already allowed the traffic through.
This seem wrong or incomplete

2nd set line 1, Allow INBOUND traffic on the0 if port = 22 and is new or established connections Line 2, Alllow OUTBOUND traffic if device = eth0 & port = 22 & connection is established

This will allow SSH connections to this host and will also allow outgoing SSH.

2 nd set is your better option