通过代理服务器的 HTTPS 连接

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

如何在 ApacheHTTPClient4中使用 Socks5代理?复制

294266 次浏览

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

如果您希望代理能够读取信息,您可以采取以下方法:

  1. 客户端启动 HTTPS 会话
  2. 代理透明地拦截连接并 返回一个 ad-hoc 生成的(可能 弱)证书 K, 由证书颁发机构签署 无条件信任的人 客户。
  3. 代理启动 HTTPS 会话到目标
  4. 代理验证 SSL 的完整性 证书; 如果 证书无效。
  5. 代理流内容,解密 然后重新加密 K < sub > a
  6. 客户展示东西

一个例子是鱿鱼的 SSL 碰撞。类似地,打嗝 可以配置做到这一点。这也是 埃及互联网服务提供商在不太友好的情况下使用

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

据我所知,您需要在代理上使用 HTTPCONNECT 查询。这将把请求连接转换为一个透明的 TCP/IP 隧道。

因此,您需要知道您使用的代理服务器是否支持此协议。

如果你仍然感兴趣,这里有一个类似问题的答案: 转换 HTTP 代理到扭曲的 HTTPS 代理

回答问题的第二部分:

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

开箱即用,大多数代理服务器将配置为只允许 HTTPS 连接到端口443,因此带有自定义端口的 HTTPS URI 将无法工作。这通常是可配置的,具体取决于代理服务器。例如,Squid 和 TinyProxy 就支持这一点。

您可以通过使用中间人技术和动态 SSL 生成来实现这一点。看看 代理服务器-它是一个基于 Python、支持 SSL 的 MITM 代理。

通过 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

下面是使用 SOCKS 代理支持 HTTP 和 HTTPS 请求的完整 Java 代码。

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

简短的回答是: 这是可能的,并且可以通过特殊的 HTTP 代理或 SOCKS 代理来实现。

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

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

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

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

我试过了

  • 开始挖掘: ssh -N -D 12345 login@proxy_server
  • 将 Firefox 设置中的代理设置为 localhost:12345
    • 勾选“所有协议使用此代理”

但这导致了错误“不安全连接”每当我试图连接到一个 https 网站。

解决办法就是

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

数字海洋文献参考

如何使用 SOCKS 隧道在没有 VPN 的情况下安全地路由 Web 流量

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


有没有可能通过代理服务器建立 HTTPS 连接?

是的,看我的问题和答案 在这里。 < a href = “ HTTPs://stackoverflow. com/questions/56981993/HTTPs-agent-server-only-works-in-SwitchOmega”> HTTP 代理服务器只能在 switchOmega 中工作

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

这种代理服务器部署 SSL 证书,就像普通网站那样。但是浏览器需要一个 pac文件来配置 SSL 上的代理连接。