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

Is there a way to limit or actively close connections? #212

Open
mayli opened this issue Apr 3, 2021 · 7 comments
Open

Is there a way to limit or actively close connections? #212

mayli opened this issue Apr 3, 2021 · 7 comments

Comments

@mayli
Copy link

mayli commented Apr 3, 2021

bjoern seems to keep the connection alive as long as possible and doesn't have a limitation of how many connections to keep. And I didn't find a way to disable, control or limit the keep-alive behavior (without editing and recompile the code)
image

It become an issue when there are tons of clients trying keeping the connection alive, since that's the default behavior, but it's a burden to the server since most connection are just idling.

@jonashaag
Copy link
Owner

Can you tell a bit more about your use case? Also I’m curious, what kind of memory footprint does the server have with that number of connections?

@mayli
Copy link
Author

mayli commented Apr 3, 2021

Can you tell a bit more about your use case? Also I’m curious, what kind of memory footprint does the server have with that number of connections?

There memory usage of the program itself didn't increase significantly, it stays almost constant. However the os is having issues when maintaining large amount of established connections. Some sysctl tuning helps but still it's helpful to have an option to close the connection from the server side.

The use case is a rss feed server, there are lots of RSS clients fetching every 30 minutes and their default behavior is to keep the connection alive.

@jonashaag
Copy link
Owner

Interesting! You can explicitly remove the Content-Length header from the WSGI response which will force bjoern to terminate the connection after the response.

I’m open to other suggestions though. How do other servers deal with this?

@mayli
Copy link
Author

mayli commented Apr 4, 2021

I've tried the wsgi server from gevent, unicorn and meinheld, they don't really have a proper way to handle it as well. How to remove the content-length header, I didn't set it and the only header I set is the content-type.

The only server that seems support this is hypercorn in the DOS/Inactive connection section
https://pgjones.gitlab.io/hypercorn/discussion/dos_mitigations.html

Other frameworks I've tried seems doesn't inject the connection: keep-alive header, so a connection: close in
Header will help if the client side is cooperative.
Without changing the wsgi framework code, I had to use nginx in front of wsgi server to mitigate this connection issue.

@mayli
Copy link
Author

mayli commented Apr 13, 2021

After few days of debugging the issue is some client keeps the connection open after sending the requests, and they they idling for a long time.
On the server side, bjoern (including other basic wsgi servers) didn't implement keepalive_timeout, or limit the number of requests that can be handled by a single connection. This is easily become a DDOS factor for use cases as feed server, and it would be cool if we can have a sane default value in the wsgi server itself, such 75s.

@jonashaag
Copy link
Owner

Yes, it definitely makes sense to fix this somehow. Did you try to set Keep-Alive: timeout/max headers? Maybe clients will terminate their connection after 30 seconds if you set Keep-Alive: timeout=30? Otherwise we need to implement a timeout on the server side, or you can simply put an nginx reverse proxy in front of bjoern and configure the timeout there.

@mayli
Copy link
Author

mayli commented Apr 16, 2021

That's what I did for now, it still nice to have it as part of the wsgi server itself, since it's an easy target of DDOS abuse. The gevent.pywsgi server has the same limitation but it's much easier to fix in python than C. I could try add that header, but some buggy clients choose to just ignore that.

import sys
import gevent.socket
def conn():
    sock = gevent.socket.create_connection(('127.0.0.1', sys.argv[1]))
    sock.recv(1024)
gevent.joinall([gevent.spawn(conn) for i in range(1000)])

Most unpatched wsgi server will stuck forever listening and keep those established connections forever :(

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