Requests: Suporte SNI TLS

Criado em 1 ago. 2012  ·  46Comentários  ·  Fonte: psf/requests

Parece que estou tendo problemas ao usar solicitações com servidores que precisam de suporte TLS SNI. Quando as solicitações terão esse recurso? Isso é algo planejado?

Obrigado,
--RAM

Comentários muito úteis

Isso é especificado em requests / packages / urllib3 / contrib / pyopenssl.py :

  • pyOpenSSL (testado com 0,13)
  • ndg-httpsclient (testado com 0.3.2)
  • pyasn1 (testado com 0.1.6)

(Ou python3.2 ou superior, que sempre funciona)

Todos 46 comentários

Não posisível no Python 2.x no topo do módulo ssl do stdlib.

Twisted tem, certo? Talvez seja hora de depender de pyopenssl ou algum outro módulo SSL?

Há uma solicitação de pull para urllib3 adicionando suporte SNI para Py32 +, mas ainda precisa de cobertura de teste. https://github.com/shazow/urllib3/pull/89

shzow: Obrigado pela indicação. Infelizmente, estou usando Twisted / Flask, o que significa que estou preso ao 2.7. Parece que o Twisted pode fazer algo assim, mas eu não vi exemplos, e seria necessária a decodificação pyopenssl + twisted para fazer isso. Não sou um especialista em fazer isso. Neste ponto, apenas pensando em envolver algum utilitário de linha de comando como wget ... :(

PyOpenSSL deve ser capaz de fazer isso no 2.x. Portanto, há esperança.

Eu poderia fazer funcionar com pyopenssl. Mas eu ainda estou tendo dificuldade em fazer isso corretamente. http://pbin.be/show/719/ - tipo de trabalhos. Mas então é preciso construir uma API nele para que seja útil. Ainda não consigo descobrir como passar o contexto correto para o Agente.

Lukasa: isso foi resolvido?

Não. Estamos bloqueados em shazow / urllib3 # 89.

Mesclado. Continuar. :)

Observe que ele só é compatível com Py32 + por enquanto. Deve ser o suficiente para começar.

Outro aviso justo: alguns testes no Py32 estão falhando no mestre urllib3 agora. Agradecemos bastante ajuda para resolver isso (e pode afetar essa funcionalidade): https://github.com/shazow/urllib3/issues/128

funciona para mim em archlinux x64 em py26, py27, py32, py33

Ah, eu deveria ter qualificado que isso é no OSX. Scumbag OSX.

t-8ch: Os testes sni estão passando em py26 / 27/32 e 33 para você?

Os testes SNI nem mesmo são executados em py2, mas em py32 e py33 funciona.
Não há como fazer SNI com o módulo ssl da biblioteca padrão antes de py32.

@shazow : Presumivelmente você não tem interesse em fazer o urllib3 depender do PyOpenSSL?

Eu ficaria feliz em ter uma biblioteca separada que adiciona SSL via suporte PyOpenSSL para urllib3.

Parece que @ t-8ch está impressionando muito com o trabalho no urllib3. Vou deixá-lo nos dizer quando isso pode ser fechado.

