5

I'm trying to block Facebook access from my home system (Ubuntu). I could add facebook.com to /etc/hosts, but that would only prevent accessing facebook.com. There are many other ways I could use facebook, like mbasic.facebook.com, m.facebook.com, touch.facebook.com, the IP address, and so on.

I guess I could use a browser extension to block this, but I'd much prefer a sytem-wide block. I had a look at this question that attempts to solve this using iptables, but that didn't work out - I could still access facebook.com after running this command (I got the range from whois 173.252.120.6 | grep CID):

sudo iptables -A OUTPUT -p tcp --destination-port 80 -d 173.252.64.0/18 -j REJECT 

So my question in essence: how do I block a website, say facebook.com, every way (doesn't have to be 100% fool-proof), that it can't be accessed by any means on the system?

4
  • now am i the only one curious why he wants to block facebook. i know this comment will be flagged but i just couldn't resist.
    – jgr208
    Nov 6, 2014 at 20:10
  • @jgr208 Might be legitimate, or might just be an example. Why does it matter for the purposes of the question what the reason for choosing a particular example is?
    – user
    Nov 6, 2014 at 20:52
  • @MichaelKjörling that is true i was just curious. wasn't trying to offend him at all
    – jgr208
    Nov 6, 2014 at 20:53
  • 1
    @jgr208: "why he wants to block facebook" — It doesn't matter. Nov 7, 2014 at 4:56

2 Answers 2

4

It depends on how foolproof you want the block to be, and how much you control the system. Since you talk about your "home system" and modifying /etc/hosts, I assume that you have legitimate root access and it doesn't need to be totally bullet-proof.

The easiest way to block access to an entire domain is to set up a local DNS "recursive resolver" and configure those domains specifically. Basically, you set up a DNS server (this can certainly run on the same host), point your local system to it, and tell that DNS server to return crafted responses for, for example, the facebook.com domain (or zone, as it is known in DNS parlace). For those, you set up no address records, which will cause any attempt to resolve any host name under facebook.com to return a "host not found".

You can set up such a DNS server either to do all name resolution itself, or to forward anything it does not know about (through its configuration) to some other DNS server; the latter configuration is often referred to as a "forwarding" resolver.

This will work for all access by name under a particular domain (www.facebook.com, m.facebook.com, touch.facebook.com, whatever.somewhere.facebook.com) but not names which are unrelated in DNS (www.facebook.example.com would still work, if that were to go to Facebook). It also won't prevent access by IP address. However, it does make it somewhat less easy to find the IP address in the first place (host or nslookup will likewise say "not found").

If the idea is simply to avoid accidentally browsing onto specific, known domains, this is likely to be good enough. If the idea is to completely block access, then it won't do.


To actually set this up, you first need to decide whether you want a local, fully configured resolver, or if you want a forwarding resolver. There are advantages and disadvantages to both, but for now, I'll show you how to configure a forwarding resolver because that is more likely to fit your use case needs.

There are many different DNS server packages available, but perhaps the best known (certainly one of the best known) in the *nix world is BIND, which is currently at version 9. You don't say which exact version of Ubuntu you are running, so I will take a stab at that you are running 14.04/trusty, which is the current Ubuntu LTS version. Others should not be significantly different.

To install BIND, open a terminal window and issue the command (you will need to provide your password when prompted)

sudo apt-get update
sudo apt-get install -u bind9

Look over the list of packages to be installed presented by the second command, make sure it looks reasonable, and confirm the installation.

The software itself is now installed, and needs to be configured. The main configuration file is /etc/bind/named.conf; open that in an editor (I use gedit here, but any text editor will do):

sudo gedit /etc/bind/named.conf

Make note of the value of the directory setting in the options block. Then, replace the entirety of the configuration file with the following:

options {
  directory "** PAST VALUE GOES IN HERE **";
  forwarders { ** YOUR UPSTREAM DNS SERVER IPS HERE, SEE BELOW ** };
  forward only;
  allow-transfer { "none"; };
  allow-query { "localhost"; };
  allow-update { "none"; };
};

For directory, use the past value (so this will likely be directory "/etc/bind"; but don't take my word for that).

For forwarders { } the format is slightly more involved. Here, list your ISP's (or other upstream) DNS servers by IP address, each IP address followed by a semicolon. You can probably find these in /etc/resolv.conf. Note that if you have a NAT router or similar, it is perfectly possible that it provides DNS forwarding services as well, and if so, you want to use the router's IP address here. For example, if your upstream DNS servers are 192.168.100.1 and 192.168.200.1, then this would become forwarders { 192.168.100.1; 192.168.200.1; }; including the final semicolon both inside and outside the brackets (they serve different purposes, which you don't need to fully understand right now; just trust me on that they both need to be there). After you edit any BIND-related configuration file, execute the command sudo rndc reload to trigger a reload of the configuration.

If you have a tightly configured firewall, you will need to allow local traffic to your system on TCP and UDP, local port 53. Something like:

sudo iptables -A INPUT -i lo -p udp --dport 53 -j ACCEPT
sudo iptables -A INPUT -i lo -p tcp --dport 53 -j ACCEPT

Now make sure you point your system's name resolver functions to this DNS server. This is likely doable by editing /etc/resolv.conf directly to replace the nameserver directive(s) with a single one pointed at 127.0.0.1, but you may want to ask separately about that because I'm not really familiar with Ubuntu's way of doing things. They probably have a GUI for that and it's possible /etc/resolv.conf is rewritten automatically for example on boot.

This gives you a very basic forwarding DNS resolver setup. To block access to specific domains, which in DNS terms means that you for those names authoritatively serve an empty zone, add zone { } stanzas to your BIND configuration file, pointing at the db.empty file which is provided for convenience by the bind9 package. For example, to block everything under facebook.com (including the bare name), add:

zone "facebook.com" { type master; file "db.empty"; };

Again execute sudo rndc reload to load this. You should now be unable to access any host name under facebook.com.

If you mess up, then simply reset your network DNS settings to use your upstream DNS server, or undo the most recent change to /etc/bind/named.conf and reload the configuration again. You can write // anywhere on a line (except within quotation marks) to turn the rest of that line into a comment; this is a good way to, for example, temporarily back out a change.

Have fun!

3
  • This could work. (And yes, I do have root access.) Could you expand the answer to include some examples, if that's not too much trouble? Nov 6, 2014 at 18:49
  • @JosephJohn Give it a read.
    – user
    Nov 6, 2014 at 20:36
  • 1
    Thank you for the detailed answer. I spent 3 hours trying to set this up, messed up my DNS settings, and another 2 hours to get everything back as normal. But I'm sure this will help someone else. Thanks again! Nov 7, 2014 at 4:55
0

A simple method that will work sufficiently well for casual users is to block the IP addresses that the DNS lookup returns. Lets assume you have minors that should not access facebook. Use ping -4 facebook.com and ping -6 facebook.com to find out the IP and IPv6 addresses you need to filter. Then

a) add these to your routers firewall filter. In case of a MikroTik router just use winbox to log in, click "New Terminal" and execute

/ip firewall filter add chain=forward src-address=185.60.217.35 action=drop
/ipv6 firewall filter add chain=forward src-address=2a03:2880:f136:83:face:b00c:0:25de action=drop

of course with the IP addresses you get instead, or click your way through the interface.

b) If you just want to block these servers on your machine use ufw or iptables to block these IP addresses.

You may have to check occasionally whether the IP addresses change, then just add the new ones.

Hope this helps.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .