0

Background

I have 2 domains. I need to allow certain IP addresses as follows:

  • a.domain.io - all IPs allowed
  • b.domain.io - only IP 1.2.3.4 is allowed

Proposed solution

I am not an infrastructure guy but I came with this idea.

  • Route53 will point either to a.domain.io Application Load Balancer ALB-A or to b.domain.io as ALB-B
  • ALB-A will point directly to a resource (EC2)
  • ALB-B will use some kind of a "firewall" (probably an ACL or Security Groups) that will let only IP 1.2.3.4 to reach it and in turn forward traffic to EC2

enter image description here

Question

Is the proposed solution a good setup or should I completely leave it OR tweak it somehow?

Amio.io
  • 133
  • 1
  • 5

1 Answers1

1

The problem with the 2 balancer solution is that either of them will indiscriminately accept any Host header and forward the request to the server. There's nothing at all wrong with pointing multiple balancers to the same server, but this configuration trivially bypasses your security group settings if a malicious user is aware of a.example.com -- they simply connect to the a.example.com balancer and inject Host: b.example.com in their request, and the instance cannot tell the difference.

ALBs add an HTTP header X-Forwarded-For to each incoming request. The rightmost value in this header represents the actual IP address of the connecting client, and cannot be forged. Any addresses to the left of the rightmost value was supplied by the client (usually a proxy or a script kiddie) and for your purposes are untrustworthy and meaningless. But the one on the right will be accurate.

The simplest configuration would be to use a single ALB, and for whatever is accepting the HTTP connections on the instance (e.g. Nginx, Apache) to simply deny HTTP requests when the Host header contains b.example.com but X-Forwarded-For does not end with the trusted IP, e.g. 203.0.113.50. The error could be 403 Forbidden but perhaps better might be 503 Service Unavailable.

With the two balancer setup, and one balancer restricted by security groups or NACLs, either your instance or the balancer needs to block requests for b.example.com via the a.example.com balancer. The instance can't, because identifying which balancer sent the request is not practical. When they scale or fail (and recover), their internal addresses change.

It is possible to blackhole specific requests through an ALB, either by Host header or path pattern matching as I discussed here on SF, by creating a dummy target group with no instances assigned to it... so the a.example.com balancer could blackhole requests for b.example.com using such a configuration.

Or you can use Amazon Web Application Firewall (WAF) in conjunction with ALB to block any unexpected requests. This is a good option if you are planning on using WAF, anyway.

However... If you do use WAF, then you don't need two balancers... you could use a single balancer for both sites, and add rules on WAF to block requests for Host: b.example.com unless the client IP matches the allowed list. The only caveat with WAF is that since it is checked for every request this means an outage in WAF would result in an outage for your sites... so WAF was designed to fail open. A WAF failure means all traffic is allowed, however unlikely such a failure may be. WAF is fully managed, so there is nothing for you to have to maintain.

Michael - sqlbot
  • 21,988
  • 1
  • 57
  • 81
  • Michael, thank you very for such a thorough explanation! The truth is that I don't understand the solutions much now - especially those without WAF. I will learn a little more and come back to you as soon as I know more about the topic. – Amio.io Sep 10 '17 at 20:05
  • Michael, I wanna go the simple way (ALB → nginx → ec2). Would you use [ngx_http_realip_module](http://nginx.org/en/docs/http/ngx_http_realip_module.html) for this kind of task as `real_ip_header X-Forwarded-For;`? – Amio.io Sep 13 '17 at 11:55
  • 1
    As long as your instances don't have public IPs of their own (so they can't be accessed directly), I'm not sure you technically need that, since the ALB will provide an `X-Forwarded-For` header that is already correct... but, yes, that't the way it's often done. You need to configure the module to trust the entirety of each of rhr subnets with the balancers, since balancers periodically change their internal addresses autonomously, but they stay on the same subnets, of course. – Michael - sqlbot Sep 13 '17 at 12:33