2010-11-23 4 views
2

Eigentlich ist dies eine zweiteilige Frage:Validierung der Benutzer-IP und Formular-IP: Sollte ich ip2long verwenden?

Erstens ist ip2long ein guter IP-Validator? Angenommen jemand fügt eine IP in ein Formular ein und ich möchte bestätigen, dass es korrekt ist. Ist es in Ordnung, nur zu überprüfen, dass ip2long nicht FALSE zurückgibt?

Zweitens: Was denkst du über das Überprüfen der IP der Besucher und den Zugriff verweigern, wenn es keine gültige IP ist? Wenn ich die Ips meines Besuchers betrachte, finde ich manchmal Dinge wie "1.1 TIBURON" .. WTF ist das? Ich habe den Ausdruck "spoofed ip" gehört, ist das was es ist? Handelt es sich um Spam-Bots?

+0

Was ist die Datenquelle? Apache-Zugriffsprotokoll? – stillstanding

+0

Die IP wurde von $ _SERVER abgerufen und in einer MySQL-Datenbank gespeichert. – HappyDeveloper

Antwort

0

Hängt davon ab, wie gründlich Sie die Validierung wollen. Eine sehr einfache Überprüfung für wohlgeformte IP-Adressen wäre ein Regex in der Form von /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/. (Eigentlich ist SubniC Regex wahrscheinlich viel besser). Dies würde Ihren 1.1 fangen. TIBURON-Eintrag, weil es nicht gut geformt ist.

Ich bin mir nicht sicher, ob ip2long dies überprüft oder nur den Teil der Zeichenfolge, der nicht wie eine IP aussieht, einfach stillschweigend verwirft.

Ein weiterer Schritt könnten Sie ‚reserviert‘ IP-Adressen und Bereiche Block, wie 127.0.0.1, 255.255.255.255 usw.

Sie könnten auch eine schwarze Liste hinzufügen möchten, um herauszufiltern Anfragen von dubiosen Netzwerke, oder von Kunden, mit denen Sie in der Vergangenheit Probleme hatten.

Ich bin neugierig, wie dieser Eintrag überhaupt dort angekommen ist - ein Angreifer sollte diesen Wert nicht in $ _SERVER ['REMOTE_ADDR'] bringen können, außer er hat das zugrundeliegende Betriebssystem oder zumindest Apache kompromittiert (oder welchen Webserver Sie auch betreiben).

Sie sind nicht zufällig lesen die IP auf dem Client (mit Javascript)?

+0

Nein, ich habe nur PHP verwendet .. Ich habe eine Funktion verwendet, die versucht, die IP aus den verschiedenen $ _SERVER Optionen zu entnehmen. Ich weiß nicht viel über Sicherheit, aber ich benutzte einen bezahlten Host (Gottaddy), also denke ich (oder hoffe), das war nicht das Problem. ip2long gibt false für "1.1 tiburon" zurück, aber es gilt für "1.1". Ist 1.1 eine gültige IP? – HappyDeveloper

+0

1.1 ist nicht gültig, aber ich denke, ip2long ist hier großzügig und interpretiert es als 0.0.1.1. Haben Sie Zugriff auf die Zugriffsprotokolldateien von Apache? Diese sollten dir die tatsächliche IP geben, egal was passiert. – tdammers

+0

Oh ich verstehe. Nein, ich hatte in diesem Moment keinen Zugang dazu. Ich hoffe es passiert jetzt wieder, dass ich es tue. – HappyDeveloper

1

Wenn Sie nur bestätigen müssen, dass die IP-Adresse im Format korrekt ist, können Sie einen regulären Ausdruck wie den folgenden verwenden.

EDIT:

if (preg_match('/\A(?:^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$)\Z/im', $subject)) { 
    # Successful match 
} else { 
    # Match attempt failed 
} 

Wenn Sie gehen wollen weiter können Sie eine ping an die IP tun, um herauszufinden, ob es aktiv ist.

über Ihre zweite Frage, ich weiß nicht, was zu sagen, ich habe,

HTH nie das „1,1 TIBURON“ Ding gesehen

+0

Ich glaube nicht, dass Pingen so eine gute Idee ist. Viele Router/Firewalls reagieren nicht auf Ping und blockieren eingehenden Ping als Sicherheitsmaßnahme. Nicht in der Lage zu sein, etwas anzupingen bedeutet nicht, dass es nicht da ist. – tdammers

+0

dieser Regex funktioniert nicht für mich, es heißt "Trennzeichen darf nicht alphanumerisch oder Backslash sein". Wofür ist \ b? – HappyDeveloper

+0

Hallo, \ b steht für Wortgrenzen und es heißt, dass die IP nur in einem Wort (keine Leerzeichen) sein muss, probiere das Neue aus. – SubniC

0

Ich hatte diesen Code herum. Es ist eine Weile her und ich kann mich nicht mehr an einige Entscheidungen erinnern, aber ich versichere Ihnen, dass es gründlich getestet wurde
(eigentlich habe ich es nur ein wenig verändert, Variablen umbenannt und Kommentare hinzugefügt, also ist es möglich, dass ich einfach kaputt gegangen bin es :)

Sie können die get_ip_addr und is_private_ip_addr Funktionen nützlich finden.
get_ip_addr kann sowohl eine IP-Adresse als auch einen Hostnamen annehmen.

