Π Π°Π±ΠΎΡ‚Π° с IPv6 Π² PHP

НСдавно ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ статус LIR ΠΈ /29 Π±Π»ΠΎΠΊ IPv6. А слСдом Π²ΠΎΠ·Π½ΠΈΠΊΠ»Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ вСсти ΡƒΡ‡Ρ‘Ρ‚ Π½Π°Π·Π½Π°Ρ‡Π΅Π½Π½Ρ‹Ρ… подсСтСй. И коль скоро наш Π±ΠΈΠ»Π»ΠΈΠ½Π³ написан Π½Π° PHP, ΠΏΡ€ΠΈΡˆΠ»ΠΎΡΡŒ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ½ΠΈΠΊΠ½ΡƒΡ‚ΡŒΡΡ вопросом ΠΈ ΠΎΡΠΎΠ·Π½Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ этот язык β€” Π½Π΅ самый Π΄Ρ€ΡƒΠΆΠ΅Π»ΡŽΠ±Π½Ρ‹ΠΉ Π² ΠΏΠ»Π°Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с IPv6. Под ΠΊΠ°Ρ‚ΠΎΠΌ β€” нашС Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π½ΠΈΠΊΡˆΠΈΡ… Π·Π°Π΄Π°Ρ‡ ΠΏΠΎ Ρ€Π°Π±ΠΎΡ‚Π΅ с адрСсами ΠΈ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π°ΠΌΠΈ. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π½Π΅ самоС элСгантноС, Π½ΠΎ поставлСнныС Π·Π°Π΄Π°Ρ‡ΠΈ выполняСт.

Π Π°Π±ΠΎΡ‚Π° с IPv6 Π² PHP

НСмного Ρ‚Π΅ΠΎΡ€ΠΈΠΈ

ДисклСймСр. Если Π’Ρ‹ Π·Π½Π°ΠΊΠΎΠΌΡ‹ с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ 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().