urllib3 tem suporte opcional para SNI com python2, embora com algumas dependências opcionais. (Veja urllib3 # 156 ).

Eu acredito que isso deve funcionar usando:

from requests.packages.urllib3.contrib import pyopenssl
pyopenssl.inject_into_urllib3

Depois de adicionar isso a packages em setup.py

requests.packages.urllib3.contrib

Observe que o pacote contrib não é importado por padrão.

Existem basicamente duas alternativas para habilitar SNI em solicitações:

  • Criar função para habilitar manualmente o SNI que basicamente executa o código acima. (a desvantagem é que os usuários precisarão habilitar explicitamente o suporte SNI).
  • Tente importar os pré-requisitos. Se eles existirem, habilite o SNI; caso contrário, não o faça.

Não tenho problemas para implementar qualquer uma das alternativas, embora prefira saber qual é a preferida para solicitações. Eu pessoalmente voto pela segunda alternativa.

BTW: podemos reabrir o problema, agora que temos o suporte do urllib3?

Na verdade, prefiro o primeiro porque as pessoas que precisam são aquelas que sabem que vão precisar e são poucos o suficiente para não causar muitas reclamações. No entanto, se quisermos ser consistentes com a API existente, a última seria a maneira de implementá-la. Atualmente, o urllib3 (e as solicitações) fornecerá a API para enviar solicitações HTTPS sem o módulo ssl presente, mas falhará no caso em que o módulo ssl não estiver disponível. Em outras palavras, a API está lá e você pode usá-la, mas ela simplesmente não funciona e isso é indicado por uma exceção.

Quanto a reabrir isso, cabe a @kennethreitz. O problema, é claro (com tudo isso), é que atualmente estamos congelando recursos (# 1165, # 1168), então não tenho certeza se vale a pena fazer o trabalho porque pode não ser aceito.

Deixe-me ser um pouco mais claro: o que eu quis dizer com a segunda alternativa foi "Tente usar SNI se os recursos opcionais estiverem disponíveis, mas ainda use SSL, pois sempre fizemos isso, eles não estão". Isso não deve quebrar nada existente até agora.

Quanto à reabertura (ou não) do assunto, IMHO, este assunto não deve ser considerado levianamente. as solicitações podem se tornar inúteis sem o suporte SNI para muitos cenários. Em particular, vários domínios em um único host IPv4 sem SNI tornam-se impossíveis. E endereços IPv4 adicionais estão fora de questão para muitos usuários (devido ao seu custo).

Em qualquer caso, isso é meio recurso, meio bug, mas vou aguardar a resposta de @kennethreitz sobre a reabertura do problema.

Hugo: Acabei de instalar as solicitações -U do pip, e quando não consigo importar o contrib.
Como faço para corrigir isso? (Importerror: Nenhum módulo denominado contrib).

Na sexta-feira, 3 de maio de 2013 às 13h12, Hugo Osvaldo Barrera <
notificaçõ[email protected]> escreveu:

urllib3 tem suporte opcional para SNI com python2, embora com alguns
dependências opcionais. (Consulte urllib3 # 156https: //github.com/shazow/urllib3/pull/156
)

Eu acredito que isso deve funcionar usando:

from request.packages.urllib3.contrib import pyopenssl
pyopenssl.inject_into_urllib3

Observe que o pacote contrib não é importado por padrão.

Existem basicamente duas alternativas para habilitar SNI em solicitações:

  • Criar função para habilitar manualmente o SNI que basicamente executa o acima
    código. (a desvantagem é que os usuários precisarão habilitar explicitamente o SNI
    Apoio, suporte).
  • Tente importar os pré-requisitos. Se eles existirem, habilite SNI, senão
    não

Não tenho problemas para implementar qualquer uma das alternativas, embora eu prefira
para saber qual seria o preferencial para solicitações. Eu pessoalmente voto em
a segunda alternativa.

-
Responda a este e-mail diretamente ou visualize-o em Gi tHubhttps: //github.com/kennethreitz/requests/issues/749#issuecomment -17406518
.

O setup.py do request não inclui esse pacote (a fonte está lá, mas é excluída ao instalar / empacotar), então não está instalado, é por isso que mencionei:

Depois de adicionar isso a packages in setup.py
request.packages.urllib3.contrib

Basicamente, você precisará instalar a partir do código-fonte.
Verifique minha solicitação de pull se estiver interessado. Para fazer este trabalho, basta algumas linhas. :)

"Tente usar SNI se os recursos opcionais estiverem disponíveis, mas ainda use SSL, pois sempre fizemos isso, eles não estão."

Porém, SSL nem sempre está lá. Esse foi o meu ponto. Atualmente, tentamos usá-lo, mas falhamos muito e rapidamente se não o tivermos e um usuário tentar fazer uma solicitação https. No entanto, da forma como você o descreveu, eu estava com a impressão de que o SNI exigiria que o usuário passasse alguma noção extra para o urllib3 e você estava se concentrando apenas na configuração dele. Se tudo o que for necessário for o # 1347, estou 100% por trás disso.

Seria muito bom se este fosse o padrão (Suporte SNI) e as solicitações
simplesmente funciona sem qualquer código extra ou configuração da fonte. Para urllib3 é 2
linhas de código. Por que não apenas adicionar isso às solicitações. Estou sonhando acordado? :)

Na sexta-feira, 3 de maio de 2013 às 22h43, Ian Cordasco [email protected] :

"Tente usar SNI se as dependências opcionais estiverem disponíveis, mas ainda use SSL como
sempre temos isso, eles não são. "

Porém, SSL nem sempre está lá. Esse foi o meu ponto. Atualmente tentamos e
usá-lo, mas falhará forte e rápido se não o tivermos e um usuário tentar fazer
uma solicitação https. No entanto, da maneira como você descreveu, eu estava sob o
SNI de impressão exigiria que o usuário passasse alguma noção extra para urllib3
e você estava se concentrando apenas na configuração para isso. Se tudo isso for necessário
é # 1347 https://github.com/kennethreitz/requests/issues/1347, então estou
100% por trás disso.

-
Responda a este e-mail diretamente ou visualize-o em Gi tHubhttps: //github.com/kennethreitz/requests/issues/749#issuecomment -17426626
.

@pythonmobile girar um pião. Se não para de girar, você está sonhando.

inception

