Запросы Python HTTPS (urllib2) на некоторые сайты выходят из строя на Ubuntu 12.04 без прокси-сервера

Ubuntuone автоматически запускается из /etc/xdg/autostart/ubuntuone-launch.desktop не из upstart. gnome-session-properties ИЛИ StartUp Appication Preference в сеансовом индикаторе не позволяет включить / отключить приложение автозапуска в /etc/xdg/autostart, так как большинство из них содержат NoDisplay=true. Вы можете сделать следующее:

Прокомментировать строку NoDisplay=true как #NoDisplay=true и отключить ее от вышеупомянутой guis.

ИЛИ сделать:

mv /etc/xdg/autostart/ubuntuone-launch.desktop /etc/xdg/autostart/ubuntuone-launch.desktop.disabled

Как добавить / удалить «скрытый». запуска приложений?

23
задан 26 March 2012 в 11:37

7 ответов

Это связано с добавлением поддержки TLS 1.1 и 1.2 версии OpenSSL, обнаруженной в 12.04. Ошибка соединения может быть воспроизведена с помощью инструмента командной строки OpenSSL:

$ openssl s_client -connect www.mediafire.com:443
CONNECTED(00000003)
140491065808544:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 320 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

Соединение выполняется успешно, если я принудительно подключу к использованию TLS 1.0 с аргументом командной строки -tls1.

[d2 ] Я предлагаю вам сообщить об ошибке об этой проблеме:

https://bugs.launchpad.net/ubuntu/+filebug

15
ответ дан 25 May 2018 в 13:13
  • 1
    Спасибо! Я сообщил об ошибке. Пожалуйста, посмотрите, можете ли вы добавить к нему любую соответствующую информацию: bugs.launchpad.net/ubuntu/+source/openssl/+bug/965371 – Pablo 26 March 2012 в 20:06
  • 2
    Как это помогает ему решить проблему в Python? – Cerin 24 September 2013 в 01:46
  • 3
    @Cerin: он изолировал проблему как ошибку OpenSSL, а не что-то в Python, и направил его на использование трекера ошибок. С тех пор эта проблема исправлена. – James Henstridge 24 September 2013 в 05:47

Для новичков-питонов, таких как я, вот способ переопределить httplib самый простой способ. В верхней части вашего сценария python включите следующие строки:


import httplib
from httplib import HTTPConnection, HTTPS_PORT
import ssl

class HTTPSConnection(HTTPConnection):
    "This class allows communication via SSL."
    default_port = HTTPS_PORT

    def __init__(self, host, port=None, key_file=None, cert_file=None,
            strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
            source_address=None):
        HTTPConnection.__init__(self, host, port, strict, timeout,
                source_address)
        self.key_file = key_file
        self.cert_file = cert_file

    def connect(self):
        "Connect to a host on a given (SSL) port."
        sock = socket.create_connection((self.host, self.port),
                self.timeout, self.source_address)
        if self._tunnel_host:
            self.sock = sock
            self._tunnel()
        # this is the only line we modified from the httplib.py file
        # we added the ssl_version variable
        self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_TLSv1)

#now we override the one in httplib
httplib.HTTPSConnection = HTTPSConnection
# ssl_version corrections are done

Здесь вы можете использовать urllib или все, что вы используете, как обычно.

Примечание. для python 2.7. Для решения python 3.x вам необходимо переопределить класс HTTPSConnection, найденный в http.client. Я оставляю это как упражнение для читателя. : -

)
12
ответ дан 25 May 2018 в 13:13
  • 1
    Мне действительно нравится это решение, оно позволяет избежать изменения каких-либо системных библиотек или другого хакера. – MarkR 20 March 2013 в 17:28
  • 2
    Не удалось использовать Python 2.7.4 на Ubuntu 12.04: NameError: имя «сокет» не определено. --- Вам нужно добавить " import socket " также. – Ben Walther 25 July 2013 в 01:34
  • 3
    Отлично работает на Ubuntu 13.04. Благодаря! – dharmatech 1 September 2013 в 03:04
  • 4
    Нет причин для исправления httplib. Люди могут использовать другие SSL-сокеты. Можно было бы исправить ssl, как в моем ответе ниже. – temoto 16 September 2013 в 13:36
  • 5
    Это дает мне ошибку BadStatusLine: '' – Cerin 24 September 2013 в 02:08

