---
title: 'Tutorial: Track Real Client IP Addresses in Access Server Behind a Proxy, Load Balancer, or Cloudflare'
canonical: https://openvpn.net/as-docs/v3/tutorials/tutorial--real-client-ip-proxy-load-balancer/
product: Access Server Docs
description: Learn how to verify real client IP addresses in Access Server when deployed behind a proxy, reverse proxy, load balancer, or Cloudflare — covers X-Forwarded-For, CF-Connecting-IP, and configuring a custom HTTP header for the proxied IP.
---

# Tutorial: Track Real Client IP Addresses in Access Server Behind a Proxy, Load Balancer, or Cloudflare

## Overview

When you deploy Access Server behind a proxy, reverse proxy, or load balancer, Access Server receives the web request from that intermediary rather than directly from the client.

Starting with Access Server 3.2.2, you can identify both addresses associated with these web requests:

- **Request IP:** The IP address from which Access Server directly receives the request. In a proxied deployment, this is typically the IP address of the proxy, reverse proxy, or load balancer facing Access Server.
- **Proxied IP:** The real client IP address, or original client IP, supplied in a supported HTTP header by the proxy, reverse proxy, or load balancer.

Access Server detects `X-Forwarded-For` and `CF-Connecting-IP` by default. `CF-Connecting-IP` is the header Cloudflare injects to identify the original visitor IP address. You can also configure another header, such as `X-Real-IP`, when your infrastructure uses a different header for the client address.

This tutorial shows you how to verify the Request IP and Proxied IP in the Activity Log and Access Server logs, test header detection with the Web API, and configure a custom proxied-IP header.

