I have a Express backend behind AWS Cloudfront. How properly set trust proxy for AWS Cloud Front:
app.set('trust proxy', function (ip) {
if ( ???????????? ) return true; // trusted IPs
else return false;
});
AWS Cloudfront use tons of ip address and is insecure validate all AWS ip address because anyone with an AWS EC2 instance have a valid IP.
As you mentioned AWS CloudFront uses a long list of IP Address ranges. It's mentioned in their documenation. You can see them via this one liner (source, requires jq
which you can get from brew
in MacOs.):
curl 'https://ip-ranges.amazonaws.com/ip-ranges.json' | jq -r '.prefixes[] | select(.service=="CLOUDFRONT") | .ip_prefix'
(Update: or directly from http://d7uri8nf7uskq.cloudfront.net/tools/list-cloudfront-ips as mentioned in their doc.)
Right now, April 2021, it is giving me 122 ranges.
You can make an AJAX call to this file in Node, parse the JSON file, get the list as an array of string (cloudFrontIps
), and pass that to app.set('trust proxy', ['loopback', ...cloudFrontIps])
.
The good news is someone else has already done it! Check https://github.com/nhammond101/cloudfront-ip-ranges out.
await
) your app start until this list is available. It's not a must though -- calling app.set
after the HTTP server is up should work, thought for that short duration you will be recording CloudFront's IP.setTimeout
.app.set
on a running server will make the new list applicable on future calls immediately, without needing to restart. I am getting this impression by how X-Forward-For
is examined on every request, and how app.set
is calling compileTrust
function on it's invocation. So, TL;DR: You shouldn't be needing to restart the server every 12 hours for this!app.set
overrides (and not appends) the list every time you call it. So if you have some IPs of your own (e.g. your VPC's CIDR
in AWS ELB), you have to manually add it to the list every time you call this app.set
in your setTimeout
.