通过代理服务器的 HTTPS 连接

发布于 2024-07-13 17:53:28 字数 215 浏览 3 评论 0原文

是否可以通过代理服务器建立 HTTPS 连接? 如果是,什么样的代理服务器允许这样做?

如何将 Socks 5 代理与 Apache 一起使用重复HTTP 客户端 4?

Is it possible to have HTTPS connections over proxy servers? If yes, what kind of proxy server allows this?

Duplicated with How to use Socks 5 proxy with Apache HTTP Client 4?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

素罗衫 2024-07-20 17:53:28

TLS/SSL(HTTPS 中的 S)保证您和您正在联系的服务器之间没有窃听者,即没有代理。 通常,您使用 CONNECT 打开通过代理的 TCP 连接。 在这种情况下,代理将无法缓存、读取或修改任何请求/响应,因此毫无用处。

如果希望proxy能够读取信息,可以采取以下做法:

  1. 客户端启动HTTPS会话
  2. Proxy透明拦截连接并
    返回临时生成的(可能
    弱)证书 Ka,
    由证书颁发机构签名
    是无条件信任的
    客户端。
  3. 代理启动与目标的 HTTPS 会话
  4. 代理验证 SSL 的完整性
    证书; 如果出现以下情况,则显示错误
    证书无效。
  5. 代理传输内容并解密
    并用它重新加密
    Ka
  6. 客户端显示内容

一个例子是 Squid 的 SSL 碰撞。 同样,可以配置 burp 来执行此操作。 这也是埃及 ISP 在不太友善的环境中使用

请注意,现代网站和浏览器可以使用 HPKP内置证书 pin 击败了这种方法。

TLS/SSL (The S in HTTPS) guarantees that there are no eavesdroppers between you and the server you are contacting, i.e. no proxies. Normally, you use CONNECT to open up a TCP connection through the proxy. In this case, the proxy will not be able to cache, read, or modify any requests/responses, and therefore be rather useless.

If you want the proxy to be able to read information, you can take the following approach:

  1. Client starts HTTPS session
  2. Proxy transparently intercepts the connection and
    returns an ad-hoc generated(possibly
    weak) certificate Ka,
    signed by a certificate authority
    that is unconditionally trusted by
    the client.
  3. Proxy starts HTTPS session to target
  4. Proxy verifies integrity of SSL
    certificate; displays error if the
    cert is not valid.
  5. Proxy streams content, decrypts it
    and re-encrypts it with
    Ka
  6. Client displays stuff

An example is Squid's SSL bump. Similarly, burp can be configured to do this. This has also been used in a less-benign context by an Egyptian ISP.

Note that modern websites and browsers can employ HPKP or built-in certificate pins which defeat this approach.

稚气少女 2024-07-20 17:53:28

简短的回答是:这是可能的,并且可以使用特殊的 HTTP 代理或 SOCKS 代理来完成。

首先,HTTPS 使用 SSL/TLS,其设计通过在不安全的通信通道上建立安全的通信通道来确保端到端安全性。 如果 HTTP 代理能够看到内容,那么它就是中间人窃听者,这违背了 SSL/TLS 的目标。 因此,如果我们想通过普通的 HTTP 代理进行代理,就必须使用一些技巧。

诀窍是,我们使用名为 CONNECT< 的特殊命令将 HTTP 代理转换为 TCP 代理/代码>。 并非所有 HTTP 代理都支持此功能,但现在很多都支持。 TCP 代理无法看到以明文形式传输的 HTTP 内容,但这并不影响其来回转发数据包的能力。 这样,客户端和服务器就可以借助代理进行通信。 这是代理 HTTPS 数据的安全方式。

还有一种不安全的方法,即 HTTP 代理成为中间人。 它接收客户端发起的连接,然后向真实服务器发起另一个连接。 在实施良好的 SSL/TLS 中,客户端将被告知代理不是真正的服务器。 因此,客户端必须通过忽略警告来信任代理才能正常工作。 之后,代理只需解密一个连接中的数据,重新加密并将其提供给另一个连接。

最后,我们当然可以通过 SOCKS 代理来代理 HTTPS,因为 SOCKS 代理工作在较低级别。 您可能认为 SOCKS 代理既是 TCP 代理又是 UDP 代理。

The short answer is: It is possible, and can be done with either a special HTTP proxy or a SOCKS proxy.

First and foremost, HTTPS uses SSL/TLS which by design ensures end-to-end security by establishing a secure communication channel over an insecure one. If the HTTP proxy is able to see the contents, then it's a man-in-the-middle eavesdropper and this defeats the goal of SSL/TLS. So there must be some tricks being played if we want to proxy through a plain HTTP proxy.

The trick is, we turn an HTTP proxy into a TCP proxy with a special command named CONNECT. Not all HTTP proxies support this feature but many do now. The TCP proxy cannot see the HTTP content being transferred in clear text, but that doesn't affect its ability to forward packets back and forth. In this way, client and server can communicate with each other with help of the proxy. This is the secure way of proxying HTTPS data.

There is also an insecure way of doing so, in which the HTTP proxy becomes a man-in-the-middle. It receives the client-initiated connection, and then initiate another connection to the real server. In a well implemented SSL/TLS, the client will be notified that the proxy is not the real server. So the client has to trust the proxy by ignoring the warning for things to work. After that, the proxy simply decrypts data from one connection, reencrypts and feeds it into the other.

