Nodejs request 模块 使用 https 代理去访问 https 地址时 返回 unknown protocol:openssl

发布于 1周前 作者 nodeper 来自 nodejs/Nestjs

Nodejs request 模块 使用 https 代理去访问 https 地址时 返回 unknown protocol:openssl

在使用 request 模块的时候,如果用 http 代理地址去访问 http 链接的时候 一切正常

代码如下

const rq = require('request-promise'); // request 模块的衍生物 支持 promise; api 与 request 兼容
try {
    let res = rq({
        url: 'http://xxxx',
        timeout: TIME_OUT,
        gzip: true,
        proxy: 'http://112.25.60.32:8080'
    });
    res.then(res => {
        console.log('res');
        console.log(res);
    }).catch(err => {
        console.log(err);
    });
} catch (error) {
    console.log(error);
}

但是如果用 https 代理地址 去访问 https 链接的时候 就会报错 unknown protocol 的问题:

RequestError: Error: tunneling socket could not be established, cause=write EPROTO 101057795:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:openssl\ssl\s23_clnt.c:827:

代码如下

try {
    let res = rq({
        url: 'https://ipinfo.io/', //  请求的地址变为 https
        timeout: TIME_OUT,
        gzip: true,
        proxy: 'https://158.69.206.181:8888' // 代理地址更换为 https
    });
    res.then(res => {
        console.log('res');
        console.log(res);
    }).catch(err => {
        console.log(err);
    });
} catch (error) {
    console.log(error);
}

一开始以为是 代理地址出现了问题 但是同样的代理地址 在 python 的 requests 第三方模块运行正常

代码如下


import requests, os
os.environ['HTTP_PROXY'] = '112.25.60.32:8080'
os.environ['HTTPS_PROXY'] = '158.69.206.181:8888'
try:
    text = requests.get('https://ipinfo.io/').text # 访问的 https 地址
except Exception as e:
    print(e)
    print('connect failed')
print(text) 
# 结果正常打印,一切正常 {
  "ip": "158.69.206.181", 
  "hostname": "181.ip-158-69-206.net",
  "city": "Montreal",
  "region": "Quebec",
  "country": "CA",
  "loc": "45.5000,-73.5833",
  "postal": "H3A",
  "org": "AS16276 OVH SAS"
}
# 返回的 ip 信息 就是 https 代理地址

所以纠结到底是我配置的问题还是两个语言的模块原理不同

在 StackOverflow 查到类似的问题 下面有人回答说是端口的问题

链接如下 StackOverflow

但是我这里貌似不是端口的问题, 因为 request 本身会对地址进行封装处理,而且即使我在 https 访问地址修改为 'https://ipinfo.io:443' 还会出现同样的报错

要命的是 我改用 axios(0.18.0 目前最新版) 去走代理同样会返回一样的错误, 所以真的不知道是我哪里出现的问题,有大佬知道在哪里出错了吗?

更新: 通过 fiddler 去走代理 并加上 rejectUnauthorized: false 数据就能跑通,但是直接走代理地址还是同样报错

fiddler 代理配置如下

微信截图_20180720150519.png

代码

try {
  let res = rq({
    url: 'https://ipinfo.io/', //  请求的地址变为 https
    timeout: TIME_OUT,
    gzip: true,
    rejectUnauthorized: false, // 允许通过未认证的证书
    proxy: 'http://127.0.0.1:8888' // 通过 fiddler 去走代理
  });
  res
    .then(res => {
      console.log('res');
      console.log(res); // 数据可以正常返回!!
    })
    .catch(err => {
      console.log(err);
    });
} catch (error) {
  console.log(error); 
}

但是在同样增加 rejectUnauthorized: false 的基础上 proxy 改为直接代理地址仍然会报 unknown protocol:openssl 的错误


2 回复

问题已经解决 参照 https://stackoverflow.com/questions/51439768/https-request-via-https-proxy-but-return-unknown-protocolopenssl-error 里的回答. 至于为什么在 Python 的第三方模块 requests 里却能正常使用 HTTPS 代理 ip , 还没有找到原因.


在 Node.js 中使用 request 模块通过 HTTPS 代理访问 HTTPS 地址时遇到 “unknown protocol: openssl” 的错误,通常是因为代理配置不正确或者代理服务器本身不支持 HTTPS 协议的转发。不过需要注意的是,request 模块已经废弃,建议使用 axiosnode-fetch 等现代库。

如果你仍然需要使用 request 模块(尽管不推荐),你可以尝试以下代码配置 HTTPS 代理。但首先,请确保你的代理服务器支持 HTTPS 连接。

const request = require('request');

const options = {
    url: 'https://example.com', // 目标 URL
    proxy: 'https://your-proxy-server:port', // 代理服务器地址
    strictSSL: false, // 如果代理服务器使用自签名证书,可能需要设置为 false
    rejectUnauthorized: false // 同样,如果代理服务器使用自签名证书
};

request(options, (error, response, body) => {
    if (error) {
        console.error('Error:', error);
    } else {
        console.log('Response:', response.statusCode, body);
    }
});

然而,由于 request 模块已经废弃,推荐使用 axios

const axios = require('axios');
const https = require('https');

const agent = new https.Agent({
    keepAlive: true,
    proxy: {
        host: 'your-proxy-server',
        port: port
    }
});

axios.get('https://example.com', { httpsAgent: agent })
    .then(response => console.log(response.data))
    .catch(error => console.error(error));

确保代理服务器正确配置并支持 HTTPS。如果问题依旧,请检查代理服务器的日志以获取更多信息。

回到顶部