Π˜ΡΡ‚ΠΎΡ€ΠΈΡ‡Π΅ΡΠΊΠ°Ρ справкаБСсклассовой ΠΏΡ€Π΅Π΄ΡˆΠ΅ΡΡ‚Π²ΠΎΠ²Π°Π»Π° классовая сСгрСгация адрСсация. Π’ Ρ‚Π΅ Π΄Π°Π»Ρ‘ΠΊΠΈΠ΅ Π³ΠΎΠ΄Ρ‹ Π½ΠΈΠΊΡ‚ΠΎ Π½Π΅ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π», Ρ‡Ρ‚ΠΎ подсСтСй Π±ΡƒΠ΄Π΅Ρ‚ Ρ‚Π°ΠΊ ΠΌΠ½ΠΎΠ³ΠΎ, Ρ€Π°Π·Π΄Π°Π²Π°Π»ΠΈ ΠΈΡ… Π½Π°ΠΏΡ€Π°Π²ΠΎ ΠΈ Π½Π°Π»Π΅Π²ΠΎ большими Π±Π»ΠΎΠΊΠ°ΠΌΠΈ: класс А β€” прСфиксом Π±Ρ‹Π»ΠΈ ΠΏΠ΅Ρ€Π²Ρ‹Π΅ 8 Π±ΠΈΡ‚ (Ρ‚.Π΅. ΠΏΠ΅Ρ€Π²ΠΎΠ΅ число), с Π»ΠΈΠ΄ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΌ Π±ΠΈΡ‚ΠΎΠΌ 0; класс Π’ β€” ΠΏΠ΅Ρ€Π²Ρ‹Π΅ 16 (ΠΏΠ΅Ρ€Π²Ρ‹Π΅ Π΄Π²Π° числа), Π»ΠΈΠ΄ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ Π±ΠΈΡ‚Ρ‹ 10; класс Π‘ β€” ΠΏΠ΅Ρ€Π²Ρ‹Π΅ 24 Π±ΠΈΡ‚Π°, Π»ΠΈΠ΄ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ Π±ΠΈΡ‚Ρ‹ 110. Π­Ρ‚ΠΈ самыС Π»ΠΈΠ΄ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ Π±ΠΈΡ‚Ρ‹ Π·Π°Π΄Π°Π²Π°Π»ΠΈ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Ρ‹, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… выдавался адрСс Ρ‚ΠΎΠ³ΠΎ ΠΈΠ»ΠΈ ΠΈΠ½ΠΎΠ³ΠΎ класса: 0.0.0.0 β€” 127.255.255.255 для класса А, 128.0.0.0 β€” 191.255.255.255 β€” класс Π’, 192.0.0.0 β€” 223.255.255.255 β€” класс Π‘. По ΠΌΠ΅Ρ€Π΅ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΈΠ½Ρ‚Π΅Ρ€Π½Π΅Ρ‚ расползался ΠΏΠΎ ΠΏΠ»Π°Π½Π΅Ρ‚Π΅, рСгуляторы поняли, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠΌΠ°Ρ…Π½ΡƒΠ»ΠΈΡΡŒ, ΠΈ Π² Π½Π°Ρ‡Π°Π»Π΅ 90-Ρ… Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ Π±Π΅ΡΠΊΠ»Π°ΡΡΠΎΠ²ΡƒΡŽ ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΡŽ, ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΠ²ΡˆΡƒΡŽ Π½Π΅ ΠΏΡ€ΠΈΠ²ΡΠ·Ρ‹Π²Π°Ρ‚ΡŒΡΡ ΠΊ Π»ΠΈΠ΄ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΌ Π±ΠΈΡ‚Π°ΠΌ. Π§ΡƒΡ‚ΡŒ большС подробностСй ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡ‡Π΅Ρ€ΠΏΠ½ΡƒΡ‚ΡŒ, скаТСм, Π² Π²Π΅Π»ΠΈΠΊΠΎΠΉ ΠΈ Π²ΡΠ΅Π·Π½Π°ΡŽΡ‰Π΅ΠΉ.

ΠŸΠ΅Ρ€Π΅ΠΉΠ΄Ρ‘ΠΌ ΠΊ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅

На ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ Ρ‚Ρ€ΠΈ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ вСроятныС, ΠΊΠ°ΠΊ ΠΌΠ½Π΅ показалось, Π·Π°Π΄Π°Ρ‡ΠΈ:

  1. ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΈ послСднСго адрСса Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π°;
  2. ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π° Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° (CIDR);
  3. ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ½ΠΎΡΡ‚ΡŒ адрСса Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Ρƒ.

РСализация Π±ΡƒΠ΄Π΅Ρ‚ для IPv6, Π½ΠΎ ΠΏΡ€ΠΈ нСобходимости Π»ΠΎΠ³ΠΈΠΊΡƒ ΠΌΠΎΠΆΠ½ΠΎ Π»Π΅Π³ΠΊΠΎ Π°Π΄Π°ΠΏΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ. НСкоторыС ΠΈΠ΄Π΅ΠΈ я ΠΏΠΎΡ‡Π΅Ρ€ΠΏΠ½ΡƒΠ» ΠΎΡ‚ΡΡŽΠ΄Π°, Π½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π» Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ½Π°Ρ‡Π΅. Π’Π°ΠΊΠΆΠ΅ Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ… Π½Π΅Ρ‚ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π½Π° ошибки Π²Π²ΠΎΠ΄Π°. Π˜Ρ‚Π°ΠΊ, ΠΏΠΎΠ΅Ρ…Π°Π»ΠΈ.

