jczic / MicroDNSSrv

A micro DNS server for MicroPython to simply respond to A queries on multi-domains with or without wildcards (used on Pycom modules & ESP32)
https://microdnssrv.hc2.fr
MIT License
74 stars 21 forks source link

Dns answers to partial FQDN match #4

Closed Liberasys closed 6 years ago

Liberasys commented 6 years ago

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

`

jczic commented 6 years ago

Thank you, I'll see that :)

2018-02-01 11:47 GMT+01:00 Liberasys notifications@github.com:

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("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("Word matched: " + word_b)
                            ipB = self._domList.get(word_b, None)
                            break
                    if ipB:
                        break

            if not ipB:
                print("wildcard")
                ipB = self._domList.get('*', None)
                if debug and ipB:
                    print("Catchall matched.")

            if not ipB:
                if debug:
                    print("No match found.")

            if ipB:
                packet = MicroDNSSrv._getPacketAnswerA(packet, ipB)
                if packet :
                    self._server.sendto(packet, cliAddr)

    except :
        if not self._started :
            break

`

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/jczic/MicroDNSSrv/issues/4, or mute the thread https://github.com/notifications/unsubscribe-auth/AAegLGmuxgaqhIdscWCIbFDC4WLqpjDsks5tQZY1gaJpZM4R1Z2A .

--

Sincèrement,

Liberasys commented 6 years ago

Code updated in initial post.

jczic commented 6 years ago

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 ?

Liberasys commented 6 years ago

What do you think as bad match ? Can you give an example ?

jczic commented 6 years ago

"www" :) Just, that's not match domains order but all worlds.

2018-02-01 18:35 GMT+01:00 Liberasys notifications@github.com:

What do you think as bad match ? Can you give an example ?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jczic/MicroDNSSrv/issues/4#issuecomment-362342959, or mute the thread https://github.com/notifications/unsubscribe-auth/AAegLJFhBycsVb8ncnY-WGwLZ1hloCzaks5tQfXdgaJpZM4R1Z2A .

--

Sincèrement,

Liberasys commented 6 years ago

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 :

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 :-)

jczic commented 6 years ago

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
Liberasys commented 6 years ago

Ok nice :-) I have still 2 remarks:

jczic commented 6 years ago

2018-02-02 14:03 GMT+01:00 Liberasys notifications@github.com:

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").

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jczic/MicroDNSSrv/issues/4#issuecomment-362580571, or mute the thread https://github.com/notifications/unsubscribe-auth/AAegLB4VUKjFzWalvQsi9zMhLorQiHixks5tQwengaJpZM4R1Z2A .

--

Sincèrement,

Liberasys commented 6 years ago

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.

jczic commented 6 years ago

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 `googledirectly to match any who contain this word :) You can also setgoogle.and.google.` if you want. It's ok ? :)

jczic commented 6 years ago

It's okay for you ?

2018-02-02 18:23 GMT+01:00 Liberasys notifications@github.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 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.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jczic/MicroDNSSrv/issues/4#issuecomment-362621193, or mute the thread https://github.com/notifications/unsubscribe-auth/AAegLFYlNHqmGcVGENm18fZuFfAsiRDwks5tQyzQgaJpZM4R1Z2A .

--

Sincèrement,

Liberasys commented 6 years ago

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 !

jczic commented 6 years ago

Yes I see. But just I you have the * only rule, this must be catch all before any sub-wildcard expression no ?

2018-02-05 0:21 GMT+01:00 Liberasys notifications@github.com:

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 !

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jczic/MicroDNSSrv/issues/4#issuecomment-362949162, or mute the thread https://github.com/notifications/unsubscribe-auth/AAegLNVvLn1by8Ya-m1ktFTndk09knK9ks5tRjtwgaJpZM4R1Z2A .

--

Sincèrement,

Liberasys commented 6 years ago

For me not :-) The catchall should come as last chance :-)

jczic commented 6 years ago

Ok you're right, I pushed the new wildcards filters order :)

Liberasys commented 6 years ago

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 !

jczic commented 6 years ago

:)

2018-02-06 14:45 GMT+01:00 Liberasys notifications@github.com:

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 !

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jczic/MicroDNSSrv/issues/4#issuecomment-363426203, or mute the thread https://github.com/notifications/unsubscribe-auth/AAegLDCKe8sGLwdnHUh2tIXAkie8CKDhks5tSFdvgaJpZM4R1Z2A .

--

Sincèrement,