问题
According to the doc of CloudFront
(https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html), client IP can be the front, middle, end of X-Forwarded-For
header.
Is it rignt? Then how can I get real client IP?
回答1:
Is it right?
Not exactly.
CloudFront follows correct semantics for X-Forwarded-For
. Specifically, each system handling the request appends its client's address to the right. This means the rightmost address in X-Forwarded-For
in the request from CloudFront is always the address of the machine that connected to CloudFront.
If the client (the machine establishing the connection to CloudFront) includes an X-Forwarded-For
header in its request, that header may be forged, or it may be legitimate if the client is a proxy server, but you rarely have a way of knowing that... so either way, you should treat this as potentially valuable, but strictly non-authoritative.
The rightmost value (which may also be the only value) is the only value you can trust in the request you receive from CloudFront.
Generally speaking, parsing from the right, any address that is known to you and trusted to have correctly identified its upstream client can be removed from the list... but once you encounter the first untrusted address, right to left, that's the one you're looking for, since nothing to the left of that address can be trusted.
This means that if components in your stack -- such as Application Load Balancer or your web server are also adding X-Forwarded-For
, then you will need to account for what those components also add onto the right side of the value, modifying what CloudFront has supplied.
For example. Client sends:
X-Forwarded-For: a, b, c
CloudFront adds the client's IP d
:
X-Forwarded-For: a, b, c, d
ALB receives the request from CloudFront, so it adds the CloudFront egress address e
:
X-Forwarded-For: a, b, c, d, e
Then your web server adds the internal address of the balancer f
:
X-Forwarded-For: a, b, c, d, e, f
You can trust and remove f
as long as it is with the CIDR range of your balancer subnets.
You can trust and remove e
as long as it is in the CloudFront address ranges.
That leaves you withd
as the client address.
The values a
and b
and c
are almost worthless, in this example, because you can't trust their authenticity since they are to the left of the first (from the right) untrusted address... occasionally, they may be forensically useful, later, but you can't make any real-time decisions based on them.
This is how X-Forwarded-For
always works. Many developers seem to make naïve assumptions due to lack of understanding. Be certain you understand it before you use it for anything important.
In Lambda@Edge triggers, CloudFront gives you the client IP address in event.Records[0].cf.request.clientIp
. This is always just a single address, and is the same as the rightmost value of X-Forwarded-For
as the request leaves CloudFront headed to your origin (which may, as noted above, add additional values onto the right side).
来源:https://stackoverflow.com/questions/51393782/how-to-get-client-ip-of-requests-via-cloudfront