2013-05-03 29 views
6

Tôi đang viết một chương trình HTTPS proxy đơn giản với Java cho mục đích giáo dục. Chương trình của tôi lắng nghe trên một cổng (ví dụ:) cho các yêu cầu HTTPS đến từ trình duyệt (ví dụ: Firefox), phân tích yêu cầu và chuyển tiếp đến đích mong muốn (ví dụ https://www.comodo.com).Thực hiện một ứng dụng HTTPS HTTPS đơn giản với Java?

Cài đặt proxy của Firefox được đặt để sử dụng cổng của tôi cho kết nối SSL (127.0.0.1 : 7443).

Mã của tôi là ngắn và đơn giản:

static // initializer 
{ 
    System.setProperty("javax.net.ssl.keyStore", "MyKeyStore"); 
    System.setProperty("javax.net.ssl.keyStorePassword", "password"); 
} 

SSLServerSocketFactory ssFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 

try { 
    SSLServerSocket listener = (SSLServerSocket) ssFactory.createServerSocket(port, 64); 
    listener.setUseClientMode(false); 
    listener.setWantClientAuth(false); 
    listener.setNeedClientAuth(false); 

    SSLSocket connection = (SSLSocket) listener.accept(); 
    browser.startHandshake(); /* <<== Exception throws at this line */ 

} catch (IOException ex) { 
    ex.printStackTrace(System.err); 
} 

Nhưng tôi bắt ngoại lệ sau đây:

javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? 

Trường hợp ngoại lệ nói rằng kết nối có thể là văn bản đơn giản, nhưng chỉ có các kết nối HTTPS từ Firefox được đặt để sử dụng cổng này. Tôi đã đăng những gì Firefox được gửi đến ứng dụng của tôi mà là thế này:

CONNECT www.comodo.com:443 HTTP/1.1 
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0 
Proxy-Connection: keep-alive 
Connection: keep-alive 
Host: www.comodo.com 

Firefox đang nói palin-văn bản, và tôi nghĩ rằng CONNECT là một lệnh SOCKS (Tôi không chắc chắn mặc dù), nơi tôi có không đặt bất kỳ thứ gì trong cài đặt SOCKS của Firefox. Dưới đây là một ảnh chụp màn hình của thiết lập proxy của Firefox:

Firefox Proxy Settings

tôi đang thiếu gì ở đây?! Những gì tôi cần làm để thực hiện công việc này với Firefox hoặc bất kỳ trình duyệt nào khác?!

---------------------------------------------- --------------------------------

Đối với những người cho rằng đây là bản sao của another question và có đã được trả lời trong câu hỏi khác tôi phải nói: Vâng, cả hai câu hỏi đều có gốc rễ trong một vấn đề tương tự nhưng câu trả lời duy nhất trong câu hỏi được trích dẫn chỉ ra việc sử dụng các Ổ cắm SSL đã gây hiểu nhầm và dẫn đến câu hỏi mới này. Vì vậy, mặc dù chúng nhằm vào một vấn đề tương tự, câu hỏi này cho thấy một con đường hoàn toàn khác và sai lệch để giải quyết vấn đề và do đó nó có thể cung cấp hướng dẫn hữu ích cho những người tương lai phải đối mặt với vấn đề như vậy.

+1

Đây không phải là bản sao của câu hỏi được trích dẫn. Hai câu hỏi rõ ràng là khác nhau và không có giải pháp chấp nhận được trong câu hỏi được trích dẫn. –

+0

Đối với những người đã kết thúc trong chủ đề này: bạn có thể quan tâm đến ví dụ làm việc của _TheConstructor_ tại đây: http://stackoverflow.com/questions/16351413/java-https-proxy-using-https-proxyport-and-https- proxyhost – Trinimon

Trả lời

6

Loại bỏ tất cả SSL. Chỉ cần xử lý lệnh CONNECT đến, tạo một kết nối văn bản thuần túy tới máy chủ ngược dòng, và sau đó bắt đầu sao chép byte. Trình duyệt và máy chủ sẽ nói SSL nhưng bạn không cần phải làm gì cả.

+0

Tôi không nghĩ rằng điều này là chính xác ... Tôi đã thử giải pháp này trước đây và nó không hoạt động ... Bạn có thể xem câu hỏi trước của tôi về giải pháp này tại http://stackoverflow.com/questions/14153662/java-https-connection-forwarding –

+1

Chắc chắn nó đúng. Xem RFC. Rõ ràng là trình duyệt đang gửi lệnh CONNECT trong văn bản thuần túy, và rõ ràng bạn có thể suy ra rằng nó đang chờ trả lời trong bản rõ, và rõ ràng là nếu bạn chuyển tất cả các byte khác theo cả hai hướng, không can thiệp thêm, máy chủ hoặc trình duyệt kết thúc. Bạn cần phải cụ thể hơn "nó không hoạt động". Câu hỏi khác bạn trích dẫn không cung cấp thêm bất kỳ thông tin nào. – EJP

+0

Như tôi đã nói, tôi đã thử chính xác những gì bạn đang gợi ý và thực sự đây là phương pháp đầu tiên xuất hiện trong đầu tôi, nhưng nó đã thất bại. Như đã đề cập trong câu hỏi khác mà tôi đã cung cấp, chuyển tiếp yêu cầu 'CONNECT' của trình duyệt tới máy chủ luôn dẫn đến lỗi' kết nối lại ', nghĩa là máy chủ không phản hồi và đóng kết nối ... Hành vi này hiển nhiên, vì máy chủ đang nghe thông báo SSL/TLS 'HELLO' trên 443 và nó nhận được' CONNECT', không phải là thông báo SSL/TLS được mong đợi. –

3

Thiết lập của bạn đang sử dụng đường hầm HTTP, trong đó yêu cầu ban đầu được gửi tới proxy là không phải Mã hóa SSL; vì ổ cắm hỗ trợ SSL đang mong đợi một cái bắt tay SSL, nó ném một ngoại lệ.

Trong cơ chế này, khách hàng yêu cầu một máy chủ HTTP Proxy để chuyển tiếp các kết nối TCP đến đích mong muốn bằng cách sử dụng "CONNECT" HTTP phương pháp. Sau đó, máy chủ sẽ thực hiện kết nối thay mặt cho ứng dụng khách. Khi kết nối đã được thiết lập bởi máy chủ, máy chủ proxy tiếp tục ủy quyền luồng TCP đến và đi từ máy khách . Lưu ý rằng chỉ yêu cầu kết nối ban đầu là HTTP - sau , máy chủ chỉ cần ủy quyền kết nối TCP đã thiết lập.

Bạn có thể đọc thêm tại trang HTTP Tunneling wiki. Để thấy điều này trong hành động, bạn có thể bắt đầu một máy chủ netcat và thiết lập proxy Firefox để trỏ đến cổng rằng:

nc -l 8000 

Bây giờ trong kiểu Firefox trong https://www.google.com, và kiểm tra đầu ra nc:

CONNECT www.google.com:443 HTTP/1.1 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) 
Proxy-Connection: keep-alive 
Connection: keep-alive 
Host: www.google.com 

Và điều này hoàn toàn trong văn bản thuần túy. Biểu đồ dưới đây minh họa cách Firefox proxy dự kiến ​​giao tiếp.

enter image description here

Các vấn đề liên quan