2016-11-28 34 views
3

我在相當的困境是,你是我最後的希望。我開始做一個使用ssl製作MITM代理的項目。我的程序使用HTTP CONNECT方法。爲了保持簡潔我的程序如下如下圖...通過SSL MITM代理上wrap_socket掛着客戶

 Client   Proxy    Server 
      +    +    + 
    CONNECT |    |    | 
      +------------> |    | 
      |    |    | 
      | 200 Established   | 
      | <-----------+    | 
      |    |    | 
      | <----------> |    | 
      | Handshake |    | 
      |    | <---------> | 
      |    | Handshake | 
      |    |    | 
      |    |    | 
      | <----------> | <---------> | 
      | Data Exchange| Data Exchange 
      |    |    | 

我的代理份額與客戶端的證書,但是我的客戶似乎無法連接,我的代理上do_handshake()掛起當我打電話接受套接字上wrap_socket()。這裏的蟒蛇的部分,其中一個客戶端連接到代理...

import ssl, socket 
from _thread import * 
port = 8000 
def run(): 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.bind(('localhost', port)) 
    sock.listen(10) 
    while True: 
     connection, addr = sock.accept() 
     data = connection.recv(8192) 
     connection.send(b"HTTP/1.0 200 OK") 
     connection = ssl.wrap_socket(connection, keyfile='private.pem', certfile='cacert.pem', server_side=True) 
     start_new_thread(connection_string, (connection, data, addr)) # start thread to handle CONNECT 

我模擬客戶端使用OpenSSL

openssl s_client -proxy 127.0.0.1:8000 -connect www.google.com:443 -state -verify 1 -CAfile cacert.pem -verify_return_error 

當客戶端連接到他們都掛代理。如果我殺了客戶端我收到

Traceback (most recent call last): 
    File "/mitm/mitm_proxy.py", line 100, in <module> 
    run() 
    File 「/mitm/mitm_proxy.py", line 92, in run 
    connection = ssl.wrap_socket(connection, keyfile='private.pem', certfile='cacert.pem', server_side=True) 
    File "/usr/lib/python3.5/ssl.py", line 1069, in wrap_socket 
    ciphers=ciphers) 
    File "/usr/lib/python3.5/ssl.py", line 752, in __init__ 
    self.do_handshake() 
    File "/usr/lib/python3.5/ssl.py", line 988, in do_handshake 
    self._sslobj.do_handshake() 
    File "/usr/lib/python3.5/ssl.py", line 633, in do_handshake 
    self._sslobj.do_handshake() 
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:645) 

,如果我殺了我的代理我的客戶說

CONNECTED(00000003) 
s_client: HTTP CONNECT failed 
--- 
no peer certificate available 
--- 
No client certificate CA names sent 
--- 
SSL handshake has read 140709212149056 bytes and written 39 bytes 
Verification: OK 
--- 
New, (NONE), Cipher is (NONE) 
Secure Renegotiation IS NOT supported 
Compression: NONE 
Expansion: NONE 
No ALPN negotiated 
--- 

我比我的代碼與其他人合作,他們在本質上是相同的這就是爲什麼我在這裏。我無法弄清楚什麼是錯誤的。

回答

1

我不知道這是否你的問題的主要原因,但這肯定一個是錯誤的:

connection.send(b"HTTP/1.0 200 OK") 

服務器的正確反應應該是狀態符合\r\n結束,可選key:value\r\n雙然後\r\n以標記HTTP報頭的末尾,即最低限度:

connection.send(b"HTTP/1.0 200 OK\r\n\r\n") 

由於客戶端沒有收到失蹤\r\n\r\n它可能會等待它,而不是啓動TLS握手(即發送ClientHello)。相反,服務器將等待客戶端開始握手,並且這種方式將永遠等待對方。

除了你沒有按照標準openssl s_client -proxy ...似乎沒有遵循標準了。它實際需要的響應含有「確立了」這個詞來自於應用程序的懶惰HTTP解析代碼以下摘錄/ s_client.c中的OpenSSL 1.1.0c提示:

case PROTO_CONNECT: 
     ... 
     BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n\r\n", connectstr); 
     (void)BIO_flush(fbio); 
     /* wait for multi-line response to end CONNECT response */ 
     do { 
      mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); 
      if (strstr(mbuf, "200") != NULL 
       && strstr(mbuf, "established") != NULL) 
       foundit++; 
     } while (mbuf_len > 3 && foundit == 0); 

因此,與以下行嘗試:

connection.send(b"HTTP/1.0 200 established\r\n\r\n") 
+0

現在這使客戶端產生上述儘快相同的輸出,因爲它試圖進行連接。該代理也產生與上述相同的EOF錯誤,表示客戶端在收到HTTP/1.0 200 OK後退出。 –

+0

@PeterKrasinski:似乎也有s_client的錯誤。看到我編輯的答案。 –