Við fengum nýlega LIR stöðu og /29 IPv6 blokk. Og þá kom upp þörfin á að halda utan um úthlutað undirnet. Og þar sem innheimta okkar er skrifuð í PHP þurftum við að kafa aðeins ofan í málið og átta okkur á því að þetta tungumál er ekki það vingjarnlegasta hvað varðar að vinna með IPv6. Fyrir neðan skurðinn er lausn okkar á þeim vandamálum sem upp koma þegar unnið er með heimilisföng og svið. Kannski ekki það glæsilegasta, en það gerir starfið.

Smá kenning
Fyrirvari. Ef þú þekkir hvað IPv6 er og hvað því fylgir gæti þessi hluti verið leiðinlegur fyrir þig. Það er kannski ekki.
Fólki sem sér IPv6 skýringuna í fyrsta skipti gæti fundist það frekar ógnvekjandi. Eftir glæsilegur 64.233.177.101 við stöndum allt í einu frammi fyrir 2607:f8b0:4002:c08::8b og við gætum ruglast. Báðir eru bara læsileg framsetning 32 og 128 bita, í sömu röð. Sérhver IP pakki inniheldur haus með stranglega staðlaðan tilgang fyrir hvern bita. Án þess að fara dýpra í uppbyggingu hausanna, þá er eitt sem við þurfum að taka frá þessu að fyrir aðgerðir með IP tölur og svið er almennt þægilegt að nota tvöfalda stærðfræði og bitaaðgerðir. Það er líka þægilegast að geyma þær í gagnagrunninum sem TVÖLDUR (4) fyrir IPv4 og TVÖLDUR (16) fyrir IPv6.
Annar mikilvægur þáttur sem vert er að snerta á eru netgrímur og CIDR merki. CIDR er skammstöfun fyrir Classless Inter-Domain Routing (). Þetta hugtak hefur komið í stað flokkahugtaksins við að ákvarða hvaða hluti IP tölunnar er netforskeyti og hvaða hluti er heimilisfang netviðmótsins innan þessa nets. Í reynd verða fyrstu n bitarnir sem samsvara forskeytinu stilltir á 1, restin á 0.
Í mannlegum skiljanlegum formi er þetta skrifað í formi ip.add.re.ss/cidr. Til dæmis, 64.233.177.0/24 gefur til kynna að fyrstu 24 bitarnir vísa til forskeytsins. Síðustu 8 bitarnir, einnig þekktir sem síðasta talan í læsilegum nótum, vísa til heimilisfangsins innan undirnetsins. Nokkrar æfingar í viðbót. 64.233.177.101/32 и 2607:f8b0:4002:c08::8b/128 - eitt ákveðið heimilisfang. 2607:f8b0:4002:c08::/64 - fyrstu 64 bitarnir (fyrstu 4 hóparnir) eru forskeytið, hinir 64 bitarnir eru staðbundi hlutinn. Við the vegur, ef einhver ruglast á "::" í færslunni, kemur tvöfaldur tvípunktur í stað handahófskenndra fjölda hluta sem innihalda 0. Hann getur aðeins birst einu sinni í athugasemdinni. Með öðrum orðum, 2607:f8b0:4002:c08::8b = 2607:f8b0:4002:c08:0:0:0:8b.
Hvað þurfum við að læra af þessu öllu? Í fyrsta lagi er hægt að fá fyrsta og síðasta undirnetsfangið með því að nota tvöfalt OG og EÐA, með því að þekkja grímuna á tvíundarformi. Í öðru lagi, næsta undirnetstærð (þ.e. með CIDR) n er hægt að reikna út með því að bæta 1 við n-þessi staða í tvíundarframsetningu. Með tvöfaldri meina ég niðurstöðu þess að nota aðgerðir pakki() и inet_pton() og frekari notkun , með tvöfaldri er tvíkerfisframsetningin sem hægt er að fá með því að segja, base_convert().
SagaÁ undan stéttlausum ávörpum var stéttaskilnaður. Á þessum fjarlægu árum ímyndaði enginn sér að það yrðu svo mörg undirnet, þau voru dreift til vinstri og hægri í stórum blokkum: flokkur A - forskeytið var fyrstu 8 bitarnir (þ.e. fyrsta talan), með fremsta bita 0; flokkur B - fyrstu 16 (fyrstu tvær tölurnar), fremstu bitar 10; flokkur C - fyrstu 24 bitarnir, fremstu bitar 110. Þessir fremstu bitar tilgreindu svið þar sem heimilisfang tiltekins flokks var gefið út: 0.0.0.0 - 127.255.255.255 fyrir A flokk, 128.0.0.0 - 191.255.255.255 - flokkur B, 192.0.0.0 - 223.255.255.255 - flokkur C. Þegar internetið dreifðist um jörðina áttuðu eftirlitsaðilar sér að þeir höfðu misst marks og snemma á tíunda áratugnum þróuðu þeir flokkslaust hugtak sem gerði það mögulegt að vera ekki bundinn til fremstu bita. Smá nánari upplýsingar má finna í td. .
Við skulum halda áfram að æfa
Í reynd munum við framkvæma þrjú líklegast, eins og mér sýndist, verkefni:
- að fá fyrsta og síðasta heimilisfang sviðsins;
- fáðu næsta stærðarsvið (CIDR);
- athuga hvort heimilisfang tilheyri svæði.
Útfærslan verður fyrir IPv6, en ef nauðsyn krefur er auðvelt að aðlaga rökfræðina. Ég fékk nokkrar hugmyndir , en útfærði það aðeins öðruvísi. Einnig athuga dæmin ekki hvort innsláttarvillur séu til staðar. Svo, við skulum fara.
Eins og ég hef áður nefnt er hægt að ákvarða fyrsta og síðasta heimilisfang sviðs með því að nota bitaaðgerðir, með því að þekkja upphaf sviðsins og tvöfalda undirnetsmaskann. Í samræmi við það, það fyrsta sem við þurfum að gera er að breyta CIDR í tvöfalda grímu. Til að gera þetta munum við safna hex framsetningu hennar og pakka henni í tvöfalda.
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);
}Hringdu pakki('H*', $mask) pakkar hex framsetningunni á sama hátt og inet_pton(). Eini munurinn er sá að þegar hringt er pakki() allar 0-tölurnar verða að vera á sínum stöðum og það ættu ekki að vera tvípunktar í færslunni, ólíkt því sem hægt er að lesa af mönnum.
Næsta skref er að reikna út upphaf og lok sviðsins. Og hér koma blæbrigði. Bitaaðgerðir takmarkast af bitagetu örgjörvans. Í samræmi við það, á 32 bita CubieTruck mínum, sem ég nota stundum fyrir alls kyns prufudekur, verður ekki hægt að vinna alla 128 bita heimilisfangsins í einni aðgerð. Hins vegar er ekkert sem kemur í veg fyrir að við skiptum því í 32 bita hópa (svona tilviljun, hver veit á hvaða örgjörva við munum keyra).
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);
}
}Til notkunar í framtíðinni munum við veita möguleika á að senda IP og taka á móti niðurstöðunni á bæði tvíundar- og mannalæsilegu formi. Parameter $sem hér tilgreinir það hvort við viljum fá upphaf eða lok sviðsins (gildi 'byrja' eða 'endir' í sömu röð).
Næsta verkefni (og líka það hagnýtasta fyrir fyrirtækið okkar) er að reikna út næsta bil. Fyrir þetta verkefni kom ekkert betra upp í hugann en að stækka heimilisfangið í tvöfaldan streng og bæta við 1 í viðkomandi stöðu og fella síðan allt saman aftur. Til að forðast að gripir birtust hvar sem er ákvað ég að skipta heimilisfanginu fyrir bæti við niðurbrot og samsetningu.
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);
}
}Við úttakið fáum við forskeytið fyrir næsta stærðarsvið sem tilgreint er í $cidr. Með þessari aðgerð úthlutum við blokkum af heimilisföngum til viðskiptavina okkar.
Að lokum, athuga hvort heimilisfangið tilheyri sviðinu. Til dæmis úthlutaðum við einum blokk /48 til að dreifa blokkum til viðskiptavina /64, og við þurfum að gæta þess að við úthlutun förum við ekki út fyrir úthlutaðan blokk (í reynd mun þetta ekki gerast fljótlega, en það er samt möguleiki). Hér er allt einfalt. Við fáum upphaf og lok sviðsins á tvíundarformi og athuga hvort heimilisfangið sé innan marka.
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);
}Ég vona að þetta hafi verið gagnlegt. Hvaða aðrar aðgerðir til að vinna með heimilisföng gætu verið gagnlegar að þínu mati? Allar viðbætur, athugasemdir og umsagnir um kóða eru hjartanlega vel þegnar í athugasemdunum.
Ef þú ert nú þegar viðskiptavinur okkar eða ert bara að hugsa um að verða það, í tilefni af birtingu þessarar greinar bjóðum við þér að fá blokk /64 algjörlega ókeypis fyrir alla vps þjónustu eða sérstakan netþjón í Equinix Tier IV gagnaverinu, Hollandi ef óskað er eftir því við söludeildina með því að gefa upp hlekk á þessa grein í miðanum. Tilboðið gildir út mars 2020.
Nokkrar auglýsingar 🙂
Þakka þér fyrir að vera hjá okkur. Líkar þér við greinarnar okkar? Viltu sjá meira áhugavert efni? Styðjið okkur með því að leggja inn pöntun eða mæla með því við vini, , einstök hliðstæða upphafsþjóna, sem var fundið upp af okkur fyrir þig: (fáanlegt með RAID1 og RAID10, allt að 24 kjarna og allt að 40GB DDR4).
Dell R730xd 2x ódýrari í Equinix Tier IV gagnaveri í Amsterdam? Aðeins hér í Hollandi! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - frá $99! Lestu um
Heimild: www.habr.com