Как я ΡƒΠΆΠ΅ ΡƒΠΏΠΎΠΌΠΈΠ½Π°Π», ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈ послСдний адрСс Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΏΠΎΠ±ΠΈΡ‚ΠΎΠ²Ρ‹Ρ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, зная Π½Π°Ρ‡Π°Π»ΠΎ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π° ΠΈ Π±ΠΈΠ½Π°Ρ€Π½ΡƒΡŽ маску подсСти. БоотвСтствСнно, ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ Π΄Π΅Π»ΠΎΠΌ Π½Π°ΠΌ Π½Π°Π΄ΠΎ ΠΏΡ€Π΅Π²Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ CIDR Π² Π±ΠΈΠ½Π°Ρ€Π½ΡƒΡŽ маску. Для этого собСрём Π΅Ρ‘ hex прСдставлСниС ΠΈ Π·Π°ΠΏΠ°ΠΊΡƒΠ΅ΠΌ Π² Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠ΅.

function cidrToMask ($cidr) {
    $mask = str_repeat('f', ceil($cidr / 4));
    $mask .= dechex(4 * ($cidr % 4));
    $mask = str_pad($mask, 32, '0');
    return pack('H*', $mask);
}

Π’Ρ‹Π·ΠΎΠ² pack(‘H*’, $mask) ΠΏΠ°ΠΊΡƒΠ΅Ρ‚ hex прСдставлСниС Ρ‚Π°ΠΊΠΈΠΌ ΠΆΠ΅ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΠΊΠ°ΠΊ ΠΈ inet_pton(). Π‘ Ρ‚ΠΎΠΉ лишь Ρ€Π°Π·Π½ΠΈΡ†Π΅ΠΉ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ pack() всС 0 Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π½Π° своих мСстах, Π° Π΄Π²ΠΎΠ΅Ρ‚ΠΎΡ‡ΠΈΠΉ Π² записи Π±Ρ‹Ρ‚ΡŒ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ, Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ чСловСкопонятной записи.

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ шаг β€” вычислСниС Π½Π°Ρ‡Π°Π»Π° ΠΈ ΠΊΠΎΠ½Ρ†Π° Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π°. И Π²ΠΎΡ‚ Ρ‚ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ Π½ΡŽΠ°Π½ΡΡ‹. ΠŸΠΎΠ±ΠΈΡ‚ΠΎΠ²Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Ρ‹ Ρ€Π°Π·Ρ€ΡΠ΄Π½ΠΎΡΡ‚ΡŒΡŽ процСссора. БоотвСтствСнно, Π½Π° ΠΌΠΎΡ‘ΠΌ 32-Π±ΠΈΡ‚Π½ΠΎΠΌ CubieTruck, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ я ΠΏΠΎΡ€ΠΎΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽ для всякого тСстового баловства, всС 128 Π±ΠΈΡ‚ адрСса ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π·Π° ΠΎΠ΄Π½Ρƒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π½Π΅ Π²Ρ‹ΠΉΠ΄Π΅Ρ‚. Π’ΠΏΡ€ΠΎΡ‡Π΅ΠΌ, Π½ΠΈΡ‡Ρ‚ΠΎ Π½Π΅ ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ Π½Π°ΠΌ Ρ€Π°Π·Π±ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Π½Π° Π³Ρ€ΡƒΠΏΠΏΡ‹ ΠΏΠΎ 32 Π±ΠΈΡ‚Π° (Π½Π° всякий случай, ΠΊΡ‚ΠΎ Π·Π½Π°Π΅Ρ‚, Π½Π° ΠΊΠ°ΠΊΠΈΡ… процСссорах Π±ΡƒΠ΄Π΅ΠΌ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ).

