Search code examples
herokuwebsocketdjango-channelsdaphne

Daphne rejects all remote requests


I have a project where I use channels and locally everything worked well but when I deployed on Heroku, I got 403 each time I tried to connect. At first I thought the problem was with Heroku as I tested it locally and even used the database and redis instance from Heroku locally and everything worked.

But then, when I used ngrok to open a public tunnel to my localhost, I discovered the result was the same as in Heroku. For every request, I get 403 and trying to debug it doesn't help much as the event loop just suddenly takes control sometimes or I get timeout error. The setup is exactly the same save that one is being accessed locally while the other is remotely. This is how I start Daphne: daphne weout.asgi:application --port 8000 --bind 0.0.0.0 -v 3.

My lib versions:

  • Django==2.0.7
  • channels==2.2.0
  • channels-redis==2.4.0
  • daphne==2.3.0

With Daphne's versbosity set to maximum, this is what I get when I try to connect:

Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,489 [asyncio] DEBUG: poll 101.195 ms took 0.023 ms: 1 events
Nov 22 07:16:34 weout-staging app/web.1 10.12.43.130:10299 - - [22/Nov/2019:15:16:33] "WSCONNECTING /api/v1/ws/" - -
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,513 [daphne.http_protocol] DEBUG: Upgraded connection ['10.x.x.x', 10299] to WebSocket
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,648 [asyncio] WARNING: Executing <Task pending coro=<AsyncConsumer.__call__() running at /app/.heroku/python/lib/python3.6/site-packages/channels/consumer.py:59> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7fe01e6979d8>()] created at /app/.heroku/python/lib/python3.6/asyncio/base_events.py:276> created at /app/.heroku/python/lib/python3.6/site-packages/daphne/server.py:209> took 0.131 seconds
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,655 [daphne.server] INFO: failing WebSocket opening handshake ('Access denied')
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,656 [daphne.server] WARNING: dropping connection to peer tcp4:10.12.43.130:10299 with abort=False: Access denied
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,656 [daphne.ws_protocol] DEBUG: WebSocket ['10.x.x.x', 10299] rejected by application
Nov 22 07:16:34 weout-staging app/web.1 10.12.43.130:10299 - - [22/Nov/2019:15:16:33] "WSREJECT /api/v1/ws/" - -
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,660 [aioredis] DEBUG: Parsing Redis URI 'redis://xxxx@xxxxx'
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,660 [aioredis] DEBUG: Creating tcp connection to ('xxx.compute.amazonaws.com', 14059)
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,663 [asyncio] DEBUG: Get address info xxx, type=<SocketKind.SOCK_STREAM: 1>
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,667 [asyncio] DEBUG: Getting address info xxx.compute.amazonaws.com:14059, type=<SocketKind.SOCK_STREAM: 1> took 3.777 ms: [(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('x.x.x.x', 14059))]
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,669 [daphne.ws_protocol] DEBUG: WebSocket closed for ['10.x.x.x', 10299]
Nov 22 07:16:34 weout-staging app/web.1 10.12.43.130:10299 - - [22/Nov/2019:15:16:33] "WSDISCONNECT /api/v1/ws/" - -
Nov 22 07:16:34 weout-staging app/web.1 2019-11-22 15:16:33,671 [asyncio] DEBUG: connect <socket.socket fd=16, family=AddressFamily.AF_INET, type=2049, proto=6, laddr=('0.0.0.0', 0)> to ('x.x.x.x', 14059)

I use Daphne to serve both my normal Django views and websocket consumers. Everything works well for the Django views, so the problem occurs only when connecting to the consumers

Does anyone have a similar issue while accessing Dapnhe remotely? At first I tried uvicorn served with gunicorn but they have a bug when the consumer is closed during the initial connection phase so I switched back to Daphne


Solution

  • Turns out it was the AllowedHostsOriginValidator! That surely wasted a whole lot of my time. By the way, any idea how that middleware will behave for requests from mobile apps or other sources without the Origin header?

    Anyway I removed it for now and the current issue was solved