See each client's own address
Behind a load balancer, every request reaches the gateway from the load balancer's address. A limit per client address then counts every client as one, and an address list cannot tell them apart. real-ip reads each client's own address from the header the load balancer writes. That address becomes the one the route's plugins see. This guide puts real-ip on orders-api. At the end, your backend and the route's plugins see each client's own address instead of the load balancer's.
Before you start
- Two facts from the team that runs the load balancer: the header it writes each client's address into,
X-Forwarded-FororX-Real-IP, and every address it connects to the gateway nodes from. This guide usesX-Forwarded-Forand the addresses10.0.0.21and10.0.0.22. - This guide starts from
orders-apias Route requests to a backend leaves it, with no other plugin. A plugin from another guide that this page does not name can change the answers below; remove it first or work on a copy of the route. - The requests below call
/orders/3001. - The host name of your gateway. In the console it is the first part of the Address line on a route's Overview tab,
api.example.comin this page's examples; replace it in every request below. - A way to see what your backend receives: its access log, or a request echo it offers. The gateway's answer to the client does not show the address it passed on.
- The Editor or Environment administrator role in this environment.
Steps
1. Choose real-ip
Open orders-api under Routes, select its Plugins tab, then Add plugin at the top right of the tab. Open the General category, or type real-ip in the search box. Select real-ip, then Configure.
2. Name the header and the load balancer's addresses
Trusted addresses is a list: type a value and press Enter for each.
| Field | Value | Why |
|---|---|---|
| Source | http_x_forwarded_for | Reads the X-Forwarded-For header. For a load balancer that sends X-Real-IP, set http_x_real_ip. |
| Trusted addresses | 10.0.0.21 and 10.0.0.22 | The header is believed only from these addresses. List every address your load balancer connects from, and nothing else. |
| Recursive | leave off | The default. Take the last address of the header, the one your load balancer added. |
Select Add plugin at the bottom of the panel. The plugin is saved like this:
{
"source": "http_x_forwarded_for",
"trusted_addresses": [
"10.0.0.21",
"10.0.0.22"
]
}
From now on, a request from the load balancer is taken as coming from the last address in its X-Forwarded-For, and your backend receives that address in X-Real-IP. A request from any other address keeps its own, whatever header it sends.
Check it
Send the request below through your load balancer, from a machine whose address you know, and read X-Real-IP in your backend's log. A request sent straight to a gateway node does not come from a trusted address, so the gateway ignores its header.
curl -i -L 'https://<gateway host>/orders/3001' \
-H 'X-Forwarded-For: 198.51.100.66, 203.0.113.7'
The X-Forwarded-For in the request shows the header as the gateway receives it from your load balancer, with your machine's address, 203.0.113.7 here, last. The answers on limit-count and ip-restriction apply only if the route also carries limit-count from Limit requests on a route or ip-restriction from Allow a network.
- What your backend receives
- Your backend receives the client's address in
X-Real-IP: a request your load balancer forwards with203.0.113.7last inX-Forwarded-Forarrives withX-Real-IP: 203.0.113.7. - An address the client wrote itself
- Only the last address counts: an address the client wrote into the header itself,
198.51.100.66inX-Forwarded-For: 198.51.100.66, 203.0.113.7, is not used. - If the route carries limit-count
- A limit-count on the same route that counts by client address counts each client under its own address. Once
203.0.113.7has used its count it is answered429, while another client behind the same load balancer still passes. - The route’s own Client addresses field
- The route is matched before real-ip runs. A route whose Client addresses leave
203.0.113.7out still takes its request, because the request arrives from the load balancer, and the backend still receivesX-Real-IP: 203.0.113.7. - If the route carries ip-restriction
- ip-restriction on the same route acts after real-ip: a client inside its allow list passes, and one outside it is answered
403.
What to know
- Leave Trusted addresses empty and the header is believed from everyone. A client that reaches a gateway node directly can then name any address, and under a limit per address it is never refused: each new address starts a fresh count.
- The route itself is matched before its plugins run. Its Client addresses field and a condition on the client address still see the load balancer's address. An address list behind a load balancer is ip-restriction on the same route, as Allow a network shows.
- With Recursive on, the addresses listed under Trusted addresses are skipped from the end of the header and the address in front of them is taken. Use it when a proxy stands between the client and your load balancer, and list that proxy too.
- Your backend also receives
X-Forwarded-For. The gateway adds the client's address at its end once more, so the address your load balancer wrote last stands there twice. Read the client's address fromX-Real-IP, or from the last address of that header, never from the first, which a client can write itself. - Behind a load balancer every route needs each client's own address, so a global rule is the usual place for real-ip. Apply a plugin to every request puts it on one, so that every plugin sees each client's own address.
Related
- Apply a plugin to every request: real-ip on a global rule, for every route at once.
- Limit requests on a route: the limit per client this plugin makes possible behind a load balancer.
- Allow a network: an address list on the same route.
- real-ip in the reference.