Project

General

Profile

[OT] Secure Websocket with proxy - connection closed

Added by barsum 11 days ago

I'm having trouble using lighttpd as proxy for secure websocket. I'm not too confident with SSL nor lighttpd so I really don't know where to look for the error. Please advice.

My setup:

I have a backend running HTTP and websocket on port 9000.

I've installed lighttpd with mod_proxy in front of my server for handling SSL and forwarding all traffic to the backend. Ordinary https works fine!

But wss:// doesn't work. It seems the connection is closed as soon as it is established. Apparently the backend server is unaware of this, as it keeps trying to send messages to the client.

(If I access the backend directly on port 9000 both http and ws works as expected)

When testing in Chrome, I don't get any error messages. Actually, it's doesn't even tell that the connection is closed. Using Postman I get a '1006 abnormal closure'

https is working fine, so I reckon that SSL is installed correctly.

Version: lighttpd/1.4.59

lighttpd.conf:

server.modules = (
        "mod_indexfile",
        "mod_access",
        "mod_alias",
        "mod_redirect",
        "mod_proxy",
        "mod_accesslog",
        "mod_openssl" 
)

server.document-root        = "/var/www/html" 
server.upload-dirs          = ( "/var/cache/lighttpd/uploads" )
server.errorlog             = "/var/log/lighttpd/error.log" 
server.pid-file             = "/run/lighttpd.pid" 
server.username             = "www-data" 
server.groupname            = "www-data" 
server.port                 = 80

debug.log-request-handling = "enable" 
debug.log-ssl-noise = "enable" 

# redirect all http to https
$HTTP["scheme"] == "http" {
  url.redirect = ("" => "https://${url.authority}${url.path}${qsa}")
}

# setup ssl/tsl
$SERVER["socket"] == "xxxxxxxx.com:443" {
  ssl.engine = "enable" 
  ssl.pemfile = "/etc/lighttpd/ssl/www_xxxxxxxx_com.pem" 
  ssl.ca-file = "/etc/lighttpd/ssl/USERTrust_RSA_Certification_Authority.crt" 
  server.name = "xxxxxxxx.com" 
  server.errorlog = "/var/log/lighttpd/www_xxxxxx_com/serror.log" 
  accesslog.filename = "/var/log/lighttpd/www_xxxxxx_com/saccess.log" 
}

# proxy everything to backend except phpmyadmin
$HTTP["url"] !~ "^/phpmyadmin" {
  proxy.server  = ( "" => ( # proxy all file extensions / prefixes
    "" => # optional label to identify requests in logs
      ( "host" => "localhost",
        "port" => 9000
      )
    )
  )
  proxy.header = ( "upgrade" => "enable" )
}

# strict parsing and normalization of URL for consistency and security
# https://redmine.lighttpd.net/projects/lighttpd/wiki/Server_http-parseoptsDetails
# (might need to explicitly set "url-path-2f-decode" = "disable" 
#  if a specific application is encoding URLs inside url-path)
server.http-parseopts = (
  "header-strict"           => "enable",# default
  "host-strict"             => "enable",# default
  "host-normalize"          => "enable",# default
  "url-normalize-unreserved"=> "enable",# recommended highly
  "url-normalize-required"  => "enable",# recommended
  "url-ctrls-reject"        => "enable",# recommended
  "url-path-2f-decode"      => "enable",# recommended highly (unless breaks app)
 #"url-path-2f-reject"      => "enable",
  "url-path-dotseg-remove"  => "enable",# recommended highly (unless breaks app)
 #"url-path-dotseg-reject"  => "enable",
 #"url-query-20-plus"       => "enable",# consistency in query string
)

index-file.names            = ( "index.php", "index.html" )
url.access-deny             = ( "~", ".inc" )
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

deflate.cache-dir          = "/var/cache/lighttpd/compress/" 
#deflate.filetype           = ( "application/javascript", "text/css", "text/html", "text/plain" )

# default listening port for IPv6 falls back to the IPv4 port
## Use ipv6 if available
#include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
include_shell "/usr/share/lighttpd/create-mime.conf.pl" 
include "/etc/lighttpd/conf-enabled/*.conf" 

#server.compat-module-load   = "disable" 
server.modules += (
        "mod_deflate",
        "mod_dirlisting",
        "mod_staticfile",
)

I've attached two screenshots from Chrome and Postman that show that the connections is established. But Postman also reveals that the connection is closed with an error.

