2011-09-03 3 views
3

Je suis un développeur iphone - nouveau sur le web dev, alors soyez patient!
J'utilise actuellement MAMP pour les tests locaux.Comment gérer les adresses IPv6 avec IPv4 PHP

J'ai une section hautement sécurisée sur mon site. Avec exiger un utilisateur/passe - il vérifie également l'adresse IP de l'utilisateur. Si le compte n'a pas déjà été utilisé depuis cette adresse IP, il ajoutera cette adresse IP, ainsi qu'un identifiant unique, à une table d'attente et enverra à l'utilisateur un courrier électronique lui demandant de confirmer l'accès à son compte depuis cet emplacement.

Si l'utilisateur se connecte et que son adresse IP ne correspond à aucune adresse IP associée à son ID utilisateur dans ma table 'allowed', il exécute la tâche ci-dessus et reçoit un e-mail.

Le code que j'utilise pour générer l'URL du lien qu'ils cliquent sur ressemble un peu à ceci:

if (preg_match('/^127./',$ip)) { 
    // accessed from this machine 
    $val_url = "http://localhost:8888/mywebsite/admin/aproove_ip.php?email=$admin_email&val=$hash"; 
} 
else if (preg_match('/^192\.168./',$ip)) { 
    // accessed form a local networked computer 
    $val_url = "http://super.local:8888/mywebsite/admin/aproove_ip.php?email=$admin_email&val=$hash"; 
    // note super.local is my machine's address, 8888 is MAMP port 
} 
else { 
    // accessed from the WWW 
    $val_url = "http://www.mywebsite.com/admin/aproove_ip.php?email=$admin_email&val=$hash"; 
} 

Maintenant, cela a parfaitement fonctionné lors des tests sur mon ordinateur. Cependant, j'ai décidé (ne me demandez pas pourquoi) de tester depuis mon iPod Touch et dans l'e-mail qu'il m'a envoyé (pour valider l'adresse IP), il m'a donné l'adresse complète en ligne comme si elle avait été accédée depuis le WWW (c'est-à-dire que ni l'une ni l'autre des regex n'étaient satisfaites). J'ai regardé dans la table d'attente qui contient les demandes, et l'adresse IP demandée était: fe80::da30:62ff:fe18:6681.

Je suppose que c'est ipv6? - Ce que je dois savoir est la suivante:

  • Dois-je attendre ipv6 addressess pour frapper mon site quand il va vivre?
  • Comment puis-je savoir si elle était une demande locale (comme mes regex est pour 192.168 ... et 127 ...)

Je vous serais très reconnaissant des conseils sur ce que je trouve vraiment déroutant

+1

+1 de vouloir rendre votre code IPv6 compatible! Trop de programmes écrits aujourd'hui ne prennent pas en charge IPv6 même si les adresses IPv4 sont déjà épuisées. – snap

Répondre

7

Si vous voulez vous assurer qu'aucune connexion IPv6 n'arrive, vous pouvez ajouter Listen 0.0.0.0:80 à votre configuration apache. Mais la plupart des hébergeurs ne supportent pas IPv6 de toute façon (je sais, nous sommes en 2011), donc il est très peu probable que les gens puissent même se connecter via IPv6. La seule raison pour laquelle vous voyez cela est parce que bonjour (ce qui rend le travail d'adresse .local) fonctionne sur IPv6.

Si vous voulez obtenir votre code IPv6 prêt, presque aucun changement ne doit être fait car la plupart des fonctions IP PHP fonctionnent à la fois sur IPv4 et sur IPv6. Le seul changement que je me souviens avoir fait était d'augmenter le type de données varchar dans la table MySQL à la longueur maximale d'une adresse IPv6 (39).

Je ne suis pas sûr que IPv6 joue par les mêmes règles de subnet que IPv4, mais je pense qu'il serait un peu plus difficile de valider une adresse IPv6 est locale.

EDIT:

fe80::/10 semble adresses lien local, il pourrait être aussi simple que de vérifier les 4 premiers chiffres.

+0

merci! - déjà fait mes varchar 39 chars longtemps - je suppose que je ne devrais pas vraiment me soucier de bonjour alors, c'est seulement pour les tests, et à la fin quand il est en ligne il fera ce que je veux qu'il fasse, IPv6 ou pas! –

+3

Vous ne devriez pas utiliser varchar pour stocker les adresses IP - que ce soit v4 ou v6. Il vous empêche de les interroger efficacement avec un masque de bits, et gaspille beaucoup de stockage. Veuillez utiliser INET_ATON() et INET_NTOA() pour stocker et récupérer (respectivement) les adresses IP dans MySQL. –

+2

Pour la plupart des applications de stockage d'IP dans les applications générales, il suffit de tracer un utilisateur, et comme MySQL ne prouve pas la manière native de stocker l'IP de manière lisible, je n'utilise normalement que varchar pour plus de commodité (surtout IPv6 ou IPv4). –

2

Pour voir si une adresse IPv6 est locale, vous devez savoir quelles adresses sont utilisées localement. IPv6 ne fait pas NAT (habituellement). Certains réseaux utilisent ULA (adresses locales uniques) en interne, mais beaucoup utilisent simplement les adresses qu'ils reçoivent du FAI en interne.

Une chose que vous devez prendre en compte est que certains (la plupart? Ces jours-ci) utilisent des extensions de confidentialité.Cela signifie que leurs adresses IPv6 changeront avec le temps. Cela entraînera une croissance importante de votre table, et l'utilisateur se ré-authentifiera encore et encore. Je pense que votre meilleure option est de stocker uniquement le sous-réseau (les 64 premiers bits) et de faire correspondre cela. Juste au cas où vous ne connaissez pas la syntaxe d'adresse IPv6: les adresses utilisent des chiffres hexadécimaux et ont la forme ssss: ssss: ssss: ssss: nnnn: nnnn: nnnn: nnnn où s est le sous-réseau et n est le nœud /hôte. Les zéros en tête de chaque bloc de 4 chiffres sont omis, et plusieurs blocs de 0 sont remplacés par :: une fois. Donc fe80::da30:62ff:fe18:6681 est actuellement . Mon propre serveur Web a l'adresse 2001:4038:0:16::16, qui correspond à 2001:4038:0000:0016:0000:0000:0000:0016, et le sous-réseau est 2001:4038:0:16::/64.

Exemple de code pour obtenir le sous-réseau à l'adresse:

<?php 

# Get the original IP address, for example from the command line 
$original_ip_str = $argv[1]; 

# Converto to binary form (suppress errors, we handle them) 
$original_ip_bin = @inet_pton($original_ip_str); 
if ($original_ip_bin === FALSE) { 
    $subnet_str = FALSE; 
    $subnet_bin = FALSE; 
} else { 
    if (strlen($original_ip_bin) == 16) { 
    # IPv6: Replace the last 64 bits with zeroes 
    $subnet_bin = substr_replace($original_ip_bin, str_repeat("\000", 8), -8); 
    } 

    # Convert the result back to readable form (optional) 
    $subnet_str = inet_ntop($subnet_bin); 
} 

# Show the result 
echo "IPv6 address: $original_ip_str\n"; 
echo "IPv6 subnet: $subnet_str\n"; 
+0

pourriez-vous fournir du code pour simplement obtenir le sous-réseau à partir d'une adresse IPv6? - puis je stocker le code dans ma base de données ... –

+0

Bien sûr! Code ajouté dans la réponse –

Questions connexes