Need help with using an internal DNS

I need help setting this up, I have a Ham Radio Wireless Mesh nodes running AREDN firmware. These nodes us 10.x.x.x addressing, so I have mine natted to my network at 192.168.1.200. Everything on that network has a domain of .Local.Mesh, I can’t just point the .local.mesh traffic to that node, but the node does handle the DNS for that system. so what I am trying to do is setup the MikroTik with 2 DNS entries. The first will be 192.168.1.200, and the second will be a Public DNS like 88.8.8. or 1.1.1.1. This configuration should work, but I Know that Mikrotiks handle things a bit different on some items. I know I had to set up a Hairpin NAT when I was getting my webserver online, so that got me wondering, do I need to set up a NAT rule or something like that to get this working. I know many other people that do this same approach with their DNS entries with different routers, so I’m hoping its just an issue offiguring out the diferences in the Mikrotik configuration. I will warn you up front, I know enough about routing and MikroTiks to get myself in trouble, so if you have a solution, don’t give it to me as a veteran Network engineer. Thanks in advance for any info

judging by the fact this hs been posted for 3 days with no response, I’m starting to wonder if this is even possible. can someone at least tell me is that is the case? if I cant get this working, I will have to pull out the Mikrotik router and go back to Untangle, and I really don’t want to do that. Is there another solution to my problem?

Generally the configuration of DNS resolvers doesn’t work as you want it to. It’s not “ask this one first and if it doesn’t know, ask another one”. It’s assumed that all are equal and have the same info. So mixing standard resolvers with others that know about some special local domain is not possible, because the public ones will never know about internal domain, they will tell the client that domain doesn’t exist and that’s it. But it’s a feature that people need, so normal resolvers allow to configure per-domain forwarding, i.e. that queries for some domains should be send to another upstream resolver.

Unfortunately, in this regard, RouterOS is not normal and this useful feature is not supported. There’s only L7 hack which has some limitations, but may be good enough for you.

The problem is rather that it is hard to understand from your description what you actually want.

If you want to assign different DNS servers to different clients using DHCP, then this is not a problem as long as you assign the same DNS servers to all clients in the same subnet.


/ip dhcp-server network

is the place where you bind the client’s IP subnet with the settings to be provided for clients from that subnet.

Only one instance of DNS can run on Mikrotik itself, which the Mikrotik uses both for its own queries (e.g. when upgrading software or when you ping a domain name from Mikrotik itself) and for client queries if these clients have been configured with Mikrotik’s IP as their DNS server. Here it is possible to define static entries like ****

server1.myowndomain.here

which will only be visible to clients using Mikrotik as their DNS server and the Mikrotik itself.

If you need more complex scenarios, like clients from a single subnet using different DNS servers, you can tell all clients to use Mikrotik itself as DNS, but use rules in ****

chain=dstnat

of

/ip firewall nat

rules together with

/ip firewall address-list

to redirect queries coming from some clients (whose addresses are on the

address-list

) to external DNS servers.

Thanks for the replies. Sob, I have attempted the L7 hack, but couldn’t get it working, but if that is the only option as of right now, I will give it another shot.

