HTTPS 代理服务器仅适用于 SwitchOmega

Ric*_*ick 11 ssl proxy http node.js

在问这个问题之前,我做了很多搜索和实践试验。

很长的故事:

我找到了一个关于如何使用 Node.js 编写 http 代理的(非英语)教程。

到目前为止,我所知道和尝试过的:

  • HTTP 代理可以处理 HTTP 请求和 HTTPS 请求,但方式不同。它通过读取客户端的请求来处理 HTTP 请求,并向目标发出新请求并将响应返回给客户端。至于 HTTPS 请求,则是通过 HTTP Tunnel处理的。

在此处输入图片说明

  • SSL proxyFirefox中的代理设置字段和Secure在IE代理设置字段(Windows)都有关设置HTTP隧道。如果设置了SSL proxySecure proxy,当浏览器想要连接到 https 站点时,它会发送CONNECT请求而不是普通请求。

问题:

CONNECT要求是纯文本,这样防火墙可以看到我想要连接到并切断连接主机什么。所以我从一开始就在考虑是否可以使用https与代理服务器对话。我阅读了所有相关的帖子,但找不到直接谈论这个的答案。有些答案还说“没有 https 代理服务器这样的东西”

但是教程说这是可以做到的(客户端和代理服务器之间的 HTTPS 没有其他变化?。所以我试了一下。我用我网站的证书将服务器更改为 https。但最终它只适用于 Chrome 中的Proxy SwitchOmega。它不适用于传统设置,例如 Firefox 代理或 IE 代理设置。

代理 SwitchOmega 设置:

Scheme|Protocol|Server|Port
....  | https  | .... |...
Run Code Online (Sandbox Code Playgroud)

https如果我启动 https 服务器,我必须在这里选择协议。同样,http如果我启动 http 服务器,我必须选择协议。我也不知道这个protocol字段代表什么。


把它们加起来:

proxy server | Firefox proxy setting |work? | SwitchOmega setting |work?|
 http        | http + ssl setting    | yes  | protocol http       |yes  |
 https       | http + ssl setting    | no   | protocol https      |yes  |
 https       |      -                |  -   | protocal http       |no   |
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

  1. 可以通过普通方式(不带扩展)连接到https代理服务器吗?如果可以,怎么做?
  2. 为什么我可以通过SwitchOmega连接到 https 代理服务器?
  3. 我想我建立了一个https代理服务器。但是为什么其他人会说“没有https代理服务器这样的东西?

源代码

https 服务器

var http = require('http');
var https = require('https');
var fs = require('fs');
var net = require('net');
var url = require('url');

console.log("qqqqq2");

function request(cReq, cRes) {
    console.log("request=====start");
    console.log(cReq.headers);
    console.log(cReq.url);
    console.log(cReq.method);
    console.log("request=====end");
    var u = url.parse(cReq.url);

    var options = {
        hostname : u.hostname, 
        port     : u.port || 80,
        path     : u.path,       
        method     : cReq.method,
        headers     : cReq.headers
    };

    var pReq = http.request(options, function(pRes) {
        cRes.writeHead(pRes.statusCode, pRes.headers);
        pRes.pipe(cRes);
    }).on('error', function(e) {
        cRes.end();
    });

    cReq.pipe(pReq);
    // console.log(cReq.headers);
    // console.log(cReq.method);
    // console.log(cReq.url);
    // console.log("^_^^_^^_^^_^^_^^_^");
    // cRes.writeHead('200');
    // cRes.end('hello world2222\n');
}

function connect(cReq, cSock) {
    console.log("connect=====start");
    console.log(cReq.headers);
    console.log(cReq.url);
    console.log(cReq.method);
    console.log("connect=====end");
    var u = url.parse('http://' + cReq.url);

    var pSock = net.connect(u.port, u.hostname, function() {
        cSock.write('HTTP/1.1 200 Connection Established\r\n\r\n');
        pSock.pipe(cSock);
    }).on('error', function(e) {
        cSock.end();
    });

    cSock.pipe(pSock);
}

var options = {
    key: fs.readFileSync('./privkey1.pem'),
    cert: fs.readFileSync('./fullchain1.pem')
};

https.createServer(options)
    .on('request', request)
    .on('connect', connect)
    .listen(9999, '0.0.0.0');
Run Code Online (Sandbox Code Playgroud)

http服务器

var http = require('http');
var net = require('net');
var url = require('url');

console.log('qqqqq2');

function request(cReq, cRes) {
    console.log("request=====start");
    console.log(cReq.headers);
    console.log(cReq.url);
    console.log(cReq.method);
    console.log("request=====end");

    var u = url.parse(cReq.url);

    var options = {
        hostname : u.hostname, 
        port     : u.port || 80,
        path     : u.path,       
        method     : cReq.method,
        headers     : cReq.headers
    };

    var pReq = http.request(options, function(pRes) {
        cRes.writeHead(pRes.statusCode, pRes.headers);
        pRes.pipe(cRes);
    }).on('error', function(e) {
        cRes.end();
    });

    cReq.pipe(pReq);
}

function connect(cReq, cSock) {
    console.log("connect=====start");
    console.log(cReq.headers);
    console.log(cReq.url);
    console.log(cReq.method);
    console.log("connect=====end");
    var u = url.parse('http://' + cReq.url);

    var pSock = net.connect(u.port, u.hostname, function() {
        cSock.write('HTTP/1.1 200 Connection Established\r\n\r\n');
        pSock.pipe(cSock);
    }).on('error', function(e) {
        cSock.end();
    });

    cSock.pipe(pSock);
}

http.createServer()
    .on('request', request)
    .on('connect', connect)
    .listen(9999, '0.0.0.0');
Run Code Online (Sandbox Code Playgroud)

测试服务器

您可以轻松构建一个 http 代理服务器并对其进行测试。但是搭建https代理服务器可能比较麻烦,因为需要部署证书。所以提供了一个https代理测试服务器,基于上面的代码。

自从我找到答案以来,测试服务器已被删除。

Ric*_*ick 7

我在 Security StackExchange 中找到了答案。 是否可以通过 ssl(或其他加密)连接连接到代理?

https://wiki.squid-cache.org/Features/HTTPS#Encrypted_browser-Squid_connection

加密浏览器-Squid 连接

虽然 HTTPS 的设计工作侧重于端到端通信,但能够加密浏览器到代理的连接(无需创建阻止 Squid 访问和缓存内容的 CONNECT 隧道)也很好。例如,这将允许安全使用位于可能敌对网络上的远程代理。

Squid 可以使用 https_port 接受常规代理流量,就像 Squid 使用 http_port 指令一样。不幸的是,流行的现代浏览器不允许配置 TLS/SSL 加密代理连接。现在有针对大多数浏览器的开放错误报告,等待支持出现。如果您有任何兴趣,请协助浏览器团队实现这一目标。

...

铬合金

如果配置为在 PAC 文件或命令行开关中使用代理,Chrome 浏览器能够通过 SSL 连接连接到代理。GUI 配置似乎不可能(还)

火狐

如果配置为在 PAC 文件中使用代理,Firefox 33.0 浏览器能够通过 TLS 连接连接到代理。GUI 配置似乎不可能(还),尽管有一个用于嵌入 PAC 逻辑的配置技巧。

有关 Chrome 的更多信息可以在http://dev.chromium.org/developers/design-documents/secure-web-proxy 中找到。


回答问题:

  1. 可以通过普通方式(不带扩展)连接到https代理服务器吗?如果可以,怎么做?

Manual proxy configuration设置http代理服务器的传统方式(例如Firefox中的字段)仅适用于HTTP代理服务器。只能通过pac文件(例如Automatic proxy configuration URLFirefox 中的字段)设置https 代理。

  1. 为什么我可以通过 SwitchOmega 连接到 https 代理服务器?

SwitchOmega 扩展实际上会生成一个pac供 Chrome 使用的文件,尽管到目前为止我还不知道它是如何与 Chrome 交互的。

通过单击Export PACSwitchOmega 中的按钮,我得到一个文件,其中包含:

var FindProxyForURL = function(init, profiles) {
    return function(url, host) {
        "use strict";
        var result = init, scheme = url.substr(0, url.indexOf(":"));
        do {
            result = profiles[result];
            if (typeof result === "function") result = result(url, host, scheme);
        } while (typeof result !== "string" || result.charCodeAt(0) === 43);
        return result;
    };
}("+test", {
    "+test": function(url, host, scheme) {
        "use strict";
        if (/^127\.0\.0\.1$/.test(host) || /^::1$/.test(host) || /^localhost$/.test(host)) return "DIRECT";
        return "HTTPS myHttpsProxyServer.com:9999"; // This line matters
    }
});
Run Code Online (Sandbox Code Playgroud)

https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_(PAC)_file

HTTP host:port   
The specified proxy should be used   
HTTPS host:port 
The specified HTTPS proxy should be used  
Run Code Online (Sandbox Code Playgroud)
  1. 我想我建立了一个https代理服务器。但是为什么其他人会说“没有https代理服务器这样的东西?

是的,我通过 tls 连接构建了一个 https 代理服务器/一个 http 代理服务器。那些说“没有 https 代理服务器这样的东西”的人是错误的。