<?php 

function get_ip_addr($host){ 
    $long_ipaddr = my_ip2long($host); 
    $host = trim($host); 
    if($long_ipaddr !== false){ 
     $str_ip = long2ip($long_ipaddr); // Because of e.g. 245.254.245 
     return $str_ip; 
    } 

    $ip_addr = @gethostbyname($host); 
    if($ip_addr and $ip_addr != -1 ){ 
     return $ip_addr; 
    } 

    return false; 
} 

function my_ip2long($ipaddr){ 
    $long_ip = ip2long($ipaddr); 
    if($long_ip === false){ 
     return false; 
    } 

    // http://php.net/manual/en/function.ip2long.php says: 
    // Note: 
    // Because PHP's integer type is signed, and many IP addresses 
    // will result in negative integers, you need to use 
    // the "%u" formatter of sprintf() or printf() to get 
    // the string representation of the unsigned IP address. 
    $long_ip = sprintf("%u", $long_ip); 
    return $long_ip; 
} 

function ip2bin($ip){ 
    $octets = explode(".", $ip); 
    foreach($octets as $k => $v){ 
     $octets[$k] = str_pad(decbin($v), 8, "0", STR_PAD_LEFT); 
    } 
    return implode('', $octets); 
} 

function ip_in_range($ip, $prefix, $mask_len){ 
    $ip = ip2bin($ip); 
    $prefix = ip2bin($prefix); 

    $ip = substr($ip, 0, $mask_len); 
    $prefix = substr($prefix, 0, $mask_len); 

    // Watch out! Two numerical strings are converted to integers 
    // when you use ==. This is trouble for long integers. 
    // Using === skips this behaviour 
    return ($ip === $prefix); 
} 


function is_private_ip_addr($ipaddr){ 
    if("localhost" === $ipaddr) return true; 

    $long_ipaddr = my_ip2long($ipaddr); 
    if($long_ipaddr === false){ 
     return false; // Shouldn't be calling this! 
    } 
    // Info below obtained from http://bugs.php.net/bug.php?id=47435#c145655 
    // Not sure why 127.0.0.0/8 isn't mentioned ...? 
    // Also, in IPv6 there's the multicast address range: ff00::/8s 
    // 
    //  IPv4 private ranges 
    //  10.0.0.0/8  // private use network (rfc1918) 
    //  172.16.0.0/12 // private use network (rfc1918) 
    //  192.168.0.0/16 // private use network (rfc1918) 
    // 
    //  IPv4 reserved ranges 
    //  0.0.0.0/8  // "this" network (rfc1700) 
    //  169.254.0.0/16 // link local network (rfc3927) 
    //  192.0.2.0/24 // test net (rfc3330) 
    //  224.0.0.0/4 // Multicast (rfc3171) 
    //  240.0.0.0/4 // Reserved for Future Use (rfc1700) 
    // 
    //  IPv6 Private range 
    //  fc00::/7  // unique-local addresses (rfc4193) 
    //  
    //  IPv6 Reserved ranges 
    //  ::/128   // unspecified address (rfc4291) 
    //  ::1/128  // loopback address (rfc4291) 
    //  fe80::/10  // link local unicast (rfc4291) 
    //  2001:db8::/32 // documentation addresses (rfc3849) 
    //  5f00::/8  // 6Bone 
    //  3ffe::/16  // 6Bone 
    //  ::ffff:0:0/96 // IPv4-Mapped addresses (rfc4291) 
    //  2001:10::/28 // ORCHID addresses (rfc4843) 
    //  ::/0   // default unicast route address 
    // 
    // Anyways, this are the relevant RFCs: 
    // RFC 3330 (Sep 2002), "Special-Use IPv4 Addresses": 
    //        see section 3 for a nice table 
    // RFC 5156 (Apr 2008), "Special-Use IPv6 Addresses" 
    // 

    // Also, this function currently only deals with IPv4 addresses, 
    // since PHP's ip2long simply doesn't support IPv6 anyway. 
    // You can't currently even trust long ints to have 64 bit, 
    // so a 128 bit long int is out of the question. 

    if(ip_in_range($ipaddr, "127.0.0.0", 8)) return true; // Loopback 
    if(ip_in_range($ipaddr, "10.0.0.0", 8)) return true; // Private addresses (Class A range) 
    if(ip_in_range($ipaddr, "172.16.0.0", 12)) return true; // Private addresses (Class B range) 
    if(ip_in_range($ipaddr, "192.168.0.0", 16)) return true; // Private addresses (Class C range) 
    if(ip_in_range($ipaddr, "169.254.0.0", 16)) return true; // "This" network 
    if(ip_in_range($ipaddr, "192.0.2.0", 24)) return true; // "TEST-NET" (documentation and examples) 
    if(ip_in_range($ipaddr, "224.0.0.0", 4)) return true; // Multicast 
    if(ip_in_range($ipaddr, "240.0.2.0", 4)) return true; // Reserved for future use 

    return false; 
} 

Sie können diesen Code betrachten unter einer permissiven CC BY-SA freigegeben.
Tun Sie, was Sie wollen, aber wenn Sie es verbessern, sagen Sie uns bitte hier darüber.
Ich markiere diesen Beitrag Community Wiki ..

+0

Okay danke =). – HappyDeveloper

Verwandte Themen