V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ridesky
V2EX  ›  Node.js

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

  •  
  •   ridesky · 2018-07-20 15:17:28 +08:00 · 5404 次点击
    这是一个创建于 2078 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在使用 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 的错误

    1 条回复    2018-08-02 18:15:46 +08:00
    ridesky
        1
    ridesky  
    OP
       2018-08-02 18:15:46 +08:00
    问题已经解决 参照 https://stackoverflow.com/questions/51439768/https-request-via-https-proxy-but-return-unknown-protocolopenssl-error 里的回答. 至于为什么在 Python 的第三方模块 requests 里却能正常使用 HTTPS 代理 ip , 还没有找到原因.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1062 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 19:02 · PVG 03:02 · LAX 12:02 · JFK 15:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.