DEV Community

Rushikesh Surve
Rushikesh Surve

Posted on

Impact of deployment topology on rate-limiting and trust proxy

The trust proxy setting is an important concept in backend development, especially when implementing rate-limiting in our APIs. But deciding its accurate value depends heavily on our deployment topology.

When we deploy our application in production, the client may not talk directly to our backend. There may be 1 or more proxies in between who forward the request to the next proxy or the backend server. Those proxies can be Load balancers, API gateways, reverse proxy like nginx or any custom service.
So effectively, our request has to do some 'hops' over these proxies to reach backend.

When we implement rate limiting in app to prevent the DOS attack, we generally intend this rate limit on the basis of client IP address. And this works fine when client request reaches our backend directly.
But when we have multi-hop architecture, the simple setup won't work as expected. Because the most recent IP will be of the proxy and not the client. So all the traffic coming from different users will be considered from the single client(our own proxy) and thus there will be false positives as the rate limiting will trigger much often.

In this scenario, we must tell our backend to ignore these extra hops(i.e. to trust our proxies). This is done by specifying trust proxy. If there is 1 proxy between client-server we set trust proxy to 1; if there are 2, or more, we set it accordingly.
This will ensure our express app skips(trusts) these IPs, and accurately figures out actual client IP. The originating IP address of client is identified from 'X-Forwarded-For' header by the express app.

But setting trust proxy is not that straightforward.
The numerical value for trust proxy will not work in every case. If there are different paths from which our request reaches backend, there is a chance that the number of proxies may be different in each path. For example - internal vs external traffic:

External(public) traffic: (Client -> Web Application Firewall -> Load balancer -> Reverse Proxy -> Backend)
Internal traffic: (Client -> Load balancer -> Backend)
Enter fullscreen mode Exit fullscreen mode

In such cases, it is not ideal to specify trust proxy as a numerical value(eg. 3)

Express supports other values for trust proxy too.
In the above case, if the proxies are within the same private network, we can set trust proxy as 'uniquelocal'.

app.set('trust proxy', 'uniquelocal')

We can also provide array of specific IP addresses or subnets.

app.set('trust proxy', ['127.0.0.1', '192.168.1.0/24'])

Trust proxy can also have other values like 'loopback', 'linklocal' and even true/false, each having their own usecases and limitations.


That’s what I learnt about how network topology affects rate-limiting and the trust proxy setting. If you have any suggestions or corrections, I'm eager to learn.

Top comments (2)

Collapse
 
bashamega profile image
Adam Naji

Nice article. I have one question: since clients can manually send headers using tools like curl, how does Express prevent users from spoofing the X-Forwarded-For header when trust proxy is enabled?

Collapse
 
rushier profile image
Rushikesh Surve

Actually as much as I know, Express cant prevent users from spoofing the XFF header. But thats wehere accurate infrastructure configuration matters, in the proxy. The proxy must override XFF header with actual IP of connection, and then forward. So that our backend gets the actual IP of user, rather than whats spoofed.