https://imgur.com/a/dK3ADdt

Here is a bit of output from serror.log

2021-07-12 10:12:33: mod_access.c.139) -- mod_access_uri_handler called
2021-07-12 10:12:33: gw_backend.c.2571) handling it in mod_gw
2021-07-12 10:12:33: response.c.519) -- before doc_root
2021-07-12 10:12:33: response.c.521) Doc-Root     : /var/www/html
2021-07-12 10:12:33: response.c.523) Rel-Path     : /chart/245
2021-07-12 10:12:33: response.c.525) Path         : /var/www/html/assets/js/jstree/jstree.min.js
2021-07-12 10:12:33: response.c.558) -- after doc_root
2021-07-12 10:12:33: response.c.560) Doc-Root     : /var/www/html
2021-07-12 10:12:33: response.c.562) Rel-Path     : /chart/245
2021-07-12 10:12:33: response.c.564) Path         : /var/www/html/chart/245
2021-07-12 10:12:33: response.c.579) -- logical -> physical
2021-07-12 10:12:33: response.c.581) Doc-Root     : /var/www/html
2021-07-12 10:12:33: response.c.583) Basedir      : /var/www/html
2021-07-12 10:12:33: response.c.585) Rel-Path     : /chart/245
2021-07-12 10:12:33: response.c.587) Path         : /var/www/html/chart/245
2021-07-12 10:12:33: response.c.398) -- parsed Request-URI
2021-07-12 10:12:33: response.c.400) Request-URI     : /ws
2021-07-12 10:12:33: response.c.402) URI-scheme      : https
2021-07-12 10:12:33: response.c.404) URI-authority   : xxxxxxx.com
2021-07-12 10:12:33: response.c.406) URI-path (clean): /ws
2021-07-12 10:12:33: response.c.408) URI-query       :
2021-07-12 10:12:33: mod_access.c.139) -- mod_access_uri_handler called
2021-07-12 10:12:33: gw_backend.c.2571) handling it in mod_gw
2021-07-12 10:12:33: response.c.519) -- before doc_root
2021-07-12 10:12:33: response.c.521) Doc-Root     : /var/www/html
2021-07-12 10:12:33: response.c.523) Rel-Path     : /ws
2021-07-12 10:12:33: response.c.525) Path         : /var/www/html/ws
2021-07-12 10:12:33: response.c.558) -- after doc_root
2021-07-12 10:12:33: response.c.560) Doc-Root     : /var/www/html
2021-07-12 10:12:33: response.c.562) Rel-Path     : /ws
2021-07-12 10:12:33: response.c.564) Path         : /var/www/html/ws
2021-07-12 10:12:33: response.c.579) -- logical -> physical
2021-07-12 10:12:33: response.c.581) Doc-Root     : /var/www/html
2021-07-12 10:12:33: response.c.583) Basedir      : /var/www/html
2021-07-12 10:12:33: response.c.585) Rel-Path     : /ws
2021-07-12 10:12:33: response.c.587) Path         : /var/www/html/ws

Replies (14)

RE: Secure Websocket with proxy - connection closed - Added by gstrauss 11 days ago

Try adding proxy.debug = 2 for info about how lighttpd is creating the backend connection.

Please print and review your entire lighttpd config: lighttpd -f /etc/lighttpd/lighttpd.conf -p

RE: Secure Websocket with proxy - connection closed - Added by barsum 11 days ago

First of all, thanks for your fast reply. So frustrating to be stuck ;)

Be aware that I'm not very experienced in SSL, so the answer may be obvious.

I've added proxy.debug = 2 to config

Here is a snippet from serror.log that I believe is relevant to websocket