Tracking the original client IP is especially useful for auditing and troubleshooting production [secure remote access](https://openvpn.net/use-cases/secure-remote-access/) deployments that place Access Server behind a proxy or load balancer.

## Prerequisites

Before you begin, ensure you have:

- Access Server 3.2.2 or newer.
- Admin Web UI access.
- Console access and the ability to get root access.
- An administrator account configured in Access Server.
- A proxy, reverse proxy, or load balancer for Step 1.
- Optional: A remote computer from which you can run Web API requests for Steps 2 and 3.

> **Note**
>
> In our documentation, we use example IPv4 addresses and subnets [reserved for documentation](https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv4), such as `192.0.2.0/24`, `198.51.100.0/24`, and `203.0.113.0/24`.
>
> Ensure you replace them with valid IPv4 addresses and subnets for your network(s).

## How Access Server detects X-Forwarded-For and CF-Connecting-IP

By default, Access Server can detect the original client IP from these HTTP request headers:

- `X-Forwarded-For`
- `CF-Connecting-IP`

A proxy or load balancer can add one of these headers before forwarding a request to Access Server.

For example:

```
Client
192.0.2.5
   |
   v
Proxy / Load Balancer
198.51.100.5
   |
   | X-Forwarded-For: 192.0.2.5
   v
Access Server
```

Access Server can then record:

```
Request IP: 198.51.100.5
Proxied IP: 192.0.2.5
```

> **Important**
>
> HTTP forwarding headers can be supplied by a client or a proxy. Treat the Proxied IP as trustworthy only when your network architecture ensures that Access Server receives these requests through a trusted proxy, reverse proxy, or load balancer.
>
> Don't use a forwarded IP address by itself as proof of client identity.

## Step 1: Verify the Request IP and Proxied IP through a proxy

Use this procedure when Access Server is already behind a proxy, reverse proxy, or load balancer that adds the original client IP to the web request.

### Verify the addresses in the Activity Log

1. From a client device, access the Admin Web UI through the proxy, reverse proxy, or load balancer.
2. Sign in to the Admin Web UI.
3. Navigate to **Status → Activity Log**.
4. Locate the `WEB_ADMIN` login activity you just generated.
5. Review **Request IP**.
   - This should display the address from which Access Server directly received the request, which is typically the proxy, reverse proxy, or load balancer IP.
6. Review **Proxied IP**.
   - This should display the real client IP address supplied in the forwarded HTTP header.
7. Optional: Sign in to the Client Web UI.
8. Locate the corresponding `WEB_CLIENT` activity in the **Activity Log**.
9. Verify its **Request IP** and **Proxied IP** values.

### Verify the addresses in the Access Server log

1. From the client device, sign in to the Admin Web UI through the proxy, reverse proxy, or load balancer.
2. Connect to the console and get root privileges.
3. Review:

   ```
   /var/log/openvpnas.log
   ```
4. Locate the `WEB_ADMIN` request corresponding to your login.
   - Example:

     ```
     2026-07-29T21:05:59+0000 [stdout#info] [WEB] OUT: '2026-07-29T21:05:59+0000 [twisted.python.log#info] "198.51.100.5 [192.0.2.5]" - - [29/Jul/2026:21:05:59 +0000] "POST /api/auth/login/userpassword HTTP/2" 200 460 "-"
     ```
   - In this example:

     `Request IP: 198.51.100.5`

     `Proxied IP: 192.0.2.5`
5. Confirm that the Request IP matches the proxy-facing address.
6. Confirm that the Proxied IP matches the original client IP.

**Expected result:** The Activity Log and Access Server log show the intermediary address as the **Request IP** and the original client address as the **Proxied IP**.

## Step 2: Test X-Forwarded-For with the Web API

Use this procedure to test Access Server's proxied-IP detection without configuring a proxy or load balancer first.

The example manually sends an `X-Forwarded-For` header to simulate the header a proxy would normally add.

> **Tip**
>
> This tutorial uses cURL to call the Access Server Web API. You can also use the embedded Swagger UI. Refer to [Tutorial: Test the New Web API (OpenAPI) in Access Server 3.0](https://openvpn.net/as-docs/v3/tutorials/tutorial--test-the-new-web-api--openapi--in-access-server-3-0.md).

1. Connect to the console and get root privileges.
2. Run the following API call from a remote machine to generate web request traffic to your Access Server:

   ```
   curl -X 'POST' 'https://203.0.113.5/api/auth/login/userpassword' -H 'accept: application/json'  -H 'Content-Type: application/json' -H "X-Forwarded-For: 192.0.2.5" -d '{"username": "<ADMIN_USERNAME>","password": "<ADMIN_PASSWORD>", "request_admin":"true"}' -k -v
   ```

   Replace `203.0.113.5` with your Access Server address.

   Replace `192.0.2.5` with the test Proxied IP.

   Replace `<ADMIN_USERNAME>` with your administrator username.

   Replace `<ADMIN_PASSWORD>` with the administrator password.

   > **Important**
   >
   > Supplying passwords directly on the command line can expose them through shell history or the process list. Use test credentials and protect or remove command history as appropriate for your environment.
3. Review the verbose cURL output.
4. Locate `X-Forwarded-For: 192.0.2.5`.
   - Example output on the client side confirming that the request included the `x-Forwarded-For` HTTP header:

     ```
     > POST /api/auth/login/userpassword HTTP/2
     > Host: 203.0.113.5
     > User-Agent: curl/8.5.0
     > accept: application/json
     > Content-Type: application/json
     > X-Forwarded-For: 192.0.2.5
     > Content-Length: 50
     ```
   - Example output on the Access Server side confirming the Request IP is `198.51.100.5` and the Proxied IP is `192.0.2.5`:

     ```
     2026-07-29T23:49:01+0000 [stdout#info] [WEB] OUT: '2026-07-29T23:49:01+0000 [twisted.python.log#info] "198.51.100.5 [192.0.2.5]" - - [29/Jul/2026:23:49:00 +0000] "POST /api/auth/login/userpassword HTTP/2" 200 460 "-" "curl/8.5.0"'
     ```

## Step 3: Configure a custom header for the Proxied IP

Access Server detects `X-Forwarded-For` and `CF-Connecting-IP` by default.

If your proxy, reverse proxy, or load balancer uses another HTTP header for the original client IP, configure Access Server to detect that header instead.

The following example uses `X-Real-IP` as our custom HTTP header to inject the real/original client IP address. Replace it with one of your preference.

1. Connect to the console and get root privileges.
2. Configure `X-Real-IP` as the proxied-IP header:

   ```
   sacli -k "cs.proxied_ip_header" -v "X-Real-IP" ConfigPut
   ```
3. Restart Access Server:

   ```
   sacli start
   ```
4. From a remote computer, run the following to test:

   ```
   curl -X 'POST' 'https://203.0.113.5/api/auth/login/userpassword' -H 'accept: application/json'  -H 'Content-Type: application/json' -H "X-Real-IP: 192.0.2.5" -d '{"username": "<ADMIN_USERNAME>","password": "<ADMIN_PASSWORD>", "request_admin":"true"}' -k -v
   ```
5. Replace the Access Server address and credentials with values for your environment.
6. Review the verbose cURL output.
7. Confirm the header output:
   - Example output on the client side confirming that it contains the X`-Real-IP` HTTP header:

     ```
     > POST /api/auth/login/userpassword HTTP/2
     > Host: 203.0.113.5
     > User-Agent: curl/8.5.0
     > accept: application/json
     > Content-Type: application/json
     > X-Real-IP: 192.0.2.5
     > Content-Length: 50
     ```
   - Example output on the Access Server side confirming the Request IP is `198.51.100.5` and the Proxied IP is 1`92.0.2.5`:

     ```
     2026-07-29T23:49:01+0000 [stdout#info] [WEB] OUT: '2026-07-29T23:49:01+0000 [twisted.python.log#info] "198.51.100.5 [192.0.2.5]" - - [29/Jul/2026:23:49:00 +0000] "POST /api/auth/login/userpassword HTTP/2" 200 460 "-" "curl/8.5.0"'
     ```

## See also

- [Tutorial: Test the New Web API (OpenAPI) in Access Server 3.0](https://openvpn.net/as-docs/v3/tutorials/tutorial--test-the-new-web-api--openapi--in-access-server-3-0.md)
- [Logging and Debugging](https://openvpn.net/as-docs/v3/tutorials/logging-and-debugging.md)
- [APIs and Automation](https://openvpn.net/as-docs/v3/tutorials/apis-and-automation.md)
- [Secure Remote Access](https://openvpn.net/use-cases/secure-remote-access/)

---

Prev: [Tutorial: Assign IPv6 Addresses to VPN Clients from a Group Pool](https://openvpn.net/as-docs/v3/tutorials/tutorial--assign-ipv6-from-group-pool.md)
Next: [Network Segmentation and Access](https://openvpn.net/as-docs/v3/tutorials/network-segmentation-and-access.md)
Index: https://openvpn.net/as-docs/llms.txt
