PHP Aus welchem Land kommt die IP ?

-Rayz-

Lieutenant
Registriert
Okt. 2010
Beiträge
897
Hallo,

ist es irgendwie möglich, herauszufinden, ob jemand aus der Schweiz eine Webseite aufruft außer über die eingestellte Browsersprache?
Hier gibt es ja eine ewig lange Auflistung von IP Blöcken, die zur Schweiz gehören.
Schweizer IPs

Gibt es da nicht eine elegantere Lösung ...?


Gruß -Rayz-
 
Zumal eingestellte Sprache auch nicht zuverlässig sein muss. Zum Beispiel gibt es für die Schweiz ein fr-ch IT-ch und de-Ch Region Layout (Und es soll ein paar freaks geben die Verwenden ein en-int oder en-us System
 
Versuche mich gerade an geoip.
Die Freeware Versionen reichen leider nicht aus. Dafür ist kommen zuviele Nutzer auf die Homepage.
Ergänzung ()

Hab nun eine Datenbank gefunden und diese soweit angepasst, dass ich nur noch die IP Bereiche für die Schweiz habe.
Allerdings sind die noch immer 4800 Einträge mit IP Bereichen.. (IPv4 und v6).

Wie kann ich nun eine PHP oder SQL Abfrage formulieren, welche hier performant arbeitet?

Ich bekomme über $_SERVER["REMOTE_ADDR"]; ja die IP, hier entferne ich zuerst die Zeichen damit ich nur noch die Zahlen habe.

Schicke ich an die Datenbank dann einfach:

WHERE IP BETWEEN Wert1 AND Wert2

?

Gruß Rayz
 
kommt wohl darauf an, in welchem format die datenbank vorliegt. bei der groesse des datensatzes wuerde ich das tatsaechlich eher in der datenbank loesen wollen (statt alle daten zu holen und dann php rechnen zu lassen), und dazu koenntest du z.b. die datenbank preprocessen indem du jedes oktett in ein eigenes int-feld schreibst. dann kannst du $_SERVER["REMOTE_ADDR"] nach punkten splitten und eine verANDete BETWEEN-abfrage formulieren. sollte das effizienteste sein.
 
Im Moment läuft es so, dass ich die IP Adresse validiere und anschließend in einen Integer umwandle.
Die Abfrage lautet dann einfach:

"SELECT country FROM db1 WHERE ip_start<=$ip AND ip_end>=$ip";

Wurde in db1 (v4) nichts gefunden, suche ich in der db2 (v6)

Läuft eigentlich... bisher :D
 
-Rayz- schrieb:
Im Moment läuft es so, dass ich die IP Adresse validiere und anschließend in einen Integer umwandle.
Die Abfrage lautet dann einfach:

"SELECT country FROM db1 WHERE ip_start<=$ip AND ip_end>=$ip";

Wurde in db1 (v4) nichts gefunden, suche ich in der db2 (v6)

Läuft eigentlich... bisher :D

Bei 4000 Blöcken würd ich mir da gar keinen Harten machen und die in Php als array hinterlegen, Db kann man da auch machen aber wenn ich mir überlege dass die Blöcke wild verteilt sein können und man das ab und an mal aktualisieren muss würd ich da gar nicht den Umweg über die Db nehmen. Wenn du das in Php als array hinterlegst läuft das in einem foreach inklusive Umrechnung und Vergleich fixer durch, als du auch nur die Verbindung zur Db aufgebaut hast....
 
naja, einfach persistente verbindung benutzen. macht bei high volume-webseiten eh sinn.

fuer 'ne "durchschnittliche" ip (128.128.128.128) hast in 'nem speicherformat wie
PHP:
$blocks = array(
  array(2155905152, 2155905152),
  // ...
)
minimum 30 zeichen pro eintrag, oder ~120KB an literalen, die fuer jeden aufruf von php geparsed werden muessen. waehrenddessen sind rdbms stark optimiert und cachen ganz viel. denke die persistente sql-variante gewinnt da performancemaessig schon sehr deutlich.
 
Benutz einfach postgreSQL dort gibt es inet als datentyp.
Der kann ipv4 und ipv6 speichern: https://www.postgresql.org/docs/9.6/static/datatype-net-types.html
und da du in bereichen arbeiten willst kannst du dir auch ein inet range type anlegen womit du die grenzen lower/upper in einem feld
speichern kannst: http://illuminatedcomputing.com/posts/2016/06/inet-range/
weiter vorteil von range neben der kompakten form,
man kan unique index drüber packen und so garantieren das es keine überschneidungen be iden blöcken gibt.
 
Zuletzt bearbeitet:
bog schrieb:
...minimum 30 zeichen pro eintrag, oder ~120KB an literalen, die fuer jeden aufruf von php geparsed werden muessen. waehrenddessen sind rdbms stark optimiert und cachen ganz viel. denke die persistente sql-variante gewinnt da performancemaessig schon sehr deutlich.

Würde ich fast bezweifeln, selbst persistent hast du den Overhead vom Netzwerk, und da kommts halt drauf an wie gut/schlecht die Datenbank angebunden ist. Cache hin oder her, imho ist das array da fünf mal geparsed und linear durchsucht eh du die Antwort von der Db hast, und da hast du dir noch keine Gedanken um eine effiziente Ablage im array gemacht(wenn ich Blöcke hab kann ich zb den Block als Schlüssel ins Array packen ala 192.168.1.* und dann drei Abfragen auf 192.*, 192.168.* Und 192.168.1.* starten, dann hätte man nur noch 3 Einträge vom array angefasst statt 4000, kommt natürlich auf die vorliegenden Daten an).

_Wenn_ es jetzt wirklich eine Website mit viel Traffic währe, würde der Kollege kaum hier fragen, ich denke das wird sich eh in einem Bereich bewegen, in dem beide Lösungen absolut ausreichen. Für High Performance Belange müsste man sich Imho eh mal die halbe Stunde nehmen und beides benchen, aber ich glaube wirklich dass ein array mit 4000 Einträgen fixer geparsed und durchsucht ist, als du bei 10gbit Netzwerk auch nur rechnerisch die Antwort hättest, also Anfrage hin, Dienst ansprechen, bissl Db Gerödel, Antwort zurück. Das summiert sich immer ganz schön(mal abgesehen von ausgelasteten Datenbankservern und dass du mit der Php Lösung einen potentiellen Flaschenhals bei jedem Request entfernst).
Letztendlich hängt es (glaube ich) an der Wartbarkeit: wenn ich, um die Ip Bereiche einzupflegen, in Php 30 Sekunden weniger brauche, würde ich das machen, sonst die Db Lösung.

Und mal davon ab: gesetzt dem Fall der Te arbeitet mit Sessions und prüft das nur einmalig ab, scheißt sich das bei einer normalen Website gegenüber den heftigeren Abfragen sowas von weg, dass wie hier Mikrooptimierungen diskutieren für eine Seite, auf der ganz andere Kaliber von Suchen laufen. Schöne hypothetische Diskussion, aber sinnfrei (so in der Art ;))
 
