Load Balance Mideye Instances with Citrix ADC (NetScaler)
This guide describes how to configure RADIUS load balancing on Citrix ADC (NetScaler) to distribute authentication requests across multiple Mideye Server nodes for high availability and resilience.
When to use RADIUS load balancing
Section titled “When to use RADIUS load balancing”Use this configuration when you have two or more Mideye Server nodes and want:
- High availability — if one Mideye Server is unreachable, traffic fails over to the remaining nodes
- Load distribution — spread authentication requests across nodes
- Health monitoring — the ADC probes each Mideye Server and removes unhealthy nodes automatically
Architecture
Section titled “Architecture”User → Gateway Virtual Server ↓ RADIUS Policy → RADIUS Action (points to LB VIP) ↓ LB Virtual Server (RADIUS, SOURCEIP persistence) ↓ ↓ Mideye_Server1_svc Mideye_Server2_svc (172.16.0.100:1812) (172.16.0.101:1812) ↓ ↓ RADIUS Monitor RADIUS MonitorThe Gateway’s RADIUS action points to the LB Virtual Server IP instead of a single Mideye Server IP. The LB Virtual Server distributes requests to the RADIUS services and uses SOURCEIP persistence to ensure that all packets within a RADIUS transaction reach the same backend.
RADIUS response path — source IP matters
Section titled “RADIUS response path — source IP matters”Correct flow — response returns through the LB:
VPN ──Access-Request──→ LB VIP (172.16.3.199) ──→ Mideye (172.16.0.100)VPN ←─Access-Accept──── LB VIP (172.16.3.199) ←── Mideye (172.16.0.100) ✓ Source IP matchesBroken flow — Mideye responds directly (asymmetric routing):
VPN ──Access-Request──→ LB VIP (172.16.3.199) ──→ Mideye (172.16.0.100)VPN ←─Access-Accept──── Mideye (172.16.0.100) ←─┘ (bypasses LB) ✗ Source IP mismatch — VPN drops the packetThis happens when the Mideye Server has a direct route to the VPN that does not pass through the ADC. The return path must go back through the load balancer so the ADC rewrites the source IP to the VIP.
How to fix asymmetric routing
Section titled “How to fix asymmetric routing”The solution depends on your network topology:
-
Use SNIP as the source (recommended) — Ensure the ADC uses a Subnet IP (SNIP) on the same network as the Mideye Servers to forward RADIUS requests. Mideye sees the SNIP as the source and responds back to it, ensuring the response traverses the ADC. This is the default NetScaler behavior when the SNIP and backend servers are on the same subnet.
-
Use Use Source IP (USIP) mode = NO (default) — By default, the ADC replaces the client’s source IP with its own SNIP when forwarding to the backend. Do not enable USIP on the RADIUS service — if you do, Mideye sees the VPN’s IP as the source and may route the response directly back, bypassing the LB.
-
Static route on Mideye Servers — If the Mideye Servers are on a different subnet, add a static route on each Mideye Server so that traffic destined for the VPN’s subnet routes through the ADC’s SNIP as the gateway.
-
Verify with a packet capture — If authentication silently fails, capture traffic on the Mideye Server to confirm whether responses are going back to the ADC (SNIP) or directly to the VPN:
Terminal window # On the Mideye Server — watch RADIUS traffictcpdump -i any udp port 1812 -nnYou should see requests arriving from the ADC SNIP and responses going to the ADC SNIP — not directly to the VPN.
Applies to
Section titled “Applies to”| Component | Supported versions |
|---|---|
| NetScaler / Citrix ADC | 12.x, 13.x, 14.x (current) |
| Feature required | Load Balancing (must be enabled) |
| Mideye Server | 4.3.0+ (5.x+ recommended) |
Prerequisites
Section titled “Prerequisites”- Load Balancing feature enabled on the ADC
- At least two Mideye Server nodes configured with RADIUS
- A RADIUS client in each Mideye Server for the ADC IP
- A dedicated IP address on the ADC for the LB Virtual Server (VIP)
- Shared secret must be the same for all Mideye Servers behind the LB VIP
1. Enable load balancing
Section titled “1. Enable load balancing”enable ns feature LoadBalancingVerify:
show ns featureLook for Load Balancing with status ON.
Navigate to System → Settings → Configure Basic Features and enable Load Balancing.
2. Create server objects
Section titled “2. Create server objects”Create a server object for each Mideye Server node.
add server Mideye_Server1 172.16.0.100add server Mideye_Server2 172.16.0.101Navigate to Traffic Management → Load Balancing → Servers and click Add for each server:
- Name:
Mideye_Server1 - IP Address:
172.16.0.100
Repeat for each Mideye Server node.
3. Create RADIUS services
Section titled “3. Create RADIUS services”Create a RADIUS service for each server object. A service binds a server to a port and protocol.
add service Mideye_Server1_svc Mideye_Server1 RADIUS 1812add service Mideye_Server2_svc Mideye_Server2 RADIUS 1812Navigate to Traffic Management → Load Balancing → Services and click Add for each:
- Service Name:
Mideye_Server1_svc - Existing Server: select
Mideye_Server1 - Protocol:
RADIUS - Port:
1812
Repeat for each Mideye Server node.
4. Create a RADIUS monitor
Section titled “4. Create a RADIUS monitor”A RADIUS monitor periodically sends an authentication request to each Mideye Server to verify it is responding. The monitor uses a test account — this account does not need to exist in Mideye and will intentionally fail authentication.
add lb monitor Mideye_RADIUS_mon RADIUS \ -respCode 3 \ -userName fake_monitor_user \ -password fake_password \ -radKey <shared-secret> \ -LRTM DISABLED \ -retries 1 \ -interval 30 \ -resptimeout 10 \ -destPort 1812| Parameter | Value | Notes |
|---|---|---|
-respCode | 3 | Access-Reject — server is alive but user is invalid (expected) |
-userName | fake_monitor_user | Fake user for health probes (will appear in Mideye logs) |
-password | fake_password | Fake password |
-radKey | Shared secret | Must match the Mideye RADIUS client configuration |
-LRTM | DISABLED | Disable Least Response Time Method for monitor |
-retries | 1 | Number of retries before marking DOWN |
-interval | 30 | Probe interval in seconds |
-resptimeout | 10 | Timeout for each probe |
Navigate to Traffic Management → Load Balancing → Monitors and click Add:
- Name:
Mideye_RADIUS_mon - Type:
RADIUS - Destination IP:
0(inherits from bound service) - Destination Port:
0(inherits from bound service) - Retries:
1 - Select the Special Parameters tab:
- Response Code: remove default
2, add3 - User Name:
fake_monitor_user - Password:
fake_password - Rad Key: shared secret matching the Mideye RADIUS client
- Response Code: remove default
- Click Create.
Alternative: HTTP/HTTPS health check
Section titled “Alternative: HTTP/HTTPS health check”If Mideye Server exposes a health API endpoint, you can use an HTTP-ECV or HTTPS monitor instead of a RADIUS monitor. This avoids the authentication log noise.
See Server Monitoring for Mideye health API details and SSL service monitoring in the NetScaler documentation.
5. Bind the monitor to services
Section titled “5. Bind the monitor to services”Replace the default ping monitor with the RADIUS monitor on each service.
# Unbind the default ping monitorunbind service Mideye_Server1_svc -monitorName pingunbind service Mideye_Server2_svc -monitorName ping
# Bind the RADIUS monitorbind service Mideye_Server1_svc -monitorName Mideye_RADIUS_monbind service Mideye_Server2_svc -monitorName Mideye_RADIUS_mon- Navigate to Traffic Management → Load Balancing → Services.
- Select
Mideye_Server1_svcand click Edit. - Scroll to the Monitors section, click Add a binding.
- Select
Mideye_RADIUS_monand click Bind. - Remove the default
pingmonitor binding. - Click Done.
- Repeat for
Mideye_Server2_svc.
After binding, verify that the services show state UP — this means the RADIUS monitor is receiving the expected response code from Mideye Server.
6. Create the LB Virtual Server
Section titled “6. Create the LB Virtual Server”Create a RADIUS LB Virtual Server with SOURCEIP persistence. This ensures that all RADIUS packets within a single authentication transaction (Access-Request → Access-Challenge → Access-Request) reach the same Mideye Server backend.
add lb vserver Mideye_LB_vsrv RADIUS 172.16.3.199 1812 \ -persistenceType SOURCEIP \ -timeout 120 \ -cltTimeout 120| Parameter | Value | Notes |
|---|---|---|
| Protocol | RADIUS | |
| IP Address | 172.16.3.199 | Dedicated VIP on the ADC |
| Port | 1812 | |
-persistenceType | SOURCEIP | Required for RADIUS MFA — ensures challenge-response stickiness |
-timeout | 120 | Persistence timeout in seconds |
-cltTimeout | 120 | Client idle timeout |
Navigate to Traffic Management → Load Balancing → Virtual Servers and click Add:
- Name:
Mideye_LB_vsrv - Protocol:
RADIUS - IP Address Type:
IP Address - IP Address:
172.16.3.199(your dedicated VIP) - Port:
1812 - Under Persistence, set Type to
SOURCEIP. - Click OK / Done.
7. Bind services to the LB Virtual Server
Section titled “7. Bind services to the LB Virtual Server”bind lb vserver Mideye_LB_vsrv Mideye_Server1_svcbind lb vserver Mideye_LB_vsrv Mideye_Server2_svc- Navigate to Traffic Management → Load Balancing → Virtual Servers.
- Select
Mideye_LB_vsrvand click Edit. - Click Load Balancing Virtual Server Service Binding.
- Bind
Mideye_Server1_svcandMideye_Server2_svc. - Click Done.
After binding, refresh the Virtual Servers page — the state should show UP with green indicators if both services are healthy.
8. Use the LB VIP in your RADIUS authentication action
Section titled “8. Use the LB VIP in your RADIUS authentication action”Now update (or create) your Gateway RADIUS action to point to the LB Virtual Server VIP instead of a single Mideye Server IP:
# If updating an existing action:set authentication radiusAction Mideye_RADIUS \ -serverIP 172.16.3.199
# Or create a new action pointing to the LB VIP:add authentication radiusAction Mideye_RADIUS_LB \ -serverIP 172.16.3.199 \ -serverPort 1812 \ -authTimeout 35 \ -radKey <shared-secret> \ -radNASip DISABLED \ -authservRetry 1 \ -passEncoding papThen follow the steps in the RADIUS Authentication guide to create a policy and bind it to your Gateway Virtual Server (if not already done).
9. Save the configuration
Section titled “9. Save the configuration”save ns configComplete CLI example
Section titled “Complete CLI example”Here is the full configuration for a two-node Mideye Server setup:
# Enable load balancingenable ns feature LoadBalancing
# Server objectsadd server Mideye_Server1 172.16.0.100add server Mideye_Server2 172.16.0.101
# RADIUS servicesadd service Mideye_Server1_svc Mideye_Server1 RADIUS 1812add service Mideye_Server2_svc Mideye_Server2 RADIUS 1812
# RADIUS health monitoradd lb monitor Mideye_RADIUS_mon RADIUS \ -respCode 3 \ -userName fake_monitor_user \ -password fake_password \ -radKey <shared-secret> \ -LRTM DISABLED \ -retries 1 \ -interval 30 \ -resptimeout 10
# Bind monitor to services (replace default ping)unbind service Mideye_Server1_svc -monitorName pingunbind service Mideye_Server2_svc -monitorName pingbind service Mideye_Server1_svc -monitorName Mideye_RADIUS_monbind service Mideye_Server2_svc -monitorName Mideye_RADIUS_mon
# LB Virtual Server with SOURCEIP persistenceadd lb vserver Mideye_LB_vsrv RADIUS 172.16.3.199 1812 \ -persistenceType SOURCEIP \ -timeout 120 \ -cltTimeout 120
# Bind services to LB Virtual Serverbind lb vserver Mideye_LB_vsrv Mideye_Server1_svcbind lb vserver Mideye_LB_vsrv Mideye_Server2_svc
# RADIUS authentication action (pointing to LB VIP)add authentication radiusAction Mideye_RADIUS \ -serverIP 172.16.3.199 \ -serverPort 1812 \ -authTimeout 35 \ -radKey <shared-secret> \ -radNASip DISABLED \ -authservRetry 1 \ -passEncoding pap
# RADIUS authentication policyadd authentication radiusPolicy Mideye_RADIUS_pol ns_true Mideye_RADIUS
# Bind policy to Gateway Virtual Serverbind vpn vserver my_gateway -policy Mideye_RADIUS_pol -priority 100
# Savesave ns configVerification
Section titled “Verification”# Check service states (should show UP)show service Mideye_Server1_svcshow service Mideye_Server2_svc
# Check LB Virtual Server state and bound servicesshow lb vserver Mideye_LB_vsrv
# Check monitor statusshow lb monitor Mideye_RADIUS_mon
# Check statisticsstat lb vserver Mideye_LB_vsrvTroubleshooting
Section titled “Troubleshooting”| Symptom | Check |
|---|---|
| Authentication silently fails — no error, no reject | RADIUS source-IP mismatch. Mideye is responding directly to the VPN instead of through the LB. The VPN drops the response because the source IP is Mideye’s IP, not the LB VIP. See RADIUS response path above. Run tcpdump -i any udp port 1812 -nn on Mideye to verify the response destination. |
| Service state shows DOWN | Monitor is not receiving expected response code. Verify shared secret, response code (3), and RADIUS connectivity. |
| LB Virtual Server shows DOWN | All bound services are DOWN. Fix individual service health first. |
| Authentication works but only hits one server | SOURCEIP persistence is working as designed — requests from the same client IP go to the same backend. |
| Challenge-Response fails intermittently | Verify SOURCEIP persistence is configured on the LB Virtual Server. Without it, the OTP response may reach a different backend. |
| Monitor floods Mideye logs | Normal — the monitor sends periodic probes. Adjust -interval to reduce frequency, or use an HTTP health check instead. |
fake_monitor_user errors in Mideye logs | Expected. The monitor intentionally sends invalid credentials to verify the server is responsive. |
Related links
Section titled “Related links”Mideye documentation
Section titled “Mideye documentation”- Citrix ADC – RADIUS Authentication — configure the RADIUS action and policy
- RADIUS Clients — configure Mideye Server to accept requests from NetScaler
- Server Monitoring — Mideye health API for alternative health checks
- RADIUS Integrations — authentication flows and supported auth types
- Support Center — contact Mideye support for integration assistance
Official NetScaler documentation
Section titled “Official NetScaler documentation”- Set up basic load balancing — servers, services, virtual servers
- RADIUS service monitoring — RADIUS monitor configuration
- Persistence and persistent connections — SOURCEIP and other persistence types
- SSL service monitoring — HTTPS health check monitors
- Configure monitors in a load balancing setup — binding monitors to services