2009-02-05 63 views

Trả lời

38

TLS/SSL (Chỉ số S trong HTTPS) đảm bảo rằng không có người nghe trộm giữa bạn và máy chủ bạn đang liên hệ, tức là không có proxy. Thông thường, bạn sử dụng CONNECT để mở kết nối TCP thông qua proxy. Trong trường hợp này, proxy sẽ không thể lưu vào bộ nhớ cache, đọc hoặc sửa đổi kết nối và do đó vô dụng.

Nếu bạn muốn proxy để có thể đọc thông tin, bạn có thể lấy phương pháp sau đây:

  1. Khách hàng bắt đầu phiên giao dịch HTTPS
  2. Proxy minh bạch chặn kết nối và trả về một ad-hoc được tạo ra (có thể là giấy chứng nhận yếu) K a, có chữ ký của cơ quan cấp chứng chỉ được khách hàng yêu cầu vô điều kiện .
  3. Proxy bắt đầu phiên HTTPS để nhắm mục tiêu
  4. Proxy xác minh tính toàn vẹn của chứng nhận SSL ; hiển thị lỗi nếu chứng chỉ không hợp lệ.
  5. Proxy suối nội dung, giải mã nó và tái mã hóa nó với K một
  6. hiển thị khách hàng nhét

Một ví dụ là Squid SSL bump. Tương tự, burp can be configured để làm điều này. Điều này cũng đã được used in a less-benign context by an Egyptian ISP.

Lưu ý rằng các trang web và trình duyệt hiện đại có thể sử dụng HPKP hoặc built-in certificate pins để đánh bại phương pháp này.

+8

Điều này có thể hoạt động theo nguyên tắc, nhưng đó không phải là cách trình duyệt nói chuyện với proxy HTTP cho các yêu cầu HTTPS. Cách nó được mô tả ở đây ngụ ý rằng máy chủ proxy có hiệu quả là một Man-In-The-Middle (do đó sẽ phải được tin cậy cho phù hợp). – Bruno

+5

Mực thực hiện điều này. Nó được gọi là [SSL Bump] (http://wiki.squid-cache.org/Features/SslBump). –

+3

Sẽ không hoạt động với nhiều cảnh báo cho người dùng cuối. "vô điều kiện được khách hàng tin tưởng" - không có thứ gì như vậy. Ngay cả là cert là hoàn hảo-AAA +++, nó vẫn cho thấy tên miền khác nhau không phù hợp với những gì người dùng cuối yêu cầu, mà sẽ làm cho bất kỳ trình duyệt lành mạnh (không có nghĩa là IE ở đây ...) nhảy lên và xuống la hét. Tất nhiên, nó có thể sử dụng wget với các tham số vô hiệu hóa kiểm tra SSL, nhưng đoán những gì? kết nối này không thể được đặt tên là "SSL" nữa sau khi kiểm tra bảo mật lõi bị vô hiệu hóa. –

14

theo như tôi có thể nhớ, bạn cần sử dụng truy vấn HTTP CONNECT trên proxy. điều này sẽ chuyển đổi kết nối yêu cầu thành đường hầm TCP/IP trong suốt.

để bạn cần biết liệu máy chủ proxy bạn sử dụng có hỗ trợ giao thức này hay không.

+2

Thật vậy, khách hàng sử dụng động từ CONNECT để sử dụng https: // URI thông qua máy chủ proxy HTTP. Trong trường hợp này, kết nối được điều chỉnh thông qua proxy, vì vậy việc xác minh chứng chỉ được thực hiện như bình thường, như thể khách hàng đang nói chuyện trực tiếp với máy chủ kết thúc. – Bruno

+0

@chburd, Nhưng proxy có thường hỗ trợ HTTP CONNECT không? – Pacerier

9

Nếu nó vẫn còn quan tâm, đây là một câu trả lời cho một câu hỏi tương tự: Convert HTTP Proxy to HTTPS Proxy in Twisted

Để trả lời phần thứ hai của câu hỏi:

Nếu có, những loại máy chủ proxy phép điều này?

Ngoài hộp, hầu hết các máy chủ proxy sẽ được định cấu hình để chỉ cho phép kết nối HTTPS tới cổng 443, do đó, URI https với cổng tùy chỉnh sẽ không hoạt động. Điều này thường có thể cấu hình, tùy thuộc vào máy chủ proxy. Ví dụ, Squid và TinyProxy hỗ trợ điều này.

2

Bạn có thể thực hiện việc này bằng cách sử dụng các kỹ thuật người trung gian với tạo SSL động. Hãy xem mitmproxy - đó là một proxy MITM có khả năng SSL dựa trên Python.

2

đường hầm HTTPS thông qua SSH (phiên bản Linux):

1) turn off using 443 on localhost 
2) start tunneling as root: ssh -N [email protected]_server -L 443:target_ip:443 
3) adding 127.0.0.1 target_domain.com to /etc/hosts 

tất cả mọi thứ bạn làm trên localhost. sau đó:

target_domain.com is accessible from localhost browser. 
4

Đây là mã Java hoàn chỉnh hỗ trợ cả yêu cầu HTTP và HTTPS sử dụng proxy SOCKS.

import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.net.Proxy; 
import java.net.Socket; 
import java.nio.charset.StandardCharsets; 

import org.apache.http.HttpHost; 
import org.apache.http.client.methods.CloseableHttpResponse; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.protocol.HttpClientContext; 
import org.apache.http.config.Registry; 
import org.apache.http.config.RegistryBuilder; 
import org.apache.http.conn.socket.ConnectionSocketFactory; 
import org.apache.http.conn.socket.PlainConnectionSocketFactory; 
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 
import org.apache.http.impl.client.CloseableHttpClient; 
import org.apache.http.impl.client.HttpClients; 
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 
import org.apache.http.protocol.HttpContext; 
import org.apache.http.ssl.SSLContexts; 
import org.apache.http.util.EntityUtils; 

import javax.net.ssl.SSLContext; 

/** 
* How to send a HTTP or HTTPS request via SOCKS proxy. 
*/ 
public class ClientExecuteSOCKS { 

    public static void main(String[] args) throws Exception { 
     Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory>create() 
      .register("http", new MyHTTPConnectionSocketFactory()) 
      .register("https", new MyHTTPSConnectionSocketFactory(SSLContexts.createSystemDefault 
       ())) 
      .build(); 
     PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg); 
     try (CloseableHttpClient httpclient = HttpClients.custom() 
      .setConnectionManager(cm) 
      .build()) { 
      InetSocketAddress socksaddr = new InetSocketAddress("mysockshost", 1234); 
      HttpClientContext context = HttpClientContext.create(); 
      context.setAttribute("socks.address", socksaddr); 

      HttpHost target = new HttpHost("www.example.com/", 80, "http"); 
      HttpGet request = new HttpGet("/"); 

      System.out.println("Executing request " + request + " to " + target + " via SOCKS " + 
       "proxy " + socksaddr); 
      try (CloseableHttpResponse response = httpclient.execute(target, request, context)) { 
       System.out.println("----------------------------------------"); 
       System.out.println(response.getStatusLine()); 
       System.out.println(EntityUtils.toString(response.getEntity(), StandardCharsets 
        .UTF_8)); 
      } 
     } 
    } 

    static class MyHTTPConnectionSocketFactory extends PlainConnectionSocketFactory { 
     @Override 
     public Socket createSocket(final HttpContext context) throws IOException { 
      InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address"); 
      Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr); 
      return new Socket(proxy); 
     } 
    } 

    static class MyHTTPSConnectionSocketFactory extends SSLConnectionSocketFactory { 
     public MyHTTPSConnectionSocketFactory(final SSLContext sslContext) { 
      super(sslContext); 
     } 

     @Override 
     public Socket createSocket(final HttpContext context) throws IOException { 
      InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address"); 
      Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr); 
      return new Socket(proxy); 
     } 
    } 
} 
5

Câu trả lời ngắn gọn là: Có thể và có thể thực hiện với proxy HTTP đặc biệt hoặc proxy SOCKS.

Đầu tiên và trước hết, HTTPS sử dụng SSL/TLS theo thiết kế đảm bảo bảo mật đầu cuối bằng cách thiết lập kênh giao tiếp bảo mật qua kênh không an toàn. Nếu proxy HTTP có thể xem nội dung, thì đó là một kẻ nghe trộm trung gian và điều này đánh bại mục tiêu của SSL/TLS. Vì vậy, phải có một số thủ thuật được chơi nếu chúng tôi muốn proxy thông qua một proxy HTTP đồng bằng.

Bí quyết là, chúng tôi chuyển proxy HTTP thành proxy TCP bằng lệnh đặc biệt có tên CONNECT. Không phải tất cả proxy HTTP đều hỗ trợ tính năng này nhưng nhiều proxy hiện đang hoạt động. Proxy TCP không thể nhìn thấy nội dung HTTP đang được chuyển trong văn bản rõ ràng, nhưng điều đó không ảnh hưởng đến khả năng chuyển tiếp các gói dữ liệu qua lại. Bằng cách này, máy khách và máy chủ có thể giao tiếp với nhau với sự trợ giúp của proxy. Đây là cách bảo mật dữ liệu HTTPS an toàn.

Ngoài ra còn có một cách không an toàn để làm như vậy, trong đó proxy HTTP trở thành một người đàn ông ở giữa. Nó nhận được kết nối khách hàng khởi tạo, và sau đó bắt đầu một kết nối khác đến máy chủ thực. Trong một SSL/TLS được triển khai tốt, máy khách sẽ được thông báo rằng proxy không phải là máy chủ thực. Vì vậy, khách hàng phải tin tưởng proxy bằng cách bỏ qua cảnh báo cho mọi thứ hoạt động. Sau đó, proxy chỉ giải mã dữ liệu từ một kết nối, reencrypts và nạp nó vào một kết nối khác.

Cuối cùng, chúng ta có thể ủy quyền HTTPS thông qua proxy SOCKS, vì proxy SOCKS hoạt động ở mức thấp hơn. Bạn có thể nghĩ rằng một SOCKS proxy như là một TCP và một UDP proxy.

+0

Có sử dụng CONNECT gây cảnh báo bảo mật như đã đề cập trong https://stackoverflow.com/a/3118759/632951 không? – Pacerier

+0

@Pacerier Tôi không nghĩ vậy. Trong chế độ CONNECT, proxy hoạt động ở tầng truyền tải. – Cyker

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