Deixar um comentário para o bem de outras pessoas que podem ter o mesmo problema que eu:
Se você estiver tendo problemas para fazer solicitações seguras usando a biblioteca requests , em particular ao tentar acessar um aplicativo hospedado no Google App Engine, esse pode ser o motivo. O erro que eu estava vendo era "EOF ocorreu em violação do protocolo". Para diagnosticar isso, tente atingir o mesmo host usando s_client (substitua example.com pelo host em questão):

openssl s_client -connect example.com:443
openssl s_client -connect example.com:443 -servername example.com

Se o primeiro comando falhar com "falha de handshake" e o segundo for bem-sucedido, você está tentando acessar um servidor que usa SNI. O presente tópico tem boas informações sobre como fazer requests trabalhar nesta situação. O que fiz foi tentar executar from requests.packages.urllib3.contrib import pyopenssl no ipython e continuei no pip instalando todos os erros de importação. YMMV.

@mshang Versão 1.2.3 já deve fazer isso por você; tem certeza de que está executando essa versão?

@hobarrera Sim, estou executando o 1.2.3. requests.packages.urllib3.contrib estava lá, mas as instruções de importação ainda geravam vários erros de importação. Tive que instalar ndg-httpsclient e esqueci o que mais.

Correto. Requests apenas tenta importar os módulos necessários e, se não conseguir, desiste e segue com sua vida. No entanto, pode ser uma boa ideia documentar o que você precisa para usar o SNI com solicitações.

Isso é especificado em requests / packages / urllib3 / contrib / pyopenssl.py :

  • pyOpenSSL (testado com 0,13)
  • ndg-httpsclient (testado com 0.3.2)
  • pyasn1 (testado com 0.1.6)

(Ou python3.2 ou superior, que sempre funciona)

Parece que as solicitações e urllib3 estão quebradas para SNI atualmente. 1
problema é que se adicionarmos tempo limite = 5.0, o código se comporta de maneira diferente
sem tempo limite. O segundo problema é com domínios que não existem.
Os testes precisam adicionar mais domínios SNI em comparação com apenas dependendo de
vértice / httpbin /. Ambos não refletem o uso de SNI.

Na segunda-feira, 10 de junho de 2013 às 4:57, Thomas Weißschuh
notificaçõ[email protected] :

Isso é especificado em requests / packages / urllib3 / contrib / pyopenssl. pyhttps: //github.com/kennethreitz/requests/blob/master/requests/packages/urllib3/contrib/pyopenssl.py
:

  • pyOpenSSL (testado com 0,13)
  • ndg-httpsclient (testado com 0.3.2)
  • pyasn1 (testado com 0.1.6)

(Ou python3.2 ou superior, que sempre funciona)

-
Responda a este e-mail diretamente ou visualize-o em Gi tHubhttps: //github.com/kennethreitz/requests/issues/749#issuecomment -19187417
.

@pythonmobile Se for esse o caso, e você tiver um caso de teste reproduzível de boa qualidade, abra um problema destacando-o no urllib3. Requests não tem código específico de SNI (até onde eu sei), então uma correção lá também nos corrigirá.

A menos que o urllib3 já esteja corrigido, o que parece acontecer muito atualmente. Shazow _et. al._ são muito legais. @ t-8ch, vocês já viram / consertaram isso?

Acho que se escrevermos os testes em solicitações, eles serão mais fáceis de escrever e testar, embora isso signifique apenas que testará principalmente o código urllib3. Dessa forma, será mais fácil verificar a cada importação do urllib3 nas requisições, se o sni está quebrado ou não e disparar um alarme. Escreverei os testes de solicitações em breve.

Desculpe @pythonmobile , não concordo. =)

SNI é explicitamente uma funcionalidade urllib3. Se o SNI estiver quebrado no urllib3, você absolutamente deve fornecer a esse projeto uma correção, um teste ou, pelo menos, um relatório de bug. Quando esse projeto for corrigido, os Requests também serão corrigidos magicamente (na próxima atualização do urllib3, o que fazemos com bastante frequência). =)

Embora mais testes para solicitações certamente não façam mal, como

Já temos muitos exames no mesmo sentido, me mande um ping se precisar de alguma ajuda.

Parece que o comportamento de tempo limite de pyOpenSSL é diferente daquele do
módulo SSL padrão:

from OpenSSL import SSL
import socket
import ssl

sock = socket.create_connection(('httpbin.org', 443), timeout=4.0)
ssl_sock = ssl.wrap_socket(sock)
ssl_sock.send('GET /ip HTTP/1.1\r\nHost: httpbin.org\r\n\r\n')
print(ssl_sock.recv(10000))

ctx = SSL.Context(SSL.TLSv1_METHOD)
sock = socket.create_connection(('httpbin.org', 443), timeout=4.0)
ctn = SSL.Connection(ctx, sock)
ctn.set_connect_state()

