Koneksi HTTPS melalui server proxy

Jawaban:

66

TLS / SSL (S dalam HTTPS) menjamin bahwa tidak ada penyadap antara Anda dan server yang Anda hubungi, yaitu tidak ada proxy. Biasanya, Anda gunakan CONNECTuntuk membuka koneksi TCP melalui proxy. Dalam kasus ini, proxy tidak akan dapat menyimpan, membaca, atau memodifikasi permintaan / tanggapan apa pun, dan oleh karena itu menjadi tidak berguna.

Jika Anda ingin proxy dapat membaca informasi, Anda dapat mengambil pendekatan berikut:

  1. Klien memulai sesi HTTPS
  2. Proxy secara transparan mencegat koneksi dan mengembalikan sertifikat K a yang dihasilkan ad-hoc (mungkin lemah) , ditandatangani oleh otoritas sertifikat yang dipercaya tanpa syarat oleh klien.
  3. Proxy memulai sesi HTTPS untuk menargetkan
  4. Proxy memverifikasi integritas sertifikat SSL; menampilkan kesalahan jika sertifikat tidak valid.
  5. Proxy mengalirkan konten, mendekripsinya, dan mengenkripsi ulang dengan K a
  6. Klien menampilkan barang

Contohnya adalah benjolan SSL Squid . Demikian pula, bersendawa dapat dikonfigurasi untuk melakukan ini. Ini juga telah digunakan dalam konteks yang tidak terlalu berbahaya oleh ISP Mesir .

Perhatikan bahwa situs web dan browser modern dapat menggunakan HPKP atau pin sertifikat bawaan yang mengalahkan pendekatan ini.

phihag
sumber
13
Ini bisa bekerja pada prinsipnya, tapi itu bukan cara browser berbicara dengan proxy HTTP untuk permintaan HTTPS. Cara yang dijelaskan di sini menyiratkan bahwa server proxy secara efektif adalah Man-In-The-Middle (jadi harus dipercaya).
Bruno
5
Squid melakukan ini. Ini disebut SSL Bump .
Adam Mackler
3
Tidak akan berfungsi tanpa banyak peringatan kepada pengguna akhir. "dipercaya tanpa syarat oleh klien" - tidak ada hal seperti itu. Meskipun sertifikatnya sempurna-AAA +++, itu masih menunjukkan domain berbeda yang tidak sesuai dengan apa yang diminta pengguna akhir, yang akan membuat browser yang waras (tidak berarti IE di sini ...) melompat-lompat menjerit. Tentu saja, mungkin untuk menggunakan wget dengan parameter yang menonaktifkan pemeriksaan SSL, tapi coba tebak? koneksi ini tidak dapat lagi dinamai "SSL" setelah pemeriksaan keamanan intinya dinonaktifkan.
Van Jone
1
@Van Jone Unconditionally trustedmengacu pada sertifikat CA. Sertifikat CA tidak memiliki domain. Saya telah mengubah jawaban dengan dua contoh di mana ini berfungsi dalam praktik tanpa peringatan apa pun kepada pengguna.
phihag
6
Jawaban saya bergantung pada apa yang Anda sebut sebagai "CA palsu". Sertifikat CA yang adalah tanpa syarat dipercaya, baik karena pengguna (atau perangkat lunak pada komputer, untuk konfigurasi misalnya perusahaan atau malware) dikonfigurasi seperti itu, atau karena CA diperoleh dari salah satu CA dipercaya oleh browser utama, seperti dalam kasus MCS. Proksi menghasilkan sertifikat baru yang valid untuk setiap domain yang diminta klien, jadi tanpa fasilitas anti-MITM yang disebutkan di akhir jawaban, klien tidak akan menyadarinya.
phihag
22

Jawaban singkatnya adalah: Ini mungkin, dan dapat dilakukan dengan proxy HTTP khusus atau proxy SOCKS.

Pertama dan terpenting, HTTPS menggunakan SSL / TLS yang dengan desain memastikan keamanan ujung ke ujung dengan membuat saluran komunikasi yang aman melalui saluran yang tidak aman. Jika proxy HTTP dapat melihat isinya, maka itu adalah penyadap man-in-the-middle dan ini mengalahkan tujuan SSL / TLS. Jadi pasti ada beberapa trik yang dimainkan jika kita ingin melakukan proxy melalui proxy HTTP biasa.

Caranya adalah, kita mengubah proxy HTTP menjadi proxy TCP dengan perintah khusus bernama CONNECT. Tidak semua proxy HTTP mendukung fitur ini, tetapi sekarang banyak yang mendukungnya. Proksi TCP tidak dapat melihat konten HTTP ditransfer dalam teks yang jelas, tetapi itu tidak memengaruhi kemampuannya untuk meneruskan paket bolak-balik. Dengan cara ini, klien dan server dapat berkomunikasi satu sama lain dengan bantuan proxy. Ini adalah cara aman untuk membuat proxy data HTTPS.

Ada juga cara yang tidak aman untuk melakukannya, di mana proxy HTTP menjadi man-in-the-middle. Ini menerima koneksi yang dimulai klien, dan kemudian memulai koneksi lain ke server sebenarnya. Dalam SSL / TLS yang diterapkan dengan baik, klien akan diberi tahu bahwa proxy tersebut bukan server sebenarnya. Jadi klien harus mempercayai proxy dengan mengabaikan peringatan agar semuanya berfungsi. Setelah itu, proxy hanya mendekripsi data dari satu koneksi, mengenkripsi ulang, dan memasukkannya ke koneksi lainnya.

Akhirnya, kita pasti dapat melakukan proxy HTTPS melalui proxy SOCKS , karena proxy SOCKS bekerja pada level yang lebih rendah. Anda mungkin menganggap proxy SOCKS sebagai proxy TCP dan UDP.

Cyker
sumber
Apakah menggunakan CONNECT akan menyebabkan peringatan keamanan seperti yang disebutkan di stackoverflow.com/a/3118759/632951 ?
Pacerier
@Perier Saya rasa tidak. Dalam mode CONNECT proxy bekerja di lapisan transport.
Cyker
Jadi, dengan metode CONNECT, setiap data https dari klien tidak diteruskan ke tingkat aplikasi proxy perantara? Dan baru saja dievaluasi pada tingkat TCP proxy dan diteruskan ke server jauh secara langsung ?
zzinny
15

Sejauh yang saya ingat, Anda perlu menggunakan query HTTP CONNECT pada proxy. ini akan mengubah koneksi permintaan menjadi terowongan TCP / IP transparan.

jadi anda perlu tahu apakah proxy server yang anda gunakan mendukung protokol ini.

chburd
sumber
3
Memang, klien menggunakan kata kerja CONNECT untuk menggunakan https: // URI melalui server proxy HTTP. Dalam hal ini, koneksi dilewatkan melalui proxy, sehingga verifikasi sertifikat dilakukan seperti biasa, seolah-olah klien berbicara langsung ke server akhir.
Bruno
1
@chburd, Tapi apakah proxy biasanya mendukung HTTP CONNECT?
Pacerier
9

Jika masih menarik, berikut adalah jawaban untuk pertanyaan serupa: Convert HTTP Proxy to HTTPS Proxy in Twisted

Untuk menjawab bagian kedua dari pertanyaan:

Jika ya, jenis server proxy apa yang mengizinkan ini?

Di luar kotak, sebagian besar server proxy akan dikonfigurasi untuk mengizinkan koneksi HTTPS hanya ke port 443, jadi https URI dengan port khusus tidak akan berfungsi. Ini umumnya dapat dikonfigurasi, tergantung pada server proxy. Squid dan TinyProxy mendukung ini, misalnya.

Bruno
sumber
5

Berikut adalah kode Java lengkap saya yang mendukung permintaan HTTP dan HTTPS menggunakan 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);
        }
    }
}
mesin jiwa
sumber
3

Anda dapat melakukannya menggunakan teknik man-in-the-middle dengan pembuatan SSL dinamis. Lihatlah mitmproxy - ini adalah proxy MITM berkemampuan SSL berbasis Python.

Zorayr
sumber
3

tunneling HTTPS melalui SSH (versi 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

semua yang Anda lakukan di localhost. kemudian:

target_domain.com is accessible from localhost browser.
Sławomir Lenart
sumber
1

Saya telah mencoba

  • mulai tunneling: ssh -N -D 12345 login@proxy_server
  • Mengatur proxy di pengaturan firefox sebagai localhost:12345
    • dan mencentang "gunakan proxy ini untuk semua protokol"

tetapi ini menghasilkan kesalahan "Sambungan tidak aman" setiap kali saya mencoba menyambung ke situs web https.

Solusinya adalah

  • "hapus centang" pada "gunakan proxy ini untuk semua protokol"
  • setel proxy "localhost: 12345" hanya sebagai proxy SOCKS
  • dan biarkan proxy HTTP, proxy SSL, proxy FTP kosong

Referensi dari dokumentasi samudra digital

Cara Merutekan Lalu Lintas Web Dengan Aman Tanpa VPN Menggunakan Terowongan SOCKS

shadi
sumber
1

Menurut saya, "memiliki koneksi HTTPS melalui server proxy" berarti jenis serangan server proxy Man-in-the-Middle. Saya pikir ini menanyakan apakah seseorang dapat terhubung ke server proxy http melalui TLS. Dan jawabannya ya.


Apakah mungkin memiliki koneksi HTTPS melalui server proxy?

Ya, lihat pertanyaan dan jawaban saya di sini. Server proxy HTTPs hanya berfungsi di SwitchOmega

Jika ya, jenis server proxy apa yang mengizinkan ini?

Jenis server proxy yang menerapkan sertifikat SSL, seperti yang dilakukan situs web biasa. Tetapi Anda memerlukan pacfile untuk browser untuk mengkonfigurasi koneksi proxy melalui SSL.

Rick
sumber