PHPде IPv6 менен иштөө

Биз жакында LIR статусун жана /29 IPv6 блогун алдык. Андан кийин дайындалган ички тармактарды эсепке алуу зарылчылыгы пайда болду. Биздин эсеп PHPде жазылгандыктан, биз маселени бир аз изилдеп, бул тил IPv6 менен иштөө жагынан эң ыңгайлуу эмес экенин түшүнүшүбүз керек. Кесилген ылдыйда даректер жана диапазондор менен иштөөдө пайда болгон көйгөйлөрдү чечүү жолдору бар. Балким, эң элеганттуу эмес, бирок бул ишти аткарат.

PHPде IPv6 менен иштөө

теориясынын бир үзүм

Жоопкерчиликтен баш тартуу. Эгер сиз IPv6 деген эмне экенин жана ал эмне менен келгенин жакшы билсеңиз, бул бөлүк сиз үчүн кызыксыз болушу мүмкүн. Болбошу мүмкүн.

IPv6 аннотациясын биринчи жолу көргөн адамдар бул абдан коркунучтуу болушу мүмкүн. Elegant кийин 64.233.177.101 биз күтүлбөгөн жерден туш болдук 2607:f8b0:4002:c08::8b жана биз чаташып калышыбыз мүмкүн. Экөө тең тиешелүүлүгүнө жараша 32 жана 128 биттин адам окуй турган көрүнүштөрү. Ар бир IP пакети ар бир бит үчүн катуу стандартташтырылган максатты камтыган башты камтыйт. Темалардын структурасына тереңирээк кирбестен, биз мындан бир нерсени алып салышыбыз керек, IP даректери жана диапазондору менен операциялар үчүн жалпысынан бинардык математиканы жана биттик операцияларды колдонуу ыңгайлуу. Ошондой эле аларды маалымат базасында сактоо эң ыңгайлуу БИнарлык(4) IPv4 үчүн жана БИнарлык(16) IPv6 үчүн.

Дагы бир маанилүү аспект - бул тармактык маскалар жана CIDR белгилер. CIDR Класссыз Домен аралык Маршрутизациянын кыскартылган түрү (класссыз даректүү). Бул концепция 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 камтылган бөлүмдөрдүн ыктыярдуу санын алмаштырат. Ал аннотацияда бир гана жолу пайда болушу мүмкүн. Башкача айтканда, 2607:f8b0:4002:c08::8b = 2607:f8b0:4002:c08:0:0:0:8b.

Мунун баарынан эмнеге үйрөнүшүбүз керек? Биринчиден, биринчи жана акыркы субнет дарегин бинардык ЖАНА жана ЖЕ колдонуп, бинардык формада масканы билип алса болот. Экинчиден, кийинки ички тармак өлчөмү (мисалы, CIDR менен) n 1 кошуу менен эсептөөгө болот n- бинардык өкүлчүлүктөгү позиция. Бинардык деп мен функцияларды колдонуунун натыйжасын айтып жатам пакет() и inet_pton() жана андан ары пайдалануу биттик операторлор, экилик менен бул экилик системанын көрсөтүлүшү, мисалы, base_convert().

тарыхый маалыматКласссыз даректүү класстарды бөлүү алдында болгон. Ошол алыскы жылдарда мынчалык көп субсеталар болот деп эч ким ойлогон эмес, алар оңго жана солго чоң блокторго бөлүштүрүлгөн: А классы - префикс биринчи 8 бит (б.а. биринчи сан), алдыңкы бит 0 болгон; класс B - биринчи 16 (биринчи эки сан), алдыңкы бит 10; C классы - биринчи 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ди бинардык маскага айландырышыбыз керек. Бул үчүн, биз анын он алтылык өкүлчүлүгүн чогултуп, экиликке топтойбуз.

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

чакыруу пакет('H*', $mask) алты бурчтуу өкүлчүлүктү дал ушундай жол менен топтойт inet_pton(). Бир гана айырмасы чалганда пакет() бардык 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 өткөрүп жана натыйжаны экилик жана адам окуй турган формада алуу мүмкүнчүлүгүн беребиз. Параметр $кайсысы бул жерде ал диапазонун башталышын же аягын алууну каалайбызбы (маанилер 'баштоо' же 'аягы' тиешелүүлүгүнө жараша).

Кийинки милдет (ошондой эле биздин компания үчүн эң практикалык) кийинки диапазонду эсептөө. Бул тапшырма үчүн, даректи экилик сапка кеңейтип, каалаган абалда 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 доллардан, биз сиз үчүн ойлоп тапкан баштапкы деңгээлдеги серверлердин уникалдуу аналогу: VPS (KVM) E5-2697 v3 (6 өзөктүү) 10 ГБ DDR4 480 ГБ SSD 1 Гбит/с 19 доллардан же серверди кантип бөлүшүү керектиги жөнүндө бардык чындык? (RAID1 жана RAID10 менен жеткиликтүү, 24 өзөккө чейин жана 40 ГБ DDR4 чейин).

Dell R730xd Амстердамдагы Equinix Tier IV маалымат борборунда 2 эсе арзанбы? Бул жерде гана 2 x 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 доллардан! Жөнүндө окуу Инфраструктураны кантип куруу керек. бир тыйынга 730 евро турган Dell R5xd E2650-4 v9000 серверлерин колдонуу менен класс?

Source: www.habr.com

DDoS коргоосу, VPS VDS серверлери бар сайттар үчүн ишенимдүү хостинг сатып алыңыз 🔥 DDoS коргоосу, VPS VDS серверлери бар ишенимдүү веб-сайт хостингин сатып алыңыз | ProHoster