Sindy, it looks like there is really only one option for this right now, but I will try to explain it better. I have a Private wireless network that spans several thousand square miles. We use Ubiquiti commercial gear on top of mountain tops with Custom Mesh firmware running on them. Every device on that network is assigned a WiFi address in the 10.x.x.x range, and on the Lan side gets a 10.x.x.x address. This is meant to replace an internet connection in an emergency so that Local government agencies/Red cross can still send data. everything on that network has a domain of .local.mesh. I use my Ubiquiti Rocket with the custom Firmware to connect to that network(I have several devices on that system (Email server, Web server, PBX, Samba server, GPS NTP server…) so I like to be able to access that network through my home network. Basically, if the Host name ends in .local.mesh, It needs to be routed to my NATed Ubiquiti rocket, and everything else should just go out to the internet as usual.

Try this:

/ip firewall layer7-protocol
add name="dns for local.mesh" regexp="\\x05local\\x04mesh.\\x01"
/ip firewall nat
add action=dst-nat chain=dstnat protocol=udp dst-port=53 in-interface=<LAN> \
    layer7-protocol="dns for local.mesh" to-addresses=<local.mesh DNS server>

Known limitations:

  • Works only for udp, not tcp (but clients don’t usually use tcp).
  • Works only with IPv4, not IPv6.
  • It bypasses cache in router (in case you use it as resolver for clients), but it’s not hard to live with it.
  • Router itself won’t be able to use it without another extremely ugly hack.

OK. So you have two DNS servers, both outside Mikrotik, and each is part of a distinct DNS network or hierarchy, so the private one won’t resolve names like ****

whatever.com

while the public one won’t resolve things like

something.local.mesh

.

And the goal is to send the query to the proper DNS network depending on the domain queried.

So I’m all for what @Sob has just posted, with two minor modifications

  • the tail of the match pattern is not ****
.0x01

(any byte followed by

0x01

byte) but

0x00
  • it is a waste of resources to use the complex and resource-intensive ****
layer7-protocol

matcher, you can get the same results if you use just


/ip firewall nat
add action=dst-nat chain=dstnat content="\05local\04mesh\00" dst-port=53 protocol=udp to-addresses=ip.of.mesh.dns.server

(yes, the syntax for specifying bytes as hex codes is different for the two matchers, it’s not a typo).

And don’t forget that you cannot test it from the Mikrotik itself, you must test it from clients, as locally originated packets do not pass through the

dstnat

chain. Of course the client must be set to use a DNS server from the public network by default.

Sob I appreciate your help, but unfortunately, it still does not work. I just don’t understand why I cant get this to work. this was so simple with Untangle, but I am determined to run MikroTik.
I will Paste the exact code that I ran to be sure I haven’t missed anything.
[admin@MikroTik] > ip firewall layer7-protocol
[admin@MikroTik] /ip firewall layer7-protocol> add name=“dns for local.mesh” regexp=“\x05local\x04mesh.\x01”
[admin@MikroTik] /ip firewall layer7-protocol> ..
[admin@MikroTik] /ip firewall> nat
[admin@MikroTik] /ip firewall nat> add action=dst-nat chain=dstnat protocol=udp dst-port=53 in-interface=ether2 layer7-protocol=“dns for local.mesh” to-address=192.168.1.200
[admin@MikroTik] /ip firewall nat>

I just want to be sure that nothing was missed, in the regexp definition, should there be a “.” after local? should that be regexp=“\x05local.\x04mesh.\x01” the full domain is .local.mesh , I am just trying to eliminate any issues.

read my post just above.

totally agree

Sindy, I tried your method also, but its still not working. Im about ready to just set up another nic in a spare computer and I will remote into that computer when I need to do anything on that network.

chechito Im not sure how to break it down any further. the way the Mesh network operates is a little different, I understand it well because I have been dealing with it for a couple of years. it is just its own private network, no internet, just a large wifi network that is meant for passing files to users on the network. The way the firmware is set up on the my Ubiquiti Rocket that it has a Wifi address of 10.x.x.x, and a NAT address of 192.168.1.200. If I undo the NAT and turn on DHCP on my rocket, this will allow me to access the entire network because the Ubiquiti gear is handling all of the DNS entries. everything on that network has a domain of .local.mesh. so my rocket has an address of KD7VEA-Rocket.local.mesh. If I am directly connected to the rocket with DHCP on, I will get an address for the mesh network, and I can go to any other machine on that network such as KD7VEA-NanoStation.local.mesh or KD7BKO-Rocket.local.mesh.

I leave my Mesh node set to NAT at 192.168.1.200. this allows me me to get to my node, and when I was running my old untangle router, I could point everything ending in .local.mesh to go 192.168.1.200 and then my Mesh node would route me to the other machines on the network.. The simplest way I can describe it is that when I try to point my browser to KD7BKO-Rocket.local.mesh(or anything else on the network that ends in .local.mesh), I need that to direct itself to 192.168.1.200 as the DNS server. I don’t know if that made it any more clear?

@sindy: I must insist on my pattern (at least for now, maybe there is some possible improvement). Null byte at the end would be correct, because that’s what’s in the packet. But RouterOS drops all null bytes from input, before it tries the regexp, and it makes the input quite unpredictable. And if you’d let it end with just “mesh”, it would also match hostnames like local.mesh.example.com. So in order to filter out false positives, you need to look for other non-null bytes. Right after hostname are two 16-bit numbers, query type (A, AAAA, …) and class. First one varies, but luckily most common records are < 256, so that’s the “.” for any byte. And class is for most uses 1.

@kd7vea: Two things to make sure about:

  1. ether2 is the interface where your PC (or whatever device you test it with) is connected to
  2. 192.168.1.200 is DNS server that knows how to resolve .local.mesh

Is so, does the counter for this rule increase? If it does, the problem might be elsewhere. E.g. if you PC would be in same subnet as 192.168.1.200, you’d also need to set up hairpin NAT.

yes, the PC is on the same network, and the Hairpin NAT was what I was wondering about from the beginning. I have set up a Hairpin NAT for my webserver. I will look at that and see if I can remember how I set it up and try to translate it for this .local.mesh network.

also, ethernet 2 is what all of my network connects to. ethernet 1 is my WAN side to the Modem, ethernet 2 connects to my switch that hosts everything (computers, servers, wifi, and the Mesh node on 192.168.1.200).

I have tried while developing my “plaintext” match. You are almost right but the sequence looks as follows:


sales.local.mesh: type A, class IN
    Name: sales.local.mesh
    [Name Length: 16]
    [Label Count: 3]
    Type: A (Host Address) (1)
    Class: IN (0x0001)

which is, in hex representation and in the network (no little-endian here!) format:


05 73 61 6c 65 73 05 6c 6f 63 61 6c 04 6d 65 73 68 00 00 01 00 01
05  s  a  l  e  s 05  l  o  c  a  l 04  m  e  s  h 00

the name terminated by a zero byte


00 01

the record type in big endian


00 01

the class in big endian

The good point is that the ****

contain

matcher does not remove the null bytes, because a regexp pattern

..\x01

could possibly be too wide.

And yes, I was concentrated on a proper matcher so I’ve forgotten about the backward path.

But the problem is RouterOS eating null bytes, so if packet contains this:

05 73 61 6c 65 73 05 6c 6f 63 61 6c 04 6d 65 73 68 00 00 01 00 01

then L7 matcher works with this:

05 73 61 6c 65 73 05 6c 6f 63 61 6c 04 6d 65 73 68 01 01

And with content=“\05local\04mesh\00”, there are two problems. First is minor, you have to use CLI to enter this, and non-printable characters will show as garbage in WinBox and WebFig. Another is that this will be case-sensitive (unlike L7 matching), so it can miss some queries.

So your ****

.\x01

actually means “type any,class in”, because each byte in the pattern represents what remains of the 16-bit word after null bytes are removed, OK.
Agreed that my matcher fails on at least one upper case letter and 2^9 ****

contains

rules would probably be equally resource-intensive like

layer7-protocol

While we’re at it, it looks like:

\0x03tld.{2,4}$

should be foolproof way to match everything (all record types and classes) without false positives. RouterOS doesn’t like this syntax, so simplied version would be:

\0x03tld...?.?$

But most importantly, none of this would be needed, if MikroTik finally implemented this basic functionality and just allowed users to configure per-domain forwarding like any other decent software allows.

I had some time to work on this again, and yes, the new NAT rule counter does increase when when I attempt to navigate to an address on the Mesh network, but the Hairpin counter does not increase. I tried to use the hairpin settings I used for my webserver and modify them for the mesh connection at 192.168.1.200, but I’m not totally sure I am doing it correctly. so it seems like the rule is sending it correctly, but the issue may be on the hairpin. I am only using 2 ports on my MikroTik, would it make sense to move my Mesh device that is 192.168.1.200 off of my main network, and place it on Port 3 of the MikroTik and eliminate the hairpin all together, or am I making things more complicated? I could set it back to its default 10.x.x.x address and to not have conflicts with my home subnet.

Post a little bit more about your config, at least the non-working hairpin NAT rule and we’ll (most likely) find some solution, without need to change everything.

Sob, I did not see this message until I had already reconfigured. It only takes me a minute to move these around, so i figured this could be the easiest way to see if it works without the Hairpin (I think) if I need to change it back I can. so the way it is set up now, My secondary network that I am trying to brows(the .local.mesh network) is now on ethernet 3 on the Mikrotik. I also change the DHCP configuration so now it is not NATed to my network, it has an IP address of 10.18.199.45 the subnet is 255.255.255.252. I tried to make a nat rule to send the .local.mesh traffic to port 3, but I assume I have not got that set up correctly. I used the code that you had already posted.

/ip firewall layer7-protocol
add name=“dns for local.mesh” regexp=“\x05local\x04mesh.\x01”
/ip firewall nat
add action=dst-nat chain=dstnat protocol=udp dst-port=53 in-interface=ether3 layer7-protocol=“dns for local.mesh” to-addresses=10.18.199.45

do I need to also set up a Masquerade for that network? or is there something elsewhere that I could be overlooking?