php ipv6 to ipv4

Calculating IP Address Long Form Number for IPv6 Compared to IPv4 Using PHP

Currently I have two ways of calculating IPv4 long-form integers:

But how do I calculate IPv6 into a long-form integer?

I’m looking for a function or something that doesn’t require me to install any extensions to PHP.

Edit:

I need the long form integer so I can compare it for an IP range query. Here’s an example row for a IPv6 range query:

php ipv6 to ipv4. Смотреть фото php ipv6 to ipv4. Смотреть картинку php ipv6 to ipv4. Картинка про php ipv6 to ipv4. Фото php ipv6 to ipv4

2 Answers 2

Suggestions:

Storing in long is not a proper way for that. Use,

This function converts a 32bit IPv4, or 128bit IPv6 address (if PHP was built with IPv6 support enabled) into an address family appropriate string representation.

You should also see,

inet_ntop() Example

Comparing in range

Both functions support IPv6 as well as IPv4. The only difference is how you unpack the address from the results. With IPv6, you will unpack with contents with A16, and with IPv4, you will unpack with A4.

To put the previous in a perspective here is a little sample output to help clarify:

We demonstrate above that the inet_* family supports both IPv6 and v4. Our next step will be to translate the packed result into an unpacked variable.

After the unpacking and packing, we can see we achieved the same result as input. This is a simple proof of concept to ensure we are not losing any data.

Источник

Работа с IPv6 в PHP

Недавно мы получили статус LIR и /29 блок IPv6. А следом возникла необходимость вести учёт назначенных подсетей. И коль скоро наш биллинг написан на PHP, пришлось немного проникнуться вопросом и осознать, что этот язык — не самый дружелюбный в плане работы с IPv6. Под катом — наше решение возникших задач по работе с адресами и диапазонами. Возможно, не самое элегантное, но поставленные задачи выполняет.

php ipv6 to ipv4. Смотреть фото php ipv6 to ipv4. Смотреть картинку php ipv6 to ipv4. Картинка про php ipv6 to ipv4. Фото php ipv6 to ipv4

Немного теории

Дисклеймер. Если Вы знакомы с тем, что такое IPv6 и с чем его едят, эта часть может быть для Вас скучной. Может и не быть.

Людей, которые впервые видят аннотацию IPv6, она вполне может обескуражить. После элегантных 64.233.177.101 мы вдруг сталкиваемся с 2607:f8b0:4002:c08::8b и можем растеряться. И то, и другое — всего лишь человекопонятное представление 32 и 128 бит соответственно. Любой IP пакет содержит заголовок со строго стандартизированным назначением каждого бита. Не вдаваясь ещё глубже в структуру заголовков, нам отсюда нужно вынести одно: для операций с IP-адресами и диапазонами в основном удобно использовать бинарную математику и побитовые операции. Хранить в базе их тоже удобнее всего как BINARY(4) для IPv4 и BINARY(16) для IPv6.

Ещё один важный аспект, который стоило бы затронуть, — это маски сети и CIDR нотация. CIDR — акроним от Classless Inter-Domain Routing (бесклассовая адресация). Эта концепция пришла на смену классовой в вопросе определения, какая часть IP-адреса является префиксом сети, а какая — адресом сетевого интерфейса внутри этой сети. На практике первым n бит, соответствующим префиксу, будут установлены значения 1, остальным — 0.

В человекопонятном виде это записывается в виде ip.add.re.ss/cidr. Например, 64.233.177.0/24 обозначает, что первые 24 бита относятся к префиксу. Последние 8 бит, они же — последнее число в человекопонятной записи, относятся к адресу внутри подсети. Ещё пару упражнений. 64.233.177.101/32 и 2607:f8b0:4002:c08::8b/128 — один конкретный адрес. 2607:f8b0:4002:c08::/64 — первые 64 бита (первые 4 группы) — префикс, остальные 64 бита — локальная часть. Кстати, если кого смущает «::» в записи, двойное двоеточие заменяет произвольное количество секций, содержащих 0. Оно может встречаться в аннотации только 1 раз. Иными словами, 2607:f8b0:4002:c08::8b = 2607:f8b0:4002:c08:0:0:0:8b.

Что нам из этого всего нужно почерпнуть? Во-первых, первый и последний адрес подсети можно получить с помощью бинарных AND и OR, зная маску в бинарном виде. Во-вторых, следующую подсеть размера (т.е. с CIDR) n можно вычислить, прибавив 1 к n-той позиции в двоичном представлении. Под бинарным видом я подразумеваю результат использования функций pack() и inet_pton() и дальнейшее использование побитовых операторов, под двоичным — представление в двоичной системе, которое можно получить, скажем, с помощью base_convert().

