Mikrotik: How to block websites/apps and force DNS queries to specific servers

In this post we’ll discuss two different ways to control standard DNS queries (UDP/TCP port 53) within a network using Mikrotik RouterOS. The intended outcome for doing this is to be able to either send all DNS queries from devices on your network to a specific external DNS server, such as 1.1.1.3 (CloudFlare DNS for Families), or to send all DNS queries on your network to the routers internal DNS server. The latter configuration allows for the addition of blackhole DNS records to be put within your routers cache for hosts to query.

DNS filtering is not a fix all. The reason that it works in some instances to restrict internet usage, is because without proper DNS resolution, serveries cannot be properly connected to. Limiting DNS queries breaks the process. In most scenarios even if a user is able to get the IP address and port of the service they want to connect to, functionally will be hugely limited without the ability to resolve DNS. That is not to say that DNS filtering is a 100% fix for content restrictions. It’s fairly easy to bypass using a VPN or proxy service. Modern browsers and apps have also gotten much better at bypassing restrictions with various encryption methods, and massive lists of DOH servers to fallback on that are difficult to reliably block all of. Without client side software, very advanced firewalls or imposing a whitelist model in the network it is not possible to totally control users traffic. DNS restrictions are better used as a surface level defense, and work best when administrators have control over the host devices, and can force them to use specific servers.

There could be many reasons for doing this, but some good use cases would be for schools, guest networks, kids networks etc.

As mentioned, keep in mind that the below configurations won’t prevent DOH (DNS Over HTTPS) which utilizes port 443 and DOT (DNS Over TLS) which utilizes TCP port 853. Due to a lot of internet traffic using port 443, blocking that would result in a broken network. The only workaround is to block known DOH server IP’s, and port 853 forwards. This is not as easy as it sounds.

For the purpose of this guide I’ll be using the default Mikrotik router config that comes packaged with most of their devices and 1.1.1.3 as my public DNS server.

Forcing all host DNS queries to a specific external server.

To being, lets head over to the device firewall NAT settings and create a NAT rule that changes the destination IP for any forwarded DNS queries. This is the base of our config, and the backbone that enables us to do this.

chain=dstnat action=dst-nat to-addresses=1.1.1.3 to-ports=53 protocol=udp dst-port=53

Lets quickly break that command down with a simple overview: We’ve just created a destination NAT rule that listens for any traffic destined to UDP port 53. Port 53 is used for DNS queries. If the router receives traffic with destination port 53 over UDP it will modify the destination address to 1.1.1.3 meaning the traffic will instead go to CloudFlares 1.1.1.3 DNS server rather than the original destination regardless of what the destination address was originally. Because of this rule, even if the user specifies the DNS server address they want to query, any queries being forwarded by the router will instead go to the server of our choosing. Remember, even though I’m using 1.1.1.3 as my DNS server, you can technically use any address.

DNS can utilise both port 53 over UDP and TCP, its important to add a second NAT rule under this one that does the same thing, only this time the router will perform the destination NAT to queries going over TCP:

chain=dstnat action=dst-nat to-addresses=1.1.1.3 to-ports=53 protocol=tcp dst-port=53

Because your network will vary to mine, I can’t tell you exactly how to implement this but in general as long as your routers got these NAT rules in place DNS queries should get sent to the server you choose. I do like to take this a step further though and include the DNS server in the DHCP leases. You can setup an entirely new DHCP server if you haven’t already and specify the DNS server, or modify your existing server, which is what I’m going to do.

ip dhcp-server network set numbers=0 dns-server=1.1.1.3

Now when clients connect up, they will get offered a DHCP lease that includes the DNS server we want all our DNS queries to go to. If for some reason the user wants to try to bypass the dynamically assigned DNS server that their device got, the router will change the destination address of their DNS queries back to 1.1.1.3. This is a nice way to make sure that queries are hitting the the right place even if the user tries to manually override this. This should be enough to create a base configuration that can be customised further if needed.

Forcing internal DNS resolution:

Lets look at an alternative method to force all DNS queries to the router, which then handles the DNS queries for the host. This is useful if you want to ensure that queries are handled solely by the router and its cache, and not the host directly. This also allows you to not only ensure the DNS queries are resolved to whatever external server you want, but also to create static DNS entries in the routers DNS cache that can be used to blackhole domains, subdomains, or even create local DNS records to other hosts on your network. Lets circle back on the former statement “It allows you to blackhole domains and subdomains” – This is a very useful feature because you can specifically block certain websites or services without needing to do much else other than create a blackhole record in the routers cache for the domain you want to block. In most scenarios even if users get the IP address and port of the service, most online services rely heavily on DNS to function, and almost all of the time functionally of the service will be hugely limited or impossible without DNS.

To start lets first get DNS setup on our router. Later on we’re going to make sure that all DNS queries are sent to the router which means that we need somewhere for the router to make DNS resolutions to. I’m going to use 1.1.1.3 again. To do this I’m going to set the routers DNS server:

ip dns set servers=1.1.1.3 allow-remote-requests=yes

What the command above does is tell the router to set its DNS server to 1.1.1.3. This is where its going to send queries to if no record exists in its cache. It also tells the router to allow remote requests. Remote requests are queries destined for the router, and enabling this allows the router to receive these queries. Its super important to make sure that your firewall is blocking incoming traffic that is not related or established from your WAN interface, otherwise unless intended, your router could be used and attacked via port 53 from the public internet. By default your router should have a filter rule for this.

Next make sure that none of your other services running are using peer DNS. This is common on DHCP clients and PPPOE interfaces usually used to connect your router to your ISP. You can check if this is the case by printing your DNS servers and checking the output to see if any servers other than the one you assigned just now are there. If others exist and are there dynamically, check what interface or services are running peer DNS and disable “use peer DNS” on those interfaces.

ip dns print

Next we need to setup NAT rules to use the redirect action. To do this we’ll put the following command into the terminal:

ip firewall nat add chain=dstnat protocol=udp dst-port=53 actio
n=redirect to-ports=53

We can do the same for TCP:

ip firewall nat add chain=dstnat protocol=tcp dst-port=53 actio
n=redirect to-ports=53

Lets take a look at those commands and break it down quick. We’ve created a NAT rule on the routers dstnat chain, and told it to redirect any traffic on TCP/UDP port 53 to port 53. The redirect rule simply redirects any traffic to the router itself. So if we redirect traffic to port 53, that traffic will go to the routers DNS server because thats the service listening on port 53 on the router.

Because of this, the router will now handle any DNS queries and populate its cache as it does so. Host on the network will receive DNS information from the router directly and not directly from 1.1.1.3.

To add onto this configuration we can also blackhole records to prevent any access to a particular domain. I’ll do this for facebook.com. Creating a blackhole record simply means that we’ll create a DNS A record with nonsense information on it to purposefully break a DNS resolution to a particular domain and subdomain. This can be achieved by creating a static DNS entry in the routers cache. Any cached DNS records will be used for queries if they exist statically and that query will not be forwarded to a resolver.

ip dns static add name=facebook.com type=A address=127.0.0.1 ma
tch-subdomain=yes

This command creates a static A record in the routers DNS cache for facebook.com and any subdomains of facebook.com and maps it to 127.0.0.1 – 127.0.0.1 is a loopback address, so any device trying to access a service over 127.0.0.1 will be looking for that service on themselves, rather than finding the actual DNS information for facebook.com.

Thats more or less going to conclude this section on DNS management, but as with anything customisation and playing around with the configuration to tailor it more to your requirements might be necessary.

#End of post