代理服务器上的HTTPS连接


Answers:


66

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

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

  1. 客户端启动HTTPS会话
  2. 代理透明地拦截连接,并返回由证书颁发机构签名,即席生成的(可能是较弱的)证书Ka ,该证书颁发机构不受客户端的无条件信任。
  3. 代理启动HTTPS会话以目标
  4. 代理验证SSL证书的完整性;如果证书无效,则显示错误。
  5. 代理流式传输内容,使用K a对其解密并重新加密
  6. 客户端显示东西

一个例子是Squid的SSL缓冲区。同样,可以将 burp 配置为执行此操作。埃及ISP也曾在较差的环境中使用过此方法

请注意,现代网站和浏览器可以使用HPKP内置证书图钉,这使该方法无效


13
从原理上讲,这可以工作,但是那不是浏览器与HTTP代理进行HTTPS请求对话的方式。这里描述的方式意味着代理服务器实际上是中间人(因此必须被相应地信任)。
布鲁诺

5
乌贼这样做。这就是SSL Bump
亚当·麦克勒

3
不会向最终用户发送大量警报,而无法正常工作。“无条件地被客户信任”-没有这样的事情。即使该证书是完美的AAA +++,它仍然显示与最终用户要求不匹配的不同域,这将使任何理智的浏览器(此处不是IE ...)都上下尖叫。当然,可以将wget与禁用SSL检查的参数一起使用,但是您猜怎么着?禁用其核心安全性检查后,该连接将无法再命名为“ SSL”。
Van Jone 2015年

1
@Van Jone Unconditionally trusted是指CA证书。CA证书没有域。我用两个示例修改了答案,在此示例中确实可以做到这一点,而不会向用户发出任何警报。
phihag 2015年

6
我的答案取决于您所说的“伪造CA”。CA证书无条件信任的,这是因为用户(或其计算机上的软件,例如企业配置或恶意软件)是通过这种方式配置的,或者是因为CA是从主要浏览器信任的一个CA获得的,例如在MCS案例中。代理会为客户端请求的每个域生成一个新的有效证书,因此,如果没有答案末尾提到的反MITM功能,客户端将不会注意到。
phihag 2015年

22

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

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

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

这样做还有一种不安全的方法,其中HTTP代理成为中间人。它接收客户端启动的连接,然后启动与真实服务器的另一个连接。在实施良好的SSL / TLS中,将通知客户端该代理不是真实的服务器。因此,客户端必须通过忽略警告来使代理工作,从而信任代理。之后,代理只需从一个连接解密数据,然后重新加密并将其馈送到另一个连接。

最后,我们当然可以通过SOCKS代理来代理HTTPS ,因为SOCKS代理工作在较低级别。您可能会将SOCKS代理视为TCP和UDP代理。


使用CONNECT是否会引起stackoverflow.com/a/3118759/632951中提到的安全警告?
佩里耶

@Pacerier我不这么认为。在CONNECT模式下,代理在传输层工作。
Cyker '17

那么,通过CONNECT方法,来自客户端的任何https数据都不会传递到中间代理的应用程序级别吗?只是在代理的TCP级别评估并直接中继到远程服务器
zzinny

15

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

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


3
确实,客户端使用CONNECT动词通过HTTP代理服务器使用https:// URI。在这种情况下,连接是通过代理建立隧道的,因此证书验证将照常进行,就好像客户端在直接与终端服务器通信一样。
布鲁诺

1
@chburd,但是代理通常支持HTTP CONNECT吗?
佩里耶

9

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

要回答问题的第二部分:

如果是,哪种代理服务器允许?

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


5

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

3

您可以使用具有动态SSL生成功能的中间人技术来完成此操作。看一下mitmproxy-它是基于Python的,具有SSL功能的MITM代理。


3

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

您在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代理为空

数字海洋文档中的参考

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


1

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


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

是的,在这里查看我的问题和答案。HTTPs代理服务器仅在SwitchOmega中工作

如果是,哪种代理服务器允许?

这种代理服务器可以像普通网站一样部署SSL证书。但是您需要供浏览器使用的pac文件来配置基于SSL的代理连接。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.