Перейдём к практике

На практике реализуем три наиболее вероятные, как мне показалось, задачи:

Как я уже упоминал, первый и последний адрес диапазона можно определить с помощью побитовых операций, зная начало диапазона и бинарную маску подсети. Соответственно, первым делом нам надо превратить CIDR в бинарную маску. Для этого соберём её hex представление и запакуем в бинарное.

Следующий шаг — вычисление начала и конца диапазона. И вот тут возникнут нюансы. Побитовые операции ограничены разрядностью процессора. Соответственно, на моём 32-битном CubieTruck, который я порой использую для всякого тестового баловства, все 128 бит адреса обработать за одну операцию не выйдет. Впрочем, ничто не мешает нам разбить его на группы по 32 бита (на всякий случай, кто знает, на каких процессорах будем запускаться).

Для будущего использования предусмотрим возможность передавать IP и получать результат как в бинарном, так и в человекочитаемом виде. Параметр $which тут задаёт, хотим ли мы получить начало или конец диапазона (значения ‘start’ или ‘end’ соответственно).

Следующая задача (к тому же наиболее практичная для нашей компании) — вычисление следующего диапазона. Для данной задачи ничего лучше не пришло в голову, кроме как разложить адрес в двоичную строку и добавить 1 в нужной позиции, после чего свернуть всё назад. Чтобы нигде не появилось артефактов, я решил при разложении и сборке дробить адрес по байту.

На выходе получим префикс следующего диапазона размера, указанного в $cidr. Этой функцией мы выделяем блоки адресов нашим клиентам.

Наконец, проверка, принадлежит ли адрес диапазону. К примеру, мы выделили один блок /48 под раздачу клиентам блоков /64, и нам нужно убедиться, что при назначении мы не выходим за пределы выделенного блока (на практике это случится нескоро, но всё же вероятность есть). Тут всё просто. Получаем начало и конец диапазона в бинарном виде и проверяем, находится ли адрес в пределах.

Надеюсь, было полезно. Какие ещё функции по работе с адресами могут по Вашему мнению быть полезны? Любые дополнения, комментарии и код-ревью горячо приветствуются в комментариях.

Если Вы уже являетесь нашим клиентом или только думаете им стать, по случаю выхода этой статьи мы предлагаем Вам получить блок /64 совершенно бесплатно для всех услуг vps или выделенный сервер в дата центре Equinix Tier IV, Нидерланды по запросу в отдел продаж, предоставив ссылку на эту статью в тикете. Предложение действует до марта 2020-го года.

Немного рекламы 🙂

Источник

Работа с IPv6 в PHP

Очень часто для большинства проектов возникает необходимость работы с IP адресами. В те времена, когда существовал только IP версии 4, для упрощения работы использовались две функции Ip2long и Long2ip, которые переводили IP адрес в обычное число и обратно. Данная реализация позволяла экономично использовать память и ресурсы системы. Но в IP версии 6 нет такой возможности.

Для преобразования IPv6 существуют функции Inet_pton и Inet_ntop, которые преобразуют человеко-понятное представление IP адреса в упакованное In_addr представление, и обратно. Поскольку результат выполнения функции Inet_pton не является чисто бинарным, необходимо воспользоваться функцией Unpack чтобы в дальнейшем можно было работать с битовыми операциями. Также можно использовать функцию Bin2hex, которая преобразует бинарные данные в шестнадцатиричное представление.

Давайте рассмотрим это на примере:
Теперь необходимо преобразовать упакованный результат в распакованное значение:
Функция Current возвращает первый элемент массива.

В результате данные после распаковывания и упаковывания сохраняются одинаковыми.

Опишем функции, которые выполняют выше описанные операции. Функция для преобразования IP адреса в бинарный вид:
Функция для обратного преобразования:
Функция Iptobin проверяет входящее значение и возвращает преобразованное значение или False в случае возникновения ошибки. Функция Bintoip преобразует результат выполнения Iptobin обратно, проверяя входящее значение на соответствие форматам A4/A16 и возвращая результат, или False в случае возникновения ошибки.

Для сохранения бинарных файлов в базе данных можно использовать человекочетаемый вид в формате VARCHAR(39). Но рекомендуется все же сохранять в бинарном виде используя BINARY(16), что позволит делать выборки по диапазонам, битовым маскам и предоставлять другие преимущества, для построения приложения поддерживающего IPv6.

Проведем эксперимент. Создадим таблицу с полем Varchar(39). В данный диапазон символов полностью поместиться Ipv6 в открытом виде. Для Ipv6 достаточно всего 15 символов (вместе с точками), которые вписываются в данное поле. И запишем в данную таблицу 10000000 записей с разными IP адресами вперемешку. Для этого будем две функции генерации случайного IP6 и IP4 адресов:
Размер таблицы зависит от данных версий адресов, но при данной реализации он составил 440 мегабайт.

