Hiljuti saime LIR staatuse ja /29 IPv6 ploki. Seejärel tekkis vajadus arvestada määratud alateid. Kuna meie arveldus on kirjutatud PHP-s, tuli natuke süveneda sellesse küsimusse ja mõista, et see keel ei ole IPv6 osas kõige sõbralikum. Allpool on meie lahendus tõusetunud probleemidele, mis on seotud aadresside ja vahemikega. Võib-olla mitte kõige elegantsem, kuid seatud eesmärgid on saavutatud.

Natuke teooriat
Distsipliin. Kui olete tuttav IPv6 kontseptsiooniga ja teate, milleks seda kasutatakse, võib see osa teile igav olla. Võib ka mitte olla.
Inimesed, kes näevad IPv6 annotatsiooni esmakordselt, võivad sellest kergesti segadusse minna. Pärast elegantseid 64.233.177.101 kohtume ootamatult 2607:f8b0:4002:c08::8b ja võime erutuda. Mõlemad on vaid inimesele arusaadavad kujutised vastavalt 32 ja 128 bitist. Iga IP-pakett sisaldab päist, millel on rangelt standarditud iga bitide määratlemine. Ilma päiste struktuuri sügavamale laskumata peaksime siit välja tooma ühe: IP-aadresside ja vahemike operatsioonide jaoks on mõistlik kasutada peamiselt binaarset matemaatikat ja bititasemel operatsioone. Neid on ka andmebaasis mugavam hoida kui BINAARNE(4) IPv4 jaoks ja BINAARNE(16) IPv6 jaoks.
Veel üks oluline aspekt, mida tasub käsitleda, on võrku maskid ja CIDR notatsioon. CIDR on akronüüm sõnadest Classless Inter-Domain Routing (). See kontseptsioon tuli klassikalise adresseerimise asemele, et määrata, milline osa IP-aadressist on võrgu prefiks ja milline on liidese aadress selle võrgu sees. Praktikas on esimesed n bitti, mis vastavad prefiksile, seadistatud väärtuseks 1, teised bitti saavad väärtuseks 0.
Inimesele arusaadavas vormis kirjutatakse see kujul ip.add.re.ss/cidr. Näiteks, 64.233.177.0/24 60.24.0.0/24 tähendab, et esimesed 24 bitti kuuluvad prefiksile. Viimased 8 bitti, mis on samuti viimane number inimkeeles arusaadavas kirjutises, viitavad aadressile alamvõrgus. Veel paar harjutust. 64.233.177.101/32 ja 2607:f8b0:4002:c08::8b/128 — üks konkreetne aadress. 2607:f8b0:4002:c08::/64 — esimesed 64 bitti (esimesed 4 gruppi) on prefiks, ülejäänud 64 bitti on lokaalosa. Muide, kui kedagi häirib "::" kirjutises, siis kahekordne koolon asendab suvalise arvu sektsioone, mis sisaldavad 0. Seda võib esineda annotatsioonis ainult 1 kord. Teisisõnu, 2607:f8b0:4002:c08::8b = 2607:f8b0:4002:c08:0:0:0:8b.
Mida me sellest kõikjast järeldame? Esiteks, alamsaadete esimese ja viimase aadressi saab määrata kasutades binaarseid AND ja OR, teades maski binaarses vormis. Teiseks, järgmist alamsaadet suurusega (st CIDR) n saab arvutada, lisades 1 n-ndale positsioonile binaarsetes esitustes. Binaarse all mõistan ma funktsioonide pack() ja inet_pton() ja edasist kasutamist , binaarsetena — esitus binaarses süsteemis, mille saab näiteks saada funktsiooni kaudu base_convert().
Ajalooline ülevaadeKlassituste eelõht eelnes klassile segmenteeritud adresseerimine. Tollal ei osanud keegi arvata, et alamsateid tuleb nii palju, neid jagati laialdaselt suurte plokkidena: klass A — eelmise 8 bitti (st esimene number), esimesel bitil 0; klass B — esimesed 16 bitti (esimesed kaks numbrit), esimesed bitid 10; klass C — esimesed 24 bitti, esimesed bitid 110. Need juhtivad bitid määrasid vahemikud, kus anti välja aadress vastava klassi jaoks: 0.0.0.0 — 127.255.255.255 klass A, 128.0.0.0 — 191.255.255.255 — klass B, 192.0.0.0 — 223.255.255.255 — klass C. Kui internet hakkas üle maailma laienema, mõistsid reguleerijad, et nad olid eksinud, ning 90ndate alguses töötati välja klassitu kontseptsioon, mis võimaldas mitte siduda end juhtivate bittidega. Veidi rohkem üksikasju saab leida näiteks .
Liigume praktika juurde
Praktikas rakendame kolme kõige tõenäolisemat, nagu mulle tundub, ülesannet:
- esimese ja viimase aadressi saamine vahemikus;
- järgmise antud suurusega vahemiku saamine (CIDR);
- aadressi kuuluvuse kontrollimine vahemikku.
Rakendus on IPv6 jaoks, kuid vajadusel saab loogikat hõlpsasti kohandada. Mõned ideed olen saanud , kuid rakendasin neid veidi teistsuguselt. Samuti ei sisalda näidetes sisendi vigade kontrollimist. Nii et lähme edasi.
Nagu juba mainisin, saab vahemiku esimese ja viimase aadressi määrata bititasemeliste operatsioonide abil, teades vahemiku algust ja binaarset alamhulga maski. Seetõttu peame esmalt CIDRi binaarseks maskiks muutma. Selleks kogume selle hex-esituse ja pakime selle binaarsesse formaati.
funktsioon cidrToMask ($cidr) {
$mask = str_repeat('f', ceil($cidr / 4));
$mask .= dechex(4 * ($cidr % 4));
$mask = str_pad($mask, 32, '0');
return pack('H*', $mask);
}Kutse pack('H*', $mask) pakendatakse hex esitus samamoodi nagu inet_pton(). Ainult et kutsumise korral pack() peavad kõik 0 olema oma kohtadel ning koolonid esituses ei tohi olla, erinevalt inimloetavast esitlusest.
Järgmine samm on vahemiku alguse ja lõpu arvutamine. Siin tulevad mängu nüansid. Bitilised operatsioonid on piiratud protsessori bitiga. Seega, minu 32-bitises CubieTruckis, mida ma mõnikord kasutan igasuguste testide jaoks, ei saa kõiki 128 bitti aadressist korraga töödelda. Siiski ei takista meid midagi jagamast seda 32-bitiseks rühmaks (igaks juhuks, keegi teab, millistel protsessoritel me jooksma hakkame).
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);
}
}Tulevaseks kasutamiseks planeerime võimaluse edastada IP ja saada tulemus nii binaarselt kui ka inimloetaval kujul. Parameeter $which määrab, kas tahame saada vahemiku algust või lõppu (väärtused 'start' või 'end' vastavalt).
Järgmine ülesanne (ja ka kõige praktilisem meie ettevõtte jaoks) on järgmise vahemiku arvutamine. Selle ülesande jaoks ei tulnud midagi paremat kui adresseerimise lahutamine binaarstringiks ja 1 lisamine vajalikes kohtades, seejärel kõik tagasi kokku panna. Et mitte jätta jälgi, otsustasin adresseerimise lahutamisel ja kogumisel adresseerimist byte-ks jagada.
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);
}
}Väljundina saame järgmise vahemiku eesliite, mille suurus on märgitud $cidr. Selle funktsiooniga anname aadressibloke oma klientidele.
Lõpuks kontrollime, kas aadress kuulub vahemikku. Näiteks, oleme eraldanud ühe bloki /48 klientidele /64 bloki jagamiseks ning peame veenduma, et määramisel ei ületa me eraldatud bloki piire (praktikas see ei juhtu varsti, kuid siiski on tõenäosus olemas). Siin on kõik lihtne. Saame vahemiku alguse ja lõpu binaarses vormis ning kontrollime, kas aadress jääb vahemikku.
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);
}Loodan, et see oli kasulik. Millised muud aadresside haldamise funktsioonid võiksid Teie arvates kasulikud olla? Igaüht, kes lisab kommentaare, täiendusi või koodivaatlust, on oodatud kommentaarides.
Kui Te olete juba meie klient või alles kaalute selleks saamist, siis seoses selle artikli ilmumisega pakume Teile võimalust saada tasuta /64 plokk kõigi VPS või dedikeeritud serverite teenuste jaoks Equinix Tier IV andmekeskuses, Hollandis, müügiosakonnale vestlusesse viidates sellele artiklile. Pakkumine kehtib kuni märtsi 2020.
Veidi reklaami 🙂
Aitäh, et olete meiega. Kas teile meeldivad meie artiklid? Kas soovite näha rohkem huvitavaid materjale? Toetage meid, tehes tellimuse või soovitades meid tuttavatele. , ainulaadne sisenemise taseme serverite analoog, mille oleme teie jaoks välja mõelnud: (saadaval on RAID1 ja RAID10 variandid, kuni 24 südamikku ja kuni 40GB DDR4).
Kas Dell R730xd on kaks korda odavam Equinixi Tier IV andmete keskuses Amsterdamis? Ainult meie juures Hollandi turul! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — alates $99! Lugege, kuidas
Allikas: habr.com
