Project

General

Profile

[Solved] Websocket timeout on idle

Added by trevellete about 2 months ago

Lighttpd v 1.4.53
Tried to update to last version, but is the last version on raspberry pi

I have a raspberry with pihole who uses lighttp.

There is another webapp (traccar) in a different port on same raspberry who uses websockets

After days of search ( I am by no means expert at all in linux or networks whatsoever ) I success to install certificates and make a proxy connection with lighttpd from internet on port:443 to the internal app on port 8082

I had problem with websockets not working through the lighttp proxy (mod_proxy) and I solve it with

proxy.header = ( "upgrade" => "enable" )

The problem I have now is that the websocket connection timeout after 1 minute and drops,

I understand that this can be solved increasing the value of

server.max-read-idle = 60 to a higher number like 600, but after that it timesout again, I could increase it even further but I think that this is not the proper solution

I believe in my ignorance that the solution might be something regarding wstunnel and addind a wstunnel.ping-interval in order to keep alive the connection but it's not working

I believe that the websocket connection is going through proxy.server instead of going through wstunnel but I am totally stuck now.

This is my config:

$HTTP["host"] == "mysite.com" {    
    $SERVER["socket"] == ":80" {
        url.access-deny = ( "" )
    }    

    $SERVER["socket"] == ":443" {
        url.access-deny = ( "" )
    }    

    # Enable the SSL engine with a LE cert, only for this specific host
    $SERVER["socket"] == ":8444" {
        ssl.engine = "enable" 
        ssl.pemfile = "/etc/letsencrypt/live/mysite.com/web.pem" 
        ssl.ca-file =  "/etc/letsencrypt/live/mysite.com/fullchain.pem" 
        ssl.honor-cipher-order = "enable" 
        ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4" 
        ssl.dh-file = "/etc/ssl/certs/dhparam.pem" 
        ssl.ec-curve = "secp384r1" 

        $HTTP["url"] =~ "^/api/socket" {
            wstunnel.server = ( "" => ( ( "host" => "127.0.0.1", "port" => "8082" ) ) )
            wstunnel.ping-interval = 5
        }

        #setenv.add-request-header   = ( "Connection" => "Upgrade")
        #setenv.add-response-header  = ( "Connection" => "Upgrade")
        proxy.header = ("upgrade" => "enable",
                    "map-host-request" => ( "-" => "127.0.0.1:8082"),
                    "map-host-response" => ("-" => "-"))

        proxy.server  = ( "" => ( "" => ( "host" => "127.0.0.1", "port" => 8082 )))
    }
}


Replies (5)

RE: Websocket timeout on iddle - Added by gstrauss about 2 months ago

Lighttpd v 1.4.53
Tried to update to last version, but is the last version on raspberry pi

Later versions of lighttpd are available on raspberry pi.
https://pimylifeup.com/upgrade-raspberry-pi-os-bullseye/

After days of search

I hope that you found answers on this site, in the lighttpd wiki documentation, e.g. lighttpd mod_proxy

lighttpd TLS docs warn that $SERVER["socket"] inside other lighttpd.conf conditions (e.g. $HTTP["host"]) might not behave as desired. $SERVER["socket"] should be in the global scope, not nested inside other lighttpd.conf conditions.

If you want mysite.com to exist only on port 8444, then:

$SERVER["socket"] == ":8444" {
  $HTTP["host"] == "mysite.com" {
    ...
  }
}

I believe that the websocket connection is going through proxy.server instead of going through wstunnel but I am totally stuck now.

module order matters in server.modules. Try listing "mod_wstunnel" before "mod_proxy" in the server.modules = ( ... ) list in lighttpd.conf for mod_wstunnel to handle /api/socket before mod_proxy.

While I am not familiar with traccar, a quick look at their website suggests that you should not be using mod_wstunnel, since traccar natively supports websockets at /api/socket. (Using mod_wstunnel appears incorrect in this case since mod_wstunnel terminates the websocket connection and delivers the payload (JSON) to the backend, where traccar will be expecting the websockets for requests to /api/socket, not JSON.)

I understand that this can be solved increasing the value of server.max-read-idle = 60 to a higher number like 600, but after that it times out again, I could increase it even further but I think that this is not the proper solution

Why not? If the client is not sending pings and the backend server (traccar) is not sending pings, why shouldn't lighttpd close the connection after timeouts? That is what the timeouts are for. (server.max-read-idle and server.max-write-idle)

$SERVER["socket"] == ":8444" {
  $HTTP["host"] == "mysite.com" {
    server.max-read-idle = 28800   # 8 hours
    server.max-write-idle = 28800  # 8 hours
  }
}

RE: [Solved] Websocket timeout on idle - Added by trevellete about 2 months ago

Appreciate a lot your help, I made the changes in conf according to your advice, and I am going to try to update lighttpd now.

The solution of increasing the `server.max-read-idle` appeared wrong to me because one thing I forgot to mention in my first message.
Until timeout, traccar server is sending information to the web page of the client every few seconds ( I guess through lighttpd), showing updates in positions, I guess that they are send through the websocket connection, that's why I thought that these updates should count as sending pings to the client and somehow reset the timeout counting.
Once again thanks a lot for your help and congratulations for the great piece of software.

RE: [Solved] Websocket timeout on idle - Added by trevellete about 2 months ago

I tried the structure that you advised me to:

```
$SERVER["socket"] ":8444" {
$HTTP["host"] "mysite.com" {
...
}
}
```
But the website does not work, it only works the other way around

RE: [Solved] Websocket timeout on idle - Added by gstrauss about 2 months ago

I tried the structure that you advised me to:
```
But the website does not work, it only works the other way around

There must be another part of your lighttpd.conf (which you did not share) that is causing this.
You should review the output of lighttpd -f /etc/lighttpd/lighttpd.conf -p which prints your complete lighttpd.conf config.

RE: [Solved] Websocket timeout on idle - Added by trevellete about 2 months ago

You are right.
Pihole install lighttpd and modifies the hole lighttpd.conf and creates and external.conf that user can modify,with

  1. Add user chosen options held in external file
  2. This uses include_shell instead of an include wildcard for compatibility
    include_shell "cat external.conf 2>/dev/null"

It is done because when pihole updates, rewrites the hole lighttpd config again so as not to lose the user config.
I will review it.
Thanks once again

    (1-5/5)