.
.
2021-07-12 16:42:55: response.c.587) Path         : /var/www/html/chart/9886
2021-07-12 16:42:55: gw_backend.c.228) got proc: pid: 0 socket: tcp:127.0.0.1:9000 load: 1
2021-07-12 16:42:55: gw_backend.c.303) released proc: pid: 0 socket: tcp:127.0.0.1:9000 load: 0
2021-07-12 16:42:55: response.c.398) -- parsed Request-URI
2021-07-12 16:42:55: response.c.400) Request-URI     : /ws
2021-07-12 16:42:55: response.c.402) URI-scheme      : https
2021-07-12 16:42:55: response.c.404) URI-authority   : xxxx.com
2021-07-12 16:42:55: response.c.406) URI-path (clean): /ws
2021-07-12 16:42:55: response.c.408) URI-query       :
2021-07-12 16:42:55: mod_access.c.139) -- mod_access_uri_handler called
2021-07-12 16:42:55: gw_backend.c.944) gw - found a host 127.0.0.1 9000
2021-07-12 16:42:55: gw_backend.c.2571) handling it in mod_gw
2021-07-12 16:42:55: response.c.519) -- before doc_root
2021-07-12 16:42:55: response.c.521) Doc-Root     : /var/www/html
2021-07-12 16:42:55: response.c.523) Rel-Path     : /ws
2021-07-12 16:42:55: response.c.525) Path         : /var/www/html/
2021-07-12 16:42:55: response.c.558) -- after doc_root
2021-07-12 16:42:55: response.c.560) Doc-Root     : /var/www/html
2021-07-12 16:42:55: response.c.562) Rel-Path     : /ws
2021-07-12 16:42:55: response.c.564) Path         : /var/www/html/ws
2021-07-12 16:42:55: response.c.579) -- logical -> physical
2021-07-12 16:42:55: response.c.581) Doc-Root     : /var/www/html
2021-07-12 16:42:55: response.c.583) Basedir      : /var/www/html
2021-07-12 16:42:55: response.c.585) Rel-Path     : /ws
2021-07-12 16:42:55: response.c.587) Path         : /var/www/html/ws
2021-07-12 16:42:55: gw_backend.c.228) got proc: pid: 0 socket: tcp:127.0.0.1:9000 load: 1
2021-07-12 16:42:55: gw_backend.c.303) released proc: pid: 0 socket: tcp:127.0.0.1:9000 load: 0
2021-07-12 16:49:11: response.c.398) -- parsed Request-URI
.
.

I'm not sure how to interpret this. If ws is being forwarded to /var/www/html/ws instead of localhost:9000 it's quite obvious why it's broken? If so, how to fix?

I've attached output from lighttpd -f. I can't really find anything suspicious.

RE: Secure Websocket with proxy - connection closed - Added by gstrauss 11 days ago

2021-07-12 16:42:55: gw_backend.c.228) got proc: pid: 0 socket: tcp:127.0.0.1:9000 load: 1
2021-07-12 16:42:55: gw_backend.c.303) released proc: pid: 0 socket: tcp:127.0.0.1:9000 load: 0

That does not indicate any error. got proc: ... indicates that lighttpd successfully connected to a backend instance. You probably should look at the logging from your backend to see if it rejected a request to "/ws".
If the debug information is not sufficient, you can (temporarily) run lighttpd under strace -s 2048 to see if lighttpd what lighttpd is sending and receiving from the backend.

Your lighttpd config is forwarding the request to the backend without modification, so something like

GET /ws HTTP/1.1
Host: xxxxxxxx.com
Connection: upgrade
Upgrade: websocket

If you need to change the url-path sent to the backend, see mod_proxy proxy.header "map-urlpath",
in addition to proxy.header = ( "upgrade" => "enable" )

RE: Secure Websocket with proxy - connection closed - Added by barsum 11 days ago

I'm struggling, but I can't figure out what's wrong.

Shouldn't it be transparent to the backend that lighttpd is in front converting wss to ws? If so, how can the problem be in the backend? Considering that ws directly works like a charm?

Here is the output I got from strace. Hopefully, it makes some sense to you?

Request made via Postman

