【问题标题】:Node.js https.get via proxy generates SSL3_GET_RECORD wrong version number errorNode.js https.get 通过代理生成 SSL3_GET_RECORD 错误版本号错误
【发布时间】:2014-01-17 10:32:22
【问题描述】:

TLDR

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

尝试下载 Casper.JS 时出错 140735122252160:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:../deps/openssl/openssl/ssl/s3_pkt.c:337:强>

更多信息

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

我尝试了以下方法:

  • 我添加了 https.globalAgent.options.secureProtocol = 'SSLv3_method';与之前一样,显示了一个未知的协议错误。
  • 使用 curl,请求可以正常完成
  • 更新了 OpenSSL 和 Node
  • 我添加了 https.globalAgent.options.secureOptions = 'SSL_OP_NO_TLSv1';但这会导致节点在发出请求后返回没有消息

简化的测试用例

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

原始码

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

【问题讨论】:

  • “错误的版本号...SSLv3_method” - 通常您使用SSLv23_method,然后使用SSL_OP_NO_SSLv2 删除不需要的协议,如SSLv2。这会让你获得 SSLv3 及更高版本。事实上,我通常将SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 用于 TLSv1.0 及更高版本(我从来没有遇到过专门使用 TLS 的问题)。不幸的是,我不知道如何在 Javascript 中做到这一点。
  • 我在使用 axios 时遇到了这个错误,发现我必须在 baseUrl 中指定端口 (443)。 https://:443/

标签: node.js ssl https proxy openssl


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      这应该可以使用 Request 模块(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);
      

      【讨论】:

      • 不幸的是,使用 Request 的错误是相同的 - 我以前尝试过这个。谢谢
      • 请注意,此库已被弃用
      猜你喜欢
      • 2012-10-05
      • 2021-06-01
      • 2021-12-12
      • 1970-01-01
      • 2014-12-10
      • 2021-06-23
      • 2014-01-12
      • 2019-04-05
      • 1970-01-01
      相关资源
      最近更新 更多