草庐IT

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

coder 2023-10-31 原文

我正在尝试连接到另一台服务器上的 MongoDB 数据库。唯一的问题是连接到服务器需要专门版本的 Kerberos。为了克服这个问题,我使用 SSH 隧道为 Pymongo 打开一个本地端口以连接数据库,我们专门为这种情况设计了安全证书作为预防措施。我知道隧道运行正常,因为 Mongo Shell 和 Robo 3T 都能够连接到数据库并显示数据。但是,对于 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'

证书是使用显式 <server name> 设置的以及*.server_domain.com在 x509 证书的 DNS 列表中,如果我们不得不将 MongoDB 移动到域中的另一个服务器位置。我们还添加了 127.0.0.1对于位于域之外的少数用户,他们需要使用 SSH 隧道来访问数据库。

使用 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'

此错误最重要的部分是 hostname '127.0.0.1' doesn't match '127.0.0.1' .这对我来说毫无意义,因为它显然确实匹配,而且 Mongo Shell 和 Robo 3T 都对使用此 x509 SSL 证书连接到数据库没有任何疑虑。

对于域外的 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

因此,隧道正常运行,MongoDB 的 SSL x509 证书没有任何问题。那么这就引出了为什么 Pymongo 无法处理给定的 x509 证书的问题?我没有在主机名列表中使用任何前导或尾随点,这似乎是所有线程在搜索此错误时所关注的。我明确给出了 x509 证书中列为备用 DNS 主机名之一的确切主机名。

我将不胜感激任何人能给我关于这个错误的任何帮助。提前致谢。

最佳答案

这是驱动程序的一些代码。 您的证书已被解析并尝试从 subjectAltName 部分加载 DNS 名称 https://github.com/mongodb/mongo-python-driver/blob/749c1a2f0bde87a6e6d8df9366e4c90666efd189/pymongo/ssl_match_hostname.py#L103-L113

请注意,驱动程序会区分 subjectAltName 中的“DNS”和“IP 地址”键控条目。 我想您已经在证书中添加了“127.0.0.1”作为 DNS hostanme,而驱动程序将字符串“127.0.0.1”视为 IP 地址 因此没有匹配项。

这就是代码因令人困惑的错误而失败的原因。匹配失败不在于直接值(value)——它在于这样一个事实 一个是 IP 地址,另一个是主机名。

混淆发生得稍早一些,其中一个变量 host_ip指定的主机名是否可以解析为 一个IP地址或没有。 https://github.com/mongodb/mongo-python-driver/blob/749c1a2f0bde87a6e6d8df9366e4c90666efd189/pymongo/ssl_match_hostname.py#L98-L102 在主机名“127.0.0.1”的情况下,我想它被正确解析并分配给了 host_ip variable

现在这个检查将失败 https://github.com/mongodb/mongo-python-driver/blob/749c1a2f0bde87a6e6d8df9366e4c90666efd189/pymongo/ssl_match_hostname.py#L107 并且它不会匹配您证书的 DNS 主机名部分中的“127.0.0.1”。

修复

您的证书 subjectAltName字段应该看起来像这样:
subjectAltName = DNS:<server1>, DNS:<server2>, IP:127.0.0.1

关于python - 使用 PyMongo 和 x509 SSL 证书连接到 MongoDB 数据库时出现 ServerSelectionTimeoutError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51830805/

有关python - 使用 PyMongo 和 x509 SSL 证书连接到 MongoDB 数据库时出现 ServerSelectionTimeoutError的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  10. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

随机推荐