Running ASP.NET Core 1.0 rc1 behind a reverse proxy

Why are my requests taking forever?

 March 21, 2016


Update: this problem has been fixed and is confirmed working as-expected with the release of ASP.NET Core 1.0.

This site is currently running on ASP.NET Core 1.0 rc1. Kestrel is the server responsible for handling requests. However, I have no plans to expose this server directly to the Internet. Instead, the server only handles local requests with nginx proxying requests to it. The nginx setup is simple and similar to the following:

server {
    listen 443 ssl;
    server_name www.billboga.com;

    ssl_certificate /path/to/certificate;
    ssl_certificate_key /path/to/certificate/key;

    location / {
        proxy_pass http://localhost:5000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

With everything up and running, I made a request and could not believe it took a full sixty-seconds to get a response. I tried a few more requests and got the same result. The next step was to eliminate potential causes and since nginx was the newest piece in the chain, I started there. I initiated a ssh-session and forwarded a local port on my machine to the internal Kestrel-server running remotely: ssh user@theip -L 10000:127.0.0.1:5000 (http://ubuntuguide.org/wiki/Using_SSH_to_Port_Forward has more information for those who are curious). Responses were quick again.

Circled back to the sixty-second response-time. It seemed too coincidental and a quick check on nginx's documentation confirmed this is the default proxy connection timeout. So maybe nginx or Kestrel has a proxying-issue. Considering one has been around for several years and the other is under two-years, I went with the latter. After looking through the repo.'s issues on GitHub, I found https://github.com/aspnet/KestrelHttpServer/issues/341. Reading through the issue, it was discovered that Kestrel reacted badly to nginx proxying the request with a Connection: close header. https://github.com/aspnet/KestrelHttpServer/issues/406 fixes the problem, but only for rc2 and beyond. Thankfully, there is a workaround, which is to force the request to include a Connection: keep-alive header:

server {
    # previous stuff is still here.

    location / {
        # previous stuff is still here.

        # see https://github.com/aspnet/KestrelHttpServer/issues/341
        proxy_set_header Connection keep-alive;
    }
}

Hopefully, reading this page and not taking sixty-seconds to load is confirmation of a successful workaround.