| | 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 | } |