25

We like to enable HSTS to our IIS deployed web application.

We have SSL terminating ELB Application load balancer. We have enabled the URL rewrite module in IIS and configured the x-Forward-Proto tag to decide and enable HSTS header in the response.

Presently, ALB does not appear to pass custom headers from IIS to the ALB, to the end-user. We wanted to see if there is a way to enable HSTS either at ALB level where it can accept custom headers or if it can be set at IIS level and ALB can pass through the HSTS headers to the browser?

Prasanna B R
  • 489
  • 2
  • 6
  • 12

2 Answers2

16

HSTS is a policy that is controlled by the backend and not by the load balancer. One could argue that AWS could enable this, but there are other issues that make this more complicated (violation of specs, permanent redirects for HTTP, etc.)

The issue with HSTS is that you cannot (should not) send Strict-Transport-Security over HTTP. The specs say to only send the header over a secure connection. HTTP is not secure. Since the load balancer is talking to the backend over HTTP, IIS is NOT sending the header. You need to use HTTPS on the backend to enable HSTS.

RFC6797

If your goal is to send "Strict-Transport-Security" to the client, use Layer 4 listeners on your load balancer and handle HTTPS at your backend. If a request arrives on HTTP, send a permanent redirect (301). Benefits include absolute control, improved HTTP/2, etc.

Another option is to change your listener to use HTTPS to talk to the backend. Setup HTTPS and SSL on the backend.

Community
  • 1
  • 1
John Hanley
  • 74,467
  • 6
  • 95
  • 159
  • Yes, We did the similar approach by enable the HSTS using URL rewrite module in IIS. But he problem is the ALB is not pass through the HSTS headers to the browser. – Prasanna B R Aug 18 '18 at 09:42
  • I recommend option #1 which is to use Layer 4 listeners in your load balancer. Now your backend has complete control over the HTTPS configuration. – John Hanley Aug 18 '18 at 17:13
  • 6
    @PrasannaBR your assertion that ALB does not pass custom headers to the browser is incorrect. Any header injected into the response by your back-end *will* be delivered to the browser by ALB. You will want to investigate why this isn't working for you, because it should. – Michael - sqlbot Aug 18 '18 at 17:45
  • I have updated my answer with details from RFC 6797. – John Hanley Aug 18 '18 at 17:53
  • I think this answers my question. Before moving to production, I was running the checks, of which HSTS came back as a warning. I have an ALB that can only be accessed via https, that connects to an ec2 over http. So I am assuming that I should have the HSTS token set to either its default (just so if I decide to make that change it might would catch my eye) or not defined in my settings.py (which will take the default). – Shmack May 25 '22 at 20:25
12

It sounds like this is the approach the OP used but for some reason the headers weren't passed. I just want to confirm this approach definitely does work and give additional details.

It is entirely possible to set the HSTS header on a backend server over HTTP. At the end of the day, it's just a header like any other and the server will happily send it.

However, what happens is that the BROWSER will ignore the HSTS header received on an HTTP response, as per the HSTS spec.

BUT, there is a way to make it work, firstly you configure your backend server to send the HSTS header.

Then, assuming the Application Load Balancer is listening on HTTPS, but your target group (and backend servers) are on HTTP, what happens is:

  • browser sends request to ALB over HTTPS
  • ALB forwards request to backend over HTTP
  • backend server sends the response including the HSTS header to the ALB over HTTP
  • ALB sends same response + header to the browser over HTTPS.

Therefore the browser receives the response and the HSTS header over HTTPS, and it will obey HSTS.

An argument against doing this is that you shouldn't send HSTS header over HTTP at all. However, the same argument applies to your whole website - no-one should be serving any websites over HTTP out to the internet. If you consider it safe to terminate HTTPS at the ALB and run the backend server on HTTP, then it's just as safe to send the HSTS header in the same way.


NOTE: If you're using HSTS then you've almost certainly got a redirect from HTTP to HTTPS in place. Bear in mind that the HSTS header will be sent with the redirect over HTTP, but the browser will ignore it. Once the redirect happens and the HSTS header comes over HTTPS, the browser will obey it.

Technically as per RFC6707 section 7.2, you shouldn't send the HSTS header back to the browser over plain HTTP. What you should do is make the setting of the header conditional, based on the X-Forwarded-Proto request header value.

Community
  • 1
  • 1
Andy Madge
  • 624
  • 5
  • 17
  • 2
    The arguments against doing this are only valid if you support HTTPS **and** HTTP. If you're enabling HSTS, you generally just want to have HTTP always redirect to HTTPS at the ELB. This protects your backend from ever being accessible via plain-text. – WhyNotHugo Jul 07 '20 at 10:16
  • 2
    Agreed, if you're doing the redirect at the ELB, then you're never sending HSTS header over HTTP anyway. As you say, much better to redirect at ELB before the request even hits the backend. – Andy Madge Jan 12 '21 at 18:12