簡體   English   中英

HTTPs 代理服務器僅在 SwitchOmega 中有效

[英]HTTPs proxy server only works in SwitchOmega

在問這個問題之前,我做了很多搜索和實踐試驗。

很長的故事:

我找到了一個(非英語)教程,介紹如何使用 Node.js 編寫 http 代理。

到目前為止,我所知道和嘗試的是:

  • HTTP 代理可以同時處理 HTTP 請求和 HTTPS 請求,但處理方式不同。 它通過讀取客戶端的請求來處理 HTTP 請求,並向目標發出新請求並將響應返回給客戶端。 至於 HTTPS 請求,它處理了一個 HTTP Tunnel

在此處輸入圖像描述

  • Firefox代理設置中的SSL proxy字段和IE代理設置(Windows)中的Secure字段都是關於設置HTTP Tunnel的。 如果設置了SSL proxySecure proxy ,當瀏覽器想要連接到 https 站點時,它會發送一個CONNECT請求,而不是普通請求。

問題:

CONNECT請求是純文本,因此防火牆可以看到我要連接的主機並切斷連接。 所以我一開始就在想能不能用https跟代理服務器對話。 我閱讀了所有相關帖子,但找不到直接談論這個的答案。 還有一些答案還說“沒有 https 代理服務器這樣的東西”

但是教程說這是可以做到的(客戶端和代理服務器之間的 HTTPS 沒有其他變化)。所以我試了一下。我用我網站的證書將服務器更改為 https。但最終它只適用於 Chrome 中的Proxy SwitchOmega 。它在 Firefox 代理或 IE 代理設置等傳統設置中不起作用。

代理 SwitchOmega 設置:

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

如果我啟動 https 服務器,我必須在此處使用 select https協議。 同樣,如果我啟動 http 服務器,我必須使用 select 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代理測試服務器,基於上面的代碼。

測試服務器被刪除,因為我找到了答案。

我在 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代理服務器嗎? 如果可以,怎么做?

設置http代理服務器的傳統方式(例如Firefox中的Manual proxy configuration字段)僅適用於HTTP代理服務器。 只能通過pac文件設置 https 代理(例如 Firefox 中的Automatic proxy configuration URL字段)。

  1. 為什么我可以通過 SwitchOmega 連接到 https 代理服務器?

SwitchOmega 擴展實際上會生成一個供 Chrome 使用的pac文件,盡管到目前為止我還不知道它是如何與 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代理服務器這樣的東西?

是的,我通過 tls 連接構建了一個 https 代理服務器/一個 http 代理服務器。 那些說“沒有 https 代理服務器這樣的東西”的人是錯誤的。

AFAIK 沒有官方的 HTTPS 代理規范。

Rick 在他的回答中所說的是 Squid 的 hack 允許他們緩存以前由於 https 而無法緩存的內容,方法是終止瀏覽器 TLS 請求,然后向目標服務器發起另一個 TLS 請求。 本質上,Squid 充當瀏覽器和服務器之間的 MITM。 雖然連接仍受 TLS 保護,但 Squid 可以看到流量。 如果 web 服務器正在實施 HSTS,瀏覽器將不允許我們連接。

我對 HTTPS 代理的期望是瀏覽器啟動兩個 TLS 連接。 它首先啟動到代理服務器的 TLS 連接,然后請求連接到預期的 web 服務器並啟動另一個 TLS。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM