Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

404 on client handshake #1343

Closed
summerwollin opened this issue Mar 30, 2018 · 16 comments
Closed

404 on client handshake #1343

summerwollin opened this issue Mar 30, 2018 · 16 comments

Comments

@summerwollin
Copy link

  • [ x] I've searched for any related issues and avoided creating a duplicate issue.

Similar to #1208

Description

I am getting this 404 response on the initial handshake and it is causing the error handler to trigger and close the socket.

Error: Unexpected server response: 404
    at ClientRequest.req.on (/Users/swollin/socket-proxy/node_modules/ws/lib/websocket.js:540:5)
    at emitOne (events.js:96:13)
    at ClientRequest.emit (events.js:191:7)
    at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:522:21)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
    at TLSSocket.socketOnData (_http_client.js:411:20)
    at emitOne (events.js:96:13)
    at TLSSocket.emit (events.js:191:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at TLSSocket.Readable.push (_stream_readable.js:134:10)

I only have this issue on version 5.1.0 of ws. Downgrading back to 5.0.0 solved the issue and I no longer receive a 404. Were there breaking changes in the 5.1.0 release?

Reproducible in:

version: 5.1.0
Node.js version(s): 7.7.2
OS version(s): OSX 10.12.4

@lpinca
Copy link
Member

lpinca commented Mar 30, 2018

Node.js v7.x is no longer supported, does the same happen with a supported release line (v4.x, v6.x, v8.x, v9.x)?

It can be this commit 9e152f9 but no breaking changes were expected.

@summerwollin
Copy link
Author

Just tried on v9.10.1, still having the same issue on 5.1.0 but not on 5.0.0.

@lpinca
Copy link
Member

lpinca commented Mar 30, 2018

Are you able to create a reproducible test case so that we can take a look?

@lpinca
Copy link
Member

lpinca commented Apr 2, 2018

@summerwollin can you try with 5.1.1?

@summerwollin
Copy link
Author

summerwollin commented Apr 2, 2018

Yes same issue on 5.1.1. I can try to give you a test case, but I have to modify what I have since it is code my company owns. I am using ws as a proxy between our clients (browser sessions) and our server. Given the following chunk of code that 404 is logged by wsClient.on('error':

const wss = new WebSocket.Server({port: 8080})

wss.on('connection', function (ws, request) {
  const wsClient = new WebSocket('wss://backendserver/example')

  ws.on('message', function (message) {
    const trySend = () => {
      if (wsClient.readyState === WebSocket.OPEN) {
        wsClient.send(message)
      } else {
        setTimeout(() => {
          trySend()
        }, 3000)
      }
    }
    trySend()
  })

  wsClient.on('error', function (err) {
    console.log('wsClient error', err)
  })

  wsClient.on('close', function () {
    console.log('wsClient closed')
  })

  wsClient.on('message', (message) => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(message)
    } else {
      wsClient.terminate()
    }
  })
})

The 404 appears to occur during the initial handshake and results in the wsClient closing with code 1006 (abnormal closure). I end up looping in trySend, and yes I know there could be better retry logic here but the point still stands that on 5.1.0 AND 5.1.1 but not 5.0.0 I get this 404 that causes the socket to close. For now I will just lock my proxy to 5.0.0. Let me know if you have more questions or if there is anything else I can clarify, and I appreciate your help!

@lpinca
Copy link
Member

lpinca commented Apr 2, 2018

Can you try running the following code to connect to your backend server? This is basically what ws does under the hood:

const crypto = require('crypto');
const https = require('https');
const tls = require('tls');

const request = https.get({
  headers: {
    'Sec-WebSocket-Key': crypto.randomBytes(16).toString('base64'),
    'Sec-WebSocket-Version': 13,
    'Connection': 'Upgrade',
    'Upgrade': 'websocket'
  },
  createConnection: tls.connect,
  hostname: 'replace',
  path: '/replace',
  port: 'replace'
});

request.on('upgrade', function () {
  console.log('It works.');
});

Does your backend server uses SNI or some special configuration?

@summerwollin
Copy link
Author

Running the above returns an error: Error: getaddrinfo ENOTFOUND which seems likely to be the same 404 from earlier. We use a wildcard cert so SNI is not necessary, and we do not support TLS 1.0 or 1.1, or SSL v2. Are you using TLS 1.2 or better? I don't see how to tell which version that npm package is using.

@summerwollin
Copy link
Author

Actually turns out we do support TLS 1.0 and 1.1. Sorry for the confusion, my IT guy just checked and updated me.

@lpinca
Copy link
Member

lpinca commented Apr 2, 2018

The above snippet only uses core modules, no npm packages. ENOTFOUND is a dns error, make sure to use the correct hostname, path, and port.

@lpinca
Copy link
Member

lpinca commented Apr 4, 2018

@summerwollin sorry to pester, any update? I guess the server is not publicly accessible. Can you somehow allow me to debug this issue?

@summerwollin
Copy link
Author

Yes sorry - it's been a busy week here at work. Running the above exactly as written using the core modules returns:

err { Error: write EPROTO 140736440177600:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:../deps/openssl/openssl/ssl/s23_clnt.c:794:

    at exports._errnoException (util.js:1033:11)
    at WriteWrap.afterWrite [as oncomplete] (net.js:816:14) code: 'EPROTO', errno: 'EPROTO', syscall: 'write' }

On 5.0.0, 5.1.0, and 5.1.1. Hostname, path, and port are all identical to what I'm connecting to in my proxy on 5.0.0.

@lpinca
Copy link
Member

lpinca commented Apr 5, 2018

Ok we are getting closer, does it work if you remove the createConnection: tls.connect, from the options object in the above example?

@summerwollin
Copy link
Author

No, same error

@lpinca
Copy link
Member

lpinca commented Apr 5, 2018

I don't know then, if the above snippet does not work I can't see how ws@5.0.0 does. Unfortunately I can't help much if I can't debug myself.

@lpinca
Copy link
Member

lpinca commented Apr 10, 2018

Closing this as it's hard to fix without a reproducible test case. I know you have one but unfortunately it can't be shared.

@lpinca lpinca closed this as completed Apr 10, 2018
@summerwollin
Copy link
Author

Fair, whenever I have time I'll try to figure out the issue. Thanks for looking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants