Seeing HTTPS requests to shared IPv4 address

I have a V2 app using a shared IPv4 address. Once or twice a week, a request to https://66.241.125.29 will reach my Django application and trigger an “Invalid HTTP_HOST header” error. Those are easy enough to suppress, but I do wonder why fly-proxy isn’t filtering out such requests at the edge? Shouldn’t the only requests that reach my application have a host header matching my fly.dev hostname or one of my certificates?

All of the requests I’ve seen have been scans from security company Censys (AS398722). I couldn’t reproduce with curl --insecure or several TLS scanners, so I’m not sure how Censys’s scanner breaks TLS to complete the request.

Possibly they are setting the TLS SNI to your hostname while setting the HTTP Host to the IP address. If the fly proxy uses the SNI to route to your app then I think that would create the scenario you’re seeing.

Oh, that’s a really good theory. The app is still in development and hasn’t been published anywhere, but the subdomain it’s using would appear in CT logs.

I think verifying the host header at the edge would be a security win for customers using shared IPs—preventing attacks such as password reset poisoning. Dedicated IPs are obviously a different situation.

1 Like

You are correct. I set up a test app at testhost.fly.dev. It successfully connects with TLS and accepts an arbitrary host header.

curl -H 'Host: evil.example.com' https://testhost.fly.dev

Responds with:

Host: evil.example.com
1 Like

I think routing using SNI only is acceptable. As with any information you receive from the client, you should validate the information before relying on it. This includes validating the Host before using it to generate links. There is a split responsibility when it comes to security and the application security side of things is definitely on the side of the fly customer.

I’m reminded of the domain fronting controversy from a few years ago, though in that case routing was based on the host header. As a result, all the major cloud providers now verify that the host and SNI match, which explains why I don’t see this issue on competing services like Google Cloud Run.

I agree about validating client-supplied data. I’m glad Django has the functionality built-in. Thanks for helping me figure this out!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.