Basic iptables Rulesets for IPv4 and IPv6
Appropriate firewall rules heavily depend on the services being run. Below are iptables rulesets to secure your Linode if you’re running a web server. These are given as an example! A real production web server may want or require more or less configuration and these rules would not be appropriate for a file or database server, Minecraft or VPN server, etc.
iptables rules can always be modified or reset later, but these basic rulesets serve only as a beginning demonstration.
IPv4
- /tmp/v4
*filter # Allow all loopback (lo0) traffic and reject traffic # to localhost that does not originate from lo0. -A INPUT -i lo -j ACCEPT -A INPUT ! -i lo -s 127.0.0.0/8 -j REJECT # Allow ping and traceroute. -A INPUT -p icmp --icmp-type 3 -j ACCEPT -A INPUT -p icmp --icmp-type 8 -j ACCEPT -A INPUT -p icmp --icmp-type 11 -j ACCEPT # Allow SSH connections. -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT # Allow HTTP and HTTPS connections from anywhere # (the normal ports for web servers). -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # Accept inbound traffic from established connections. -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Log what was incoming but denied (optional but useful). -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables_INPUT_denied: " --log-level 7 # Reject all other inbound. -A INPUT -j REJECT # Log any traffic which was sent to you # for forwarding (optional but useful). -A FORWARD -m limit --limit 5/min -j LOG --log-prefix "iptables_FORWARD_denied: " --log-level 7 # Reject all traffic forwarding. -A FORWARD -j REJECT COMMIT Optional: If you plan to use Linode Longview, add this additional rule below the section for allowing HTTP and HTTPS connections:
# Allow incoming Longview connections -A INPUT -s longview.linode.com -m state --state NEW -j ACCEPT
IPv6
If you would like to supplement your web server’s IPv4 rules with IPv6 too, this ruleset will allow HTTP(S) access and all ICMP functions.
- /tmp/v6
*filter # Allow all loopback (lo0) traffic and reject traffic # to localhost that does not originate from lo0. -A INPUT -i lo -j ACCEPT -A INPUT ! -i lo -s ::1/128 -j REJECT # Allow ICMP -A INPUT -p icmpv6 -j ACCEPT # Allow HTTP and HTTPS connections from anywhere # (the normal ports for web servers). -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # Accept inbound traffic from established connections. -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Log what was incoming but denied (optional but useful). -A INPUT -m limit --limit 5/min -j LOG --log-prefix "ip6tables_INPUT_denied: " --log-level 7 # Reject all other inbound. -A INPUT -j REJECT # Log any traffic which was sent to you # for forwarding (optional but useful). -A FORWARD -m limit --limit 5/min -j LOG --log-prefix "ip6tables_FORWARD_denied: " --log-level 7 # Reject all traffic forwarding. -A FORWARD -j REJECT COMMIT
- /tmp/v6
*filter # Reject all IPv6 on all chains -A INPUT -j REJECT -A FORWARD -j REJECT -A OUTPUT -j REJECT
- Create the files
/tmp/v4
and/tmp/v6
. Paste the above rulesets into their respective files. - Import the rulesets into immediate use.
1 2
sudo iptables-restore < /tmp/v4 sudo ip6tables-restore < /tmp/v6
- iptables-persistent automates loading iptables rules on boot for Debian and Ubuntu. Install it from the distro repositories.
1
sudo apt-get install iptables-persistent
- You’ll be asked if you want to save the current IPv4 and IPv6 rules. Answer
yes
to each prompt. - Remove the temporary rule files.
1
sudo rm /tmp/{v4,v6}
- Install Fail2Ban by entering the following command:Debian/Ubuntu
1
sudo apt-get install fail2ban
Fedora
1
sudo dnf install fail2ban
CentOS
1
sudo yum install epel-release && sudo yum install fail2ban
- Optionally, you can override the default Fail2Ban configuration by creating a new
jail.local
file. Enter the following command to create the file:sudo nano /etc/fail2ban/jail.local
To learn more about Fail2Ban configuration options, see this article on the Fail2Ban website.
- Set the
bantime
variable to specify how long (in seconds) bans should last. - Set the
maxretry
variable to specify the default number of tries a connection may be attempted before an attacker’s IP address is banned. - Press
Control-x
and then pressy
to save the changes to the Fail2Ban configuration file. - Then restart Fail2Ban:If you’re using a distribution which uses systemd:
sudo systemctl restart fail2ban
- If your init system is SystemV or Upstart:
sudo service fail2ban restart
Alternatively, the ruleset below should be used if you want to reject all IPv6 traffic:
APT attempts to resolve mirror domains to IPv6 as a result of
apt-get update
. If you choose to deny IPv6 entirely, this greatly slows down the update process for Debian and Ubuntu because APT waits for each resolution to time out before moving on.To remedy this, uncomment the line
precedence ::ffff:0:0/96 100
in/etc/gai.conf
. This is not necessary for Pacman, DNF or Yum.
How these IPv4 and IPv6 rules are deployed differs among the various Linux distros.
Debian / Ubuntu
ufw is the iptables controller included with Ubuntu but is also available in Debian’s repositories. If you would prefer to use ufw instead of ipables, see our ufw guide to get a ruleset up and running.
Verify iptables Rulesets
Recheck your Linode’s firewall rules:
1 2 | sudo iptables -L sudo ip6tables -L |
The output should show for IPv4 rules:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere REJECT all -- anywhere loopback/8 reject-with icmp-port-unreachable ACCEPT icmp -- anywhere anywhere icmp destination-unreachable ACCEPT icmp -- anywhere anywhere icmp echo-request ACCEPT icmp -- anywhere anywhere icmp time-exceeded ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh ACCEPT tcp -- anywhere anywhere tcp dpt:http ACCEPT tcp -- anywhere anywhere tcp dpt:https ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED LOG all -- anywhere anywhere limit: avg 5/min burst 5 LOG level debug prefix "iptables_INPUT_denied: " REJECT all -- anywhere anywhere reject-with icmp-port-unreachable Chain FORWARD (policy ACCEPT) target prot opt source destination LOG all -- anywhere anywhere limit: avg 5/min burst 5 LOG level debug prefix "iptables_FORWARD_denied: " REJECT all -- anywhere anywhere reject-with icmp-port-unreachable Chain OUTPUT (policy ACCEPT) target prot opt source destination |
Output for IPv6 rules will look like this:
1 2 3 4 5 6 7 8 9 10 11 | Chain INPUT (policy ACCEPT) target prot opt source destination REJECT all anywhere anywhere reject-with icmp6-port-unreachable Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all anywhere anywhere reject-with icmp6-port-unreachable Chain OUTPUT (policy ACCEPT) target prot opt source destination REJECT all anywhere anywhere reject-with icmp6-port-unreachable |
Your firewall rules are now in place and protecting your Linode. Remember, you may need to edit these rules later if you install other packages which require network access.
Inserting, Replacing or Deleting iptables Rules
iptables rules are enforced in a top-down fashion, so the first rule in the ruleset is applied to traffic in the chain first, then the second, third and so on. This means that rules can not necessarily be added to a ruleset with iptables -A
or ip6tables -A
. Instead, we must insert a rule with iptables -I
or ip6tables -I
.
Insert
Inserted rules need to be placed in the correct order with respect other rules in the chain. To get a numerical list of your iptables rules:
1 | sudo iptables -L --line-numbers |
For example, let’s say we want to insert a rule into the ruleset above which accepts incoming Linode Longview connections. We’ll add it as rule 9 to the INPUT chain, following the web traffic rules.
1 | sudo iptables -I INPUT 9 -p tcp --dport 8080 -j ACCEPT |
If you now run sudo iptables -L
again, you’ll see the new rule in the output.
Replace
Replacing a rule is similar to inserting but instead uses iptables -R
. For example, let’s say you want to reduce the logging of denided entires to only 3 per minute, down from 5 in the original ruleset. The LOG rule is the 11th in the INPUT chain:
1 | sudo iptables -R INPUT 11 -m limit --limit 3/min -j LOG --log-prefix "iptables_INPUT_denied: " --log-level 7 |
Delete
Deleting a rule is also done with the rule number. For example, to delete the rule we just inserted for Linode Longview:
1 | sudo iptables -D INPUT 9 |
Editing rules does not automatically save them! To this, see the area above for your distro and save your iptables edits so they’re loaded on reboots.
Installing and Configuring Fail2Ban
Fail2Ban is an application that prevents dictionary attacks on your server. When Fail2Ban detects multiple failed login attempts from the same IP address, it creates temporary firewall rules that block traffic from the attacker’s IP address. Attempted logins can be monitored on a variety of protocols, including SSH, HTTP, and SMTP. By default, Fail2Ban monitors SSH only.
Here’s how to install and configure Fail2Ban:
Fail2Ban is now installed and running on your Linode. It will monitor your log files for failed login attempts. After an IP address has exceeded the maximum number of authentication attempts, it will be blocked at the network level and the event will be logged in /var/log/fail2ban.log
.
Next Steps
Good work! You have secured your Linode to harden it against unauthorized access. Next, you’ll learn how to host a website. Start reading the Hosting a Website quick start guide to get going!