36

I am using wss (secured web sockets) with spring from backend and STOMP for javascript client.

Does anyone knows why a get:

Handshake failed due to invalid Upgrade header: null
mspapant
  • 1,860
  • 1
  • 22
  • 31
  • could you give more details? spring version? your web configuration? are you using sockjs? could you copy/paste the request and response headers? – Brian Clozel Jul 04 '15 at 17:08
  • For future references, when we experienced this problem "Handshake failed", we also had an HTTP connection leak on the backend (JBoss 7.1.6 GA + Spring 5.2.7.RELEASE) that you could see by monitoring `connection-count` at `/subsystem=io/worker=default/server=/127.0.0.1:6080` in JBoss CLI. Simply applying `http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html` recommendations for "Proxying both HTTP and websockets at the same time" made both error logs and leak disappear. – Romain Buquet Sep 14 '21 at 10:29

4 Answers4

45

I met the same problem with nginx https proxy to tomcat. This is because I haven't support the wss request. To support the wss request, I use the config like below:

# WebSocketSecure SSL Endpoint
#
# The proxy is also an SSL endpoint for WSS and HTTPS connections.
# So the clients can use wss:// connections 
# (e.g. from pages served via HTTPS) which work better with broken 
# proxy servers, etc.

server {
    listen 443;

    # host name to respond to
    server_name ws.example.com;

    # your SSL configuration
    ssl on;
    ssl_certificate /etc/ssl/localcerts/ws.example.com.bundle.crt;
    ssl_certificate_key /etc/ssl/localcerts/ws.example.com.key;

    location / {
        # switch off logging
        access_log off;

        # redirect all HTTP traffic to localhost:8080
        proxy_pass http://localhost:8080;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket support (nginx 1.4)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
Jonguo
  • 681
  • 1
  • 10
  • 17
  • 3
    Looks like I am facing the same problem. Where does this configuration go? – Artyom Emelyanenko Feb 05 '18 at 06:03
  • I am facing same issue. but my URL is ws://localhost:8070/gs-guide-websocket/518/ufd3l0ca/websocket. I have added support for port 8070 for ws request. Can u plz help @Jonguo – haripcce Aug 22 '18 at 09:07
  • sorry I don't remember how to solved it, long time haven't login to stackoverflow. upgrade your nginx and tomcat, maybe it works. and now I am using golang, I haven't use tomcat. sorry – Jonguo Mar 03 '19 at 06:26
3

the following solution works for me

<VirtualHost _default_:443>
    
    ServerName my.app
    ServerAdmin admin@my.app
    DocumentRoot /var/www/html
    SSLCertificateFile ...
    SSLCertificateKeyFile ...
    SSLCertificateChainFile ...
    
    ProxyPreserveHost on
    RequestHeader set X-Forwarded-Proto https
    RequestHeader set X-Forwarded-Port 443
    
    RewriteEngine on
    RewriteCond %{HTTP:Upgrade}^websocket$ [NC,OR]
    RewriteCond %{HTTP:Connection}^upgrade$ [NC]
    RewriteRule .* wss:/127.0.0.1:8081%{REQUEST_URI} [P,QSA,L]
    RewriteCond %{REQUEST_URI} ^/api/wsendpoint/%{var1}/%{var2}/websocket [NC,OR]

    ....
    
</VirtualHost>

I hope, that helps... The solution above is part of the following link: https://forum.mattermost.org/t/solved-apache2-reverseproxy-with-websocket-https/437/3

G. Boh
  • 31
  • 3
1

this post seems closed, but I don't found an exact solution here so I will post for future needes

I resolved with reverse proxy configuration (in my case apache httpd)

at first you have to enable some mods in httpd.conf

LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule rewrite_module modules/mod_rewrite.so

then go into your virtual host configuration and use this rules

RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule /(.*) "ws://[YOUR_URL]:[YOUR_PORT]/$1" [P,L]

obviously substitute [YOUR_URL] and [YOUT_PORT] with real url and port, and substitute "ws" with "wss" if you are using secure web socket

that's all!

if you have done the right things in your server you can read the following headers

upgrade: WebSocket
connection: Upgrade
Ging3r
  • 2,010
  • 2
  • 17
  • 26
0

DefaultHandshakeHandler - "Handshake failed due to invalid Upgrade header: null"

here the URL should contain the port number

example: ws:// or wss://{baseUrl}:8080/your websocket endpoint

and use these commands on the server to enable proxy

$ sudo a2enmod proxy
$ sudo service apache2 restart
$ sudo a2enmod proxy_wstunnel
$ sudo service apache2 restart

you may read this article https://github.com/spring-projects/spring-framework/issues/16978#issuecomment-453418847