Finally, we can certainly proxy HTTPS through a SOCKS proxy, because the SOCKS proxy works at a lower level. You may think a SOCKS proxy as both a TCP and a UDP proxy.

与之呼应 2024-07-20 17:53:28

据我记得,您需要在代理上使用 HTTP CONNECT 查询。 这会将请求连接转换为透明的 TCP/IP 隧道。

所以你需要知道你使用的代理服务器是否支持该协议。

as far as i can remember, you need to use a HTTP CONNECT query on the proxy. this will convert the request connection to a transparent TCP/IP tunnel.

so you need to know if the proxy server you use support this protocol.

圈圈圆圆圈圈 2024-07-20 17:53:28

如果仍然感兴趣,这里是类似问题的答案:
将 Twisted 中的 HTTP 代理转换为 HTTPS 代理

回答问题的第二部分:

如果有,是什么类型的代理服务器
允许这样做吗?

大多数代理服务器开箱即用,将配置为仅允许 HTTPS 连接到端口 443,因此具有自定义端口的 https URI 不起作用。 这通常是可配置的,具体取决于代理服务器。 例如,Squid 和 TinyProxy 支持此功能。

If it's still of interest, here is an answer to a similar question:
Convert HTTP Proxy to HTTPS Proxy in Twisted

To answer the second part of the question:

If yes, what kind of proxy server
allows this?

Out of the box, most proxy servers will be configured to allow HTTPS connections only to port 443, so https URIs with custom ports wouldn't work. This is generally configurable, depending on the proxy server. Squid and TinyProxy support this, for example.

乞讨 2024-07-20 17:53:28

这是我的完整 Java 代码,它支持使用 SOCKS 代理的 HTTP 和 HTTPS 请求。

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);
        }
    }
}

Here is my complete Java code that supports both HTTP and HTTPS requests using SOCKS proxy.

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);
        }
    }
}
孤云独去闲 2024-07-20 17:53:28

您可以使用中间人技术和动态 SSL 生成来实现此目的。 看一下 mitmproxy - 它是一个基于 Python、支持 SSL 的 MITM 代理。

You can accomplish this using man-in-the-middle techniques with dynamic SSL generation. Take a look at mitmproxy - it's a Python based, SSL-capable MITM proxy.

热情消退 2024-07-20 17:53:28

通过 SSH 建立隧道(端口转发)HTTPS(Linux 版本):

  1. localhost 上使用 443 关闭。

  2. 以 root 身份启动隧道:

    ssh -N login@proxy_server -L 443:target_ip:443 
      
  3. 127.0.0.1 target_domain.com 添加到 /etc/hosts

您在本地主机上执行的所有操作。
然后:可以从 localhost 浏览器访问 target_domain.com

Tunneling (port forwarding) HTTPS through SSH (Linux version):

  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.

Everything you do on localhost.
Then: target_domain.com is accessible from localhost browser.

不语却知心 2024-07-20 17:53:28

我不认为“通过代理服务器有 HTTPS 连接”意味着代理服务器的中间人攻击类型。 我认为这是在询问是否可以通过 TLS 连接到 http 代理服务器。 答案是肯定的。


是否可以通过代理服务器建立 HTTPS 连接?

是的,请参阅我的问题和答案
这里。 HTTPs 代理服务器仅适用于 SwitchOmega

如果是,什么样的代理服务器允许这样做?

这种代理服务器会像普通网站一样部署SSL证书。 但是您需要一个 pac 文件供浏览器配置通过 SSL 的代理连接。

I don't think "have HTTPS connections over proxy servers" means the Man-in-the-Middle attack type of proxy server. I think it's asking whether one can connect to a http proxy server over TLS. And the answer is yes.


Is it possible to have HTTPS connections over proxy servers?

Yes, see my question and answer
here. HTTPs proxy server only works in SwitchOmega

If yes, what kind of proxy server allows this?

The kind of proxy server deploys SSL certificates, like how ordinary websites do. But you need a pac file for the brower to configure proxy connection over SSL.

乖乖公主 2024-07-20 17:53:28

我尝试

  • 启动隧道:ssh -N -D 12345 login@proxy_server
  • 在firefox设置中将代理设置为localhost:12345
    • 并勾选“将此代理用于所有协议”

但这会导致每当我尝试连接到 https 网站时出现“不安全连接”错误。

解决方案是

  • “取消勾选”“对所有协议使用此代理”,
  • 将代理“localhost:12345”仅设置为 SOCKS 代理
  • ,并将 HTTP 代理、SSL 代理、FTP 代理留空

参考数字海洋文档

如何使用 SOCKS 隧道无需 VPN 即可安全路由 Web 流量

I had tried

  • start tunneling: ssh -N -D 12345 login@proxy_server
  • Setting the proxy in the firefox settings as localhost:12345
    • and ticking "use this proxy for all protocols"

but this resulted in the error "Insecure connection" whenever I tried to connect to an https website.

The solution was to

  • "untick" the "use this proxy for all protocols"
  • set the proxy "localhost:12345" only as a SOCKS proxy
  • and leave the HTTP proxy, SSL proxy, FTP proxy blank

Reference from digital ocean documentation

How To Route Web Traffic Securely Without a VPN Using a SOCKS Tunnel

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文