---
url: 'https://docs.smoxy.eu/developer-guide/client-ip.md'
---
# Client IP at Your Origin

Because all traffic flows through smoxy, every connection your origin server sees comes from a smoxy address - `REMOTE_ADDR` no longer contains the visitor's IP. smoxy forwards the visitor's real IP address in the `X-Real-IP` request header. Configure your origin to read the client IP from exactly this header.

***

### Use `X-Real-IP`, not `X-Forwarded-For`

smoxy sends two IP-related headers with every request to your origin:

| Header            | Content                                                                                                                                                            |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `X-Real-IP`       | Always exactly **one** address: the visitor's IP as determined by smoxy at the edge.                                                                                |
| `X-Forwarded-For` | The full forwarding chain. It can contain **several** addresses: entries the client sent itself, hops of an upstream CDN (e.g. Cloudflare), and smoxy's own hops.   |

`X-Real-IP` is the address smoxy itself uses for security checks, logging, and load balancing - and it is also the basis for the [GeoIP headers](/developer-guide/geoip-headers). It stays correct even when another CDN such as Cloudflare runs in front of smoxy.

`X-Forwarded-For`, by contrast, is a chain that grows with every hop, and its first entries are client-controlled - anyone can send an `X-Forwarded-For` header. Extracting the visitor from it means counting proxy hops correctly; one hop off and your logs, IP allowlists, and rate limits use the address of a proxy instead of the visitor. Treat it as an audit trail, not as the source of the client IP.

***

### Apache

Use [mod\_remoteip](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html) so Apache treats the forwarded address as the client IP for logging, access control (`Require ip`), and everything downstream:

```apache
RemoteIPHeader X-Real-IP
```

In your log format, use `%a` (the client IP after mod\_remoteip) instead of `%h` (the peer address).

### nginx

Use the [realip module](https://nginx.org/en/docs/http/ngx_http_realip_module.html):

```nginx
set_real_ip_from <address of the proxy in front of your origin>;
real_ip_header X-Real-IP;
```

### Application code

If you cannot change the web server configuration, read the header directly, e.g. in PHP:

```php
$clientIp = $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'];
```

Many frameworks offer a "trusted proxies" setting for this; where possible, configure it to use `X-Real-IP`.

***

### Only trust the header behind smoxy

Like any forwarded header, `X-Real-IP` is only trustworthy when the request actually came through smoxy. If your origin is also reachable directly from the internet, restrict the trust (`RemoteIPTrustedProxy` in Apache, `set_real_ip_from` in nginx) to the addresses that reach your origin, or block direct access to the origin entirely.
