Configuring iptables firewall RedHat/CentOS 6 from command line

IPTABLES is the firewall kernel-level included in Linux distributions, it’s very powerful (once understood its operation), very useful and flexible. This post has been made on a CentOS 6 (clone of RedHat), almost all should be able to apply to any distribution.

The basic operation of iptables is the following:

  1. Exist chains of rules. Basically 3: INPUT, OUTPUT and FORWARD.
  2. The rules within a chain are evaluated in order. This is where there is a multitude of filtering options.
  3. When a rule is evaluated positively, it is directed at a TARGET. It can be accepted, rejected, deleted, written in a log or other much more (see man TARGET EXTENSIONS iptables).

We can list the current rules:

Source   
/sbin/iptables -L

The list of ports and services can be viewed at:

Source   
/etc/services

iptables works with concept the chains (chains), 3 types:

  • INPUT, incoming traffic.
  • OUTPUT, outgoing traffic.
  • FORWARD, traffic through the machine.

IPTABLES syntax (very summarized, for more details see man):

Source   
iptables [-t tabletype] COMMAND  [-m MATCH_EXTENSION] -j TARGET

tabletype=>

  • filter, packet filtering (default)
  • nat, NAT configuration or masking

<COMMAND>=>

  • -A, –append chain rule-specification, add a rule to the end of the chain
  • -D –delete chain [rulenum|rule-specification] , remove a rule. If specified by rulenum, the first rule is one.
  • -I, –insert chain [rulenum] rule-specification, insert a rule before numrule (by default 1, the first)
  • -R, –replace chain rulenum rule-specification, replace a rule inside of chain (numrule=1 is the first)
  • -L, –list [chain], list of rules
  • -F, –flush [chain], flush of rules in actual chains

<rule-specification>=>

  • [!] -s –source address[/mask], package source, can be an ip with or without mask or the name of a host.
  • [!] -d –destination address[/mask], packet destination, can be an IP with or without mask or the name of a host (note that the name is only resolved once the rules before sending the kernel).
  • [!] -p –protocol, protocol used in the communication: tcp, udp, udplite, icmp, esp, ah, sctp o all
  • [!] –source-port,–sport port[:port], port or port range of source communication
  • [!] –destination-port,–dport port[:port], port or port range of destination communication
  • [!] -i –in-interface name, name input interface communication. By default all interfaces.
  • [!] -o –out-interface name, name output interface communication. By default all interfaces.

If prepends a !, this means that we are denying the condition.

<MATCH_EXTENSION>, You can be specified with -m or –match

  • state, allows filtering by connection status. options:
    • [!] –state STATE, you can specify several states using as separator “,”. The states include:
      • -INVALID, invalid package.
      • -NEW, new connection.
      • -ESTABLISHED, existing connection.
      • -RELATED, relating to another connection.

For example, accept all connections or established(is best to apply filtering only connections NEW):

Source   
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
  • comment, apply comments to a rule. Options:
    • –comment COMMENT

Example:

Source   
iptables -A INPUT -m state --state ESTABLISHED,RELATED -m comment --comment "Allow connections existing" -j ACCEPT
  • mac, apply MAC filtering, is not applicable to the OUTPUT chain. Options:
    • [!] –mac-source address, the MAC format is XX:XX:XX:XX:XX:XX

Example:

Source   
iptables -A INPUT -p TCP --dport 80 -m mac --mac-source FE:54:00:FC:4F:CC -j ACCEPT
  • limit, applying limits averages and bursts . Options:
    • –limit rate[/second|/minute|/hour|/day], specifies an average frequency per unit time.
    • –limit-burst number, specifies a number of requests to which the limit will not apply. Once surpassed will stick to the specification limit.

Example, take an average of 1 connection per second with bursts of 2:

Source   
iptables -A INPUT -m state --state NEW -p tcp --dport 25 -m limit --limit 1/second --limit-burst 2 -j ACCEPT

<TARGET>=>

  • DROP, remove package without informing the sender.
  • REJECT, remove package informing with error to sender, by default return port-unreachable.  by default. The reported error can define: –reject-with [icmp-net-unreachable, icmp-host-unreachable, icmp-port-unreachable, icmp-proto-unreachable, icmp-net-prohibited, icmp-host-prohibited, icmp-admin-prohibited].
  • ACCEPT, accepted package.
  • LOG, is a TARGET EXTENSIONS. Write something in the log, you can set the prefix with –log-prefix “text_of_prefix”. By default written to /var/log/messages.