Вы можете избежать изменения файла httplib.py, изменив свой объект HTTPSConnection:

import httplib, ssl, socket

conn = httplib.HTTPSConnection(URL.hostname)
sock = socket.create_connection((conn.host, conn.port), conn.timeout, conn.source_address)
conn.sock = ssl.wrap_socket(sock, conn.key_file, conn.cert_file, ssl_version=ssl.PROTOCOL_TLSv1)
conn.request('POST', URL.path + URL.query)

Метод запроса создает новый сокет, только если connection.sock не определен. Создавая свой собственный, добавляя параметр ssl_version, он будет использовать метод запроса. Тогда все остальное работает как обычно.

У меня была одна и та же проблема, и это работает для меня.

С уважением

8
ответ дан 25 May 2018 в 13:13

Проблема в ssl, она не имеет ничего общего с HTTP, поэтому зачем исправлять httplib, если вы можете исправить ssl. Следующий код должен исправить все SSL-сокеты, включая, но не ограничиваясь HTTPS, для Python 2.6+ (встроенный в ssl, не пытался с pyopenssl).

import functools
import ssl

old_init = ssl.SSLSocket.__init__

@functools.wraps(old_init)
def ubuntu_openssl_bug_965371(self, *args, **kwargs):
  kwargs['ssl_version'] = ssl.PROTOCOL_TLSv1
  old_init(self, *args, **kwargs)

ssl.SSLSocket.__init__ = ubuntu_openssl_bug_965371
7
ответ дан 25 May 2018 в 13:13
  • 1
    Хороший ответ. Хороший, элегантный способ решить проблему. – chnrxn 10 May 2015 в 16:39

EDIT httplib.py (/usr/lib/pythonX.X/httplib.py в Linux)

НАЙТИ Объявление класса HTTPSConnection

  class HTTPSConnection(HTTPConnection):
....

Код внутри класса CHANGE [ ! d2]

self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)

TO

self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_TLSv1)

Затем httplib HTTPS-запрос должен работать

import httplib
from urlparse import urlparse
url = XXX
URL = urlparse(url)
connection = httplib.HTTPSConnection(URL.hostname)
connection.request('POST', URL.path + URL.query)
response = connection.getresponse()
3
ответ дан 25 May 2018 в 13:13
  • 1
    На самом деле нет прав на редактирование системного файла. Вместо этого переопределите любые определения, которые необходимо изменить, путем переопределения их в вашем коде. – hexafraction 13 January 2013 в 06:47

Вероятно, эта проблема связана с отключением SSLv2 на веб-сервере, но Python 2.x пытается установить соединение с PROTOCOL_SSLv23 по умолчанию.

Вот ссылка на мой ответ для аналогичного вопроса о Переполнение стека - https://stackoverflow.com/a/24166498/41957

Обновление: это функционально то же самое, что и ответ @ temoto выше.

2
ответ дан 25 May 2018 в 13:13
  • 1
    TypeError: unbound method __init __ () должен быть вызван с экземпляром SSLSocket в качестве первого аргумента (вместо этого был получен экземпляр _socketobject) – sureshvv 8 May 2015 в 11:14
  • 2
    Hmm, partial () не работает для методов класса. В ближайшее время опубликует лучшее решение. – chnrxn 10 May 2015 в 05:47
  • 3
    @sureshvv, если вы можете помочь проверить решение, это будет оценено. – chnrxn 10 May 2015 в 12:19
  • 4
    Ответ @ temeto сработал. – sureshvv 12 May 2015 в 09:59

Простое исправление, которое сработало для меня, это переопределить протокол SSL по умолчанию:

import ssl
ssl.PROTOCOL_SSLv23 = ssl.PROTOCOL_TLSv1
1
ответ дан 25 May 2018 в 13:13
  • 1
    Это хаки, но в сегодняшнем контексте он довольно хорошо работает. С тех пор, как была обнаружена уязвимость пуделя, TLSv1 в значительной степени стал единственной приемлемой версией в Интернете. – chnrxn 10 May 2015 в 07:51

Другие вопросы по тегам:

Похожие вопросы: