Isihloko sinxibe kakuhle, ndiyazi. Ngokomzekelo, kukho into emangalisayo
Ngenxa yokuba iinkundla kunye ne-RKN zivimba yonke into ekhohlo nasekunene, kwaye ababoneleli bazama nzima ukuba bangaweli phantsi kweentlawulo ezikhutshwe nguRevizorro, ilahleko ehambelanayo yokuthintela zikhulu kakhulu. Kwaye phakathi kweendawo ezivaliweyo "ngokusemthethweni" zininzi eziluncedo (hello, rutracker)
Ndihlala ngaphandle kolawulo lwe-RKN, kodwa abazali bam, izalamane nabahlobo bam basahleli kwilizwe lam lokuzalwa. Ngoko ke kwagqitywa ekubeni kuze nendlela elula yokuba abantu abakude ne-IT badlulele ekuthinteleni, ngokukhethekileyo ngaphandle kokuthatha inxaxheba kwabo konke.
Kule nqaku, andiyi kuchaza izinto ezisisiseko zenethiwekhi inyathelo ngesinyathelo, kodwa ndiya kuchaza imigaqo jikelele yendlela esi sikimu esinokuphunyezwa ngayo. Ke ulwazi malunga nendlela inethiwekhi esebenza ngayo ngokubanzi kwaye kwiLinux ngokukodwa kufuneka ube nayo.
Iintlobo zokutshixa
Okokuqala, masihlaziye inkumbulo yethu malunga nokuba yintoni evaliweyo.
Kukho iindidi ezininzi zokutshixa kwi-XML ekhutshelweyo esuka kwi-RKN:
- IP
- Indawo
- URL
Ukuze kube lula, siya kuzinciphisa zibe zimbini: i-IP kunye nesizinda, kwaye ukusuka ekuvimbeni nge-URL siya kukhupha nje i-domain (okanye kunoko, oku sele kwenziwe kuthi).
Abantu abalungileyo ukusuka
- IP:
https://api.reserve-rbl.ru/api/v2/ips/json - Imimandla:
https://api.reserve-rbl.ru/api/v2/domains/json
Ukufikelela kwiindawo ezivaliweyo
Ukwenza oku, sidinga i-VPS encinci yangaphandle, ngokukhethekileyo kunye netrafikhi engenamkhawulo - zininzi zazo kwi-3-5 bucks. Kufuneka uyithenge kufuphi phesheya ukuze i-ping ingabi phezulu kakhulu, kodwa kwakhona khumbula ukuba i-intanethi kunye nejografi ayihlali ihambelana. Kwaye ekubeni akukho SLA ye-5 bucks, kungcono ukuthatha iziqwenga ze-2 + kubaboneleli abahlukeneyo ukwenzela ukunyamezela impazamo.
Emva koko, kufuneka simise itonela efihliweyo ukusuka kumzila womxhasi ukuya kwiVPS. Ndisebenzisa i-Wireguard njengeyona ikhawulezayo kwaye ilula ukuyiqwalasela kuba... Iirotha zomthengi wam zisekwe kwi Linux (
Ukuchongwa kunye nokuhlengahlengiswa kwetrafikhi yomdla
Unako, ewe, ukumisa konke ukugcwala kwi-Intanethi ukusuka phesheya. Kodwa, kunokwenzeka ukuba, isantya sokusebenza kunye nomxholo wendawo siya kubandezeleka kakhulu kule nto. Ngaphezu koko, iimfuno ze-bandwidth kwi-VPS ziya kuba phezulu kakhulu.
Ke ngoko, kuya kufuneka ukuba ngandlel 'ithile sibeke bucala itrafikhi kwiindawo ezivaliweyo kwaye sikhethe indlela eya kwitonela. Nokuba ezinye zetrafikhi "ezongezelelweyo" zifika apho, kusengcono kakhulu kunokuqhuba yonke into ngetonela.
Ukulawula i-traffic, siya kusebenzisa i-protocol ye-BGP kwaye sibhengeze iindlela kwiinethiwekhi eziyimfuneko ukusuka kwi-VPS yethu kubaxhasi. Masithathe INYAKA njengedaemon ye-BGP, njengoko yenye yezona zinto zisebenzayo kwaye zilungele.
IP
Yonke into icacile ngokuvalwa kwe-IP: sibhengeza nje zonke ii-IP ezivaliweyo ezivela kwiVPS. Ingxaki kukuba kukho malunga ne-600 yamawaka e-subnets kuluhlu olunikezwa yi-API, kwaye uninzi lwazo luyi-/32 hosts. Eli nani leendlela linokubhidanisa iirotha zabaxumi ababuthathaka.
Ke ngoko, xa kusetyenzwa uluhlu, kwagqitywa ekubeni kushwankathelwe ukuya kwinethiwekhi ye-24 ukuba kukho i-2 okanye iinginginya ezingaphezulu kuyo. Ngaloo ndlela, inani leendlela liye lancitshiswa ukuya kwi- ~ 100 lamawaka. Iscript soku siya kulandela.
Domains
Kunzima ngakumbi kwaye kukho iindlela ezininzi. Umzekelo, ungafaka i-squid ebonakalayo kwi-router yomxhasi ngamnye kwaye uthintele i-HTTP apho kwaye uhlole ukuxhawula ngesandla kwe-TLS ukuze ufumane i-URL eceliweyo kwimeko yokuqala kunye nesizinda esivela kwi-SNI okwesibini.
Kodwa ngenxa yayo yonke into entsha ye-TLS1.3 + eSNI, uhlalutyo lwe-HTTPS luya lusiba luncinci kwaye luncinci yonke imihla. Kwaye iziseko zoncedo kwicala lomxhasi ziba nzima kakhulu - kuya kufuneka usebenzise ubuncinci i-OpenWRT.
Ke ngoko, ndigqibe kwelokuba ndithathe indlela yokuthintela iimpendulo kwimibuzo ye-DNS. Apha, kwakhona, zonke iintlobo ze-DNS-over-TLS / HTTPS ziqala ukuhamba phezu kweentloko zethu, kodwa sinako (okwangoku) ukulawula le nxalenye kumxhasi - mhlawumbi uyikhubaze okanye sisebenzise iseva yethu ye-DoT / DoH.
Uyiqweqwedisa njani iDNS?
Kusenokubakho iindlela ezininzi apha.
- Ukuthintela itrafikhi ye-DNS ngePCAP okanye iNFLOG
Zombini ezi ndlela zokuthintela ziphunyezwa kusetyenzisosidmat . Kodwa ayizange ixhaswe ixesha elide kwaye ukusebenza kukude kakhulu, ngoko ke kusafuneka ubhale isibophelelo sayo. - Uhlalutyo lwelog yeseva ye-DNS
Ngelishwa, ii-recursors endizaziyo aziyazi indlela yokungena iimpendulo, kodwa zicela kuphela. Ngokomgaqo, oku kunengqiqo, kuba, ngokungafaniyo nezicelo, iimpendulo zinesakhiwo esiyinkimbinkimbi kwaye kunzima ukuzibhala kwifomu yombhalo. DNStap
Ngethamsanqa, uninzi lwabo sele luxhasa i-DNSTap ngezi njongo.
Yintoni iDNStap?
Le yiprotocol yomxhasi-server esekwe kwiProtocol Buffers kunye neFrame Streams ukudlulisa eyakhiweyo imibuzo yeDNS kunye neempendulo ukusuka kumncedisi we DNS ukuya kumqokeleli. Ngokusisiseko, iseva ye-DNS ithumela i-metadata yesicelo kunye nempendulo (uhlobo lomyalezo, umxhasi/umncedisi we-IP, njl. njl.) kunye nemiyalezo epheleleyo ye-DNS kwifom (yesibini) apho isebenza nabo kwinethiwekhi.
Kubalulekile ukuqonda ukuba kwi-paradigm ye-DNStap, iseva ye-DNS isebenza njengomthengi, kwaye umqokeleli wenza njengomncedisi. Oko kukuthi, iseva ye-DNS idibanisa nomqokeleli, kwaye kungekhona ngokuphambene.
Namhlanje, i-DNStap ixhaswa kuzo zonke iiseva ze-DNS ezidumileyo. Kodwa, umzekelo, BIND kunikezelo oluninzi (njengoBuntu LTS) ihlala iqokelelwa ngesizathu esithile ngaphandle kwenkxaso yayo. Ke masingakhathali ngokwakha kwakhona, kodwa masithathe irecursor ekhaphukhaphu kwaye ekhawulezayo-Ingabotshwanga.
Uyibamba njani iDNStap?
kukho
I-algorithm yomsebenzi:
- Xa iqaliswa, ilayisha uluhlu lwemimandla ukusuka kwifayile yombhalo, iyayiguqula (habr.com -> com.habr), ingabandakanyi imigca ephukileyo, i-duplicates kunye ne-subdomains (oko kukuthi ukuba uluhlu luqulethe i-habr.com kunye ne-www.habr.com, izakulayishwa kuphela eyokuqala) kwaye yakha umthi wesimaphambili sokukhangela ngokukhawuleza ngolu luhlu
- Isebenza njengomncedisi we DNStap, ilinda uqhagamshelo olusuka kwiseva yeDNS. Ngokomgaqo, ixhasa zombini iisokethi ze-UNIX kunye ne-TCP, kodwa abancedisi be-DNS endibaziyo baxhasa iziseko ze-UNIX kuphela.
- Iipakethi ezingenayo ze-DNStap ziqale zachithwa kwisakhiwo seProtobuf, kwaye emva koko umyalezo wokubini weDNS ngokwawo, obekwe kwenye yemihlaba yeProtobuf, ucalulwe kwinqanaba leerekhodi ze-DNS RR.
- Iyajongwa ukuba ingaba umamkeli oceliweyo (okanye ummandla womzali) ukuluhlu olulayishiweyo ukuba akunjalo, impendulo ayinanzwa
- Kuphela i-A/AAAA/CNAME RRs ekhethiweyo kwimpendulo kwaye iidilesi ezihambelanayo ze-IPv4/IPv6 zitsalwa kuzo.
- Iidilesi ze-IP zigcinwe nge-TTL eqwalaselweyo kwaye ibhengezwe kubo bonke oontanga beBGP eziqwalaselweyo.
- Xa ufumana impendulo ekhomba kwi-IP esele igcinwe, i-TTL yayo ihlaziywa
- Emva kokuba i-TTL iphelelwe, ukungena kuyasuswa kwi-cache nakwi-BGP izaziso
Umsebenzi owongezelelweyo:
- Ukufunda kwakhona uluhlu lwemimandla ngu-SIGHUP
- Ngqamanisa i-cache kunye nezinye iimeko idnstap-bgp nge-HTTP/JSON
- Ukuphinda-phinda i-cache kwidiski (kwi-database ye-BoltDB) ukubuyisela imixholo yayo emva kokuqalisa kwakhona
- Inkxaso yokutshintshela kwisithuba somsebenzi womnatha esahlukileyo (kutheni oku kufuneka kuchazwe ngezantsi)
- IPv6 inkxaso
Imida:
- Imimandla ye-IDN ayikaxhaswa
- Izicwangciso ezimbalwa ze-BGP
Ndaqokelela
Iskimu
Ke, masiqale ukudibanisa onke amacandelo kunye. Ngenxa yoko, kufuneka sifumane into efana nale yetopology yenethiwekhi:
Ingqiqo yomsebenzi, ndicinga ukuba, icacile kumzobo:
- Umxhasi unomncedisi wethu olungiselelwe njenge-DNS, kwaye izicelo ze-DNS kufuneka zihambe nge-VPN. Oku kuyimfuneko ukwenzela ukuba umboneleli akakwazi ukusebenzisa i-DNS interception ukuvala.
- Xa umxhasi evula iwebhusayithi, ithumela isicelo seDNS esifana βneyiphi i-IP enayo i-xxx.org?β
- engadityaniswanga isombulula i-xxx.org (okanye iyithathe kwi-cache) kwaye ithumela impendulo kumxhasi "xxx.org ine-IP enjalo", ngaxeshanye ikhuphela nge-DNStap
- idnstap-bgp ithengisa ezi dilesi INTAKA nge BGP ukuba indawo ikuluhlu oluvaliweyo
- INTAKA ithengisa indlela eya kwezi IPs nge
next-hop self
umzila womxhasi - Iipakethi ezilandelayo ukusuka kumxhasi ukuya kwezi IPs zihamba ngetonela
Kumncedisi, ndisebenzisa itafile eyahlukileyo ngaphakathi kwe-BIRD kwiindlela eziya kwiindawo ezivaliweyo kwaye ayidibanisi ne-OS nangayiphi na indlela.
Kukho ukubuyisela umva kolu dweliso: ipakethi yokuqala ye-SYN evela kumxhasi inokuba nexesha lokudlula kumnikezeli wasekhaya kuba Indlela ayibhengezwa ngoko nangoko. Kwaye apha kukho iinketho ezinokwenzeka kuxhomekeke kwindlela umnikezeli akwenza ngayo ukuvimba. Ukuba uwisa nje i-traffic, akukho ngxaki. Kwaye ukuba iphinda ibuyisele kwi-DPI ethile, ngoko (ngokwethiyori) iziphumo ezikhethekileyo zinokwenzeka.
Imimangaliso nayo inokwenzeka kunye nabathengi abangayithobeliyo i-DNS TTL, enokubangela ukuba umxhasi asebenzise ezinye iirekhodi eziphelelwe yisikhathi kwi-cache yayo ebolileyo endaweni yokucela i-Unbound.
Enyanisweni, akukho nto yokuqala okanye yesibini eyabangela iingxaki kum, kodwa i-mileage yakho inokwahluka.
ULungiselelo lweseva
Ukuze kube lula ukukhupha, ndabhala
Masihambe kumacandelo aphambili.
BGP
Xa usebenzisa iidaemoni ezimbini ze-BGP kwinginginya enye, ingxaki ebalulekileyo iyavela: I-BIRD ayifuni ukuphakamisa i-BGP yokujonga ngenginginya yendawo (okanye nalo naluphi na ujongano lobulali). Ukususela kwigama ngokupheleleyo. I-Googling kunye nokufunda uluhlu lokuposa aluzange luncede, babanga ukuba luyilo. Kusenokubakho indlela ethile, kodwa andikayifumani.
Ungazama enye i-daemon ye-BGP, kodwa ndiyayithanda i-BIRD kwaye ndiyisebenzisa kuyo yonke indawo, andifuni ukwenza amaziko amaninzi.
Ngoko ke, ndifihle i-dnstap-bgp ngaphakathi kwendawo yamagama yenethiwekhi, edibaniswe kwingcambu ngokusebenzisa i-interface ye-veth: ifana nombhobho, iziphelo eziphuma kwiindawo zamagama ezahlukeneyo. Kwisiphelo ngasinye kwezi sincamathelisa iidilesi ze-IP zabucala ze-p2p ezingagqithiyo ngaphaya komsingathi, ngoko zinokuba nantoni na. Le ikwayindlela enye esetyenziselwa ukufikelela kwiinkqubo ngaphakathi wonke umntu ozithandayo Docker kunye nezinye izitya.
Kungenxa yoko le nto kwabhalwayo
Umzekelo wombhalo wokwenza isithuba samagama
#!/bin/bash
NS="dtap"
IP="/sbin/ip"
IPNS="$IP netns exec $NS $IP"
IF_R="veth-$NS-r"
IF_NS="veth-$NS-ns"
IP_R="192.168.149.1"
IP_NS="192.168.149.2"
/bin/systemctl stop dnstap-bgp || true
$IP netns del $NS > /dev/null 2>&1
$IP netns add $NS
$IP link add $IF_R type veth peer name $IF_NS
$IP link set $IF_NS netns $NS
$IP addr add $IP_R remote $IP_NS dev $IF_R
$IP link set $IF_R up
$IPNS addr add $IP_NS remote $IP_R dev $IF_NS
$IPNS link set $IF_NS up
/bin/systemctl start dnstap-bgp
dnstap-bgp.conf
namespace = "dtap"
domains = "/var/cache/rkn_domains.txt"
ttl = "168h"
[dnstap]
listen = "/tmp/dnstap.sock"
perm = "0666"
[bgp]
as = 65000
routerid = "192.168.149.2"
peers = [
"192.168.149.1",
]
intaka.conf
router id 192.168.1.1;
table rkn;
# Clients
protocol bgp bgp_client1 {
table rkn;
local as 65000;
neighbor 192.168.1.2 as 65000;
direct;
bfd on;
next hop self;
graceful restart;
graceful restart time 60;
export all;
import none;
}
# DNSTap-BGP
protocol bgp bgp_dnstap {
table rkn;
local as 65000;
neighbor 192.168.149.2 as 65000;
direct;
passive on;
rr client;
import all;
export none;
}
# Static routes list
protocol static static_rkn {
table rkn;
include "rkn_routes.list";
import all;
export none;
}
rkn_routes.list
route 3.226.79.85/32 via "ens3";
route 18.236.189.0/24 via "ens3";
route 3.224.21.0/24 via "ens3";
...
DNS
Ngokungagqibekanga, ku-Ubuntu, i-binary engabotshwanga ibotshelelwe ngeprofayile ye-AppArmor, eyithintelayo ekudibaneni kuyo nayiphi na iziseko ze-DNStap. Ungayicima le nkangeleko okanye uyivale:
# cd /etc/apparmor.d/disable && ln -s ../usr.sbin.unbound .
# apparmor_parser -R /etc/apparmor.d/usr.sbin.unbound
Oku kufanele ukuba kongezwe kwincwadi yokudlala. Kuya kuba kuhle, ngokuqinisekileyo, ukulungisa iphrofayili kwaye ndikhuphe amalungelo ayimfuneko, kodwa ndandisonqena kakhulu.
unbound.conf
server:
chroot: ""
port: 53
interface: 0.0.0.0
root-hints: "/var/lib/unbound/named.root"
auto-trust-anchor-file: "/var/lib/unbound/root.key"
access-control: 192.168.0.0/16 allow
remote-control:
control-enable: yes
control-use-cert: no
dnstap:
dnstap-enable: yes
dnstap-socket-path: "/tmp/dnstap.sock"
dnstap-send-identity: no
dnstap-send-version: no
dnstap-log-client-response-messages: yes
Ukhuphelo kunye noluhlu lokuqhuba
Ikhuphela uluhlu, ishwankathela isimaphambili pfx. Ku unga_ukongeza ΠΈ dont_shwankathela ungaxelela ii-IPs kunye neenethiwekhi ezifuna ukutsitywa okanye zingashwankathelwa. Bendiyidinga lento kuba... I-subnet yam ye-VPS yayikuluhlu lwebhlokhi :)
Into ehlekisayo kukuba i-RosKomSvoboda API ivala izicelo kunye ne-agent ye-Python yomsebenzisi engagqibekanga. Kubonakala ngathi bafumene umntwana weskripthi. Ke ngoko, siyitshintshela kwi-Ognelis.
Okwangoku isebenza kuphela nge-IPv4 kuba... Isabelo se-IPv6 sincinci, kodwa kuya kuba lula ukusilungisa. Ngaphandle kokuba kufuneka usebenzise intaka6.
rkn.py
#!/usr/bin/python3
import json, urllib.request, ipaddress as ipa
url = 'https://api.reserve-rbl.ru/api/v2/ips/json'
pfx = '24'
dont_summarize = {
# ipa.IPv4Network('1.1.1.0/24'),
}
dont_add = {
# ipa.IPv4Address('1.1.1.1'),
}
req = urllib.request.Request(
url,
data=None,
headers={
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
}
)
f = urllib.request.urlopen(req)
ips = json.loads(f.read().decode('utf-8'))
prefix32 = ipa.IPv4Address('255.255.255.255')
r = {}
for i in ips:
ip = ipa.ip_network(i)
if not isinstance(ip, ipa.IPv4Network):
continue
addr = ip.network_address
if addr in dont_add:
continue
m = ip.netmask
if m != prefix32:
r[m] = [addr, 1]
continue
sn = ipa.IPv4Network(str(addr) + '/' + pfx, strict=False)
if sn in dont_summarize:
tgt = addr
else:
tgt = sn
if not sn in r:
r[tgt] = [addr, 1]
else:
r[tgt][1] += 1
o = []
for n, v in r.items():
if v[1] == 1:
o.append(str(v[0]) + '/32')
else:
o.append(n)
for k in o:
print(k)
Ndiyiqhuba kanye ngosuku ngesithsaba, mhlawumbi kufanelekile ukuyiqhuba kanye kwiiyure ze-4 kuba ... Oku, ngokombono wam, lixesha lokuhlaziya elifunwa yi-RKN kubaboneleli. Ukongeza, banezinye izithintelo ezingxamisekileyo ezinokufika ngokukhawuleza.
Yenza oku kulandelayo:
- Yenza iscript sokuqala kwaye ihlaziye uluhlu lweendlela (
rkn_routes.list
) ye-INTAKA - Phinda ulayishe INYAKA
- Uhlaziyo kunye nokucoca uluhlu lwemimandla ye-dnstap-bgp
- Layisha kwakhona i-dnstap-bgp
rkn_update.sh
#!/bin/bash
ROUTES="/etc/bird/rkn_routes.list"
DOMAINS="/var/cache/rkn_domains.txt"
# Get & summarize routes
/opt/rkn.py | sed 's/(.*)/route 1 via "ens3";/' > $ROUTES.new
if [ $? -ne 0 ]; then
rm -f $ROUTES.new
echo "Unable to download RKN routes"
exit 1
fi
if [ -e $ROUTES ]; then
mv $ROUTES $ROUTES.old
fi
mv $ROUTES.new $ROUTES
/bin/systemctl try-reload-or-restart bird
# Get domains
curl -s https://api.reserve-rbl.ru/api/v2/domains/json -o - | jq -r '.[]' | sed 's/^*.//' | sort | uniq > $DOMAINS.new
if [ $? -ne 0 ]; then
rm -f $DOMAINS.new
echo "Unable to download RKN domains"
exit 1
fi
if [ -e $DOMAINS ]; then
mv $DOMAINS $DOMAINS.old
fi
mv $DOMAINS.new $DOMAINS
/bin/systemctl try-reload-or-restart dnstap-bgp
Zabhalwa ngaphandle kokucinga kakhulu, ngoko ke ukuba ubona into enokuphuculwa, yiya kuyo.
Ukuseta umxumi
Apha ndiza kunika imizekelo yeerutha zeLinux, kodwa kwimeko yeMikrotik/Cisco kufuneka ibe lula ngakumbi.
Okokuqala, seta i-BIRD:
intaka.conf
router id 192.168.1.2;
table rkn;
protocol device {
scan time 10;
};
# Servers
protocol bgp bgp_server1 {
table rkn;
local as 65000;
neighbor 192.168.1.1 as 65000;
direct;
bfd on;
next hop self;
graceful restart;
graceful restart time 60;
rr client;
export none;
import all;
}
protocol kernel {
table rkn;
kernel table 222;
scan time 10;
export all;
import none;
}
Ngale ndlela siya kungqamanisa iindlela ezifunyenwe kwi-BGP kunye nenombolo yetafile yomzila wekernel 222.
Emva koku, kwanele ukucela i-kernel ukuba ijonge le tafile ngaphambi kokuba ujonge engagqibekanga:
# ip rule add from all pref 256 lookup 222
# ip rule
0: from all lookup local
256: from all lookup 222
32766: from all lookup main
32767: from all lookup default
Yiyo loo nto, konke okuseleyo kukuqwalasela i-DHCP kwi-router ukusabalalisa idilesi ye-IP ye-IP yomncedisi njenge-DNS kunye neskimu silungile.
Iingxaki
Nge-algorithm yangoku yokuvelisa kunye nokuqhuba uluhlu lwemimandla, ibandakanya, phakathi kwezinye izinto, youtube.com
kunye neeCDN zayo.
Kwaye oku kukhokelela ekubeni zonke iividiyo ziya kuthunyelwa ngeVPN, enokuthi ivale ishaneli yonke. Kunokuba luncedo ukuqulunqa uluhlu lwemimandla engaqhelekanga ethandwayo i-RKN isebuthathaka kakhulu ukuyivala. Kwaye ubatsibe xa usahlula-hlula.
isiphelo
Indlela echaziweyo ikuvumela ukuba ugqithe phantse naluphi na uthintelo oluphunyezwa ngababoneleli ngoku.
Ngokomgaqo, idnstap-bgp ingasetyenziselwa naziphi na ezinye iinjongo apho umgangatho othile wolawulo lwendlela esekelwe kwigama lesizinda liyafuneka. Kufuneka nje uthathele ingqalelo ukuba kule mihla iisayithi eziliwaka zinokuxhoma kwidilesi ye-IP efanayo (emva kwe-Cloudflare, umzekelo), ke le ndlela inokuchaneka okuphantsi.
Kodwa kwiimfuno zokudlula ukubhloka, oku kwanele.
Ukongezwa, ukuhlelwa, izicelo zokutsalwa zamkelekile!
umthombo: www.habr.com