| 6445 | |
| 6446 | /** |
| 6447 | * Determines the user's actual IP address and attempts to partially |
| 6448 | * anonymize an IP address by converting it to a network ID. |
| 6449 | * |
| 6450 | * Geolocating the network ID usually returns a similar location as the |
| 6451 | * actual IP, but provides some privacy for the user. |
| 6452 | * |
| 6453 | * $_SERVER['REMOTE_ADDR'] cannot be used in all cases, such as when the user |
| 6454 | * is making their request through a proxy, or when the web server is behind |
| 6455 | * a proxy. In those cases, $_SERVER['REMOTE_ADDR'] is set to the proxy address rather |
| 6456 | * than the user's actual address. |
| 6457 | * |
| 6458 | * Modified from https://stackoverflow.com/a/2031935/450127, MIT license. |
| 6459 | * Modified from https://github.com/geertw/php-ip-anonymizer, MIT license. |
| 6460 | * |
| 6461 | * SECURITY WARNING: This function is _NOT_ intended to be used in |
| 6462 | * circumstances where the authenticity of the IP address matters. This does |
| 6463 | * _NOT_ guarantee that the returned address is valid or accurate, and it can |
| 6464 | * be easily spoofed. |
| 6465 | * |
| 6466 | * @since 4.8.0 |
| 6467 | * |
| 6468 | * @return false|string The anonymized address on success; the given address |
| 6469 | * or false on failure. |
| 6470 | */ |
| 6471 | function wp_get_unsafe_client_ip() { |
| 6472 | $client_ip = false; |
| 6473 | |
| 6474 | // In order of preference, with the best ones for this purpose first. |
| 6475 | $address_headers = array( |
| 6476 | 'HTTP_CLIENT_IP', |
| 6477 | 'HTTP_X_FORWARDED_FOR', |
| 6478 | 'HTTP_X_FORWARDED', |
| 6479 | 'HTTP_X_CLUSTER_CLIENT_IP', |
| 6480 | 'HTTP_FORWARDED_FOR', |
| 6481 | 'HTTP_FORWARDED', |
| 6482 | 'REMOTE_ADDR', |
| 6483 | ); |
| 6484 | |
| 6485 | foreach ( $address_headers as $header ) { |
| 6486 | if ( array_key_exists( $header, $_SERVER ) ) { |
| 6487 | /* |
| 6488 | * HTTP_X_FORWARDED_FOR can contain a chain of comma-separated |
| 6489 | * addresses. The first one is the original client. It can't be |
| 6490 | * trusted for authenticity, but we don't need to for this purpose. |
| 6491 | */ |
| 6492 | $address_chain = explode( ',', $_SERVER[ $header ] ); |
| 6493 | $client_ip = trim( $address_chain[0] ); |
| 6494 | |
| 6495 | break; |
| 6496 | } |
| 6497 | } |
| 6498 | |
| 6499 | if ( ! $client_ip ) { |
| 6500 | return false; |
| 6501 | } |
| 6502 | |
| 6503 | $anon_ip = wp_privacy_anonymize_ip( $client_ip, true ); |
| 6504 | |
| 6505 | if ( '0.0.0.0' === $anon_ip || '::' === $anon_ip ) { |
| 6506 | return false; |
| 6507 | } |
| 6508 | |
| 6509 | return $anon_ip; |
| 6510 | } |