Uploaded image for project: 'Python Driver'
  1. Python Driver
  2. PYTHON-3630

SRV resolution uses only the first nameserver

    • Type: Icon: Question Question
    • Resolution: Works as Designed
    • Priority: Icon: Unknown Unknown
    • None
    • Affects Version/s: None
    • Component/s: None
    • None

      My company uses WireGuard to secure connection to our MongoDB. Some time ago I got troubles with connecting to it from my Windows system using pymongo. I still was able to connect to it via mongosh or MongoCompass.

      Connection is done via

      MongoClient(
              f'mongodb+srv://user:password@'
              f'13.mongodb.db.domain',
              tls=True,
              tlsCAFile=ca_file,
              )
      

      Error received:

      Traceback (most recent call last):
        File "E:\REDACTED\.venv\lib\site-packages\pymongo\srv_resolver.py", line 89, in _resolve_uri
          results = _resolve(
        File "E:\REDACTED\.venv\lib\site-packages\pymongo\srv_resolver.py", line 43, in _resolve
          return resolver.resolve(*args, **kwargs)
        File "E:\REDACTED\.venv\lib\site-packages\dns\resolver.py", line 1367, in resolve
          return get_default_resolver().resolve(
        File "E:\REDACTED\.venv\lib\site-packages\dns\resolver.py", line 1231, in resolve
          (answer, done) = resolution.query_result(response, None)
        File "E:\REDACTED\.venv\lib\site-packages\dns\resolver.py", line 768, in query_result
          raise NoAnswer(response=answer.response)
      dns.resolver.NoAnswer: The DNS response does not contain an answer to the question: _mongodb._tcp.13.mongodb.db.domain. IN SRV
      
      During handling of the above exception, another exception occurred:
      
      Traceback (most recent call last):
        File "E:\REDACTED\main.py", line 27, in <module>
          MongoClient(
        File "E:\REDACTED\.venv\lib\site-packages\pymongo\mongo_client.py", line 736, in __init__
          res = uri_parser.parse_uri(
        File "E:\REDACTED\.venv\lib\site-packages\pymongo\uri_parser.py", line 542, in parse_uri
          nodes = dns_resolver.get_hosts()
        File "E:\REDACTED\.venv\lib\site-packages\pymongo\srv_resolver.py", line 121, in get_hosts
          _, nodes = self._get_srv_response_and_hosts(True)
        File "E:\REDACTED\.venv\lib\site-packages\pymongo\srv_resolver.py", line 101, in _get_srv_response_and_hosts
          results = self._resolve_uri(encapsulate_errors)
        File "E:\REDACTED\.venv\lib\site-packages\pymongo\srv_resolver.py", line 97, in _resolve_uri
          raise ConfigurationError(str(exc))
      pymongo.errors.ConfigurationError: The DNS response does not contain an answer to the question: _mongodb._tcp.13.mongodb.db.domain. IN SRV
      

      I looked into the order of nameservers.

      >>> import dns.resolver
      >>> dns_resolver = dns.resolver.Resolver()
      >>> print(dns_resolver.nameservers)
      ['192.168.100.1', '10.103.0.2']
      

      192.168.100.1 is name server of my local Ethernet, 10.103.0.2 is nameserver specified in WireGuard configuration.

      By default dnspython uses registry to get available nameservers. I found registry entries responsible for this and cleared some obsolete ones. After that the order changed.

      >>> import dns.resolver
      >>> dns_resolver = dns.resolver.Resolver()
      >>> print(dns_resolver.nameservers)
      ['10.103.0.2', '192.168.100.1']
      

      And then I was able to connect to MongoDB with no issues.

      pymongo uses dns.resolver.resolve to resolve SRV queries. This function uses default resolver which is created with the same approach as I used above.

      Current workaround is to setup default resolver manually.

      import dns.resolver
      dns.resolver.default_resolver = dns.resolver.Resolver(configure=False)
      dns.resolver.default_resolver.nameservers = ['10.103.0.2']
      

      But I do not like such approach because it affects the whole project rather than only this specific connection.

      Overall, if such behavior is a bug, then it should be fixed. If this behavior is intended or the issue is not related to pymongo, then I would like to have an option to specify resolver in MongoClient constructor.

      I also posted this issue in dnspython repository. Library maintainer answered that order of nameservers matters.

      Versions

      pymongo 4.3.3
      dnspython 2.3.0.

            Assignee:
            shane.harvey@mongodb.com Shane Harvey
            Reporter:
            prometheus3375@gmail.com Svyatoslav S
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: