A Working Method to Precisely Block Distracting Websites using a MikroTik Router

July 29, 2020

Introduction: Eliminating Distractions


I've recently been looking for ways to keep myself from getting sidetracked during the day, and came across this blog post about blocking distracting websites using a MikroTik router. This solution sounded perfect to me:

So, I ordered a MikroTik router (specifically, the RBD52G-5HacD2HnD-TC, which seemed to be one of their cheaper offerings). Unfortunately, I quickly came across many problems that many online blog posts fail to mention, despite purportedly offering instructions on how to block websites on MikroTik routers. In this post, I discuss the problems, and give my amended (and unfortunately far more complicated) procedures to work around them.

The Problem


The problem with the blog post linked above quickly becomes apparent if you want to block a "large" website, such as youtube: youtube.com may resolve to one of many IP addresses. An end user may never know all of these IP addresses, so adding them to a block list is virtually impossible---block one IP and you may simply be directed to a different, unblocked IP address next time you try to visit the site. It's a simple problem, but not one with a straightforward solution.

Proposed Approaches


Other websites and blogs often list different approaches for blocking websites on a Mikrotik router. They're all garbage, and here's why:

The Working Solution

The approach I settled on, and that is now working to my satisfaction, simply builds on the block-list approach discussed in the original blog post I had tried to follow. However, it requires a key additional step:

This means that other users can continue to use the sites, but I can create a firewall rule to block the specific, known, addresses on my own systems. If, for some reason, the website's IP address changes, updating my static DNS rule will be easy.

