代理服务器上的HTTPS连接

是否可以通过代理服务器进行HTTPS连接? 如果是的话,什么样的代理服务器允许这个?

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

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

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

  1. 客户端启动HTTPS会话
  2. 代理透明地截获连接,并返回由客户端无条件信任的证书颁发机构签署的临时生成(可能很弱)的证书K a
  3. 代理将HTTPS会话启动到目标
  4. 代理validationSSL证书的完整性; 如果证书无效,则显示错误。
  5. 代理对内容进行stream处理,解密并用K a重新encryption
  6. 客户显示的东西

一个例子是Squid的SSL碰撞 。 同样,打嗝可以configuration来做到这一点。 埃及的ISP也在一个不太友善的环境中使用这种技术 。

请注意,现代网站和浏览器可以使用HPKP或内置的证书引脚来打败这种方法。

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

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

如果仍然感兴趣,下面是一个类似问题的答案: 将HTTP代理转换为扭曲的HTTPS代理

回答问题的第二部分:

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

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

这里是我完整的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); } } } 

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

首先,HTTPS使用SSL / TLS,它通过devise确保端到端的安全性,通过build立一个安全的通信通道而不安全。 如果HTTP代理能够看到内容,那么它就是一个中间窃听者,这就违背了SSL / TLS的目标。 所以如果我们想通过一个普通的HTTP代理来进行代理,那么必须要有一些技巧。

诀窍是,我们用名为CONNECT的特殊命令将HTTP代理转换为TCP代理。 并不是所有的HTTP代理都支持这个function,但现在有很多。 TCP代理无法以明文forms查看正在传输的HTTP内容,但这并不影响其来回转发数据包的能力。 通过这种方式,客户端和服务器可以在代理的帮助下相互通信。 这是代理HTTPS数据的安全方式。

还有一种不安全的方式,HTTP代理变成了一个中间人。 它接收客户端启动的连接,然后启动到真实服务器的另一个连接。 在一个良好实施的SSL / TLS中,客户端将被通知代理不是真正的服务器。 所以客户必须通过忽略对事情的警告来信任代理。 之后,代理只需从一个连接解密数据,重新encryption并将其传送到另一个连接。

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

您可以使用dynamicSSL生成中的man-in-the-middle技术来完成此操作。 看一下mitmproxy – 这是一个基于Python的,具有SSLfunction的MITM代理。

通过SSH(linux版本)隧道HTTPS:

 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 

你在本地主机上所做的一切。 然后:

 target_domain.com is accessible from localhost browser. 

我曾试过

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

但是每当我尝试连接到https网站时,都会导致错误“不安全的连接”。

解决的办法是

  • “解开”“为所有协议使用此代理”
  • 仅将代理“localhost:12345”设置为SOCKS代理
  • 并将HTTP代理,SSL代理,FTP代理留空

来自数字海洋文件的参考

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