HTTPs代理服务器仅在SwitchOmega中工作

时间:2019-07-11 05:11:17

标签: node.js http ssl proxy

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

长话:

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

到目前为止,我已经知道并尝试过:

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

enter image description here

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

问题:

CONNECT请求为纯文本,因此防火墙可以查看我要连接到的主机并断开连接。 因此,我一直在考虑是否可以从一开始就使用https与代理服务器进行对话。我阅读了所有相关文章,但找不到直接谈论此内容的答案。并且一些答案还说“没有https代理服务器之类的东西”

但是该教程说可以做到这一点(客户端和代理服务器之间的HTTPS,没有其他改变)。因此,我尝试一下。我已使用网站的证书将服务器更改为https ,但是最终它只能与Chrome中的 Proxy SwitchOmega 一起使用。不适用于Firefox代理或IE代理设置等传统设置。

Proxy SwitchOmega设置:

Scheme|Protocol|Server|Port
....  | https  | .... |...

如果我启动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   |

所以我的问题是:

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

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

测试服务器

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

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

1 个答案:

答案 0 :(得分:2)

我在Security StackExchange中找到了答案。 Is it possible to connect to a proxy with an ssl (or otherwise encrypted) connection?

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

  

加密的浏览器-鱿鱼连接

     

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

     

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

     

...

     

Chrome

     

如果将Chrome浏览器配置为在PAC文件或命令行开关中使用一个代理,则可以通过SSL连接连接到代理。 尚未(可能)进行GUI配置

     

Firefox

     

如果Firefox 33.0浏览器配置为在PAC文件中使用TLS连接,则可以通过TLS连接连接到代理。 GUI配置似乎还没有实现,尽管存在用于嵌入PAC逻辑的配置黑客。

有关Chrome的更多信息,请参见http://dev.chromium.org/developers/design-documents/secure-web-proxy


回答问题:

  
      
  1. 我可以通过普通方式(不带扩展名)连接到https代理服务器吗?如果可能的话,怎么办?
  2.   

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

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

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

通过在SwitchOmega中单击Export PAC按钮,我得到一个包含以下内容的文件:

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

来自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  
  
      
  1. 我想我建立了一个https代理服务器。但是为什么其他人会说“没有像https代理服务器这样的东西?
  2.   

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