Something went wrong. Try again.
@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
Something went wrong. Try again.
PHP
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778<?php
/** * Parse the "X_FORWARDED_FOR" HTTP header to determine the original client * address. * * @param int $layers (optional) Number of devices to trust. * @return void */function preamble_trust_x_forwarded_for_header($layers = 1) { if (!is_int($layers) || ($layers < 1)) { echo 'preamble_trust_x_forwarded_for_header(<layers>): '. '"layers" parameter must an integer larger than 0.'."\n"; echo "\n"; exit(1); }
if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { return; }
$forwarded_for = $_SERVER['HTTP_X_FORWARDED_FOR']; if (!strlen($forwarded_for)) { return; }
$address = preamble_get_x_forwarded_for_address($forwarded_for, $layers);
$_SERVER['REMOTE_ADDR'] = $address;}
function preamble_get_x_forwarded_for_address($raw_header, $layers) { // The raw header may be a list of IPs, like "1.2.3.4, 4.5.6.7", if the // request the load balancer received also had this header. In particular, // this happens routinely with requests received through a CDN, but can also // happen illegitimately if the client just makes up an "X-Forwarded-For" // header full of lies.
// We can only trust the N elements at the end of the list which correspond // to network-adjacent devices we control. Usually, we're behind a single // load balancer and "N" is 1, so we want to take the last element in the // list.
// In some cases, "N" may be more than 1, if the network is configured so // that that requests are routed through multiple layers of load balancers // and proxies. In this case, we want to take the Nth-to-last element of // the list.
$addresses = explode(',', $raw_header);
// If we have more than one trustworthy device on the network path, discard // corresponding elements from the list. For example, if we have 7 devices, // we want to discard the last 6 elements of the list.
// The final device address does not appear in the list, since devices do // not append their own addresses to "X-Forwarded-For".
$discard_addresses = ($layers - 1);
// However, we don't want to throw away all of the addresses. Some requests // may originate from within the network, and may thus not have as many // addresses as we expect. If we have fewer addresses than trustworthy // devices, discard all but one address.
$max_discard = (count($addresses) - 1);
$discard_count = min($discard_addresses, $max_discard); if ($discard_count) { $addresses = array_slice($addresses, 0, -$discard_count); }
$original_address = end($addresses); $original_address = trim($original_address);
return $original_address;}