2009-03-23 4 views
3

파이썬에서 TLS를 사용해야하는 HTTP 클라이언트가 있습니다. 암호화 된 연결을 위해 을 입력 할 필요가 없으며 인증서 발급자와 같은 원격 컴퓨터에서 정보를 검색 할 수도 있습니다. 내가 종종 많은 HTTP 서버에 연결을 만들 필요가 심하게 행동, 그래서 나는 절대적으로 시간 제한이 필요합니다. 비 TLS 연결의 경우 mysocket.settimeout(5) 내가 원하는 것을 수행합니다. 많은 TLS 파이썬 모듈 중TLS 연결 제한 시간 (기타 몇 가지 어려움)

:

gnutls.errors.OperationWouldBlock: Function was interrupted. 

python-openssl가 유사한 문제가 있습니다 :

python-gnutls이 비 블로킹 소켓을 사용 때문에 소켓의 setTimeout()를 사용하는 것을 허용하지 않습니다

OpenSSL.SSL.WantReadError 

표준 라이브러리의 SSL module은 파이썬에서 작동하지 않습니다.2.5.

TLSlite과 같은 다른 라이브러리는 인증서의 메타 데이터에 에 대한 액세스 권한을 부여하지 않은 것 같습니다.

프로그램이 스레드되어 있으므로 신호를 사용할 수 없습니다. urllib2와 같은 표준 라이브러리를 사용할 수 없으므로 HTTP 대화 상자에서 자세한 컨트롤이 필요합니다.

배경 : 이것은 조사 프로젝트 DNSwitness입니다. 관련 SO 스레드 : Timeout on a Python function callHow to limit execution time of a function call in Python.

답변

1

정확하게이 용도로 사용해 본 적이 없지만 Twisted은 원하는대로해야합니다. 유일한 단점은 상당히 큰 라이브러리이므로 PyOpenSSL (Twisted는 이에 따라 다름)을 설치해야합니다. Twisted의 콜백 기반 아키텍처를 사용 해 본 적이 없다면 익숙해지기 시작합니다 ( 시작하기 전에 자습서를 읽고 싶습니다).

이외에도 많은 연결을 관리한다는 아이디어를 바탕으로 설계되었으므로 타임 아웃, 재 연결 등을 지정하고 인증서 정보를 검색 할 수 있습니다 (here 참조).

1

다음과 같은 문제가 있다고 가정하고, PyOpenSSL을 사용하여 연결을 열면 항상 WantReadError 예외가 발생합니다. 그리고이 오류와 시간 초과를 구분할 수 없습니다. 다음의 예를 생각해

#!/usr/bin/python 

import OpenSSL 
import socket 
import struct 

context = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD) 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.settimeout(5) 
connection = OpenSSL.SSL.Connection(context,s) 
connection.connect(("www.gmail.com",443)) 

# Put the socket in blocking mode 
connection.setblocking(1) 

# Set the timeout using the setsockopt 
tv = struct.pack('ii', int(6), int(0)) 
connection.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, tv) 

print "Connected to " , connection.getpeername() 
print "Sate " , connection.state_string() 

while True: 
    try: 
     connection.do_handshake() 
     break 
    except OpenSSL.SSL.WantReadError: 
     print "Exception" 
     pass 
print "Sate " , connection.state_string() 


print connection.send("koekoek\r\n") 


while True: 
    try: 
     recvstr = connection.recv(1024) 
     break 
    except OpenSSL.SSL.WantReadError: 
     print "Exception" 
     pass 

print recvstr 

이 잘못된 문자열을 보내, Gmail로 SSL 연결을 열 응답을 읽고 그것을 인쇄 할 수 있습니다. 참고 : * 연결은 명시 적으로 차단 모드 으로 설정됩니다 * recv 제한 시간은 명시 적으로이 경우 6 초로 설정됩니다.

이제는 어떤 상황이 발생합니까? 시간 제한이 발생하면 WantReadError 예외가 발생합니다 (이 경우 6 초 후). (재 시도를 피하기 위해 True를 제거 할 수 있지만이 경우 테스트를 위해 추가했습니다.) 소켓의 타임 아웃 설정은 connect() 호출에서만 유효합니다.

GNUTLS의 경우에도 적용 할 수있는 비 차단 모드의 소켓을 유지할 때 대안으로는 시간 측정을 직접 수행하고, 호출을 시작할 때를 얻는 반면, 실제로는 : WantReadError를 제외하고는 매번 스스로 체크하여 너무 오래 기다리지 않았는지 확인하십시오.

+0

전에에서는 setTimeout (없음) 또는 (1) setblocking으로 시간 제한을 제거하십시오 그러나 프로세서를위한 매우 비용이 많이 드는 바쁜 대기의 일종 아닌가요? – bortzmeyer

+0

수면을 삽입하거나, 스케줄러를 양보하거나, 다른 일을 할 수 있습니다. 그리고 루프에서 오랜 기간을 보내는 것처럼 좋은 서버는 매우 빠르게 응답하려고합니다. –

0

하나의 간단한 해결책은 작업에 따라 소켓 유형을 변경할 수 있습니다. 나는 gnutls와이 테스트는 일 :

  1. 마에서는 setTimeout()를 소켓에, 그 방법은()에 연결 gnutls 래핑 베어 소켓()에 연결하기 전에 당신이 원하는대로 시간 제한이 적용됩니다.
  2. 당신이 GnuTLS의 핸드 셰이크()