Alexander Rehbein: Check: IP in IP-Ranges?

Hallo,

wie kann ich am einfachsten und am schonensten überprüfen, ob eine bestimmte IP in einer bestimmten IP-Range ist?

Ich habe dabei ca. 200-300 Ranges in einer DB gespeichert und muss diese auf eine IP hin ueberprüfen.

Als einfachstes dachte ich mir, ich könnte die IP-Grenzen (der Ranges) in 32-Bit-Zahlen umwandeln und die IP auch und dann ueber einfache größer/kleiner-Beziehungen feststellen, ob ein Fall eintritt:

// -------------------------------------------------------------------------------

// User muss gecheckt werden
    $ip = abs(ip2long($ip));

$query = 'SELECT ip_start, ip_end FROM al_iprange WHERE ('.$ip.' >= ip_start AND '.$ip.' <= ip_end)';

if ($debug_mode) { echo '<span class="debug">'.$query.'</span><br><br>'; }

$db_query = mysql_query($query);

if (mysql_num_rows($db_query) > 0) {
      // In einer verbotenen Range...
      echo '<h1>RANGE verboten</h1>';
      } else {
        echo '<h1>RANGE erlaubt</h1>';
        }

// -------------------------------------------------------------------------------

Aber irgendwie scheint das nicht zu klappen :( Kann mich jemand korrigieren, oder mir eine einfachere und/oder bessere Lösung nennen?

Vielen Dank im Voraus und schöne Grüße
Alexander Rehbein

  1. wenn du Scannen willst, da gibt es fertige tools... http://www.computec.ch/

    1. wenn du Scannen willst, da gibt es fertige tools... http://www.computec.ch/

      Nein ich möchte nicht scannen, sondern meine Seite vor bestimmten IP-Ranges "fernhalten".

      1. Moin Moin !

        wenn du Scannen willst, da gibt es fertige tools... http://www.computec.ch/

        Nein ich möchte nicht scannen, sondern meine Seite vor bestimmten IP-Ranges "fernhalten".

        Apache? Lies Dir in der Apache-Doku mal die mod_access-Doku durch. Das wirkt dann nicht nur für PHP, sondern für *alle* Resourcen.

        Du bist Dir bewußt, daß viele IP-Adressen dynamisch vergeben werden (PPP-Einwahl per Modem / ISDN /DSL)?

        Alexander

        --
        Nein, ich beantworte keine Fragen per eMail. Dafür ist das Forum da.
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
        1. Apache? Lies Dir in der Apache-Doku mal die mod_access-Doku durch. Das wirkt dann nicht nur für PHP, sondern für *alle* Resourcen.

          Das ist mir sehr wohl bewusst! Aber ich habe ca. 300-400 IP-Ranges, die ich nicht unbedingt alle in eine htaccess eintragen möchte.
          Außerdem muss ich auch nur eine Datei schützen (index.php - die alle anderen Seiten generiert). Und per PHP kann ich die Ranges einfach per DB durchforsten.

          Du bist Dir bewußt, daß viele IP-Adressen dynamisch vergeben werden (PPP-Einwahl per Modem / ISDN /DSL)?

          Ja das weiss ich sehr wohl, aber die Leute, vor denen ich meine Seite fernhalten möchte, die haben gewisse IP-Ranges...

  2. Moin Moin !

    Als einfachstes dachte ich mir, ich könnte die IP-Grenzen (der Ranges) in 32-Bit-Zahlen umwandeln und die IP auch und dann ueber einfache größer/kleiner-Beziehungen feststellen, ob ein Fall eintritt:

    Bitoperationen mit IP-Adresse, Netz-Adresse und Netz-Maske bringen es:

    Netz-Adresse: 10.1.0.0     = 0A 01 00 00
    Netz-Maske:   255.255.0.0  = FF FF 00 00
    IP-Adresse:   10.1.1.64    = 0A 01 01 40

    IP-Adresse bitweise und Netz-Maske ergibt Netzadresse, wenn die IP-Adresse im durch Netz-Maske und Netz-Adresse spezifizierten Netz liegt.

    0A 01 01 40 & FF FF 00 00 = 0A 01 00 00

    Andere IP-Adressen passen so nicht:

    IP-Adresse 2: 10.2.1.64 = 0A 02 01 40

    0A 02 01 40 & FF FF 00 00 = 0A 02 00 00 = 10.2.0.0 -> nicht das 10.1.0.0-Netz

    Die Broadcast-Adresse ergibt sich übrigens aus Netz-Adresse bitweise oder verknüpft mit der negierten Netz-Maske:

    0A 01 00 00 | !FF FF 00 00 = 0A 01 00 00 | 00 00 FF FF = 0A 01 FF FF = 10.1.255.255

    Alexander

    --
    Nein, ich beantworte keine Fragen per eMail. Dafür ist das Forum da.
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
    1. Hmm, vielen Dank - aber damit kann ich jetzt recht wenig anfangen!

      Das einzige was gegeben ist, ist die erste IP der Range und die Letzte und eben die zu überprüfende IP.

      Gibts nicht eine einfachere Lösung?

      1. Moin Moin !

        Hmm, vielen Dank - aber damit kann ich jetzt recht wenig anfangen!

        Das einzige was gegeben ist, ist die erste IP der Range und die Letzte und eben die zu überprüfende IP.

        Gibts nicht eine einfachere Lösung?

        Wie sind deine Ranges definiert?

        Alexander

        --
        Nein, ich beantworte keine Fragen per eMail. Dafür ist das Forum da.
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
        1. Wie sind deine Ranges definiert?

          Anfangs-IP und End-IP, also z.B. (local):

          192.168.0.0 - 192.168.10.255

          1. Moin Moin !

            Wie sind deine Ranges definiert?

            Anfangs-IP und End-IP, also z.B. (local):

            192.168.0.0 - 192.168.10.255

            Das sind 10 Netze à 256 Addressen:
            192.168.0.0 mask 255.255.255.0
            bis
            192.168.10.0 mask 255.255.255.0

            10 Prüfungen und Du bist durch - vorausgesetzt, Du speicherst die Netze in dieser Form (Netzwerkadresse und Netzwerkmaske).

            Damit kannst Du alles von einzelnen Hosts (mask 255.255.255.255) bis zum gesamten Internet (mask 0.0.0.0) erfassen.

            Alexander

            --
            Nein, ich beantworte keine Fragen per eMail. Dafür ist das Forum da.
            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
            1. Damit kannst Du alles von einzelnen Hosts (mask 255.255.255.255) bis zum gesamten Internet (mask 0.0.0.0) erfassen.

              Alexander

              Vielen Dank! Ich hab das entsprechende, was ich wissen wollte an anderer Stelle erfahren! Trotzdem danke für Deine Bemühungen!

  3. wie kann ich am einfachsten und am schonensten überprüfen, ob eine bestimmte IP in einer bestimmten IP-Range ist?

    Als einfachstes dachte ich mir, ich könnte die IP-Grenzen (der Ranges) in 32-Bit-Zahlen umwandeln und die IP auch und dann ueber einfache größer/kleiner-Beziehungen feststellen, ob ein Fall eintritt:

    Richtig.

    // User muss gecheckt werden
        $ip = abs(ip2long($ip));

    Das geht in die Hose. Nehmen wir mal ein 4-bittiges Beispiel:

    8421
         ----
      14 1110
      -2 1110
       2 0010

    Wie Du siehst, entspricht die "Adresse" 14 der Binärzahl 1110. Da ip2long() eine vorzeichenbehaftete Zahl ausspuckt, gibt die Funktion die Dezimalzahl -2 zurück. Machst Du daraus jetzt mit abs() einen positiven Wert, erhältst Du 0010, und das wiederum entspricht nicht dem ursprünglichen Wert 1110 (14).

    Benutze wie in der PHP-Anleitung angegeben sprintf() mit dem Platzhalter %u. %u interpretiert die übergebenen Daten als vorzeichenlos und gibt dementsprechend für 1110 auch tatsächlich 14 aus.

    $query = 'SELECT ip_start, ip_end FROM al_iprange WHERE ('.$ip.' >= ip_start AND '.$ip.' <= ip_end)';

    $query = sprintf("SELECT ip_start,ip_end FROM al_iprange WHERE %u>=ip_start AND %u<=ip_end)",$ip);

    Ich gehe mal davon aus, daß auch Dezimalzahlen in Deiner Tabelle hast.

    Aber irgendwie scheint das nicht zu klappen :(

    "Geht nicht", das ist eine Fehlerbeschreibung, wie ich sie liebe :/ So überaus präzise und ausführlich, daß man sich vor Informationen garnicht mehr retten kann.
    Ist Dir das Problem nicht wichtig genug, daß Du nichtmal ein paar Beispielzahlen mitliefern konntest?

    Gruß,
      soenk.e

    1. "Geht nicht", das ist eine Fehlerbeschreibung, wie ich sie liebe :/ So überaus präzise und ausführlich, daß man sich vor Informationen garnicht mehr retten kann.
      Ist Dir das Problem nicht wichtig genug, daß Du nichtmal ein paar Beispielzahlen mitliefern konntest?

      Gruß,
        soenk.e

      Vielen Dank für Deine Hilfe - ich hab an anderer Stelle genau das erfahren was ich wollte (einige Antworten weiter oben).

      Danke für Deine Mühe und Hilfe!

  4. Hi!

    Wie es aussieht schient ip2long bei PHP nicht das zurückgeben was Du erwartest, ich habe keine Ahnung ob das beabsichtigt ist, nur weiß ich das vergleichbare Funktionen z.B. in MySQl was anderes zurückgeben.

    Damals, als ich nicht wusste das es diese Funktion gibt, habe ich mir mal eine eigene geschreiben:

    function my_ip2long ($ip) {
      $num = explode(".", $ip);
      return $num[0]*16777216 + $num[1]*65536 + $num[2]*256 + $num[3];
    }

    echo my_ip2long ('192.168.0.1');

    Das sollte Funktionieren, ich würde die IPs in der DB aber im LONG-Format speichern, dann nur die aktuelle IP umrechnen und vergleichen.

    Grüße
    Andreas

    1. function my_ip2long ($ip) {
        $num = explode(".", $ip);
        return $num[0]*16777216 + $num[1]*65536 + $num[2]*256 + $num[3];
      }

      echo my_ip2long ('192.168.0.1');

      Genau das habe ich gesucht! Ich speicher naemlich die "kleinste" und "größte" IP der Range in der DB im Long-Format und vergleiche diese dann mit der entsprechenden IP!

      Vielen vielen Dank und schöne Grüße!