HOWTO · PHP
Benutzer-IP-Adresse in PHP abrufen
Dieses Tutorial zeigt, wie Sie die IP-Adresse des Benutzers in PHP erhalten
Auf dieser Seite
Um die Netzwerkadresse einer PHP-Anfrage auszulesen, beginnen Sie mit $_SERVER['REMOTE_ADDR']. Sie bezeichnet den Peer, der die Verbindung zum Webserver hergestellt hat. Steht ein Reverse-Proxy vor der Anwendung, kann dieser Peer der Proxy statt des Besuchers sein. Anfrage-Header zum Proxy sind nur dann verwendbar, wenn Ihre Anwendung eine ausdrückliche Vertrauenskonfiguration für den Proxy hat, der sie bereitstellt und validiert.
Verbindungsadresse mit $_SERVER['REMOTE_ADDR'] auslesen
$_SERVER ist eine PHP-Superglobale mit Informationen zu Server und Anfrage. Das Element REMOTE_ADDR enthält die Adresse des Peers, der mit dem Server verbunden ist, der die Anfrage bearbeitet. Bei einer direkten Verbindung ist das in der Regel der verbindende Client. Hinter einem Load Balancer oder Reverse-Proxy ist es häufig die Adresse des Proxys. Welche Werte PHP erhält, hängt von der Konfiguration des Webservers und des Proxys ab. Daher lässt sich dieser Wert nicht als garantierte Adresse des Endbenutzers bezeichnen.
Bei einer lokalen Anfrage kann der Peer die IPv6-Loopback-Adresse ::1 sein. Loopback-Adressen verweisen auf den lokalen Rechner; ::1 ist die IPv6-Loopback-Adresse und entspricht der IPv4-Adresse 127.0.0.1. Der genaue Wert hängt vom lokalen Server und der Verbindung ab. Weitere Informationen finden Sie in dieser Erläuterung zur Loopback-Adresse.
Das folgende ausführbare Beispiel setzt einen repräsentativen Serverwert, damit der Zugriff in sich geschlossen ist. display_output bleibt auf false; das Beispiel liest also die Adresse aus, ohne sie als Ausgabe anzuzeigen. In einer Anwendung können Sie den Wert je nach Bedarf für die Antwort oder Protokollierung verwenden. Ein englischer Ausgabetext in einem unverändert übernommenen Beispiel bleibt Englisch.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
<?php
$_SERVER['REMOTE_ADDR'] = '::1';
$peerAddress = $_SERVER['REMOTE_ADDR'];
$display_output = false;
if ($display_output) {
echo "The connected peer is: " . $peerAddress . PHP_EOL;
}
?>
Bei einer echten Anfrage verwenden Sie den vom Server bereitgestellten Wert $_SERVER['REMOTE_ADDR'] statt eines Beispielwerts. Die Referenz zu Servervariablen im PHP-Handbuch beschreibt die verfügbaren Einträge in $_SERVER.
Proxy-Header nur verwenden, wenn der Proxy vertrauenswürdig ist
PHP kann Anfrage-Header als $_SERVER-Einträge wie HTTP_X_FORWARDED_FOR und HTTP_CLIENT_IP bereitstellen. Ihr Vorhandensein beweist nicht, dass sie die Adresse eines Besuchers enthalten: Ein Client kann eigene Headerwerte senden, und ein Proxy kann sie beibehalten, ergänzen oder ersetzen. Insbesondere kann HTTP_X_FORWARDED_FOR eine durch Kommas getrennte Kette statt einer einzelnen Adresse enthalten. Wählen Sie nicht einfach den ersten Wert aus und bezeichnen Sie ihn als echte Clientadresse, ohne die dokumentierten Vertrauensregeln Ihrer Infrastruktur anzuwenden.
Verwenden Sie einen weitergeleiteten Wert nur dann, wenn der Verbindungs-Peer einem Proxy entspricht, dem Ihre Anwendung ausdrücklich vertraut, und dieser Proxy so konfiguriert ist, dass er vom Client gesetzte Weiterleitungs-Header entfernt oder validiert. Die Liste vertrauenswürdiger Proxys muss zu Ihrer Bereitstellung passen; übernehmen Sie Beispieladressen nicht als Produktionskonfiguration. Ist der Peer nicht vertrauenswürdig, verwenden Sie REMOTE_ADDR. Für HTTP_CLIENT_IP gilt dasselbe Vertrauensproblem; der Header eignet sich nicht als Sonderlösung für gemeinsam genutzte Internetverbindungen.
Dieses ausführbare Snippet zeigt eine Bereitstellung, in der der vertrauenswürdige Proxy X-Forwarded-For mit einer einzelnen validierten Adresse überschreibt. Ersetzen Sie die Beispieladresse des Proxys und die Validierungsregeln durch die für Ihre Infrastruktur festgelegten Werte. Das Snippet gibt für diese repräsentativen Werte die ausgewählte weitergeleitete Adresse aus. Eine Kette mit mehreren Proxys wird darin nicht ausgewertet. Ein englischer Ausgabetext im unverändert übernommenen Beispiel bleibt Englisch.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
<?php
$_SERVER['REMOTE_ADDR'] = '192.0.2.10';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '198.51.100.24';
$trustedProxies = ['192.0.2.10'];
$peerAddress = $_SERVER['REMOTE_ADDR'];
if (in_array($peerAddress, $trustedProxies, true)
&& isset($_SERVER['HTTP_X_FORWARDED_FOR'])
&& filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP) !== false) {
$clientAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$clientAddress = $peerAddress;
}
echo "Selected address: " . $clientAddress . PHP_EOL;
?>
Selected address: 198.51.100.24
Die Dokumentation zu filter_var() erläutert die hier verwendete Validierungsfunktion. Zu prüfen, ob eine Zeichenfolge eine IP-Adresse ist, belegt nicht, dass sie aus einer vertrauenswürdigen Quelle stammt. Diese Vertrauensentscheidung ergibt sich aus der Prüfung des Peers und der Proxy-Konfiguration. Leitet Ihr Proxy eine Kette weiter, verwenden Sie ein Framework oder sorgfältig geprüften Code, der die Kette gemäß den genauen Regeln für vertrauenswürdige Proxys Ihrer Bereitstellung durchläuft.
Bedingten Ausdruck als kompakte Ausweichlösung verwenden
Ein übersichtlicher if/elseif/else-Block lässt sich in der Regel leichter prüfen, besonders wenn er eine Prüfung auf vertrauenswürdige Proxys enthält. Ein bedingter Ausdruck kann dieselbe Auswahl kompakt darstellen, macht einen nicht vertrauenswürdigen Header aber nicht sicher. Das folgende ausführbare Beispiel prüft, ob der Proxy vertrauenswürdig ist, und verwendet dieselbe zuvor beschriebene Richtlinie: eine einzelne Adresse, die der Proxy überschreibt. Die Serverwerte sind repräsentativ; ausgegeben wird die ausgewählte weitergeleitete Adresse. Ein englischer Ausgabetext im unverändert übernommenen Beispiel bleibt Englisch.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
<?php
$_SERVER['REMOTE_ADDR'] = '192.0.2.10';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '198.51.100.24';
$trustedProxies = ['192.0.2.10'];
$peerAddress = $_SERVER['REMOTE_ADDR'];
$forwardedAddress = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
$clientAddress = in_array($peerAddress, $trustedProxies, true)
&& filter_var($forwardedAddress, FILTER_VALIDATE_IP) !== false
? $forwardedAddress
: $peerAddress;
echo "Selected address: " . $clientAddress . PHP_EOL;
?>
Selected address: 198.51.100.24
Die Reihenfolge der Ausweichwerte ist bewusst gewählt: Akzeptieren Sie die validierte weitergeleitete Adresse nur, wenn der verbundene Peer auf der Liste vertrauenswürdiger Proxys steht. Andernfalls behalten Sie die Adresse des verbundenen Peers bei. Klammern können verschachtelte bedingte Ausdrücke verständlicher machen, doch verschachtelte ternäre Ausdrücke sind schwerer zu warten und ersetzen die Vertrauensprüfungen nicht. Stimmen Sie das Header-Verhalten des Proxys und die Zulassungsliste der Anwendung aufeinander ab, damit ein Client seinen eigenen Header nicht als vertrauenswürdige Eingabe einschleusen kann.