Как обращаться с адресами IPv6 вместе с IPv4 PHP

Я разработчик iphone – новый для веб-разработчиков, поэтому, пожалуйста, будьте терпеливы!
В настоящее время я использую MAMP для локального тестирования.

У меня очень безопасный раздел на моем сайте. Наряду с требованием пользователя / пароля – он также проверяет IP-адрес пользователя. Если учетная запись не использовалась ранее с этого IP-адреса, она добавит этот IP-адрес вместе с уникальным идентификатором в таблицу хранения и вызовет пользователю электронное письмо с просьбой подтвердить доступ к ним из своей учетной записи из этого места.

Если пользователь входит в систему, а их IP-адрес не соответствует IP-адресам, связанным с их идентификатором пользователя, в моей таблице «разрешено», он выполняет вышеуказанную задачу и получает электронное письмо.

Код, который я использую для создания URL-адреса ссылки, на которую они нажимают, выглядит примерно так:

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"; } 

Теперь это отлично работает при тестировании на моем компьютере.

Тем не менее, я решил (не спрашивать, почему), чтобы протестировать мой iPod Touch и в электронном письме, которое он мне отправил (чтобы проверить IP-адрес), он дал мне полный адрес в Интернете, как если бы он был доступен из WWW (т. Е. Ни регулярных выражений). Я заглянул в холдинг-стол, содержащий запросы, и запрошенный IP был: fe80::da30:62ff:fe18:6681 .

Я предполагаю, что это ipv6? – Мне нужно знать следующее:

  • Должен ли я ожидать, что адреса ipv6 попадут на мой сайт, когда он появится в прямом эфире?
  • Как я могу определить, был ли это локальный запрос (например, мое регулярное выражение для 192.168 … и 127 …)

Я был бы очень признателен за любые советы по этому поводу, поскольку я считаю, что это действительно запутывает

Если вы хотите убедиться, что никакие подключения IPv6 не могут быть добавлены, Listen 0.0.0.0:80 в настройку apache. Но большинство веб-узлов еще не поддерживают IPv6 (я знаю, мы в 2011 году), поэтому очень маловероятно, что люди могут даже подключиться к вам через IPv6. Единственная причина, по которой вы видите это, – это то, что bonjour (что делает работу с .local адресом) работает над IPv6.

Если вы хотите получить готовый код IPv6, почти никаких изменений не требуется, так как большинство функций IP PHP работают как на IPv4, так и на IPv6. Единственное изменение, которое я помню, это увеличение типа данных varchar в таблице MySQL до максимальной длины IPv6-адреса ( 39 ).

Я не уверен, что IPv6 играет по тем же правилам подсети, что и IPv4, но я ожидаю, что будет довольно сложно проверить, что IPv6-адрес является локальным.

РЕДАКТИРОВАТЬ:

fe80::/10 – это локальные ссылки, это может быть так же просто, как проверить первые 4 цифры.

Чтобы узнать, является ли адрес IPv6 локальным, вы должны знать, какие адреса используются локально. IPv6 не выполняет NAT (обычно). Некоторые сети используют ULA (уникальные локальные адреса) внутри, но многие просто используют адреса, которые они получают от ISP внутри компании.

Одна вещь, которую вы должны принять во внимание, – это то, что некоторые (большинство из них в наши дни) используют расширения конфиденциальности. Это означает, что их IPv6-адреса будут меняться со временем. Это заставит ваш стол расти много, и он заставит пользователя повторно аутентифицироваться снова и снова. Я думаю, что ваш лучший вариант – сохранить только подсеть (первые 64 бита) и совпадение с этим.

На всякий случай, если вы не знаете синтаксис адреса IPv6: адреса используют шестнадцатеричные цифры и имеют форму ssss: ssss: ssss: ssss: nnnn: nnnn: nnnn: nnnn где s – подсеть, а n – узел / хост. Ведущие нули в каждом блоке из 4 цифр опущены, а несколько блоков из 0 заменяются на: один раз. Итак, fe80::da30:62ff:fe18:6681 на самом деле fe80:0000:0000:0000:da30:62ff:fe18:6681 . Мой собственный веб-сервер имеет адрес 2001:4038:0:16::16 , что является коротким для 2001:4038:0000:0016:0000:0000:0000:0016 , а подсеть – 2001:4038:0:16::/64 .

Пример кода для получения подсети с адреса:

 <?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";