function getRangeBoundary ($ip, $cidr, $which, $ipIsBin = false, $returnBin = false) {
    $mask = cidrToMask($cidr);
    if (!$ipIsBin) {
        $ip = inet_pton($ip);
    }
    $ipParts   = str_split($ip, 4);
    $maskParts = str_split($mask, 4);
    $rangeParts  = [];
    for ($i = 0; $i < count($ipParts); $i++) {
        if ($which == 'start') {
            /* ΠŸΠΎΠ±ΠΈΡ‚ΠΎΠ²Ρ‹ΠΉ & адрСса ΠΈ маски оставит Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π±ΠΈΡ‚Ρ‹ прСфикса. */
            $rangeParts[$i] = $ipParts[$i] & $maskParts[$i];
        } else {
            /* ΠŸΠΎΠ±ΠΈΡ‚ΠΎΠ²Ρ‹ΠΉ | с ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΉ маской (~) оставит Π±ΠΈΡ‚Ρ‹ прСфикса ΠΈ установит всС Π±ΠΈΡ‚Ρ‹ локальной части Π² 1. */
            $rangeParts[$i] = $ipParts[$i] | ~$maskParts[$i];
        }
    }
    $rangeBoundary = implode($rangeParts);
    if ($returnBin) {
        return $rangeBoundary;
    } else {
        return inet_ntop($rangeBoundary);
    }
}

Для Π±ΡƒΠ΄ΡƒΡ‰Π΅Π³ΠΎ использования прСдусмотрим Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ IP ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΊΠ°ΠΊ Π² Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠΌ, Ρ‚Π°ΠΊ ΠΈ Π² Ρ‡Π΅Π»ΠΎΠ²Π΅ΠΊΠΎΡ‡ΠΈΡ‚Π°Π΅ΠΌΠΎΠΌ Π²ΠΈΠ΄Π΅. ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ $which Ρ‚ΡƒΡ‚ Π·Π°Π΄Π°Ρ‘Ρ‚, Ρ…ΠΎΡ‚ΠΈΠΌ Π»ΠΈ ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π½Π°Ρ‡Π°Π»ΠΎ ΠΈΠ»ΠΈ ΠΊΠΎΠ½Π΅Ρ† Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π° (значСния ‘start’ ΠΈΠ»ΠΈ ‘end’ соотвСтствСнно).

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ Π·Π°Π΄Π°Ρ‡Π° (ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ практичная для нашСй ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ) β€” вычислСниС ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π°. Для Π΄Π°Π½Π½ΠΎΠΉ Π·Π°Π΄Π°Ρ‡ΠΈ Π½ΠΈΡ‡Π΅Π³ΠΎ Π»ΡƒΡ‡ΡˆΠ΅ Π½Π΅ ΠΏΡ€ΠΈΡˆΠ»ΠΎ Π² Π³ΠΎΠ»ΠΎΠ²Ρƒ, ΠΊΡ€ΠΎΠΌΠ΅ ΠΊΠ°ΠΊ Ρ€Π°Π·Π»ΠΎΠΆΠΈΡ‚ΡŒ адрСс Π² Π΄Π²ΠΎΠΈΡ‡Π½ΡƒΡŽ строку ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ 1 Π² Π½ΡƒΠΆΠ½ΠΎΠΉ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, послС Ρ‡Π΅Π³ΠΎ ΡΠ²Π΅Ρ€Π½ΡƒΡ‚ΡŒ всё Π½Π°Π·Π°Π΄. Π§Ρ‚ΠΎΠ±Ρ‹ Π½ΠΈΠ³Π΄Π΅ Π½Π΅ появилось Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚ΠΎΠ², я Ρ€Π΅ΡˆΠΈΠ» ΠΏΡ€ΠΈ Ρ€Π°Π·Π»ΠΎΠΆΠ΅Π½ΠΈΠΈ ΠΈ сборкС Π΄Ρ€ΠΎΠ±ΠΈΡ‚ΡŒ адрСс ΠΏΠΎ Π±Π°ΠΉΡ‚Ρƒ.

function getNextBlock ($ipStart, $cidr, $ipIsBin = false, $returnBin = false) {
    if (!$ipIsBin) {
        $ipStart = inet_pton($ipStart);
    }
    $ipParts = str_split($ipStart, 1);
    $ipBin   = '';
    foreach ($ipParts as $ipPart) {
        $ipBin .= str_pad(base_convert(unpack('H*', $ipPart)[1], 16, 2), 8, '0', STR_PAD_LEFT);
    }
    /* ДобавляСм 1 Π² Π½ΡƒΠΆΠ½ΠΎΠΌ разрядС Π΄Π²ΠΎΠΈΡ‡Π½ΠΎΠ³ΠΎ прСдставлСния строки "Π²Π»ΠΎΠ±" :) */
    $i = $cidr - 1;
    while ($i >= 0) {
        if ($ipBin[$i] == '0') {
            $ipBin[$i] = '1';
            break;
        } else {
            $ipBin[$i] = '0';
        }
        $i--;
    }
    $ipBinParts = str_split($ipBin, 8);
    foreach ($ipBinParts as $key => $ipBinPart) {
        $ipParts[$key] = pack('H*', str_pad(base_convert($ipBinPart, 2, 16), 2, '0', STR_PAD_LEFT));
    }
    $nextIp = implode($ipParts);
    if ($returnBin) {
        return $nextIp;
    } else {
        return inet_ntop($nextIp);
    }
}

На Π²Ρ‹Ρ…ΠΎΠ΄Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ прСфикс ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π° Ρ€Π°Π·ΠΌΠ΅Ρ€Π°, ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ Π² $cidr. Π­Ρ‚ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ ΠΌΡ‹ выдСляСм Π±Π»ΠΎΠΊΠΈ адрСсов нашим ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°ΠΌ.

НаконСц, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°, ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ‚ Π»ΠΈ адрСс Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Ρƒ. К ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, ΠΌΡ‹ Π²Ρ‹Π΄Π΅Π»ΠΈΠ»ΠΈ ΠΎΠ΄ΠΈΠ½ Π±Π»ΠΎΠΊ /48 ΠΏΠΎΠ΄ Ρ€Π°Π·Π΄Π°Ρ‡Ρƒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°ΠΌ Π±Π»ΠΎΠΊΠΎΠ² /64, ΠΈ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡƒΠ±Π΅Π΄ΠΈΡ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΈ ΠΌΡ‹ Π½Π΅ Π²Ρ‹Ρ…ΠΎΠ΄ΠΈΠΌ Π·Π° ΠΏΡ€Π΅Π΄Π΅Π»Ρ‹ Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ° (Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅ это случится нСскоро, Π½ΠΎ всё ΠΆΠ΅ Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒ Π΅ΡΡ‚ΡŒ). Π’ΡƒΡ‚ всё просто. ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π½Π°Ρ‡Π°Π»ΠΎ ΠΈ ΠΊΠΎΠ½Π΅Ρ† Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π° Π² Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠΌ Π²ΠΈΠ΄Π΅ ΠΈ провСряСм, находится Π»ΠΈ адрСс Π² ΠΏΡ€Π΅Π΄Π΅Π»Π°Ρ….

function ipInRange ($ip, $rangeStart, $cidr) {
    $start = getRangeBoundary($rangeStart, $cidr, 'start',false, true);
    $end = getRangeBoundary($rangeStart, $cidr, 'end',false, true);
    $ipBin = inet_pton($ip);
    return ($ipBin >= $start && $ipBin <= $end);
}

НадСюсь, Π±Ρ‹Π»ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ. КакиС Π΅Ρ‰Ρ‘ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΠΎ Ρ€Π°Π±ΠΎΡ‚Π΅ с адрСсами ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎ Π’Π°ΡˆΠ΅ΠΌΡƒ мнСнию Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹? Π›ΡŽΠ±Ρ‹Π΅ дополнСния, ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ ΠΈ ΠΊΠΎΠ΄-Ρ€Π΅Π²ΡŒΡŽ горячо ΠΏΡ€ΠΈΠ²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‚ΡΡ Π² коммСнтариях.

Если Π’Ρ‹ ΡƒΠΆΠ΅ ΡΠ²Π»ΡΠ΅Ρ‚Π΅ΡΡŒ нашим ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ ΠΈΠ»ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄ΡƒΠΌΠ°Π΅Ρ‚Π΅ ΠΈΠΌ ΡΡ‚Π°Ρ‚ΡŒ, ΠΏΠΎ ΡΠ»ΡƒΡ‡Π°ΡŽ Π²Ρ‹Ρ…ΠΎΠ΄Π° этой ΡΡ‚Π°Ρ‚ΡŒΠΈ ΠΌΡ‹ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅ΠΌ Π’Π°ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π±Π»ΠΎΠΊ /64 ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎ бСсплатно для всСх услуг vps ΠΈΠ»ΠΈ Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ сСрвСр Π² Π΄Π°Ρ‚Π° Ρ†Π΅Π½Ρ‚Ρ€Π΅ Equinix Tier IV, НидСрланды ΠΏΠΎ запросу Π² ΠΎΡ‚Π΄Π΅Π» ΠΏΡ€ΠΎΠ΄Π°ΠΆ, прСдоставив ссылку Π½Π° эту ΡΡ‚Π°Ρ‚ΡŒΡŽ Π² Ρ‚ΠΈΠΊΠ΅Ρ‚Π΅. ΠŸΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ дСйствуСт Π΄ΠΎ ΠΌΠ°Ρ€Ρ‚Π° 2020-Π³ΠΎ Π³ΠΎΠ΄Π°.

НСмного Ρ€Π΅ΠΊΠ»Π°ΠΌΡ‹ πŸ™‚

Бпасибо, Ρ‡Ρ‚ΠΎ ΠΎΡΡ‚Π°Ρ‘Ρ‚Π΅ΡΡŒ с Π½Π°ΠΌΠΈ. Π’Π°ΠΌ нравятся наши ΡΡ‚Π°Ρ‚ΡŒΠΈ? Π₯ΠΎΡ‚ΠΈΡ‚Π΅ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ большС интСрСсных ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ²? ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΡ‚Π΅ нас, ΠΎΡ„ΠΎΡ€ΠΌΠΈΠ² Π·Π°ΠΊΠ°Π· ΠΈΠ»ΠΈ ΠΏΠΎΡ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΠΎΠ²Π°Π² Π·Π½Π°ΠΊΠΎΠΌΡ‹ΠΌ, ΠΎΠ±Π»Π°Ρ‡Π½Ρ‹Π΅ VPS для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² ΠΎΡ‚ $4.99, ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Π°Π½Π°Π»ΠΎΠ³ entry-level сСрвСров, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±Ρ‹Π» ΠΏΡ€ΠΈΠ΄ΡƒΠΌΠ°Π½ Π½Π°ΠΌΠΈ для Вас: Вся ΠΏΡ€Π°Π²Π΄Π° ΠΎ VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps ΠΎΡ‚ $19 ΠΈΠ»ΠΈ ΠΊΠ°ΠΊ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Π΄Π΅Π»ΠΈΡ‚ΡŒ сСрвСр? (доступны Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Ρ‹ с RAID1 ΠΈ RAID10, Π΄ΠΎ 24 ядСр ΠΈ Π΄ΠΎ 40GB DDR4).

Dell R730xd Π² 2 Ρ€Π°Π·Π° дСшСвлС Π² Π΄Π°Ρ‚Π°-Ρ†Π΅Π½Ρ‚Ρ€Π΅ Equinix Tier IV Π² АмстСрдамС? Волько Ρƒ нас 2 Ρ… Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 Π’Π’ ΠΎΡ‚ $199 Π² НидСрландах! Dell R420 β€” 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB β€” ΠΎΡ‚ $99! Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΎ Ρ‚ΠΎΠΌ Как ΠΏΠΎΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ инфраструктуру ΠΊΠΎΡ€ΠΏ. класса c ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ сСрвСров Dell R730xd Π•5-2650 v4 ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒΡŽ 9000 Π΅Π²Ρ€ΠΎ Π·Π° ΠΊΠΎΠΏΠ΅ΠΉΠΊΠΈ?

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com