[英]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'不匹配你的证书。
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.