Skip to content
← Back to Functions
Code

IP Risk Normalizer

Normalizes IP data and assigns risk signals without blindly trusting proxy headers.

Function signature

ogNormalizeClientIpRisk(server_data = array(), trusted_proxies = array())

Categories

  • Security

Parameters

server_dataServer header data, normally copied from server environment data by caller. Recognized keys: `HTTP_X_FORWARDED_FOR`, `REMOTE_ADDR`.trusted_proxiesApproved proxy IP addresses.

Return value

Short public-safe status message.

  • client_ip
  • remote_addr
  • source
  • risk_score
  • risk_flags

Compatibility

Existing function name and call order preserved; metadata signature corrected to source.

Minimum PHP version: 7.4

Security notes

Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets out of public output.

Code

<?php

/*
 * Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
 * Free for personal and internal use. Paid project use requires visible credit
 * to Jeffery L. Paris. Corporate use requires a paid license fee unless a
 * separate written license states otherwise.
 */

/**
 * Normalizes IP data and assigns risk signals without blindly trusting proxy headers.
 *
 * Primary use case: Security logs, rate limits, admin alerts.
 * Typical inputs: server headers, trusted proxy config.
 * Typical output: IP and risk metadata.
 *
 * Implementation note: Only trust forwarded headers from known proxies.
 *
 * @param array $server_data Server header data, normally copied from $_SERVER by caller.
 * @param array $trusted_proxies Approved proxy IP addresses.
 * @return array Structured result data with success, message, and data keys.
 */
function ogNormalizeClientIpRisk($server_data = array(), $trusted_proxies = array()) {
	$result = array(
		'success' => false,
		'message' => '',
		'data' => array()
	);

	if (!is_array($server_data)) {
		$server_data = array();
	}
	if (!is_array($trusted_proxies)) {
		$trusted_proxies = array();
	}

	$remote_addr = '';
	if (!empty($server_data['REMOTE_ADDR'])) {
		$remote_addr = trim((string)$server_data['REMOTE_ADDR']);
	}

	$client_ip = $remote_addr;
	$source = 'remote_addr';
	$trusted_proxy_used = false;

	if (!empty($remote_addr) && in_array($remote_addr, $trusted_proxies, true)) {
		if (!empty($server_data['HTTP_X_FORWARDED_FOR'])) {
			$forwarded_parts = explode(',', (string)$server_data['HTTP_X_FORWARDED_FOR']);
			$forwarded_ip = trim($forwarded_parts[0]);
			if (filter_var($forwarded_ip, FILTER_VALIDATE_IP)) {
				$client_ip = $forwarded_ip;
				$source = 'trusted_x_forwarded_for';
				$trusted_proxy_used = true;
			}
		}
	}

	if (empty($client_ip) || filter_var($client_ip, FILTER_VALIDATE_IP) === false) {
		$result['message'] = 'Client IP could not be validated.';
		return $result;
	}

	$risk_score = 0;
	$risk_flags = array();
	if (filter_var($client_ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
		$risk_score += 20;
		$risk_flags[] = 'private_or_reserved_ip';
	}
	if (!$trusted_proxy_used && !empty($server_data['HTTP_X_FORWARDED_FOR'])) {
		$risk_score += 10;
		$risk_flags[] = 'untrusted_forwarded_header_present';
	}

	$result['success'] = true;
	$result['message'] = 'Client IP risk normalized.';
	$result['data'] = array(
		'client_ip' => $client_ip,
		'remote_addr' => $remote_addr,
		'source' => $source,
		'risk_score' => $risk_score,
		'risk_flags' => $risk_flags
	);

	return $result;
}