I have an AWS application load balancer set up to access a target group in an ECS Fargate. I have a custom domain example.com
with an AWS-managed certificate with an alias targeting the load balancer. Thus if I enter https://example.com/
, it hits the load balancer which forwards to my ECS Fargate container. It seems to work fine.
However if I go into the AWS console for the load balancer, I see a DNS name in the form foo-bar-1234567890.region.elb.amazonaws.com
. It turns out that I can bypass the example.com
and access the load balancer directly (ignoring the certificate warning) using https://foo-bar-1234567890.region.elb.amazonaws.com
.
How can I easily prevent someone from directly accessing the load balancer by its AWS DNS name, bypassing the domain name in the hosted zone I’ve set up with the SSL certificate?
Surely this is a common scenario. I wouldn’t be surprised if many setups in the wild did not address this detail, and have their load balancers directly exposed via the AWS DNS name. However I don’t feel this configuration is ideal nor desirable. Note that how likely or easily someone could discover the load balancer DNS name is a separate issue and is not what I’m asking.
2
Answers
I went with Marc B's suggestion of adding an Application Load Balancer rule to restrict the
Host
header to match that of the expected domain (the one I have the SSL certificate for).Rather than redirecting, I indicate the request is forbidden. Redirecting from HTTP to HTTPS is a user convenience; the user might have intended HTTPS but inadvertently left off the
https:
in the URL; and redirecting is helping them out. But no user accidentally discovers the load balancer URL and inadvertently tries to connect to it. Thus I forbid direct access to the load balancer URL altogether.I could approach this two ways: I could deny access if the load balancer URL is used, or I could only allow access if the correct domain is used (denying all others). The latter seems safer. (Maybe there is some additional third URL I don't know about; this would prevent that as well.)
Unfortunately AWS application load balancer listener rules don't seem to accept
NOT
Boolean logic, so I can't easily override the default forwarding to the target group if the domain is not correct. So I take the opposite approach: I forbid all connections by default, and add an override rule to only allow connections if the domain is correct. Here's an example in CloudFormation. (Note that the SSL certificate and domain name are defined elsewhere.)(You'll see lots of encouragement to use Terraform instead of CloudFormation, and I don't doubt it is more powerful. But it is my understanding that the IaC framework is still limited by the capabilities of the cloud platform. In this case, for example, I highly doubt that Terraform would somehow add support for a
NOT
condition in load balancer rules, because AWS itself does not support that. In theory a complex rules engine might allow it and then transform it to a default forbid with an override as I have done here, but don't imagine Terraform does this. In other words, in Terraform I would guess that you would be stuck with the same sort of configuration I've shown here. If my assumption is incorrect please let me know.)I could allow the HTTP listener to continue indiscriminately redirecting to the HTTPS port, which eventually would provide the same HTTP Forbidden response if the domain were incorrect. But I prefer to take the same approach as above even with HTTP, to deny access to an incorrect domain even before redirection takes place.
Interestingly a rule based upon the
Host
header even matches if I include an explicit port in the URL. Supposedly theHost
header can include a port as well, so I don't know if A) AWS is ignoring the port when it does the comparison forhost-header
, or B) if the browser is stripping out the port if the default port is used. If the latter, then this could prevent access even to the correct domain if a browser decided to send the port in theHost
header value. Hopefully AWS is parsing out the host part and only comparing that.This is commonly handled on the backend, by returning a redirect if the host name doesn’t match whatever host name your server is configured to respond to.
However with Application Load Balancers you can also configure a rule to handle this. The rule would specify that if the Host-header is
foo-bar-1234567890.region.elb.amazonaws.com
then 301 redirect to your preferred domain name.