How to block sites with iptables

I would like to block sites using iptables. How do I go about this, and how do I ensure that the iptables rules are saved?


Solution 1:

Blocking sites with iptables rules is a very bad idea, mainly because iptables (as most firewalls) deals with the IP addresses, and relationship between a site and its IP address(es) is rather loose:

  1. One site can have many IP addresses, which can be changed rather frequently. Once iptables rules are created, even if you specify a site's name as part of a rule, the first IP address at that moment is used. If site's address changes, your iptables rules will be out of date.

  2. One IP address can host many sites (and it happens often). This will only get more frequent, because of the IP address scarcity. If you block an IP address, you block all sites hosted on it.

So, even though other answers explain how you do it, I urge you to seek some other solution. For example, installing a transparent http proxy will achieve what you need. This transparent HTTP proxy HOWTO is a bit outdated, but it will help you get started.

Once you have a transparent proxy, you can add arbitrary rules to it to block specific sites, you don't even need to use the caching feature of squid, if you don't want it.

There are other ways to handle site blocking (other firewalls, proxies, etc.), but iptables rules is pretty much one of the worst possible ways to handle it.

Solution 2:

You can use iptables string matching to achieve this:

iptables -A OUTPUT -p tcp -m string --string "block-me.com" --algo kmp -j REJECT

-A OUTPUT adds the following rule to the OUTPUT chain.

-m string --string "block-me.com" --algo kmp tells iptables to look for the string block-me.com using the Knuth-Morris-Pratt matching algorithm.

The easiest way to make your iptables are restored when you restart your machine is to install the package iptables-persistent if available on your system. If you install the package after you set the new rules you will be asked if you want to save the presently used rules for permanent use. iptables-persistent basically just loads the rules saved in files /etc/iptables/rules.v4 and /etc/iptables/rules.v6.

If you change your rules again, to save changes and restore them at a reboot, you have to save them to the above mentioned files using the commands

iptables-save > /etc/iptables/rules.v4
iptables-save > /etc/iptables/rules.v6

They will now be restored at a reboot.

Actually you don't need iptables-persistent either. This question has another almost as simple solution.

Note that you need to run iptables-save as root, or with sudo like this:

sudo bash -c "iptables-save > /etc/iptables/rules.v4"

If you just run sudo iptables-save > /etc/iptables/rules.v4 you will get an "access denied" message for rules.v4.