write(7, "2021-07-12 21:50:20: response.c.581) Doc-Root     : /var/www/html\n", 66) = 66
write(7, "2021-07-12 21:50:20: response.c.583) Basedir      : /var/www/html\n", 66) = 66
write(7, "2021-07-12 21:50:20: response.c.585) Rel-Path     : /ws\n", 56) = 56
write(7, "2021-07-12 21:50:20: response.c.587) Path         : /var/www/html/ws\n", 69) = 69
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 11
connect(11, {sa_family=AF_INET, sin_port=htons(9000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
epoll_ctl(9, EPOLL_CTL_ADD, 11, {EPOLLOUT|EPOLLERR|EPOLLHUP, {u32=2744007920, u64=94500614454512}}) = 0
epoll_ctl(9, EPOLL_CTL_MOD, 10, {EPOLLERR|EPOLLHUP|EPOLLRDHUP, {u32=2744013360, u64=94500614459952}}) = 0
epoll_wait(9, [{EPOLLOUT, {u32=2744007920, u64=94500614454512}}], 1025, 1000) = 1
getsockopt(11, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
write(7, "2021-07-12 21:50:20: gw_backend.c.228) got proc: pid: 0 socket: tcp:127.0.0.1:9000 load: 1\n", 91) = 91
epoll_ctl(9, EPOLL_CTL_MOD, 11, {EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP|EPOLLRDHUP, {u32=2744007920, u64=94500614454512}}) = 0
writev(11, [{iov_base="GET /ws HTTP/1.1\r\nHost: xxxxxx.com\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: koftJbL6H4ZdZdtNGA5SXA==\r\nUpgrade: websocket\r\nSec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\nX-Forwarded-For: 188.178.182.98\r\nX-Host: xxxxxx.com\r\nX-Forwarded-Host: xxxxxx.com\r\nX-Forwarded-Proto: https\r\nConnection: close, upgrade\r\n\r\n", iov_len=361}], 1) = 361
epoll_ctl(9, EPOLL_CTL_MOD, 11, {EPOLLIN|EPOLLERR|EPOLLHUP|EPOLLRDHUP, {u32=2744007920, u64=94500614454512}}) = 0
epoll_wait(9, [{EPOLLIN, {u32=2744007920, u64=94500614454512}}], 1025, 1000) = 1
ioctl(11, FIONREAD, [164])              = 0
read(11, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nSec-WebSocket-Accept: NO7b1/d3466VZHdKA6XlIk6teHM=\r\nDate: Mon, 12 Jul 2021 19:50:20 GMT\r\nConnection: close\r\n\r\n", 8191) = 164
setsockopt(11, SOL_TCP, TCP_NODELAY, [1], 4) = 0
read(10, 0x55f2a38dbd03, 5)             = -1 EAGAIN (Resource temporarily unavailable)
write(10, "\27\3\3\0\320t\365F\355RR\223d\257Q\250\341A\2418T?\342V\323\301\350V\251xVl\2sK=0\313W\224un\215\2\311\315-\3U\363$,\10\205Y\314\244\36\206\7\312\314\232\273%3D\237o\3465\351\356\276I\220\3429\254\312:d9\31\365\"%=\311\37\374\262\2172/\3109V9X\325\266\276\325\31so\333\342V&\360\206S\306;\316\10\260\202\257\213e\260I\264\302\274\224c\1\376iR\360\341\10\220\276\34\2603]Q\374\255\277\221\263\323\20\361\252\206z\331j\1b.\234\331\365\2\373\264d\\\33:\232\2475\357\362\321\t\353\250XN\330\245\0363$\371\5\2060\325\362\33R\1R\231q/\376\203$\363\275\26\0355\326z\306\350\243\0", 213) = 213
epoll_ctl(9, EPOLL_CTL_MOD, 10, {EPOLLIN|EPOLLERR|EPOLLHUP|EPOLLRDHUP, {u32=2744013360, u64=94500614459952}}) = 0
epoll_wait(9, [{EPOLLIN|EPOLLRDHUP, {u32=2744007920, u64=94500614454512}}], 1025, 1000) = 1
ioctl(11, FIONREAD, [0])                = 0
read(11, "", 8191)                      = 0
epoll_ctl(9, EPOLL_CTL_DEL, 11, NULL)   = 0
write(7, "2021-07-12 21:50:20: gw_backend.c.303) released proc: pid: 0 socket: tcp:127.0.0.1:9000 load: 0\n", 96) = 96
close(11)                               = 0
write(8, "188.178.182.98 xxxxxx.com - [12/Jul/2021:21:50:20 +0200] \"GET /ws HTTP/1.1\" 101 0 \"-\" \"-\"\n", 98) = 98
write(10, "\27\3\3\0\23:q\27\263\307\fej\345\367N\231\16qp\v\272\243\32", 24) = 24
read(10, 0x55f2a39a48a3, 5)             = -1 EAGAIN (Resource temporarily unavailable)
read(10, 0x55f2a39a48a3, 5)             = -1 EAGAIN (Resource temporarily unavailable)
epoll_wait(9, [{EPOLLIN|EPOLLRDHUP, {u32=2744013360, u64=94500614459952}}], 1025, 1000) = 1
read(10, "", 5)                         = 0
epoll_ctl(9, EPOLL_CTL_DEL, 10, NULL)   = 0
close(10)                               = 0
epoll_wait(9, [], 1025, 1000)           = 0
wait4(195206, 0x7ffe2cedfc74, WNOHANG, NULL) = 0

Gstrauss: If it can help. You're very welcome to try yourself against my server. Just send me a pm on bobvivius (at) gmail.com and I'll mail you the address.

RE: Secure Websocket with proxy - connection closed - Added by gstrauss 11 days ago

I'm struggling, but I can't figure out what's wrong.

Let's start with probabilities. lighttpd works with websockets. There is a high probability that something is wrong with your backend configuration.

From the strace, I see that lighttpd connects to the backend and forwards the request

GET /ws HTTP/1.1
Host: xxxxxx.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: koftJbL6H4ZdZdtNGA5SXA==
Upgrade: websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
X-Forwarded-For: 188.178.182.98
X-Host: xxxxxx.com
X-Forwarded-Host: xxxxxx.com
X-Forwarded-Proto: https
Connection: close, upgrade

The backend responds

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Sec-WebSocket-Accept: NO7b1/d3466VZHdKA6XlIk6teHM=
Date: Mon, 12 Jul 2021 19:50:20 GMT
Connection: close

which lighttpd forwards back to the client (over the encrypted TLS connection, so you can't read that in clear text unless you use debug.log-request-header = "enable" and debug.log-response-header = "enable")

Then, I see that lighttpd reads EOF from the backend (reading 0 bytes), indicating that the backend has closed the connection.

If I have not been abundantly clear: LOOK AT THE LOGS FROM YOUR BACKEND. Your backend is closing the connection and you need to find out why your backend is closing the connection after it has upgraded to use the websocket protocol.

Everything you have presented suggests lighttpd is behaving properly and that your backend is the source of your issue. If you connect directly to your backend, you say that it works. Therefore, you need to figure out what the difference is between what you send to lighttpd and what lighttpd sends to the backend, compared to what you send to the backend directly from your client. If you connect directly to your backend, are you sending the request GET /ws HTTP/1.1 or are you sending something else?

Once you understand this, please re-read my prior comments to look for the error in your backend configuration. Your problem is unlikely to be caused by lighttpd and unlikely to be related to TLS terminated by lighttpd. You may need to configure lighttpd to remap the request to make your backend happy, but there is no way for lighttpd to know what your backend needs. lighttpd forwards to the backend the request that lighttpd receives from the client unless you configure lighttpd to do otherwise.

RE: Secure Websocket with proxy - connection closed - Added by barsum 10 days ago

Thanks for your patience :) I'll give it another shot and be back.

RE: Secure Websocket with proxy - connection closed - Added by barsum 10 days ago

Hi again.

Listening to port 9000 I see a difference in what's being sent using ws and wss. But I'm not sure how to determine the cause. Hope you have an idea?

I've installed a simple websocket server just to make sure it's not my backend which is buggy.

The project I installed: [[https://github.com/alvinj/PlayFrameworkScalaWebSockets]]
As described here: [[https://alvinalexander.com/scala/play-framework-websocket-simple-example-hello-world/]]

Using Postman, if I shoot directly at the server with ws://xxxxx.com:9000/ws, the websocket answers as expected.

If I shoot at wss://server.com/ws (which in turn forwards to ws://localhost:9000/ws) then the connection is immediately terminated with an error.

The backend log shows nothing.

Using tcpflow I record what is being sent to port 9000.

Using Postman - connecting directly to ws://xxxx.com:9000/ws i get:
(Working!)

GET /ws HTTP/1.1
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: kiliUHe9b7TjqgBp5sNVJQ==
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Host: xxxxxx.com:9000

Using Postman - connecting to lighttpd wss://xxxx.com/ws i get:
(Not working!)

GET /ws HTTP/1.1
Host: xxxxxx.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: vrPH46cZiHuAHfkVS1BxGw==
Upgrade: websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
X-Forwarded-For: 213.32.242.139
X-Host: xxxxxx.com
X-Forwarded-Host: xxxxxx.com
X-Forwarded-Proto: https
Connection: close, upgrade

Notice close + upgrade - why close? Where does it come from?

Using the javascript client in the project, I see two requests:
(Not working!)

Req#1:

GET /ws HTTP/1.1
Host: xxxxx.com
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: https://xxxxx.com
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Accept-Encoding: gzip, deflate, br
Accept-Language: da-DK,da;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: PLAY_SESSION=eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7ImNzcmZUb2tlbiI6ImZmMWQzYjdhOTY2NmU5NGRmMmRhMTMwNGRmZDE0YTk2MWRhOTU5OTMtMTYyNjE1OTgyOTgwNC1mODQ3ZjZmOWRlZWYyNTNhMjIzZTA0YjgifSwibmJmIjoxNjI2MTU5ODI5LCJpYXQiOjE2MjYxNTk4Mjl9.oJuFTObNUL_DabcmuQef5VMWPmUIhsgUp1cJyAeOT8s
Sec-GPC: 1
Sec-WebSocket-Key: oVXxHxdyyI8pSXsDcG3cqg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
X-Forwarded-For: 213.32.242.139
X-Host: xxxxx.com
X-Forwarded-Host: xxxxx.com
X-Forwarded-Proto: https
Connection: close, upgrade

Again close?

Req#2:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Sec-WebSocket-Accept: btn58UoiDZ3UYtv6CyQvKLCFjSI=
Date: Tue, 13 Jul 2021 20:48:50 GMT
Connection: close

Looks a bit like this: [[https://stackoverflow.com/questions/50281155/websocket-connection-attempt-fails-returns-connection-upgrade-close]]

RE: Secure Websocket with proxy - connection closed - Added by gstrauss 10 days ago

lighttpd sends Connection: close to backends with HTTP/1.1 requests since lighttpd does not re-use the HTTP/1.1 connection. Connection: close indicates to the backend that keep-alive should be disabled on the connection.

When lighttpd requests Connection: close, upgrade, lighttpd is requesting that the connection be upgraded, but if not, that the connection be serviced as HTTP/1.1 and then closed (no keep-alive).

This is all proper behavior as defined by the HTTP/1.1 specifications: RFC 7230, RFC 7231, et al.

If your backend sends a response with Connection: upgrade and Upgrade: websocket, then the connection has been upgraded to the websocket protocol immediately following that HTTP/1.1 response. If your backend then closes the connection, that is a problem with your backend. The strace suggests that the backend is closing the connection. Continuing to ask me to debug lighttpd is illogical. Figure out why your backend is closing the connection.

lighttpd has supported websockets since lighttpd 1.4.46, released Oct 2017, over 3 1/2 years ago. It is quite improbable that this is an issue with lighttpd. It is much, much, much, much, much, much, much, much more likely that you or your backends are not following the HTTP specification, or are doing something else wrong.

RE: Secure Websocket with proxy - connection closed - Added by gstrauss 10 days ago

The following response is invalid for websocket upgrade.

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Sec-WebSocket-Accept: btn58UoiDZ3UYtv6CyQvKLCFjSI=
Date: Tue, 13 Jul 2021 20:48:50 GMT
Connection: close

Upgrade is a hop-by-hop header. Connection must contain the token upgrade -- as in Connection: upgrade -- for the recipient of the response to honor Upgrade

RE: Secure Websocket with proxy - connection closed - Added by barsum 10 days ago

Ok. Thanks! I'll consult the Play community.

N.B. Play Framework has supported WebSockets since 2009 ;)

RE: Secure Websocket with proxy - connection closed - Added by gstrauss 9 days ago

I added an example to mod_wstunnel which demonstrates that lighttpd supports WebSockets through mod_proxy and mod_wstunnel.

RE: [OT] Secure Websocket with proxy - connection closed - Added by barsum 8 days ago

Again, thanks for your extensive support. I'm still waiting for the Play community to help me avoid closing the socket upon receiving 'close'. Apparently it's not a common problem?!

I can't figure out if mod_wstunnel will help solve my problem? Would you expect the backend to behave differently, and does the websocket remain alive when tunneled?

RE: [OT] Secure Websocket with proxy - connection closed - Added by barsum 4 days ago

For anyone that comes across this thread.

To my regret, I didn't get it working. So I tried Nginx and it worked out of the box. So that ended up being my solution.

RE: [OT] Secure Websocket with proxy - connection closed - Added by gstrauss 3 days ago

Thanks for the update.

I'm still waiting for the Play community to help me avoid closing the socket upon receiving 'close'. Apparently it's not a common problem?!

Other people have lighttpd mod_proxy working to proxy back to a websocket server, though not with the specific app with which you are having trouble.

e.g. https://stackoverflow.com/questions/65862891/lighttpd-with-websocket

    (1-14/14)