apify / proxy-chain

Node.js implementation of a proxy server (think Squid) with support for SSL, authentication and upstream proxy chaining.
https://www.npmjs.com/package/proxy-chain
Apache License 2.0
804 stars 138 forks source link

Proxy-chain never reconnect when get this error: "Failed to connect to upstream proxy: Error: socket hang up" #530

Open meotimdihia opened 4 months ago

meotimdihia commented 4 months ago

I had to restart the service manually when proxy-chain got this error. This problem didn't happen on the old version.

ProxyServer[8000]: 4054 | Failed to connect to upstream proxy: Error: socket hang up
    at connResetException (node:internal/errors:720:14)
    at Socket.socketCloseListener (node:_http_client:468:25)
    at Socket.emit (node:events:526:35)
    at Socket.emit (node:domain:489:12)
    at TCP.<anonymous> (node:net:337:12)
Connection 4054 closed
{ srcTxBytes: 0, srcRxBytes: 106, trgTxBytes: null, trgRxBytes: null }

ProxyServer[8000]: 4055 | Failed to connect to upstream proxy: Error: socket hang up
    at connResetException (node:internal/errors:720:14)
    at Socket.socketCloseListener (node:_http_client:468:25)
    at Socket.emit (node:events:526:35)
    at Socket.emit (node:domain:489:12)
    at TCP.<anonymous> (node:net:337:12)
Connection 4055 closed
{ srcTxBytes: 0, srcRxBytes: 106, trgTxBytes: null, trgRxBytes: null }

ProxyServer[8000]: 4771 | !!! Handling CONNECT 94.100.180.61:443 HTTP/1.1
ProxyServer[8000]: 4771 | Using upstream proxy http://tknzgzth-rotate:<redacted>@
ProxyServer[8000]: 4771 | Using HandlerTunnelChain => 94.100.180.61:443
ProxyServer[8000]: 4029 | Failed to connect to upstream proxy: Error: socket hang up
    at connResetException (node:internal/errors:720:14)
    at Socket.socketCloseListener (node:_http_client:468:25)
    at Socket.emit (node:events:526:35)
    at Socket.emit (node:domain:489:12)
    at TCP.<anonymous> (node:net:337:12)
Connection 4029 closed
jirimoravcik commented 4 months ago

Hello @meotimdihia, can you please specify what is "the old version"? Thank you

meotimdihia commented 4 months ago

@jirimoravcik I used proxy-chain since "proxy-chain": "^2.2.1". It works fine.

But when I upgraded to the latest version several months ago. I have to restart the proxy service manually when something is broken.

meotimdihia commented 4 months ago

proxy-chain is easy to set up.

But I guess everyone got this problem but switched to other software instead of reporting it. From the screenshot, maybe something was broken at this time.

image

This problem is easy to spot when the proxy servers have problems.

image

jirimoravcik commented 4 months ago

Can you please tell me on which version did you start seeing problems?

proxy-chain is easy to set up.

yes, it is. but you can set it up in many ways, that's why I'm asking for minimal code from your side to reproduce this issue.

The peaks in npm download graph actually started and ended in times where there were no package releases, so I highly doubt it has any correlation with the health of the package 😉

Thank you

meotimdihia commented 4 months ago

Can you please tell me on which version did you start seeing problems?

I don't sure but I guess it is ^2.3.0 or ^2.4.0. I updated the nodejs version since that time too. Currently, I am using node 20.5.1

@jirimoravcik I used this code:

// @ts-nocheck
const ProxyChain = require("proxy-chain")

const server = new ProxyChain.Server({
  // Port where the server will listen. By default 8000.
  port: 8000,

  // Enables verbose logging
  verbose: true,

  // Custom user-defined function to authenticate incoming proxy requests,
  // and optionally provide the URL to chained upstream proxy.
  // The function must return an object (or promise resolving to the object) with the following signature:
  // { requestAuthentication: Boolean, upstreamProxyUrl: String }
  // If the function is not defined or is null, the server runs in simple mode.
  // Note that the function takes a single argument with the following properties:
  // * request      - An instance of http.IncomingMessage class with information about the client request
  //                  (which is either HTTP CONNECT for SSL protocol, or other HTTP request)
  // * username     - Username parsed from the Proxy-Authorization header. Might be empty string.
  // * password     - Password parsed from the Proxy-Authorization header. Might be empty string.
  // * hostname     - Hostname of the target server
  // * port         - Port of the target server
  // * isHttp       - If true, this is a HTTP request, otherwise it's a HTTP CONNECT tunnel for SSL
  //                  or other protocols
  // * connectionId - Unique ID of the HTTP connection. It can be used to obtain traffic statistics.
  prepareRequestFunction: ({
    request,
    username,
    password,
    hostname,
    port,
    isHttp,
    connectionId
  }) => {
    return {
      // Sets up an upstream HTTP proxy to which all the requests are forwarded.
      // If null, the proxy works in direct mode, i.e. the connection is forwarded directly
      // to the target server. This field is ignored if "requestAuthentication" is true.
      // The username and password must be URI-encoded.
      upstreamProxyUrl: `http://[user]:[password]@p.webshare.io`,

      // If "requestAuthentication" is true, you can use the following property
      // to define a custom error message to return to the client instead of the default "Proxy credentials required"
      failMsg: "Bad username or password, please try again."
    }
  }
})

server.listen(() => {
  console.log(`Proxy server is listening on port ${server.port}`)
})

// Emitted when HTTP connection is closed
server.on("connectionClosed", ({ connectionId, stats }) => {
  console.log(`Connection ${connectionId} closed`)
  console.dir(stats)
})

// Emitted when HTTP request fails
server.on("requestFailed", ({ request, error }) => {
  console.log(`Request ${request.url} failed`)
  console.error(error)
})