Node.js https.get 通过代理生成 SSL3_GET_RECORD 错误版本号错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20841242/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 16:34:49  来源:igfitidea点击:

Node.js https.get via proxy generates SSL3_GET_RECORD wrong version number error

node.jssslhttpsproxyopenssl

提问by foiseworth

TLDR

TLDR

I get the following error when attempting to download a zip file from github using https.request via my company proxy:

尝试通过我的公司代理使用 https.request 从 github 下载 zip 文件时出现以下错误:

An error occured whilst trying to download Casper.JS 140735122252160:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:../deps/openssl/openssl/ssl/s3_pkt.c:337:

尝试下载 Casper.JS 140735122252160:error:1408F10B:SSLroutines:SSL3_GET_RECORD:wrong version number:../deps/openssl/openssl/ssl/s3_pkt.c:337 时发生错误:

More information

更多信息

I'm attempting to edit the grunt-casperjs install script to allow myself and my colleagues to install behind our proxy. The script fetches Casper from Github and downloads it. Originally the script didn't support a proxy so I copied the grunt-phantomjs proxy support. Phantomjs is downloaded via a http connection and this works fine via our proxy (if I change it to a https URL it fails with the same error).

我正在尝试编辑 grunt-casperjs 安装脚本,以允许我自己和我的同事安装在我们的代理后面。该脚本从 Github 获取 Casper 并下载它。最初脚本不支持代理,所以我复制了 grunt-phantomjs 代理支持。Phantomjs 是通过 http 连接下载的,这可以通过我们的代理正常工作(如果我将其更改为 https URL,它会失败并出现相同的错误)。

I have attempted the following:

我尝试了以下方法:

  • I added https.globalAgent.options.secureProtocol = 'SSLv3_method'; as previously an unknown protocol error was displayed.
  • Using curl, the request completes fine
  • Updated OpenSSL and Node
  • I added https.globalAgent.options.secureOptions = 'SSL_OP_NO_TLSv1'; but this results in node returning with no message after the request is made
  • 我添加了 https.globalAgent.options.secureProtocol = 'SSLv3_method'; 如前所述,显示了未知的协议错误。
  • 使用 curl,请求完成
  • 更新的 OpenSSL 和节点
  • 我添加了 https.globalAgent.options.secureOptions = 'SSL_OP_NO_TLSv1'; 但这导致节点在发出请求后没有消息返回

Reduced test case

减少测试用例

var https = require('https');
https.globalAgent.options.secureProtocol = 'SSLv3_method'

var url = require('url');
var downloadUrl = 'https://codeload.github.com/n1k0/casperjs/zip/1.0.3'
var proxy = 'https://username:password@IP:port';

var options = url.parse(proxy);
options.path = downloadUrl;
options.headers = { Host: url.parse(downloadUrl).host }
// If going through proxy, spoof the User-Agent, since may commercial proxies block blank or unknown agents in headers
options.headers['User-Agent'] = 'curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5'
// Turn basic authorization into proxy-authorization.
options.headers['Proxy-Authorization'] = 'Basic ' + new Buffer(options.auth).toString('base64');
delete options.auth;

var request = https.get(options, function(response) {
    console.log('response received');
}).on('error', function(e) {
    console.log('An error occurred whilst trying to download Casper.JS ' + e.message);
});

Original Code

原始代码

function downloadZipFromGithub() {
    var file = fs.createWriteStream(path.join(tmpPath, "archive.zip"));
    var lengthSoFar = 0;
    var npmconfDeferred = kew.defer();
    npmconf.load(npmconfDeferred.makeNodeResolver());

    npmconfDeferred.then(function(conf){
        var requestOptions = getRequestOptions(conf.get('https-proxy'));

        https.globalAgent.options.secureProtocol = 'SSLv3_method';

        var request = https.get(requestOptions, function(response) {
            if (response.statusCode === 301 || response.statusCode === 302) {
                downloadUrl = response.headers.location;
                downloadZipFromGithub();
            } else {
                response.pipe(file);
                response.on('data', function(chunk) {
                    console.log('Receiving ' + Math.floor((lengthSoFar += chunk.length) / 1024) + 'K...' );
                }).
                    on('end', unzipTheZippedFile).
                    on('error', function(e) {
                        console.log('An error occured whilst trying to download Casper.JS ' + e.message);
                        tidyUp();
                    });
            }
         }).on('error', function(e) {
            console.log('An error occured whilst trying to download Casper.JS ' + e.message);
            tidyUp();
        });
     });
 }

function getRequestOptions(proxyUrl) {
    if (proxyUrl) {
        var options = url.parse(proxyUrl);
        options.path = downloadUrl;
        options.headers = { Host: url.parse(downloadUrl).host }
        // If going through proxy, spoof the User-Agent, since may commerical proxies block blank or unknown agents in headers
       options.headers['User-Agent'] = 'curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5'
        // Turn basic authorization into proxy-authorization.
        if (options.auth) {
            options.headers['Proxy-Authorization'] = 'Basic ' + new Buffer(options.auth).toString('base64');
            delete options.auth;
        }

        return options;
    } else {
        return url.parse(downloadUrl);
    }
}

采纳答案by foiseworth

It looks like this error is caused when squid (the proxy) does not have https enabled or you're connecting to the wrong port.

看起来这个错误是由于鱿鱼(代理)没有启用 https 或者您连接到错误的端口引起的。

Source: https://github.com/joyent/node/issues/6779

来源:https: //github.com/joyent/node/issues/6779

回答by Ampp3

None of the above solutions worked for me, but I was able to resolve my issues by updating the https-proxy URL from an httpS URL to an http URL

上述解决方案都不适合我,但我能够通过将 https-proxy URL 从 httpS URL 更新为 http URL 来解决我的问题

回答by Tim Williams

This should be possible using the Request module (npm install request). The below works for standard HTTPS requests over an HTTP proxy. As you are tunnelling the HTTPS request to the end server (in this example Github) I'm not sure its necessary for the proxy to also be HTTPS.

这应该可以使用请求模块(npm install request)来实现。以下适用于通过 HTTP 代理的标准 HTTPS 请求。当您将 HTTPS 请求通过隧道传输到终端服务器(在本示例中为 Github)时,我不确定代理是否也必须是 HTTPS。

var request = require('request');

var proxy = 'http://username:password@IP:port';
var downloadUrl = 'https://codeload.github.com/n1k0/casperjs/zip/1.0.3'
var options = {
    proxy: proxy,
    url: downloadUrl
};

function callback(error, response, body) {
  console.log(error);
  console.log(response);        
    if (!error && response.statusCode == 200) {
        console.log(body);        
    }

}

request(options, callback);