Hiljuti saime LIR staatus ja \/29 IPv6 blokk. Järgnevalt tekkis vajadus jälgida määratud alamvõrke. Ja kuna meie arveldus on kirjutatud PHP-s, pidime natuke selle küsimusega tegelema ja mõistma, et see keel ei ole IPv6-ga töötamisel kõige sõbralikum. Allpool on meie lahendus tekkinud ülesannetele seoses aadresside ja vahemikega. Võib-olla mitte kõige elegantsim, kuid seatud eesmärgid on täidetud.

Veidi teooriat
Äratus. Kui te olete tuttav IPv6-ga ja teate, milleks see mõeldud on, võib see osa olla teile igav. Võib-olla ka mitte.
Inimesed, kes näevad IPv6 annotatsiooni esmakordselt, võivad olla üsnagi segaduses. Pärast elegantsseid 64.233.177.101 kohtame järsku 2607:f8b0:4002:c08::8b ja võime jääda segadusse. Mõlemad numbrid on lihtsalt inimkeele mõistmine 32 ja 128 bitti vastavalt. Iga IP paketis sisaldab pealkirja, millel on rangelt standardiseeritud igas bitis ettenähtud otstarve. Rikkumata sügavamale pealkirjade struktuuri, peame siit välja tooma ühe: IP-aadresside ja vahemike operatsioonide jaoks on kõige mugavam kasutada binaarset matemaatikat ja bitipõhiseid operatsioone. Neid on ka mugavam salvestada andmebaasis kui BINARY(4) IPv4 jaoks ja BINARY(16) IPv6 jaoks.
Veel üks oluline aspekt, mida tasub mainida, on võrgu maskid ja CIDR notaation. CIDR on akronüüm Classless Inter-Domain Routing (). See kontseptsioon asendas klassikalise pädevuse küsimuses, milline osa IP-aadressist on võrgu prefiks ja milline - võrgu liidese aadress sees. Praktikas esimesed n bitti, mis vastavad prefiksile, on seatud väärtuseks 1, ülejäänud - 0.
Inimkeeles kirjutatakse see kujul ip.add.re.ss\/cidr. Näiteks, 64.233.177.0/24 tähendab, et esimesed 24 bitti on seotud prefiksiga. Viimased 8 bitti, mis on ka viimane number inimkeeles, on seotud alamvõrgi sees asuva aadressiga. 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 rühma) on prefiks, ülejäänud 64 bitti on kohalik osa. Ükskõik, kui keegi on häiritud, et "::" on kirjas, asendab topelt-kaks punkti juhusliku arvu sektsioone, mis sisaldavad 0. See 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õigest õppida võiksime? Esiteks, alamtõrve esimene ja viimane aadress saadakse binaarsete AND ja OR operatsioonide abil, teades maski binaarses vormis. Teiseks, järgmise alamtõrve suuruse (st CIDR) n saab arvutada, kui liita 1 n-le positsioonile binaarsete representatsioonis. Binaarse all, mõtlen ma funktsioonide kasutamise tulemusi pack() ja inet_pton() ja edasist kasutamist , binaarses - binaarsüsteemis esitus, mille saame näiteks funktsiooni abil base_convert().
2DOMAINS on 16 aastat teeninud professionaale, kes on valmis maksma vaid nende valikute eest, mida nad tõeliselt kasutavad.Klassivaba aadressimine eelnes klassipõhisele segmenteerimisele. Neil ammustel aastatel ei osanud keegi arvata, et alamtõrve tuleb nii palju, ja neid jagati vasakule ja paremale suurte blokkmääradena: klass A - esimesed 8 bitti (st esimene number), juhtiva bitiga 0; klass B - esimesed 16 (esimesed kaks numbrit), juhtivad bitid 10; klass C - esimesed 24 bitti, juhtivad bitid 110. Need juhtivad bitid määrasid vahemikud, milles jagati teiste klasside aadresse: 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. Aja jooksul, kui internet levis üle maailma, mõistsid reguleerijad, et nad olid eksinud, ja 90-ndate alguses töötati välja klassivaba kontseptsioon, mis võimaldas mitte siduda end juhtivate bittidega. Veidi rohkem teavet saab leida näiteks .
Liigume praktikale
Praktikas rakendame kolm kõige tõenäolisemat ülesannet, mis mulle tunduvad:
- esimese ja viimase aadressi saamine vahemikus;
- järgmise vahemiku saamine määratud suurusega (CIDR);
- aadressi kuuluvuse kontroll vahemikku.
Rakendus on IPv6 jaoks, kuid vajadusel on loogikat lihtne kohandada. Mõningaid ideid olen ma saanud , kuid rakendasin neid veidi teisiti. Samuti ei sisalda näidetes sisendi vigade kontrolli. Nii et hakkame minema.
Kuidas mainisin, esimese ja viimase aadressi vahemikus saab määrata bitipõhiste operatsioonide abil, teades vahemiku algust ja binaarset alamtõrve maski. Seega peame kõigepealt CIDRi muutma binaarseks maskiks. Selleks kogume selle hex-esituse ja pakime binaarsesse.
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);
}Kutsumine pack(‘H*’, $mask) pakib hex-esituse samamoodi nagu inet_pton(). Ainult selle erinevusega, et väljakutse tegemisel pack() kõik 0 peaksid olema oma kohtades, ja üheskirjas ei tohiks olla kolmikpunkti, erinevalt loetavatest kirjetest.
Järgmine samm on vahemiku alguse ja lõpu arvutamine. Ja siin tekivad nüansid. Bititaseme operatsioonid on piiratud protsessori sõnumiga. Seega, minu 32-bitises CubieTruckis, mida ma aeg-ajalt kasutan erinevate testide tegemiseks, ei saa kõiki 128 bitti aadressi ühe operatsiooniga töötlema. Siiski, miski ei takista meil jagada see 32-bitisteks gruppideks (igaks juhuks, kes 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);
}
}Tulevase kasutuse jaoks plaanime võimalust edastada IP ja saada tulemus nii binaarses kui ka loetavas vormis. Parameeter $which määrab, kas tahame saada vahemiku algust või lõppu (väärtused 'start' või 'end' vastavalt).
Järgmine ülesanne (samuti kõige praktilisem meie firma jaoks) - järgmise vahemiku arvutamine. Selle ülesande jaoks ei tulnud midagi paremat pähe kui jagada aadress binaarstringiks ja lisada 1 vajaliku positsiooni juurde, seejärel kõik uuesti kokku panna. Et mitte peaks artefakte ilmuma, otsustasin aadressi jagamisel ja kokkupanemisel jagada aadressi baidi kaupa.
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 prefikse suurusele, nagu on näidatud $cidr. Selle funktsiooni abil eraldame aadressiblokid meie klientidele.
Lõpuks kontrollimine, kas aadress kuulub vahemikku. Näiteks oleme eraldanud ühe bloki /48 klientidele /64 blokeerimiseks, ja peame veenduma, et määramisel ei ületa me eraldatud ploki piire (praktikas juhtub see harva, kuid siiski on tõenäosus olemas). Siin on kõik lihtne. Saame vahemiku alguse ja lõpu binaarvormis ja kontrollime, kas aadress jääb piiridesse.
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 käsitlemise funktsioonid võiks teie arvates olla kasulikud? Kõik täiendused, kommentaarid ja koodiarvustused on kommentaarides sooja vastuvõtuga oodatud.
Kui olete juba meie klient või kaalute selleks saamist, siis seoses selle artikli ilmumisega pakume teile täielikult tasuta /64 ploki kõigi VPS- või dedikeeritud serverite teenuste jaoks Equinixi Tier IV andmekeskuses Hollandis, kui esitate müügiosakonnale selle artikli lingi pileti kaudu. Pakkumine kehtib kuni 2020. aasta märtsi lõpuni.
Veidi reklaami 🙂
Aitäh, et olete meiega. Kas teile meeldivad meie artiklid? Kas soovite näha rohkem huvitavat sisu? Toetage meid, tellides teenuse või soovitades meid tuttavatele. , ainulaadne entry-level serverite analoog, mille oleme teie jaoks välja mõelnud: (saadaval RAID1 ja RAID10 variandid, kuni 24 tuuma ja kuni 40GB DDR4).
Dell R730xd on Equinixi Tier IV andmekeskuses Amsterdamis kaks korda odavam? Ainult meie juures Hollandis! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — alates $99! Lugege sellest
Allikas: habr.com
