Replace firewalld with iptables in CentOS 7

This is a short HOWTO replace or disable firewalld with iptables in CentOS 7.

Install iptables service
# yum -y install iptables-services

If you would like to save the firewall rules you need to run the following command
# iptables-save > iptables-rules.txt

These rules can be added to /etc/sysconfig/iptables but I usually use the rules that come with iptables package and add my rules to better suit my needs.

# systemctl enable iptables
# systemctl enable ip6tables

Stop firewalld
# systemctl stop firewalld

Disable firewalld
# systemctl disable firewalld

Start iptables service
# systemctl start iptables
# systemctl start ip6tables

And thats it.

Note
Always make sure that you are not locking yourself out of your server when starting the iptables firewall.

iptables connection tracking table full

I’ve recently experienced that my workstation (Ubuntu Jaunty Jackalope, 9.04, x86_64) “hangs” periodically when my internet browser, Mozilla Firefox, has a lot of active tabs.
In my case I had > 100 active tabs in more than 20 windows. I know I should have closed some of them but that is not an option right now.

The problem reveiled itself doing a dmesg on my workstation

# dmesg

[1737157.057528] nf_conntrack: table full, dropping packet.
[1737157.160357] nf_conntrack: table full, dropping packet.
[1737157.260534] nf_conntrack: table full, dropping packet.
[1737157.361837] nf_conntrack: table full, dropping packet.
[1737157.462305] nf_conntrack: table full, dropping packet.
[1737157.564270] nf_conntrack: table full, dropping packet.
[1737157.666836] nf_conntrack: table full, dropping packet.
[1737157.767348] nf_conntrack: table full, dropping packet.
[1737157.868338] nf_conntrack: table full, dropping packet.
[1737157.969828] nf_conntrack: table full, dropping packet.
[1737162.214064] __ratelimit: 53 callbacks suppressed

This bahaviour looks like Denial-Of-Service and is caused by a full iptables connection_table.

The default size of the iptables connection tracing table is

# cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max
65536

The solution I went for was to double the size of connection table to 131072 and restarted firefox.

# echo "131072" > /proc/sys/net/ipv4/netfilter/ip_conntrack_max

This value is a 32-bit integer so the table size can be quite large and you will need much more RAM before you can use this size.

To make this solution permanent I added the following line to /etc/sysctl.conf

net.ipv4.netfilter.ip_conntrack_max = 131072

You can test this by executing the following command

# sysctl -p
131072

This command loads the /etc/sysctl.conf settings.

ufw and IP masquerading

I’ve just upgraded my home server from Ubuntu 8.10 to 9.04 and experienced that my ufw firewall (iptables) would not route traffic from my local network to the Internet. My IP masquerading was not working anymore and since I had not documented the process when I set it up I had to search the Ubuntu pages to find the solution and came up with this.

The purpose of IP Masquerading is to allow machines with private, non-routable IP addresses on your network to access the Internet through the machine doing the masquerading. Traffic from your private network destined for the Internet must be manipulated for replies to be routable back to the machine that made the request. To do this, the kernel must modify the source IP address of each packet so that replies will be routed back to it, rather than to the private IP address that made the request, which is impossible over the Internet. Linux uses Connection Tracking (conntrack) to keep track of which connections belong to which machines and reroute each return packet accordingly. Traffic leaving your private network is thus “masqueraded” as having originated from your Ubuntu gateway machine. This process is referred to in Microsoft documentation as Internet Connection Sharing.

ufw Masquerading

IP Masquerading can be achieved using custom ufw rules. This is possible because the current back-end for ufw is iptables-restore with the rules files located in