mambokurt schrieb:
Für High Performance Belange müsste man sich Imho eh mal die halbe Stunde nehmen und beides benchen,

glaube dabei koennen wir's belassen. ich sehe durchaus die moeglichkeit, dass eine bei potenziell mehreren seitenkomponenten inkludierte 120KB datei die response times durchaus drueckt. das hauptargument war auch das datenbank-caching und die implizierte optimierung der anfragen, dass man durch datenstrukturspielereien von n in php auf irgendeinen logarithmus von n kommt ist klar (ist aber immernoch lahmes php ;)). fuer die wahrheit braeucht's jetzt natuerlich die komplette quellensammlung der anwendung.

mambokurt schrieb:
Letztendlich hängt es (glaube ich) an der Wartbarkeit: wenn ich, um die Ip Bereiche einzupflegen, in Php 30 Sekunden weniger brauche, würde ich das machen, sonst die Db Lösung.
das ist sowieso der beste punkt. ausschlaggebend sollte wohl am ehesten sein, ob, oder genauer mit welcher frequenz diese ip bloecke sich aendern. IPv4 mag recht ausgekartet erscheinen, aber IPv6 z.B. ist wieder ein ganz anderes feld, bei dem man sicher immer mal wieder an datenbestaenden fuer eben solche lookups feilen darf.

cheers. :)
 
Zurück
Oben