Как настроить Python на игнорирование проверки имени хоста? - PullRequest
6 голосов
/ 14 марта 2019

Мы относительно новичок в Python, поэтому вопрос может быть слишком простым.Мы используем Python версии 2.7.15.

Мы пытаемся использовать Python поверх TLS без успеха.

Это наш код:

import ssl,socket
import urllib2

context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = False
context.load_verify_locations("/py-test/python/bin/certificate.pem")
url = "https://10.0.0.12"
request = urllib2.Request(url)
websocket = urllib2.urlopen(request,None,None,None,None,None,context)
pages=websocket.readlines()
print pages

Как видите,мы настроили context.check_hostname = False

К сожалению, происходит сбой со следующим исключением

Traceback (most recent call last):
 File "./test.py", line 11, in <module>
   websocket = urllib2.urlopen(request,None,None,None,None,None,context)
 File "/py-test/python/lib/python2.7/urllib2.py", line 154, in urlopen
   return opener.open(url, data, timeout)
 File "/py-test/python/lib/python2.7/urllib2.py", line 429, in open
   response = self._open(req, data)
 File "/py-test/python/lib/python2.7/urllib2.py", line 447, in _open
   '_open', req)
 File "/py-test/python/lib/python2.7/urllib2.py", line 407, in _call_chain
   result = func(*args)
 File "/py-test/python/lib/python2.7/urllib2.py", line 1241, in https_open
   context=self._context)
 File "/py-test/python/lib/python2.7/urllib2.py", line 1198, in do_open
   raise URLError(err)
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:726)>

Это определенно проверка имени хоста.Если мы используем правильный сертификат и правильное имя хоста, запрос успешно выполнен.

Если мы используем неправильный сертификат, он завершается неудачей со следующим исключением.

File "./test.py", line 8, in <module>
   context.load_verify_locations("/py-test/python/bin/certificate_bad.pem")
ssl.SSLError: [X509] PEM lib (_ssl.c:3027)

Поэтому нам нужна помощь, чтобы понять, какнастройте Python на игнорирование проверки имени хоста.

Еще один вопрос (может быть задан в отдельном потоке).

Есть ли в Python файл trustore, который включает все известные CA?Как cacerts.jks в Java.Где мы можем найти доверенного лица?

Добавлено

Мы «хотим убедиться, что сертификат был подписан действительным центром сертификации», но нам «все равно,он идентифицирует сайт, к которому вы фактически подключаетесь ».

Нам нужна помощь, чтобы настроить Python на игнорирование проверки имени хоста?В чем ошибка в нашем коде?Мы попытались создать код в соответствии с документацией https://docs.python.org/2/library/ssl.html

Добавлено 2

Мы потратили много времени, но, к сожалению, у нас нетпрогресс.

У кого-нибудь есть рабочий пример в Python 2.7?Я имею в виду, что код работает, если вы обращаетесь к другому URL, а затем появляется в сертификате.Может быть, Python 2.7 не может быть настроен на игнорирование проверки имени хоста?

В чем может быть наша проблема?Мы используем его на CentOS 6. Может быть, это связано с OpenSSL?Мы используем последнюю версию openssl-1.0.1e-57.el6.x86_64.Может быть, мы должны обновить до Python 3.x?

Ответы [ 2 ]

3 голосов
/ 15 марта 2019

Как вы обнаружили, вы можете сделать это, настроив объект SSLContext, используемый для проверки соединения.

Однако, чтобы подключить это к urllib2.urlopen, вам нужно будет создать настраиваемый открыватель и установитьчто.

Вот пример:

import httplib
import socket
import ssl
import urllib2

import certifi


class InterceptedHttpsConnection(httplib.HTTPSConnection):
    def connect(self):
        # Open an unencrypted TCP socket first
        sock = socket.create_connection((self.host, self.port), self.timeout)

        # Build up a custom SSLContext. (Might be better to do this once rather
        # than on every request.)
        context = ssl.SSLContext(ssl.PROTOCOL_TLS)

        # We require the SSL context to verify the certificate.
        context.verify_mode = ssl.CERT_REQUIRED

        # But we instruct the SSL context to *not* validate the hostname.
        context.check_hostname = False

        # Load CA certificates from the certifi bundle.
        context.load_verify_locations(cafile=certifi.where())

        # Use our SSLContext object to wrap the bare socket into an SSL socket.
        self.sock = context.wrap_socket(sock, server_hostname=self.host)


class InterceptedHttpsHandler(urllib2.HTTPSHandler):
    def https_open(self, req):
        return self.do_open(InterceptedHttpsConnection, req)


def main():
    opener = urllib2.build_opener(InterceptedHttpsHandler)
    urllib2.install_opener(opener)

    contents = urllib2.urlopen('https://example.com/').read()
    print contents
3 голосов
/ 15 марта 2019
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

Заставляет python пропускать проверку сертификатов по умолчанию.Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...