I am trying to pass incoming traffic from amazon's Network Load Balancer to Application Load Balancer, I am using NLB since it has an Elastic IP attachment and I want it to serve as a proxy for the ALB. is that even possible?
问题:
回答1:
It is possible, but it's slightly messy.
The problem is that Application Load Balancers can scale up, out, in, and/or down, and in each case the internal IP addresses of the balancers can change... but NLB requires static addresses for its targets.
So, at a low level, this means the NLB target group must be modified every time the IPs of the ALB change.
AWS has published an official solution for accomplishing this, using a Lambda function on a schedule to capture the addresses of the ALB and update the NLB configuration whenever the results change.
https://aws.amazon.com/blogs/networking-and-content-delivery/using-static-ip-addresses-for-application-load-balancers/
One notable limitation, here, is that this solution does not allow you to identify the client IP address. It is lost when the traffic goes through the NLB, because NLBs only preserve the source IP when the target is an instance (not an IP address) or when the target understands the Proxy protocol on the client side and the feature is enabled on the NLB, but ALB doesn't support such a configuration. With the setup shown at the link, above, the rightmost address in X-Forwarded-For
will be set by the ALB to the internal address of the NLB.
回答2:
This is correct. Your app server behind the ALB (or the ALB itself) will always see the source IP as that of the NLB.
As a workaround that works for some use cases you can enforce HTTPS and configure access logs on the NLB. Then the access logs will have the original source IP.
In case this was not clear, what I mean is:
- make sure to enable access logs on your NLB
- make sure to configure your NLB listener to use TLS
There are some additional complications if you want to accept plain HTTP and issue redirects to HTTPS. In that case you would have 2 listeners and 2 target groups, so you need to either spin up 2 copies of the Lambda to monitor (and eventually update) both target groups or you need to modify the Lambda code (which is what I did).
In addition IMO the code in that example is far from production ready (especially for scale - if you have many instances of this setup), so I had to practically rewrite it.
Relevant excerpts from CloudFormation template are below:
NLB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
Scheme: internet-facing
Type: network
LoadBalancerAttributes:
- Key: load_balancing.cross_zone.enabled
Value: 'true'
- Key: access_logs.s3.enabled
Value: 'true'
# make sure the bucket policy grants access - https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-access-logs.html
- Key: access_logs.s3.bucket
Value: !Ref S3BucketForNLBAccessLogs
- Key: access_logs.s3.prefix
Value: !Sub 'raw/${AppInstance}'
nlbHTTPSListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
Certificates:
- CertificateArn: !Ref FrontEndSSLCertificateArn
LoadBalancerArn: !Ref NLB
Port: 443
Protocol: TLS
DefaultActions:
- Type: 'forward'
TargetGroupArn: !Ref nlbHTTPSTargetGroup