The "Disparity Extender" Algorithm, and F1/Tenth

Introduction: Autonomous Racing Recently, my team from UNC-Chapel Hill won an F1/Tenth competition, held at CPSWeek 2019, in Montreal. ...

Wednesday, July 29, 2020

A working method to precisely block distracting websites using a MikroTik router

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:
  • It could be applied only during specified times, so my internet would only be blocked during working hours leaving me free to watch youtube videos in the evening.
  • It could be applied to specified devices only, so other people or devices on my network won't be affected.
So, I ordered a MikroTik router (specifically, the hAP ac² RBD52G-5HacD2HnD-TC, which seemed to be one of their cheaper offerings).  Unfortunately, I quickly come 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 of these IP addresses 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:
  • Block sites using the "TLS host" filter in the firewall rules:  This never worked at all for me.  The firewall rule never matched a single packet.  It may have to do with the topic discussed in this forum post.  However, no good solution was presented there, so I don't really care about the underlying reason it didn't work.
  • Block sites using Layer 7 protocols: Not only does the MikroTik website say not to do this for efficiency reasons, it's not even guaranteed to work, especially for encrypted (HTTPS) traffic.
  • Block sites using a DNS black hole: This is at least feasible, but there is one major problem: it affects all systems on the network.  Great for blocking ads, but not great if I want to prevent only myself from listening to youtube livestreams while I'm supposed to be working.  On top of that it often doesn't even work!  DNS-over-HTTPS prevents this from working, and end users can easily bypass the restriction by changing the DNS server in their computer's settings to point to something like google (8.8.8.8) or cloudflare (1.1.1.1).

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:
  • Statically resolve DNS requests for websites I want to block to a single, valid, IP address for that site.
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:

0) Pre-step: I'm assuming that your router is already working and you are able to access the internet normally.

1) 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.)
2) 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.
3) 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 can just 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".
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.

4) 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:
  1. Clear the router's DNS cache: Go to IP->DNS, and click on the "Cache" button.  Then click "Flush cache".
  2. Clear your browser's DNS cache.  This differs based on the browser, you'll need to check online for instructions on how to do it in yours.
  3. Clear your operating system's DNS cache.  Once again, this may differ on different systems, so I'd recommend searching online for how to do it.
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.

5) (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.
6) 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

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:
  • Forced the router to act as a DNS server.
  • Assigned static IP addresses to each device to restrict, and added these addresses to a list.
  • Configured the router's DNS server to return only one IP address per site to block.
  • Added the site IP addresses to a separate list.
  • Created a firewall rule to block traffic going from the addresses in the device list to addresses in the site list.
  • Prevented some methods for bypassing this, such as DNS over HTTPS or manual DNS server settings.
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.

No comments:

Post a Comment