Dns answers to partial FQDN match
Closed this issue · 18 comments
I did an improvement in order to match a word in the fqdn asked.
Now in the domain list, you can put something like : {'"test" : "192.168.4.1"}
And making a DNS request on www.test.com, test.fr, test, will replay with "192.168.4.1".
This is useful for configuration web portal.
`
# ============================================================================
# ===( Server Thread )========================================================
# ============================================================================
def _serverProcess(self) :
self._started = True
debug = True
while True :
try :
packet, cliAddr = self._server.recvfrom(256)
domName = MicroDNSSrv._getAskedDomainName(packet)
if domName:
ipB = self._domList.get(domName.lower(), None)
if debug and ipB:
print("DNS: full domain matched: " + domName.lower())
if not ipB:
for word_a in domName.lower().split("."):
for word_b in self._domList.keys():
if word_a == word_b:
if debug:
print("DNS: word matched: " + word_b)
ipB = self._domList.get(word_b, None)
break
if ipB:
break
if not ipB:
ipB = self._domList.get('*', None)
if debug and ipB:
print("DNS: catchall matched.")
if not ipB:
if debug:
print("DNS: no match found.")
if ipB:
packet = MicroDNSSrv._getPacketAnswerA(packet, ipB)
if packet :
self._server.sendto(packet, cliAddr)
except :
if not self._started :
break
`
Code updated in initial post.
I have not updated the code :
if not ipB:
for word_a in domName.lower().split("."):
for word_b in self._domList.keys():
if word_a == word_b:
if debug:
print("DNS: word matched: " + word_b)
ipB = self._domList.get(word_b, None)
break
if ipB:
break
Because it can be causes a bad match.
The top will be to recognize partials wildcards like "*.toto.com".
What do you think about that ?
What do you think as bad match ? Can you give an example ?
Yes and it is the purpose :-)
Documentation:
The DNS resolver algorithm resolves entries of the configuration table in a determined order. As soon as a result is found, it is sent to the DNS client. The order is :
- full match of FQDN (ex : www.github.com"),
- the request (splited by dots) contains en entry of the configuration table (ex : github),
- the catchall (*), if present is returned.
I don't see a case where this algorithm could cause problems. Maybe there will be some non addressed cases (ex : matching *.toto.com).
After that, we could use regexps for matching configuration. But this will take much more CPU to compute...
Choice is yours JC :-)
Hello :)
I've added a wildcards domains parts rules (using regex).
You can check :
*.test.com
www.*.com
titi.toto.*
and also :
*.toto.*.titi.com
www.*.*
What do you think about that and the code ?
for domChk in self._domList.keys() :
if domChk.find('*') >= 0 :
r = domChk.replace('.', '\.').replace('*', '.+') + '$'
if match(r, domName) :
ipB = self._domList.get(domChk, None)
break
Ok nice :-) I have still 2 remarks:
- wildcard is matched before regexp, for me it is a problem
- while using regexp, why to replace dot and star with escaped version and not use expression as this ? While doing it you assis the users of your code but you remove some possibilities (ex : maching titi.com and tata.com with "t.t..com").
wildcard is matched before regexp, for me it is a problem
Why ? It's for not check all regex for nothing :o
In my case I want to do a configuration portal. For this I need to have DNS answers to some words, listed here for example : DNS_ANSWERS = ['ncsi', 'msftconnecttest', 'connectivitycheck', 'clients3', 'google', 'login', 'gvt3', 'apple', 'gvt2'] (from : https://github.com/lemariva/uPyPortal/blob/master/captive_portal/config.py). This is for telling various devices that there is a captive portal, it is normal. Then I want that any FQDN to be resolved to the IP of the ESP32 in order to go to the MicroWebSRV root (index.html) in order to serve the configuration page.
Yes, I don't want add the direct possibility to set regex but just humain writable rules.
You can add "toto.com" and "*.toto.com" for exemple.
Ok but in the case of captive portal, the mobile devices can change the target FQDN, but it always contains the same word.
Ok, yes, I understand.
I've just changed that : wildcards (*) match any char zero or more times in domains rules
And not just one or more times.
Now, you can set *google*
directly to match any who contain this word :)
You can also set google.*
and *.google.*
if you want.
It's ok ? :)
Sorry for late response. I was quite busy these days.
Your proposal seems to be a good compromise.
But you still match the catchall before the regexp, which I think is not good. The systematic behaviour that is most specific first to less specific last seems better for me.
I will test that monday or tuesday.
Thank you JC !
For me not :-)
The catchall should come as last chance :-)
Ok you're right, I pushed the new wildcards filters order :)
It seems to be great !
`
dnssrv = microDNSSrv.MicroDNSSrv.Create({
"www.testa.com" : "192.168.4.1",
"testb" : "192.168.4.2",
"testc." : "192.168.4.3",
"" : "192.168.4.4"
})
www.testa.com => 192.168.4.1
www.testb.com => 192.168.4.2
www.testb.fr => 192.168.4.2
testb.me => 192.168.4.2
testb => 192.168.4.2
testc.fr => 192.168.4.3
testc => 192.168.4.4
www.testc.com => 192.168.4.4
www.perdu.com => 192.168.4.4
`
The only not logical case is : testc. => 192.168.4.4
But as this is not a valid FQDN we don't care so much :-)
Thank you JC !