1

Everything is fine if I request 'HTTP' address via 'HTTP' proxy

    const rq = require('request-promise'); 
    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);
}

But if request 'https' addrss via 'https' proxy, it will return '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 address
        timeout: TIME_OUT,
        gzip: true,
        rejectUnauthorized: false,
        proxy: 'https://149.56.109.24:3128' //  https proxy
    });
    res.then(res => {
        console.log('res');
        console.log(res);
    }).catch(err => {
        console.log(err);
    });
} catch (error) {
    console.log(error);
}

At first I thought it was a problem with the proxy address. But the same proxy address works fine in python requests module

python code

import requests, os
os.environ['HTTP_PROXY'] = '112.25.60.32:8080'
os.environ['HTTPS_PROXY'] = '149.56.109.24:3128'
try:
    text = requests.get('https://ipinfo.io/').text # request https address
except Exception as e:
    print(e)
    print('connect failed')
print(text) 
# it works fine!  {
  "ip": "149.56.109.24:3128", 
  "hostname": "181.ip-158-69-206.net",
  "city": "Montreal",
  "region": "Quebec",
  "country": "CA",
  "loc": "45.5000,-73.5833",
  "postal": "H3A",
  "org": "AS16276 OVH SAS"
}
# The returned 'ip' information is the 'https' proxy address.

A similar problem was found in StackOverflow. Someone replied that it is a port problem.

Here is the link StackOverflow

But I think this is not a problem about the port,because when I use proxy by fiddler, it works!

Here is my configuration about fiddler

enter image description here

code (by fiddler)

try {
  let res = rq({
    url: 'https://ipinfo.io/',
    timeout: TIME_OUT,
    gzip: true,
    rejectUnauthorized: false,
    proxy: 'http://127.0.0.1:8888' // through fiddler
  });
  res
    .then(res => {
      console.log('res');
      console.log(res); // it works!!
    })
    .catch(err => {
      console.log(err);
    });
} catch (error) {
  console.log(error); 
}

However, based on the above code, Proxy changed to '149.56.109.24:3128' (without fiddler) will still report 'unknown protocol:openssl\ssl\s23_clnt.c:827' error

So what went wrong? I have not solved it.

Manish Balodia
  • 1,863
  • 2
  • 23
  • 37
Ridesky
  • 21
  • 1
  • 2

1 Answers1

0
   proxy: 'https://149.56.109.24:3128' //  https proxy

A HTTP proxy will handle HTTP and HTTPS. HTTPS is handled by connecting in plain to the HTTP proxy, issuing a CONNECT request to build a tunnel to the server and then upgrade the connection to TLS within this tunnel - which results in end-to-end HTTPS.

What you have instead configured is to access the proxy itself by HTTPS, essentially asking for HTTPS inside a HTTPS tunnel. This is very likely not supported by the proxy, i.e. use http:// to access the proxy and not https://.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Do you know of some official documentation that supports this? I don't doubt it, I'm just looking to justify a technical decision. – Jason Kleban Mar 23 '19 at 13:36
  • 1
    I'm not sure what kind of documentation you expect. But you can have a look how this needs to be configured for example with curl or inside a browser and you will see the same. It might help if you make yourself clear how the underlying CONNECT method (documented [here](https://tools.ietf.org/html/rfc7231#section-4.3.6)) works and that it lets you create a tunnel for the TLS end-to-end connection. – Steffen Ullrich Mar 23 '19 at 14:10
  • Thanks. For the record, I'm just trying to make node proxy correctly with fiddler. I am pretty sure I had it working in the past using https proxy for https requests but lately it isn't working and hangs requests, timing out with that `SSL23_GET_SERVER_HELLO:unknown protocol` but http works so I'm justifying that this is the right way and not consequential/dev-environment specific. Referencing this answer in my code as justification. – Jason Kleban Mar 23 '19 at 14:14
  • Just came across this comment and for anyone reading this - nested TLS is completely fine and is done everywhere the proxy is an HTTPS server. For reference take a look at GO's implementation of this case: https://golang.org/src/net/http/transport.go `Add TLS to a persistent connection, i.e. negotiate a TLS session. If pconn is already a TLS tunnel, this function establishes a nested TLS session inside the encrypted channel.` – omricoco Sep 22 '20 at 07:29
  • @omricoco: It is actually typical that the proxy is HTTP only but one can still end-to-end access `https://` via CONNECT method. A typical error is to assume that one needs to access a proxy with HTTPS in order to access a `https://` site. This common error has nothing to do with the technical capability of __some__ clients and proxies to support accessing the proxy by HTTPS, which can protect both `http://` and `https://` traffic on their way to the proxy. Note that this is not universally supported (albeit growing), e.g. Python does not support this. – Steffen Ullrich Sep 22 '20 at 08:18