Proxies and Load Balancers
Proxy servers, load balancers, and other intermediaries can change how a request reaches the application. When TLS termination occurs at the proxy or traffic is forwarded through another host, the application can no longer directly see some information about the original connection:
- If the client accesses the proxy over HTTPS, but the proxy communicates with the application over HTTP (for example, after terminating the TLS connection), the application sees HTTP on the incoming connection. For the application to know that the original request used HTTPS, the proxy must provide the original scheme in a header.
- Since the connection reaches the application from the proxy, the remote address seen by the server is usually the proxy's IP address, not the client's. To obtain the client's IP address, the proxy must forward it in a header, such as
X-Forwarded-Foror a provider-specific header.
This information is useful for redirects, generating absolute URLs, access logs, enforcing policies, and approximate geolocation. However, a header is not trustworthy simply because it is present: the application must accept these values only from explicitly trusted proxies.
Configuration
A quick guide to configuring Inphinit when the application runs behind a load balancer or reverse proxy.
1. Check which headers the server sends
Verify which headers the load balancer or proxy actually sends to the application. The names below are common conventions; the available set depends on the product and its configuration:
- X-Forwarded-For
- X-Forwarded-Proto
- X-Forwarded-Host
- X-Forwarded-Prefix
2. Determine the trusted IP addresses
Define which IP addresses or networks correspond to the proxies authorized to provide these headers. Inphinit trusts the forwarded values only when the address that connected directly to the application is included in this list:
-
Load balancer/proxy IP address: use
setKnownProxies. -
Load balancer/proxy network (CIDR): use
setKnownNetworks.
Examples:
| Type | Example |
|---|---|
| Single IP address | 10.0.0.5 |
| CIDR network | 10.0.0.0/24 |
Security: any client can send spoofed X-Forwarded-* headers. Register only proxies you trust, avoid broad network ranges, and, whenever possible, block direct access to the application (using a firewall or security group) so that nobody can bypass the proxy.
3. Enable APP_FORWARDED
In the server's environment variables, set:
APP_FORWARDED=1
If you are using the .env file, enable this variable there.
4. Configure system/main.php
Use one of the options below.
By network (CIDR)
$forwarded->setKnownNetworks(array(
'10.0.0.0/24',
'192.168.0.0/16'
));
By IP address (proxy)
$forwarded->setKnownProxies(array(
'10.0.0.5',
'10.0.0.6'
));
Quick reference: common providers
| Provider | Common headers | Trusted IP addresses |
|---|---|---|
| Cloudflare | X-Forwarded-For, X-Forwarded-Proto, CF-Connecting-IP, CF-Visitor | Use the official IP ranges and keep them up to date: https://www.cloudflare.com/ips/ |
| AWS ALB/ELB | X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Port | Node IP addresses are not fixed. Use the CIDR ranges of the subnets where the ALB is deployed, not the entire VPC, and restrict inbound access to the application to the ALB's security group. |
| AWS CloudFront | X-Forwarded-For, CloudFront-Forwarded-Proto, CloudFront-Viewer-Address (some are optional and must be enabled in the distribution) | Ranges published at https://ip-ranges.amazonaws.com/ip-ranges.json
(the CLOUDFRONT_ORIGIN_FACING service, which contains the IP addresses CloudFront uses to connect to your origin). CloudFront does not send X-Forwarded-Proto; see the example in the "Adjusting headers" section.
|
If there is more than one proxy in front of the application (e.g., Cloudflare + ALB), include all intermediate proxy IP addresses/networks in the trusted list. Each proxy must append its value to the headers or overwrite them, and must never forward arbitrary values sent by the client.
Retrieving Information
With APP_FORWARDED enabled, the $forwarded and $app->forwarded variables become available. The getIp(), getProto(), getHost(), and getPrefix() methods return, respectively, the client's IP address, the original scheme, the original host, and the path prefix provided by the proxy, according to the configured headers and flags. Example:
$app->action('GET', '/sample', function ($app) {
$ip = $app->forwarded->getIp();
});
If the application may run in different environments, with or without a proxy, handle both scenarios. Without the component, use $_SERVER['REMOTE_ADDR'], which contains the address of the host that connected directly to the server:
$app->action('GET', '/sample', function ($app) {
if ($app->forwarded) {
$ip = $app->forwarded->getIp();
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
});
To build URLs, always use the INPHINIT_PATH and INPHINIT_BASE_URL constants:
they already reflect the forwarded values (scheme, host, and prefix), including custom headers
configured with $forwarded->setHeaderName(). Since the host and scheme affect absolute URLs,
accept these values only from trusted proxies. Example:
$app->action('GET', '/sample', function ($app) {
// Get the IP address
$ip = $app->forwarded ? $app->forwarded->getIp() : $_SERVER['REMOTE_ADDR'];
// Get protocol://host/prefix/route
$url = INPHINIT_BASE_URL . INPHINIT_PATH;
});