$trusted_proxies CIDRs/IPs. */ public static function resolve( string $remote_addr, ?string $xff, array $trusted_proxies ): string { if ( $xff === null || $xff === '' || $trusted_proxies === array() || ! self::in_any( $remote_addr, $trusted_proxies ) ) { return $remote_addr; } $hops = array_values( array_filter( array_map( 'trim', explode( ',', $xff ) ), static fn( string $h ): bool => filter_var( $h, FILTER_VALIDATE_IP ) !== false ) ); for ( $i = count( $hops ) - 1; $i >= 0; $i-- ) { if ( ! self::in_any( $hops[ $i ], $trusted_proxies ) ) { return $hops[ $i ]; } } return $hops[0] ?? $remote_addr; } /** @param list $cidrs */ public static function in_any( string $ip, array $cidrs ): bool { foreach ( $cidrs as $cidr ) { if ( self::in_cidr( $ip, $cidr ) ) { return true; } } return false; } public static function in_cidr( string $ip, string $cidr ): bool { $parts = explode( '/', $cidr, 2 ); $range = $parts[0]; $ipb = inet_pton( $ip ); $rb = inet_pton( $range ); if ( $ipb === false || $rb === false || strlen( $ipb ) !== strlen( $rb ) ) { return false; } $total = strlen( $ipb ) * 8; $bits = isset( $parts[1] ) ? (int) $parts[1] : $total; if ( $bits < 0 || $bits > $total ) { return false; } $bytes = intdiv( $bits, 8 ); $rem = $bits % 8; if ( $bytes > 0 && substr( $ipb, 0, $bytes ) !== substr( $rb, 0, $bytes ) ) { return false; } if ( $rem === 0 ) { return true; } $mask = 0xFF << ( 8 - $rem ) & 0xFF; return ( ord( $ipb[ $bytes ] ) & $mask ) === ( ord( $rb[ $bytes ] ) & $mask ); } }