Далее мы будем выполнять операции поиска существования IP адресов и время, потраченное на данную операцию. Более подробно можно почитать в статье: Время выполнения скрипта. Проход по всем значениям составляет 1.876 сек.

А теперь создадим таблицу с полем IP и типом VARBINARY(16):
Запись в таблицу будет осуществляться функцией UNHEX:
Таблица с 10000000 записями во втором варианте будет занимать 326 мегабайт. Поиск по всей таблице будет занимать 1.775 сек.

Как видно из примеров, для уменьшения места для хранения IP адресов необходимо использовать тип поля VARBINARY(16), а для быстроты поиска большой разницы нет.

Источник

Convert IPV4 to IPV6 php

4 Answers 4

IPv6 is not merely a different «format». IPv6 is a complete replacement of IPv4. There’s no «conversion» of an IPv4 address to an IPv6 address. Your client either has an IPv4 address or they have an IPv6 address, period. Maybe they even have both, but that would only be because they run both IP stacks in parallel and can be reached via both methods; both stacks are running entirely independently of one another though, both may suddenly change their IPs independently. They’re not correlated. As far as you know, each IP (whether v4 or v6) is an entirely different client.

In short: no. IPv6 is an entirely new address range. Imagine if IPv4 was extended from 255 as the maximum value for a byte to 512 and the whole new range 256.0.0.0 through 512.512.512.512 would become available; that’s what IPv6 is.

It sounds like you are whitelisting the IP of each user during the initial registration process. If that is the case, then the issue you are experiencing is not easily resolvable. If your users have both an IPv4 and an IPv6 address, you will not be able to control which they use to connect to your server (aside from disabling IPv6 on your server). In addition, this method will not work for users with a dynamic IP address, as they will regularly get assigned a new IP and not be able to authenticate.

It is not possible to determine the users IPv4 address from their IPv6 address, as there is no guaranteed correlation between a user’s IPv4 and IPv6 address*. As others have stated, IPv6 addresses do not directly convert into IPv4 addresses, as they are different formats. IPv6 addresses are much larger numbers (128-bit vs 32-bit), so converting an IPv6 address to IPv4 would not be possible even if the standard allowed for it.

*: the only exception I can think of on the correlation between IPv4 and IPv6 would be on a LAN with each device having a static private IP. If the static IPv4 and IPv6 addresses were selected so that they correlated somehow, then it would be possible to determine a v4 address from the v6 one. This is not a likely setup for most people though, and it assumes that your server is on the same local network as the end users (so that it would see the private IPs).

Given the high probability of locking out valid users (due to dynamic IPs or IPv6), this does not seem to be a reliable method of securing your server. If you have a very specific user base and dynamic IPs are not an issue, you might be able to bind your registration page to an IPv4 address and not have it listen on the IPv6 address. That way, you could at least be sure to get their IPv4 address at registration.

Edit: rewrote my answer to be more relavent to the question

Источник

Change IPv4 to IPv6 string

Addresses like 0000:0000:0000:0000:0000:0000:192.168.0.1 are written as 0000:0000:0000:0000:0000:0000:c0a8:0001 which is exactly the same address but in hex notation.

Am I correct, to change this to IPv4 will be something like:

. or are correct IP string representations more complex than what this snippet could do?

php ipv6 to ipv4. Смотреть фото php ipv6 to ipv4. Смотреть картинку php ipv6 to ipv4. Картинка про php ipv6 to ipv4. Фото php ipv6 to ipv4

3 Answers 3

I can’t believe I wrote this all out in one go and it worked the first time.

Your best bet is to not do this manually, but instead call inet_pton to get a binary representation, and then convert that to the format you wish to have.

php ipv6 to ipv4. Смотреть фото php ipv6 to ipv4. Смотреть картинку php ipv6 to ipv4. Картинка про php ipv6 to ipv4. Фото php ipv6 to ipv4

First of all: why would you care how the address is written? inet_pton() will parse all variations for you and give you a consistent result, which you can then transform into binary, hex, or whatever you want.

All the code for converting things like ::192.168.0.1 to 0000:0000:0000:0000:0000:0000:c0a8:0001 was actually in my post. That’s exactly what my example function does.

If you feed 0000:0000:0000:0000:0000:0000:192.168.0.1 to inet_pton() and then to inet_ntop() you’ll get the canonical IPv6 notation, which is ::192.168.0.1 in this case. If that string begins with :: and the rest contains no : and three dots then you can be pretty sure it’s an IPv4 address 😉

To combine the answer to your previous question with this question:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *