AWS EB: Error during WebSocket handshake: Unexpected response code: 400
Asked Answered
L

4

5

There is a Laravel/Vue.JS app hosted on AWS behind a Classic Load Balancer (Elastic Beanstalk) and proxied internally via Nginx down to socket.io server. SSL is terminated on the Nginx.

This is the nginx config:

location /socket.io {
    proxy_pass          http://127.0.0.1:6001;
    proxy_http_version  1.1;
    proxy_set_header    Upgrade           $http_upgrade;
    proxy_set_header    Connection        "upgrade";
    proxy_set_header    Host $host;
    proxy_set_header    X-Real-IP         $remote_addr;
    proxy_set_header    X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Proto $scheme;
}

Right now the long-polling mode works fine, but it fails to initiate an upgrade:

WebSocket connection to 'wss://example.com/socket.io/?EIO=3&transport=websocket&sid=HmDFtq-aj1WgfGUyAAAJ' failed: Error during WebSocket handshake: Unexpected response code: 400

P.S Chrome's Frames tab I can only see this weird message: (Opcode -1)

Has anybody successfully got socket.io working on an AWS Elastic Beanstalk environment? I just wasted two weeks dealing with this issue, would be very thankful for ANY suggestions or ideas. Thanks!

Update. I turned on a verbose logging and here are the variables within Nginx:

$host example.com
$proxy_add_x_forwarded_for 134.xxx.xxx.xxx
$http_upgrade -
$remote_addr 172.31.10.208
$remote_user -
$server_name _
$upstream_addr 127.0.0.1:6001
$request GET /socket.io/?EIO=3&transport=polling&t=Lw26sYn&sid=6L5iHma-GJOeE3JQAAAX HTTP/1.1
$upstream_response_time 24.658 msec
$request_time 24.658

Maybe someone will find some of these values incorrect so I would appreciate any advise.

Littles answered 14/9, 2017 at 17:43 Comment(9)
Remove proxy_set_header Host $host; and testUntie
@TarunLalwani unfortunately it doesn't work.Littles
What do you see on your 6001 socket server logs?Untie
As I understand the WSS request does not even come to nginx, it's blocked by a LoadBalancer or something...Littles
Classic ELB doesn't support websockets.Tandi
Btw did you use .ebextensions/files.config to configure the nginx?Untie
@TarunLalwani Before — yes, but now I created a custom platform based on Ubuntu and all the stuff I need. Why?Littles
@Michael-sqlbot Hmm. How and what to use then?Littles
Because from the logs I can see the request from EB is not using upgrade headers. And you need to make sure that you configure EB nginx also to do soUntie
C
11

Is your ELB using HTTP/HTTP listeners or TCP/SSL listeners? Websockets only works on the latter protocol types. Change the listener to TCP and it will work.

Alternatively, if you built your environment using CLI or API, you can also rebuild your ElasticBeanstalk App using an Application Load Balancer (ALB) instead of a Classic Load Balancer (ELB) as the ALB also supports websockets. This option is not available via the web console.

Corron answered 20/9, 2017 at 5:59 Comment(6)
Thank you, I'll try it and get back soon. I think I tried it before, but I'll try once again.Littles
Cool, it seems to be working, but still, I have 400 error from one of the instances (I have two). Does your method work with multiple instances?Littles
Yes, but on the ELB, you either need to enable sticky sessions or disable cross-zone load balancing. The aim is to ensure both HTTP and websocket requests go to the same instance. I don't have a test case setup to prove it works, but let me know if it does and I will update the answer.Corron
Sticky sessions cannot be applied to TCP/SSL layer, HTTP(S) only. And Disabling cross-zone load balancing doesn't sound to be a good solution, does't it?Littles
Should ProxyProtocol be configured additionally?Littles
Thankyou so much sir, it took me a week to solve this issue. Your answer helped a lot.Bloke
P
2

Another option is to just use the New Application balancer which does not come by default when running elasticbeanstalk

Could create a new environment with the new type or try migrating the classic balancer to Application(I made it with clean recreate)

Once create add one more Listener for port 443 HTTPS and everything worked out of the box.

Chris

Preconcerted answered 4/7, 2019 at 8:42 Comment(0)
D
0

I was facing same issue and backend was on aws elasticbeanstalk, so we set Load Balancer, to handle multiple request calls and this error was fixed. So I think you need to configure Load Balancer in amazon elastic beanstalk. Also change your ec2 instance RAM 2GB+, or t2.large

Dehart answered 7/9, 2022 at 0:1 Comment(0)
K
-1

Try switching from the Apache proxy server to Nginx in your ElasicBeanStalk "Software" configuration.

Kitchen answered 21/5, 2020 at 21:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.