Unfortunately, carrying this out is deceptively complicated; it turns out that modern computers can do all sorts of things to ignore your router's DNS settings. Regardless, we'll cover those issues later. For now, it's probably easier to just start with the steps:

  1. Pre-step: I'm assuming that your router is already working and you are able to access the internet normally.
  2. Ensure that your router is acting as your DNS server:
    1. Go to the router's settings (I accessed mine just using the "WebFig" interface at 192.168.88.1 by default).
    2. Under IP→DHCP Server, select the "Networks" tab and click on the network under "defconf" to change its settings. Click the arrow next to "DNS Servers", and put the router's IP address (by default, 192.168.88.1) into the box. Click OK.
    3. Under IP→DNS, click on the down arrow next to "Servers" and enter 1.1.1.1 into the box (cloudflare's default DNS server). You can use different servers if you want. For example, if you have a PiHole ad-blocking DNS server on your network then you'll need to put its IP address in this field. (Though, if you have such a setup you probably already have done so.) Make sure the "Allow remote requests" box is checked. Click on "Apply".
    4. Under IP→DHCP Client, click on the first entry under "defconf". Uncheck "Use Peer DNS" and click "Apply". This should prevent the router from trying to use your ISP's DNS servers. (This may not be necessary.)
  3. Make sure your devices have static IP addresses, and create a list of devices:
    1. Under IP→DHCP Server, select the "Leases" tab. Look for the device(s) for which you want to restrict access. Click on the address for each device, then click on the "Make static" button.
    2. Now that your devices will have static IP addresses, we'll add them to a list that can be used later. Go to IP→Firewall, and click on the "Address lists" tab. For each device from the previous step:
      1. Click on "Add New"
      2. In the "Name" box, enter the name of the list to create (or select the name of the list if you've already registered at least one address). I'll use "blocked_devices" for my list name.
      3. In the "Address" box, enter the (now static) IP of the device.
  4. Set static DNS rules for each website you want to block, and create a list of website addresses: Important note: you may need to carry out these steps for each subdomain, too, since subdomains may have different IP addresses from the higher-level domains. For example, I carried out these steps for both "youtube.com" and "www.youtube.com"--both have different addresses, and you can't just block one of them and expect it to work!
    1. Obtain the IP address of the domain you want to block. In my opinion, the easiest way is just to use "ping" in a terminal (e.g. ping www.youtube.com). Copy the IP address.
    2. In the router's settings, go to IP→DNS, then click on the "Static" button. Click on "Add New". Enter the full domain (e.g. "www.youtube.com") in the "Name" box, and the IP you copied in step 1 into the "Address" box. Keep the "Type" option set to "A". Click on OK.
    3. We'll also create a list of restricted site addresses.
      1. Go to IP→Firewall, and click on the "Address lists" tab again.
      2. Click on "Add New".
      3. In the "Name" box, enter the name of a different list from the one you created for your devices. I'll use "blocked_sites" for my list name here. (You should be able to select the existing "blocked_sites" name if you've already registered at least one address in this list.)
      4. In the "Address" box, enter the IP address you set for the domain.
      5. Click "Ok".
  5. In the future, if you want to add additional blocked sites, you only need to follow the above steps in this section: set a DNS rule to supply a known IP address, and then add that IP address to the block list. Additionally, if you know that the site you wish to block only has a single IP address, you don't need to add the DNS entry---just put the IP directly into the "blocked_sites" address list.
  6. Quick aside: making sure we haven't broken anything yet: After adding all of these addresses, but before adding any firewall rules, you may want to test out your new DNS settings to make sure everything still works and that your IP addresses are used properly. You may need to clear several DNS caches: After this, restart your router. Once your computer is connected back to the internet, try accessing the domains that you set the IP addresses for. Since we haven't added any firewall rules yet, you still should be able to access them. For sanity, check the IPs for each domain using "ping" or whatever method you used earlier. (Don't use a browser to test the IPs, since browsers may still be using DNS over HTTPS, which we prevent in a later step.) If the IPs differ from the ones you statically set in the router's DNS settings, then your computer is still not using your router as a DNS server. If that happens, you may want to make sure your computer hasn't been manually set to use a specific DNS server other than your router.
  7. (Finally) Add a firewall rule to block the websites:
    1. In the router's settings, go to IP→Firewall. Click on "Add New".
    2. Keep the "Chain" set to "Forward".
    3. Next to "Src. Address List", select "blocked_devices" (or whatever you named your list of devices to be restricted).
    4. Next to "Dst. Address List", select "blocked_sites" (or whatever you named your list of addresses to be blocked).
    5. Click the arrow next to "Time". Enter the start and stop times that you want sites restricted. I wanted mine restricted from 8:00 AM until 6:30 PM, so my boxes contain "08:00:00" and "18:30:00". Also select the days on which it applies.
    6. Next to "Action", select "drop".
    7. You may want to add a comment, like "block distracting sites" to help you find the rule.
    8. Click "Ok".
    9. The new rule should now appear at the bottom of the list of rules. However, we want it to apply before any rule that explicitly allows anything. So, just use the mouse to drag the rule up the list, above any rule that "accept"s anything.
  8. Preventing DNS over HTTPS, or accessing other DNS servers (at least for Firefox, maybe others):

    The problem with the system outlined above is that it completely relies on the router's DNS server supplying addresses for websites. If you have a browser, like firefox, using DNS-over-HTTPS, then this bypasses traditional DNS resolution and obtains IP addresses for websites regardless of what you set earlier. Obviously, this is no good since most of the time you probably won't end up with the static, blocked IP address set earlier.

    You can just disable DNS over HTTPS in firefox's settings, but this is useless for preventing distractions because it can be re-enabled with just a single click. Supposedly, Firefox checks a "canary" URL to disable DoH, but this is completely meaningless, as FF ignores the canary in favor of the easily modified user setting. We need to do something a bit stronger. So, here's what I did that finally worked:

    1. Block the site that firefox uses to carry out DNS over HTTPS. Go to "about:config" (accept the warning; we won't change anything), and search for "trr.uri". You should see a single URL. For me, it was https://mozilla.cloudflare-dns.com/dns-query.
    2. We want to block the URL listed above, using the same steps as before. First, use ping or any tool of your choice to look up the IP address for mozilla.cloudflare-dns.com, as well as cloudflare-dns.com for good measure. (They have different IP addresses.) If your "trr.uri" setting had a different domain, then look up that domain instead.
    3. Add Static DNS rules in the router's IP→DNS→Static settings to force the router to resolve these addresses to IPs you just looked up. (We're doing the same thing as before with the blocked websites.)
    4. Add both of these IP addresses to a new "dns_servers" address list. (You can name the list whatever you want.) Create and add addresses to the address list the same way you did earlier, under IP→Firewall→Address Lists.
    5. For good measure, also add google's and cloudflare's "normal" DNS servers to the "dns_servers" address list. The server addresses are 8.8.8.8, 8.8.4.4, 1.1.1.1, and 1.0.0.1. Add any other DNS server addresses you want.
    6. Create a firewall rule to block any access to these DNS servers from your restricted devices:
      1. Go to IP→Firewall, and click on "Add New" under the "Filter" tab.
      2. Keep the "chain" setting set to "forward".
      3. For "Src. Address list", select "blocked_devices" from earlier.
      4. For the "Dst. Address list", select the new "dns_servers" list.
      5. Set "action" to "drop"
      6. Add a comment, if you want, like "block DNS workarounds".
      7. Click "Ok"
      8. Drag the new rule to a position above the previous rule you added, near the top of the list.

    Now, firefox's DNS-over-HTTPS should fail and fall back to a different option, regardless of whether it is enabled.

    Should you find yourself trying to work around the blocking in the future, hopefully preventing that is simply a matter of adding another DNS server to the dns_servers list.

    As a final step, repeat the procedure in section 4. above to clear any cached DNS addresses. You may need to restart your web browsers and your router before some of the changes take effect.

Conclusion


With this, your websites should be blocked. In summary, we:

Finally, when you have settings you are satisfied with, get someone you trust to set the password on your router! We only should have added two firewall rules, so to return everything to normal, you can disable or delete the rules, and then disable or delete any static DNS settings you added.