简体   繁体   English

ServerSelectionTimeoutError使用PyMongo和x509 SSL证书连接到MongoDB数据库时

[英]ServerSelectionTimeoutError When connecting to MongoDB Database with PyMongo and x509 SSL Certificate

I am trying to connect to a MongoDB Database on another server. 我正在尝试连接到另一台服务器上的MongoDB数据库。 The only problem is that to connect to the server requires a specialized version of Kerberos. 唯一的问题是连接到服务器需要专门版本的Kerberos。 To overcome this, I was using SSH Tunnels to open a local port for Pymongo to interface with the database and we designed our Security Certificate specifically for this eventuality as a precaution. 为了解决这个问题,我使用SSH隧道打开Pymongo的本地端口以与数据库连接,我们专门针对这种可能性设计了我们的安全证书作为预防措施。 I know that the tunnel is functioning properly as the Mongo Shell and Robo 3T both are able to connect to the database and display the data. 我知道隧道运行正常,因为Mongo Shell和Robo 3T都能够连接到数据库并显示数据。 However, with PyMongo version 3.7.1, I get the following error: 但是,使用PyMongo版本3.7.1,我收到以下错误:

ServerSelectionTimeoutError: hostname '127.0.0.1' doesn't match either of '<redacted server1>', '<redacted server1 wildcard domain>', '127.0.0.1'

The certificate was setup with the explicit <server name> as well as *.server_domain.com in the DNS list for the x509 certificate in the event we had to move our MongoDB to another server location in the domain. 如果我们必须将MongoDB移动到域中的另一个服务器位置,则在x509证书的DNS列表中使用显式<server name>*.server_domain.com证书。 We also added 127.0.0.1 for the few users located outside of the Domain who would need to use SSH Tunnels to access the database. 我们还为位于域外的少数用户添加了127.0.0.1 ,这些用户需要使用SSH隧道来访问数据库。

Using PyMongo, we get the following error: 使用PyMongo,我们收到以下错误:

from pymongo import MongoClient
client = MongoClient('127.0.0.1', 27017, ssl_ca_certs='/Users/<user>/ssl_cert_location/mongodb.pem')
db = client['admin']
db.authenticate('<username>', '<password>')

---------------------------------------------------------------------------
ServerSelectionTimeoutError               Traceback (most recent call last)
<ipython-input-26-ca905a055830> in <module>()
----> 1 db.authenticate('<username>', '<password>')

/Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/database.pyc in authenticate(self, name, password, source, mechanism, **kwargs)
   1272             self.name,
   1273             credentials,
-> 1274             connect=True)
   1275
   1276         return True

/Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/mongo_client.pyc in _cache_credentials(self, source, credentials, connect)
    607         if connect:
    608             server = self._get_topology().select_server(
--> 609                 writable_preferred_server_selector)
    610
    611             # get_socket() logs out of the database if logged in with old

/Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/topology.pyc in select_server(self, selector, server_selection_timeout, address)
    222         return random.choice(self.select_servers(selector,
    223                                                  server_selection_timeout,
--> 224                                                  address))
    225
    226     def select_server_by_address(self, address,

/Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/topology.pyc in select_servers(self, selector, server_selection_timeout, address)
    181         with self._lock:
    182             server_descriptions = self._select_servers_loop(
--> 183                 selector, server_timeout, address)
    184
    185             return [self.get_server_by_address(sd.address)

/Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/topology.pyc in _select_servers_loop(self, selector, timeout, address)
    197             if timeout == 0 or now > end_time:
    198                 raise ServerSelectionTimeoutError(
--> 199                     self._error_message(selector))
    200
    201             self._ensure_opened()

ServerSelectionTimeoutError: hostname '127.0.0.1' doesn't match either of '<redacted server1>', '<redacted server1 wildcard domain>', '127.0.0.1'

The most important part of this error being hostname '127.0.0.1' doesn't match '127.0.0.1' . 这个错误最重要的部分是hostname '127.0.0.1' doesn't match '127.0.0.1' This makes zero sense to me as it clearly does match and both the Mongo Shell and Robo 3T have zero qualms using this x509 SSL Certificate for connecting to the Database. 这对我来说毫无意义,因为它显然匹配,并且Mongo Shell和Robo 3T使用此x509 SSL证书连接到数据库时没有任何疑虑。

With the Mongo shell from outside the Domain, there does not seem to be an issue: 使用域外的Mongo shell,似乎没有问题:

$  pkinit -f <user>
     <user> PIN:  *****************

$  /usr/local/ossh/bin/ssh -4K -nNT -L 27017:127.0.0.1:<mongo_port> <user>@<server1>

$ ./mongo --host 127.0.0.1 --port 27017 --ssl --sslCAFile ~/ssl_cert_location/mongodb6.pem

    MongoDB shell version v4.0.1
    connecting to: mongodb://127.0.0.1:27017/
    MongoDB server version: 3.6.5
    WARNING: shell and server versions do not match
  MongoDB Enterprise > use admin
    switched to db admin

So, the tunnel is functioning as it should and MongoDB does not have any issues with the SSL x509 Certificate. 因此,隧道正常运行,MongoDB与SSL x509证书没有任何问题。 So that begs the question of why Pymongo cannot handle the given x509 Certificate? 这就引出了为什么Pymongo无法处理给定的x509证书的问题? I am not using any leading or trailing dots in the list of hostnames which seems to be what all the threads concentrate on when searching for this error. 我没有在主机名列表中使用任何前导或尾随点,这似乎是所有线程在搜索此错误时所关注的。 I explicitly give the exact hostname that is listed as one of the Alternate DNS hostnames from the x509 certificate. 我明确地给出了x509证书中列为备用DNS主机名之一的确切主机名。

I would greatly appreciate any help anyone can give me concerning this error. 我将非常感谢任何人可以提供有关此错误的任何帮助。 Thanks in advance. 提前致谢。

Here's some code from the driver. 这是驱动程序的一些代码。 Your cert is parsed and it tries to load DNS names from the subjectAltName section https://github.com/mongodb/mongo-python-driver/blob/749c1a2f0bde87a6e6d8df9366e4c90666efd189/pymongo/ssl_match_hostname.py#L103-L113 您的证书已解析,并尝试从subjectAltName部分加载DNS名称https://github.com/mongodb/mongo-python-driver/blob/749c1a2f0bde87a6e6d8df9366e4c90666efd189/pymongo/ssl_match_hostname.py#L103-L113

Notice that the driver differentiates between 'DNS' and 'IP Address' keyed entries within the subjectAltName. 请注意,驱动程序区分subjectAltName中的“DNS”和“IP地址”键控条目。 I imagine you've added '127.0.0.1' as a DNS hostanme in the cert, while the driver is treating the string '127.0.0.1' as an IP Address and hence there is no match. 我想你已经在证书中添加了“127.0.0.1”作为DNS hostanme,而驱动程序将字符串'127.0.0.1'视为IP地址,因此没有匹配。

This is why the code fails with the confusing error. 这就是代码因混淆错误而失败的原因。 The match failure isn't on the direct value- its on the fact that one is an IP address and the other is a hostname. 匹配失败不是直接值 - 它是因为一个是IP地址而另一个是主机名。

The confusion happens slightly earlier, where a variable host_ip is assigned on whether the specified hostname can be parsed as an IP address or not. 混淆稍早发生,其中分配变量host_ip是否可以将指定的主机名解析为IP地址。 https://github.com/mongodb/mongo-python-driver/blob/749c1a2f0bde87a6e6d8df9366e4c90666efd189/pymongo/ssl_match_hostname.py#L98-L102 In the case of a hostname '127.0.0.1' I imagine it is parsed correctly and assigned to the host_ip variable https://github.com/mongodb/mongo-python-driver/blob/749c1a2f0bde87a6e6d8df9366e4c90666efd189/pymongo/ssl_match_hostname.py#L98-L102如果是主机名'127.0.0.1',我想它会被正确解析并分配给host_ip variable

Now this check will fail https://github.com/mongodb/mongo-python-driver/blob/749c1a2f0bde87a6e6d8df9366e4c90666efd189/pymongo/ssl_match_hostname.py#L107 and it won't match for '127.0.0.1' from the DNS hostnames section of your cert. 现在这个检查将失败https://github.com/mongodb/mongo-python-driver/blob/749c1a2f0bde87a6e6d8df9366e4c90666efd189/pymongo/ssl_match_hostname.py#L107并且它与来自DNS主机名部分的'127.0.0.1'不匹配你的证书。

The Fix 修复

Your cert's subjectAltName field should probably look something like this: 您的cert的subjectAltName字段应该看起来像这样:
subjectAltName = DNS:<server1>, DNS:<server2>, IP:127.0.0.1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 pymongo 连接到 aws 时出现 ServerSelectionTimeoutError - ServerSelectionTimeoutError when connecting to aws with pymongo 使用 pymongo 连接到 Atlas MongoDb - ServerSelectionTimeoutError - Connecting to Atlas MongoDb using pymongo - ServerSelectionTimeoutError 获取 ssl.SSLError: [X509] 在 python 中找不到证书或 crl (_ssl.c:4062) - getting ssl.SSLError: [X509] no certificate or crl found (_ssl.c:4062) in python 在Python中验证X509证书上的签名 - Verify signature on X509 certificate in Python 用Python读取X509证书 - Reading an X509 Certificate in Python 尝试连接到 CosmosDB 数据库时出现 pymongo.errors.ServerSelectionTimeoutError - Getting pymongo.errors.ServerSelectionTimeoutError when attempting to connect to a CosmosDB database pyopenssl 无法设置 x509 证书 [证书必须是 X509 实例] - pyopenssl can't set x509 certificate [cert must be an X509 instance] 如何使用m2crypto在非SSL设置中验证X509证书链 - How do I use m2crypto to validate a X509 certificate chain in a non-SSL setting Errno 185090050 _ssl.c:343:错误:0B084002:x509证书例程:X509_load_cert_crl_file:系统库,在由PyInstaller打包到exe之后 - Errno 185090050 _ssl.c:343: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib, after packaging to exe by PyInstaller Pymongo MongoDB SSL 证书过期错误 - Pymongo MongoDB SSL Certificate Expired Error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM