Work with IPTables

Nowadays I happened to IPTables again. To be honest, I'm not familiar with it. This post is just my note about working with IPTables these days.

What's iptables?

CentOS has a powerful firewall, that's called iptables, aka iptables/netfilter. It's the userscope module, and netfilter is a kernel module, built into the kernel, that actually does the filtering.

IPTables places rules into predefined chains(INPUT, OUTPUT and FORWORD) that are checked against any traffic(IP packets) relevant to those chains. And a decision is made about what to do with each packet based upon the outcome of those rules, for example, accepting or dropping.

Chains

There are 3 predefined chains in the filter table to which we can add rules for processing IP packets passing through those chains.

  • INPUT - All packets destined for the host computer.
  • OUTPUT - All packets originating from the host computer.
  • FORWARD - All packets neither destined for nor originating the host, but passing through the host computer.

A packet is checked against each rule in turn, starting at the top, and if it matches the rule, then an action is taken such as accepting(ACCEPT) or dropping (DROP) the packet. Once a rule has been matched and an action taken, then the packet is processed according to the outcome of that rule and isn't processed by further rules in the chain.

Begin Start

We can use iptables -L to inspect the currently loaded rules. This is aliyun server, we can see the default set of rules. The default set seems that the firewall is the same as closed.

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

P.S. If iptables is not running, you can enable it by running:

# system-config-securitylevel

Server Setups

At first, I'll explain our server setups. We have 5 servers totally. And we use Load Balancer policy to setup our servers:

  1. One Load Balancer Server(Reverse Proxy)
  2. Three app-backend Servers
  3. One Database Server

OK, it's time to go start. At first, we decide the following basic iptables policies. For Reverse Proxy server, we only open port 22 and 80, allowing tcp packets that have specific bits(flags) set, to match a rule. For three app-backend servers, we just open port 22 and 80. For database server, we open the port 22 and database port.

Set IPTables Rule (Load Balancer Server)

At first, we may add a rule allowing SSH connections over tcp port 22. This is to prevent accidental lockouts when working on remote systems over an SSH connection.

# iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT

And the same as HTTP connections over tcp port 80.

# iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

Then we may allow all incoming packets destined for the localhost interface to be accepted. This is generally required as many software applications expect to be able to communicate with the localhost adaptor.

# iptables -A INPUT -i lo -j ACCEPT

After these basic setting rules, we add three tcp packets that have specific bits (flags) rules.

# -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP 
# -A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP
# -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP

Then we add the last rule to the INPUT chain. ESTABLISHED and RELATED refers to incoming packets that are part of an already established connection or related to and already established connection.

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

At last, we set the default policy on the INPUT chain and FORWARD chain.

# iptables -P INPUT DROP
# iptables -P FORWARD DROP

Now we can see our iptables setting.

# iptables -S
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
-A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

It seems fine, and our iptables on Reverse Proxy Server needs to be saved.

# /sbin/service iptables save

For other three app-backend servers:

# iptables -S
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

And the database server:

# iptables -S
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport [Your_database_port] -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

End

If you have something to correct, welcome to point it out:D

References: