การเชื่อมต่อ HTTPS ผ่านพร็อกซีเซิร์ฟเวอร์


103

เป็นไปได้ไหมที่จะเชื่อมต่อ HTTPS ผ่านพร็อกซีเซิร์ฟเวอร์ ถ้าใช่พร็อกซีเซิร์ฟเวอร์ประเภทใดที่อนุญาตให้ทำเช่นนี้

ซ้ำกับวิธีใช้พร็อกซีถุงเท้า 5 กับ Apache HTTP Client 4?


คิดว่าไม่ซ้ำกับstackoverflow.com/questions/22937983/…
Uri

ใช่มันเป็นไปได้ ดูตัวอย่างการใช้งานได้ที่นี่ stackoverflow.com/questions/56981993/…
ริก

คำตอบ:


67

TLS / SSL (S ใน HTTPS) รับประกันว่าไม่มีผู้ดักฟังระหว่างคุณและเซิร์ฟเวอร์ที่คุณกำลังติดต่อนั่นคือไม่มีพร็อกซี โดยปกติคุณใช้CONNECTเพื่อเปิดการเชื่อมต่อ TCP ผ่านพร็อกซี ในกรณีนี้พร็อกซีจะไม่สามารถแคชอ่านหรือแก้ไขคำขอ / การตอบกลับใด ๆ ได้ดังนั้นจึงค่อนข้างไร้ประโยชน์

หากคุณต้องการให้พร็อกซีสามารถอ่านข้อมูลได้คุณสามารถใช้แนวทางต่อไปนี้:

  1. ไคลเอนต์เริ่มเซสชัน HTTPS
  2. พร็อกซีสกัดกั้นการเชื่อมต่ออย่างโปร่งใสและส่งคืนใบรับรอง K a ที่สร้างขึ้น (อาจอ่อนแอ) เฉพาะกิจซึ่งลงนามโดยผู้ออกใบรับรองที่ไคลเอ็นต์เชื่อถือโดยไม่มีเงื่อนไข
  3. พร็อกซีเริ่มเซสชัน HTTPS เพื่อกำหนดเป้าหมาย
  4. พร็อกซีตรวจสอบความสมบูรณ์ของใบรับรอง SSL แสดงข้อผิดพลาดหากใบรับรองไม่ถูกต้อง
  5. พร็อกซีสตรีมเนื้อหาถอดรหัสและเข้ารหัสอีกครั้งด้วย K a
  6. ลูกค้าแสดงสิ่งของ

ตัวอย่างคือปลาหมึกของชน SSL ในทำนองเดียวกันเรอสามารถกำหนดค่าให้ทำเช่นนี้ได้ นอกจากนี้ยังได้รับการใช้ในบริบทน้อยอ่อนโยนโดยอียิปต์ ISP

โปรดทราบว่าเว็บไซต์และเบราว์เซอร์สมัยใหม่สามารถใช้HPKPหรือพินใบรับรองในตัวซึ่งเอาชนะวิธีนี้ได้


13
โดยหลักการนี้สามารถทำงานได้ แต่นั่นไม่ใช่วิธีที่เบราว์เซอร์พูดคุยกับพร็อกซี HTTP สำหรับคำขอ HTTPS วิธีที่อธิบายไว้ในที่นี้หมายความว่าพร็อกซีเซิร์ฟเวอร์เป็น Man-In-The-Middle อย่างมีประสิทธิภาพ (ดังนั้นจะต้องได้รับความเชื่อถือตามนั้น)
Bruno

5
ปลาหมึกทำแบบนี้ มันเรียกว่าSSL Bump
Adam Mackler

3
จะไม่ทำงานโดยไม่มีการแจ้งเตือนแก่ผู้ใช้ปลายทาง "เชื่อถือโดยไม่มีเงื่อนไขจากลูกค้า" - ไม่มีสิ่งนั้น แม้ว่าใบรับรองจะสมบูรณ์แบบ-AAA +++ แต่ก็ยังแสดงโดเมนที่แตกต่างกันซึ่งไม่ตรงกับสิ่งที่ผู้ใช้ร้องขอซึ่งจะทำให้เบราว์เซอร์ที่มีสติ (ไม่ใช่ IE ที่นี่ ... ) กระโดดขึ้นและลงกรีดร้อง แน่นอนว่าเป็นไปได้ที่จะใช้ wget กับพารามิเตอร์ที่ปิดใช้งานการตรวจสอบ SSL แต่เดาอะไร การเชื่อมต่อนี้ไม่สามารถตั้งชื่อว่า "SSL" ได้อีกต่อไปหลังจากปิดใช้งานการตรวจสอบความปลอดภัยหลักแล้ว
Van Jone

1
@ Van Jone Unconditionally trustedหมายถึงใบรับรอง CA ใบรับรอง CA ไม่มีโดเมน ฉันได้แก้ไขคำตอบด้วยสองตัวอย่างที่ใช้งานได้จริงโดยไม่มีการแจ้งเตือนใด ๆ ให้กับผู้ใช้
phihag

6
คำตอบของฉันขึ้นอยู่กับสิ่งที่คุณเรียกว่า "ปลอม CA" ใบรับรองของ CA นั้นเชื่อถือได้โดยไม่มีเงื่อนไขไม่ว่าจะเป็นเพราะผู้ใช้ (หรือซอฟต์แวร์บนคอมพิวเตอร์ของเขาเช่นการกำหนดค่าองค์กรหรือมัลแวร์) กำหนดค่าด้วยวิธีนั้นหรือเนื่องจาก CA ได้มาจาก CA ที่เบราว์เซอร์หลัก ๆ ไว้วางใจเช่น ในกรณี MCS พร็อกซีจะสร้างใบรับรองใหม่ที่ถูกต้องสำหรับทุกโดเมนที่ไคลเอ็นต์ร้องขอดังนั้นหากไม่มีสิ่งอำนวยความสะดวกต่อต้าน MITM ที่กล่าวถึงในตอนท้ายของคำตอบลูกค้าจะไม่สังเกตเห็น
phihag

24

คำตอบสั้น ๆ คือ: เป็นไปได้และทำได้ด้วยพร็อกซี HTTP พิเศษหรือพร็อกซี SOCKS

ก่อนอื่น HTTPS ใช้ SSL / TLS ซึ่งจากการออกแบบทำให้มั่นใจได้ถึงความปลอดภัยแบบ end-to-end โดยการสร้างช่องทางการสื่อสารที่ปลอดภัยบนช่องที่ไม่ปลอดภัย หากพร็อกซี HTTP สามารถมองเห็นเนื้อหาได้แสดงว่าเป็นผู้ดักฟังแบบ man-in-the-middle และสิ่งนี้เอาชนะเป้าหมายของ SSL / TLS ดังนั้นต้องมีเทคนิคบางอย่างในการเล่นหากเราต้องการพร็อกซีผ่านพร็อกซี HTTP ธรรมดา

เคล็ดลับคือเราหันพร็อกซี HTTP เข้าไปในพร็อกซี่ TCP CONNECTที่มีคำสั่งพิเศษชื่อ พร็อกซี HTTP บางรายการไม่สนับสนุนคุณลักษณะนี้ แต่มีหลายคนที่สนับสนุนคุณสมบัตินี้ พร็อกซี TCP ไม่สามารถเห็นเนื้อหา HTTP ที่ถูกถ่ายโอนในรูปแบบข้อความที่ชัดเจน แต่จะไม่ส่งผลต่อความสามารถในการส่งต่อแพ็กเก็ตไปมา ด้วยวิธีนี้ไคลเอนต์และเซิร์ฟเวอร์สามารถสื่อสารกันได้ด้วยความช่วยเหลือของพร็อกซี นี่เป็นวิธีที่ปลอดภัยในการพร็อกซีข้อมูล HTTPS

นอกจากนี้ยังมีวิธีที่ไม่ปลอดภัยในการดำเนินการดังกล่าวซึ่งพร็อกซี HTTP จะกลายเป็น man-in-the-middle ได้รับการเชื่อมต่อที่เริ่มต้นโดยไคลเอนต์จากนั้นเริ่มการเชื่อมต่ออื่นไปยังเซิร์ฟเวอร์จริง ใน SSL / TLS ที่ใช้งานได้ดีไคลเอนต์จะได้รับแจ้งว่าพร็อกซีไม่ใช่เซิร์ฟเวอร์จริง ดังนั้นไคลเอนต์จึงต้องไว้วางใจพร็อกซีโดยละเว้นคำเตือนเพื่อให้สิ่งต่างๆทำงานได้ หลังจากนั้นพร็อกซีจะถอดรหัสข้อมูลจากการเชื่อมต่อหนึ่งเข้ารหัสใหม่และป้อนข้อมูลไปยังอีก

ในที่สุดเราสามารถพร็อกซี HTTPS ผ่านพร็อกซีSOCKS ได้อย่างแน่นอนเนื่องจากพร็อกซี SOCKS ทำงานในระดับที่ต่ำกว่า คุณอาจคิดว่าพร็อกซี SOCKS เป็นทั้งพร็อกซี TCP และ UDP


การใช้ CONNECT จะทำให้เกิดคำเตือนด้านความปลอดภัยดังที่กล่าวไว้ในstackoverflow.com/a/3118759/632951หรือไม่
Pacerier

@Pacerier ฉันไม่คิดอย่างนั้น ในโหมด CONNECT พร็อกซีจะทำงานที่เลเยอร์การขนส่ง
Cyker

ดังนั้นโดยวิธีการ CONNECT ข้อมูล https ใด ๆ จากไคลเอนต์จะไม่ถูกส่งผ่านไปยังระดับแอปพลิเคชันของพร็อกซีตัวกลาง? และเพิ่งประเมินที่ระดับ TCP ของพร็อกซีและส่งต่อไปยังเซิร์ฟเวอร์ระยะไกลโดยตรง ?
zzinny

15

เท่าที่ฉันจำได้คุณต้องใช้แบบสอบถาม HTTP CONNECT บนพร็อกซี สิ่งนี้จะแปลงการเชื่อมต่อคำขอเป็นอุโมงค์ TCP / IP แบบโปร่งใส

ดังนั้นคุณต้องทราบว่าพร็อกซีเซิร์ฟเวอร์ที่คุณใช้รองรับโปรโตคอลนี้หรือไม่


3
ลูกค้าใช้คำกริยา CONNECT เพื่อใช้ https: // URI ผ่านพร็อกซีเซิร์ฟเวอร์ HTTP ในกรณีนี้การเชื่อมต่อจะถูกสร้างทันเนลผ่านพร็อกซีดังนั้นการตรวจสอบใบรับรองจึงทำได้ตามปกติราวกับว่าไคลเอนต์กำลังคุยโดยตรงกับเซิร์ฟเวอร์ปลายทาง
Bruno

1
@chburd แต่โดยปกติแล้วพร็อกซีจะรองรับ HTTP CONNECT หรือไม่
Pacerier

9

หากยังคงเป็นที่สนใจนี่คือคำตอบสำหรับคำถามที่คล้ายกัน: แปลง HTTP Proxy เป็น HTTPS Proxy ใน Twisted

เพื่อตอบคำถามส่วนที่สอง:

ถ้าใช่พร็อกซีเซิร์ฟเวอร์ประเภทใดที่อนุญาตให้ทำเช่นนี้

พร็อกซีเซิร์ฟเวอร์ส่วนใหญ่จะได้รับการกำหนดค่าให้อนุญาตการเชื่อมต่อ HTTPS เฉพาะกับพอร์ต 443 เท่านั้นดังนั้น https URI ที่มีพอร์ตที่กำหนดเองจะไม่ทำงาน โดยทั่วไปสามารถกำหนดค่าได้ขึ้นอยู่กับพร็อกซีเซิร์ฟเวอร์ Squid และ TinyProxy สนับสนุนสิ่งนี้เช่น


5

นี่คือรหัส Java ที่สมบูรณ์ของฉันที่รองรับทั้งคำขอ HTTP และ HTTPS โดยใช้พร็อกซี 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);
        }
    }
}

3

คุณสามารถทำสิ่งนี้ให้สำเร็จได้โดยใช้เทคนิค man-in-the-middle ด้วยการสร้าง SSL แบบไดนามิก ดูmitmproxyซึ่งเป็นพร็อกซี MITM ที่ใช้ SSL และใช้ Python


3

การขุดอุโมงค์ HTTPS ผ่าน SSH (เวอร์ชัน linux):

1) turn off using 443 on localhost
2) start tunneling as root: ssh -N login@proxy_server -L 443:target_ip:443
3) adding 127.0.0.1 target_domain.com to /etc/hosts

ทุกสิ่งที่คุณทำบน localhost แล้ว:

target_domain.com is accessible from localhost browser.

1

ฉันพยายามแล้ว

  • เริ่มขุดอุโมงค์: ssh -N -D 12345 login@proxy_server
  • การตั้งค่าพร็อกซีในการตั้งค่า firefox เป็น localhost:12345
    • และทำเครื่องหมาย "ใช้พร็อกซีนี้สำหรับทุกโปรโตคอล"

แต่ทำให้เกิดข้อผิดพลาด "การเชื่อมต่อที่ไม่ปลอดภัย" เมื่อใดก็ตามที่ฉันพยายามเชื่อมต่อกับเว็บไซต์ https

วิธีแก้ปัญหาคือ

  • "ยกเลิกการเลือก" ที่ "ใช้พร็อกซีนี้สำหรับโปรโตคอลทั้งหมด"
  • ตั้งค่าพร็อกซี "localhost: 12345" เป็นพร็อกซี SOCKS เท่านั้น
  • และปล่อยพร็อกซี HTTP, พร็อกซี SSL, พร็อกซี FTP ว่างไว้

อ้างอิงจากเอกสาร Digital Ocean

วิธีกำหนดเส้นทางการรับส่งข้อมูลเว็บอย่างปลอดภัยโดยไม่ต้องใช้ VPN โดยใช้อุโมงค์ SOCKS


1

ฉันไม่คิดว่า "มีการเชื่อมต่อ HTTPS ผ่านพร็อกซีเซิร์ฟเวอร์" หมายถึงประเภทการโจมตีของพร็อกซีเซิร์ฟเวอร์แบบ Man-in-the-Middle ฉันคิดว่าถามว่าจะเชื่อมต่อกับพร็อกซีเซิร์ฟเวอร์ http ผ่าน TLS ได้หรือไม่ และคำตอบคือใช่


เป็นไปได้ไหมที่จะเชื่อมต่อ HTTPS ผ่านพร็อกซีเซิร์ฟเวอร์

ใช่ดูคำถามและคำตอบของฉันที่นี่ พร็อกซีเซิร์ฟเวอร์ HTTPs ใช้งานได้ใน SwitchOmega เท่านั้น

ถ้าใช่พร็อกซีเซิร์ฟเวอร์ประเภทใดที่อนุญาตให้ทำเช่นนี้

ประเภทของพร็อกซีเซิร์ฟเวอร์ใช้ใบรับรอง SSL เช่นเดียวกับเว็บไซต์ทั่วไป แต่คุณต้องมีpacไฟล์สำหรับ brower เพื่อกำหนดค่าการเชื่อมต่อพร็อกซีผ่าน SSL

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.