Example, to allow ICMP port 22, accept port 80 for a specific MAC, deny all connections to port 80 and write log, limiting traffic to port 22 and write log, allow outbound connections from port 22, eliminate all outbound connections and allow communications through the machine:

Source   
#!/bin/bash
#flush all rules and all chains
iptables -F
#incoming traffic
iptables -A INPUT -m state --state ESTABLISHED,RELATED -m comment --comment "Allow existing connections" -j ACCEPT
iptables -A INPUT -p icmp -m comment --comment "Allow ping" -j ACCEPT
iptables -A INPUT -i lo -m comment --comment "Allow internal connections" -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -m comment --comment "Allow port 22" -j ACCEPT
iptables -A INPUT -p TCP --dport 80 -m mac --mac-source FE:54:00:FC:4F:CC -m comment --comment "Allow port 80, filtering for an MAC" -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 80 -m comment --comment "Write log access attempts to port 80" -j LOG --log-prefix "deny_port_80"
iptables -A INPUT -m state --state NEW -p tcp --dport 80 -m comment --comment "Remove access port 80" -j DROP
iptables -A INPUT -m state --state NEW -p tcp --dport 25 -m limit --limit 1/second --limit-burst 2 -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 25 -j LOG --log-prefix "DDOS attack port 25"
iptables -A INPUT -m comment --comment "Remove everything else" -j DROP
#outgoing traffic
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -m comment --comment "Allow existing outgoing connections" -j ACCEPT
iptables -A OUTPUT -m state --state NEW -p tcp --dport 22 -m comment --comment "Allow port 22 outgoing" -j ACCEPT
iptables -A OUTPUT -m comment --comment "Remove all other outgoing" -j DROP
#internal traffic
iptables -A FORWARD -m comment --comment "Allow all internal traffic" -j ACCEPT

Comments help much to identify the task of each of the rules:

Source   
[root@tester1 ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED /* Allow existing connections */
ACCEPT icmp -- anywhere anywhere /* Allow ping */
ACCEPT all -- anywhere anywhere /* Allow internal connections */
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh /* Allow port 22 */
ACCEPT tcp -- anywhere anywhere tcp dpt:http MAC FE:54:00:FC:4F:CC /* Allow port 80, filtering for an MAC */
LOG tcp -- anywhere anywhere state NEW tcp dpt:http /* Write log access attempts to port 80 */ LOG level warning prefix `deny_port_80'
DROP tcp -- anywhere anywhere state NEW tcp dpt:http /* Remove access port 80 */
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:smtp limit: avg 1/sec burst 2
LOG tcp -- anywhere anywhere state NEW tcp dpt:smtp LOG level warning prefix `DDOS attack port 25'
DROP all -- anywhere anywhere /* Remove everything else */
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere /* Allow all internal traffic */
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED /* Allow existing outgoing connections */
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh /* Allow port 22 outgoing */
DROP all -- anywhere anywhere /* Remove all other outgoing */

Now from outside the machine we can try (4 times in less than 2 seconds) one:

Source   
[jcmolinos@ppcjuancmolinos ~]$ telnet 192.168.122.150 25
Trying 192.168.122.150...
telnet: connect to address 192.168.122.150: Connection refused

And we will see in the log /var/log/messages:

Source   
8.122.150 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=1351 DF PROTO=TCP SPT=46644 DPT=25 WINDOW=14600 RES=0x00 SYN URGP=0
Mar 7 20:38:03 tester1 yum: Installed: wget-1.12-1.4.el6.i686

Application of rules automatically

If we activated at start the iptables service:

Source   
[root@tester1 ~]# chkconfig --list iptables
iptables 0:off 1:off 2:on 3:on 4:on 5:on 6:off

For the rules to be permanent they are to be included in the file:

Source   
/etc/sysconfig/iptables

Content example:

Source   
[root@tester1 sysconfig]# cat iptables
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -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
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

Manual editing is not recommended you should use system-config-firewall, or never use it directly and thus does not overwrite our rules.

What you can do is make all changes in iptables as we have seen above and then directly to:

Source   
/etc/init.d/iptables save

This updates the file:

Source   
/etc/sysconfig/iptables

With the rules we have in memory until now, we ensure that the iptables service with automatic start is that the rules are applied in the next boot.

Source   
[root@tester1 ~]# chkconfig iptables on

Keep in mind that the utilities system-config-firewall-tui and system-config-firewall override these settings, I prefer not to use them.

Leave a Reply