ctn.send('GET /ip HTTP/1.1\r\nHost: httpbin.org\r\n\r\n')
print(sock.read(10000))

Isso lança um WantReadError , o mesmo que também é jogado fora do urllib3
ao especificar um tempo limite.

A documentação tem
isso a dizer sobre o erro:

The operation did not complete; the same I/O method should be called again
later, with the same arguments. Any I/O method can lead to this since new
handshakes can occur at any time.

The wanted read is for dirty data sent over the network, not the clean data
inside the tunnel. For a socket based SSL connection, read means data coming at
us over the network. Until that read succeeds, the attempted
OpenSSL.SSL.Connection.recv, OpenSSL.SSL.Connection.send, or
OpenSSL.SSL.Connection.do_handshake is prevented or incomplete. You probably
want to select() on the socket before trying again. 

Não sei como lidar com o tempo limite. O soquete magicamente
lembre-se do tempo limite sobre as invocações de select() ou esta é a tarefa de
urllib3?
Manter o controle do tempo limite manualmente não parece muito engraçado.

@pythonmobile O que você quer dizer com domínios inexistentes. Eu não posso te seguir.

@pythonmobile Você poderia tentar as alterações de shazow / urllib3 # 233 e ver se o código funciona com pyopenssl e tempos limite?

@ t-8ch @pythonmobile : https://github.com/kennethreitz/requests/issues/1522#issuecomment -22443282

Seria bom obter essas solicitações em um teste de unidade dentro de urllib3 ou solicitações.

O problema de obtê-los como um teste de unidade é que eles só aparecem em configurações muito específicas. Por exemplo, nunca consegui reproduzir a segunda metade deste problema ou o # 1522 em nenhum dos meus sistemas, seja Windows, OS X ou Ubuntu. É por isso que pedi ao @pythonmobile um teste de unidade reproduzível. Se pudermos encontrar um, podemos desenvolver contra ele, caso contrário, ficaremos presos na esperança de que @ t-8ch continue a ser um gênio e conserte magicamente todos os nossos problemas em urllib3 .

NB: @ t-8ch, acho que não agradeço o suficiente pelo seu trabalho, tanto aqui quanto em urllib3 . Você é incrível. = D: bolo:: abacaxi:: banana:: biscoito:: cervejas:

@lukasa Obrigado: smile: Acho que poderia me adicionar a AUTHORS.txt algum momento no futuro.

@ t-8ch Faça isso. : +1:

As mudanças em shazow / urllib3 # 233 (agora puxado para urllib3 master) corrigem o problema para mim ( SSLError('bad handshake', WantReadError()) ) que ocorria para alguns urls, algumas vezes, em algumas configurações: rage4 :. Podemos colocar isso no mestre de solicitações?

@rcoup Colocaremos uma versão atualizada em Requests quando

Estou executando o Python 2.7.6 e não consigo instalar o pyOpenSSL. Tentei a solução alternativa na postagem do htis -> https://stackoverflow.com/questions/18578439/using-requests-with-tls-doesnt-give-sni-support/18579484#18579484

Eu também não posso atualizar pelo Python. Alguma outra solução?

Estou solicitando que reconsideremos o uso incondicional (se houver) de "inject_into_urllib3 ()".

Adicionado há 7 anos, o objetivo era "adicionar suporte SNI para Python 2"

"urllib3.contrib.pyopenssl.inject_into_urllib3 ()" é descrito como "Monkey-patch urllib3 com suporte SSL apoiado por PyOpenSSL.":
(https://github.com/urllib3/urllib3/blob/master/src/urllib3/contrib/pyopenssl.py)

Justificação:
1: Segurança / estabilidade: o patching do Monkey para trocar o uso da biblioteca padrão por uma biblioteca de terceiros deve ser mais cirúrgico, especialmente para SSL. Se o patch for para suporte em Python2, então, pelo menos, verifique se há uma versão principal. Ou melhor ainda, verifique se o suporte SNI já está presente ssl.HAS_SNI .

2: Desnecessário: a partir de 10 de dezembro de 2014, todo o módulo ssl do Python 3.4 foi portado para o Python 2.7.9. Veja PEP 466 para justificativa. https://www.python.org/downloads/release/python-279/. Isso ativa o suporte SNI na biblioteca padrão para> v2.7.9

3: Inflexível: conforme implementado, não há como desativar esse comportamento. A única opção para evitar o uso de requests do contexto pyopenssl é desinstalar o pyopenssl de todo o meu ambiente python.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

eromoe picture eromoe  ·  3Comentários

NoahCardoza picture NoahCardoza  ·  4Comentários

ghtyrant picture ghtyrant  ·  3Comentários

remram44 picture remram44  ·  4Comentários

8key picture 8key  ·  3Comentários