/etc/ufw/*.rules

These files are a great place to add legacy iptables rules used without ufw, and rules that are more network gateway or bridge related.

The rules are split into two different files, rules that should be executed before ufw command line rules, and rules that are executed after ufw command line rules.

  • First, packet forwarding needs to be enabled in ufw. Two configuration files will need to be adjusted, in /etc/default/ufw change the
    DEFAULT_FORWARD_POLICY

    to “ACCEPT”:

    DEFAULT_FORWARD_POLICY="ACCEPT"

    Then edit /etc/ufw/sysctl.conf and uncomment:

    net.ipv4.ip_forward=1

    Similarly, for IPv6 forwarding uncomment:

    net.ipv6.conf.default.forwarding=1
  • Now we will add rules to the /etc/ufw/before.rules file. The default rules only configure the filter table, and to enable masquerading the nat table will need to be configured. Add the following to the top of the file just after the header comments:
    # nat Table rules
    *nat
    :POSTROUTING ACCEPT [0:0]
    
    # Forward traffic from eth1 through eth0.
    -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE
    
    # don't delete the 'COMMIT' line or these nat table rules won't be processed
    COMMIT

    The comments are not strictly necessary, but it is considered good practice to document your configuration. Also, when modifying any of the rules files in /etc/ufw, make sure these lines are the last line for each table modified:

    # don't delete the 'COMMIT' line or these rules won't be processed
    COMMIT

    For each Table a corresponding COMMIT statement is required. In these examples only the nat and filter tables are shown, but you can also add rules for the raw and mangle tables.

    [Note]
    In the above example replace eth0, eth1, and 192.168.0.0/24 with the appropriate interfaces and IP range for your network.
  • Finally, disable and re-enable ufw to apply the changes:
    sudo ufw disable && sudo ufw enable

IP Masquerading should now be enabled. You can also add any additional FORWARD rules to the /etc/ufw/before.rules. It is recommended that these additional rules be added to the ufw-before-forward chain.

Source: https://help.ubuntu.com/9.04/serverguide/C/firewall.html

Some iptables tricks

Multiport

The Multiport extension allows you to specify multiple ports and ranges and makes it possible to create complex rules in one line. Here’s an example of how you can allow SSH, Web, IMAP and X terminal traffic

iptables -A INPUT -p tcp -m multiport --dports 22,80,143,6000:6003 -j ACCEPT

The alternative to using this rule would be

iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 143 -j ACCEPT
iptables -A INPUT -p tcp --dport 6000:6003 -j ACCEPT

The multiport directive saves you a lot of lines to maintain and requires less system processing.

Using ufw / iptables in Ubuntu 8.04 LTS

ufw (Uncomplicated Firewall) is a new and easy firewall/iptables tool introduced in Ubuntu 8.04 LTS (Hardy Heron).

ufw is a front-end for iptables-restore, with its rules saved in /etc/ufw/before.rules, /etc/ufw/after.rules and /var/lib/ufw/user.rules. Administrators can customize before.rules and after.rules as desired using the standard iptables-restore syntax. Rules are evaluated as follows: before.rules first, user.rules next, and after.rules last. IPv6 rules are evaluated in the same way, with the rules files named before6.rules, user6.rules and after6.rules.

Please note that ufw status only shows rules added with ufw and not the rules found in the /etc/ufw rules files.

This is a simple example to create a firewall that has a default deny rule and we explicitly tell it what services we would like to allow, like SSH. The order that you type the following commands are vital and should not be changed unless you know what you are doing or you’re not working towards your machine through network/SSH.

Turn on firewall logging

# ufw logging on

Default rule value for the firewall is DENY

# ufw default deny

Allow SSH traffic

# ufw allow ssh/tcp

Start firewall

# ufw enable

You can now check the status of your new firewall

# ufw status

Firewall loaded

To                         Action  From
--                         ------  ----
22:tcp                     ALLOW   Anywhere

We can see that port 22 (SSH) is allowed from everywhere. ufw status only shows rules added with ufw and not the rules found in the /etc/ufw rules files.

Deleting a rule

# ufw delete allow ssh/tcp

You just put a delete in front of the rule you would like to delete.

Limit access to port 22/SSH from subnet 192.168.0.0/255.255.255.0

# ufw allow proto tcp from 192.168.0.0/24 to any port 22

Adding a rule with a range of (multiple) ports is not possible using ufw in Ubuntu 8.04 and 8.10. If I was using iptables the rule would look like this

iptables -A FIREWALL -p tcp --dport 5900:5910 -j ACCEPT

One way to work around this limitation is to do some bash scripting.
This example shows how I manage to open arange of 10 ports for VNC, though not gracefully…

for port in {5900..5910}; do ufw allow proto tcp from any to any port $port; done

Result

To                         Action  From
--                         ------  ----
...
5900:tcp                   ALLOW   Anywhere
5901:tcp                   ALLOW   Anywhere
5902:tcp                   ALLOW   Anywhere
5903:tcp                   ALLOW   Anywhere
...

Adding custom rules without using ufw can be done by adding the rules to the files in /etc/ufw/before.rules and /etc/ufw/after.rules. Rules manually added to /var/lib/ufw/user.rules will be deleted the next time you use ufw from the command line!

These are my custom rules added to /etc/ufw/before.rules

...
*filter
...
:SSH_CHECK - [0:0]
### RULES ###

# Script kiddie check
-A ufw-before-input -p tcp --dport 22 -m state --state NEW -j SSH_CHECK
-A SSH_CHECK -m recent --set --name SSH
-A SSH_CHECK -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP
...

These rules are explained in a earlier post about SSH dictionary prevention

ufw status only shows the part you tell it to modify. The whole iptables output looks like this

# iptables -L -n
Chain INPUT (policy DROP)
target     prot opt source               destination
ufw-before-input  all  --  0.0.0.0/0            0.0.0.0/0
ufw-after-input  all  --  0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy DROP)
target     prot opt source               destination
ufw-before-forward  all  --  0.0.0.0/0            0.0.0.0/0
ufw-after-forward  all  --  0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ufw-before-output  all  --  0.0.0.0/0            0.0.0.0/0
ufw-after-output  all  --  0.0.0.0/0            0.0.0.0/0           

Chain SSH_CHECK (1 references)
target     prot opt source               destination
           all  --  0.0.0.0/0            0.0.0.0/0           recent: SET name: SSH side: source
DROP       all  --  0.0.0.0/0            0.0.0.0/0           recent: UPDATE seconds: 60 hit_count: 4 name: SSH side: source 

Chain ufw-after-forward (1 references)
target     prot opt source               destination
LOG        all  --  0.0.0.0/0            0.0.0.0/0           limit: avg 3/min burst 10 LOG flags 0 level 4 prefix `[UFW BLOCK FORWARD]: '
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           

Chain ufw-after-input (1 references)
target     prot opt source               destination
RETURN     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:137
RETURN     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:138
RETURN     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:139
RETURN     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:445
RETURN     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:67
RETURN     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:68
LOG        all  --  0.0.0.0/0            0.0.0.0/0           limit: avg 3/min burst 10 LOG flags 0 level 4 prefix `[UFW BLOCK INPUT]: '
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           

Chain ufw-after-output (1 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           

Chain ufw-before-forward (1 references)
target     prot opt source               destination
ufw-user-forward  all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           

Chain ufw-before-input (1 references)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           ctstate RELATED,ESTABLISHED
DROP       all  --  0.0.0.0/0            0.0.0.0/0           ctstate INVALID
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 3
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 4
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 11
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 12
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 8
ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp spt:67 dpt:68
ufw-not-local  all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     all  --  224.0.0.0/4          0.0.0.0/0
ACCEPT     all  --  0.0.0.0/0            224.0.0.0/4
ufw-user-input  all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           

Chain ufw-before-output (1 references)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW,RELATED,ESTABLISHED
ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           state NEW,RELATED,ESTABLISHED
ufw-user-output  all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           

Chain ufw-not-local (1 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           ADDRTYPE match dst-type LOCAL
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           ADDRTYPE match dst-type MULTICAST
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           ADDRTYPE match dst-type BROADCAST
LOG        all  --  0.0.0.0/0            0.0.0.0/0           limit: avg 3/min burst 10 LOG flags 0 level 4 prefix `[UFW BLOCK NOT-TO-ME]: '
DROP       all  --  0.0.0.0/0            0.0.0.0/0           

Chain ufw-user-forward (1 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           

Chain ufw-user-input (1 references)

target     prot opt source               destination
SSH_CHECK  tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:4949
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           

Chain ufw-user-output (1 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0