Ճիշտ է, մենք այսօր նույնը կասենք գաղտնագրման աստծուն:
Այստեղ մենք կխոսենք չգաղտնագրված IPv4 թունելի մասին, բայց ոչ թե «տաք լամպի», այլ ժամանակակից «LED» թունելի մասին։ Եվ այստեղ կան նաև չմշակված վարդակներ, և աշխատանքներ են տարվում օգտատերերի տարածքում փաթեթների հետ:
Յուրաքանչյուր ճաշակի և գույնի համար կան N թունելային արձանագրություններ.
Բայց ես ծրագրավորող եմ, ուստի N-ը միայն մի կոտորակով կավելացնեմ, իսկ իրական պրոտոկոլների մշակումը կթողնեմ Կոմերսանտի ծրագրավորողներին։
Մեկ չծնված նախագիծըԱյն, ինչ ես հիմա անում եմ, արտաքինից NAT-ի հետևում գտնվող տանտերերին հասնելն է: Դրա համար օգտագործելով մեծահասակների գաղտնագրման արձանագրություններ, ես չէի կարող զսպել այն զգացումը, որ դա նման է թնդանոթից ճնճղուկներին կրակելուն: Որովհետեւ թունելը մեծ մասամբ օգտագործվում է միայն NAT-e-ում անցքեր բացելու համար, ներքին երթևեկությունը սովորաբար նույնպես կոդավորված է, բայց դրանք դեռ խեղդվում են HTTPS-ում:
Տարբեր թունելային արձանագրություններ ուսումնասիրելիս, իմ ներքին պերֆեկցիոնիստի ուշադրությունը կրկին ու կրկին հրավիրվում էր IPIP-ի վրա՝ դրա նվազագույն ծախսերի պատճառով: Բայց այն ունի մեկ ու կես նշանակալի թերություններ իմ առաջադրանքների համար.
այն պահանջում է երկու կողմերի հանրային IP-ներ,
և ձեզ համար նույնականացում չկա:
Հետևաբար, պերֆեկցիոնիստը հետ մղվեց գանգի մութ անկյունը կամ որտեղ էլ որ նա նստի այնտեղ։
Եվ հետո մի օր, երբ կարդում էի հոդվածները բնիկ աջակցվող թունելներ Linux-ում ես հանդիպեցի FOU (Foo-over-UDP), այսինքն. ինչ էլ որ լինի, UDP-ով փաթաթված: Առայժմ աջակցվում են միայն IPIP և GUE (Generic UDP Encapsulation):
«Ահա արծաթե փամփուշտը: Պարզ IPIP-ն ինձ բավական է»։ - Ես մտածեցի.
Փաստորեն, փամփուշտը, պարզվեց, ամբողջովին արծաթագույն չէր։ UDP-ում ընդգրկումը լուծում է առաջին խնդիրը. դուք կարող եք արտաքինից միանալ NAT-ի հետևում գտնվող հաճախորդներին՝ օգտագործելով նախապես հաստատված կապը, բայց այստեղ IPIP-ի հաջորդ թերության կեսը ծաղկում է նոր լույսի ներքո. մասնավոր ցանցից յուրաքանչյուրը կարող է թաքնվել տեսանելիի հետևում: հանրային IP և հաճախորդի պորտ (մաքուր IPIP-ում այս խնդիրը գոյություն չունի):
Այս մեկուկես խնդիրը լուծելու համար ծնվեց կոմունալը իպիպու. Այն իրականացնում է հեռակա հոսթի նույնականացման տնային մեխանիզմ՝ առանց միջուկի FOU-ի աշխատանքը խաթարելու, որն արագ և արդյունավետ կերպով կմշակի փաթեթները միջուկի տարածքում:
Մեզ ձեր սցենարը պետք չէ:
Լավ, եթե գիտեք հաճախորդի հանրային պորտը և IP-ն (օրինակ, դրա հետևում գտնվող բոլորը ոչ մի տեղ չեն գնում, NAT-ը փորձում է քարտեզագրել 1-ը 1-ում նավահանգիստները), կարող եք ստեղծել IPIP-over-FOU թունել հետևյալ հրամանները՝ առանց որևէ սցենարի։
սերվերի վրա.
# Подгрузить модуль ядра FOU
modprobe fou
# Создать IPIP туннель с инкапсуляцией в FOU.
# Модуль ipip подгрузится автоматически.
ip link add name ipipou0 type ipip
remote 198.51.100.2 local 203.0.113.1
encap fou encap-sport 10000 encap-dport 20001
mode ipip dev eth0
# Добавить порт на котором будет слушать FOU для этого туннеля
ip fou add port 10000 ipproto 4 local 203.0.113.1 dev eth0
# Назначить IP адрес туннелю
ip address add 172.28.0.0 peer 172.28.0.1 dev ipipou0
# Поднять туннель
ip link set ipipou0 up
հաճախորդի վրա.
modprobe fou
ip link add name ipipou1 type ipip
remote 203.0.113.1 local 192.168.0.2
encap fou encap-sport 10001 encap-dport 10000 encap-csum
mode ipip dev eth0
# Опции local, peer, peer_port, dev могут не поддерживаться старыми ядрами, можно их опустить.
# peer и peer_port используются для создания соединения сразу при создании FOU-listener-а.
ip fou add port 10001 ipproto 4 local 192.168.0.2 peer 203.0.113.1 peer_port 10000 dev eth0
ip address add 172.28.0.1 peer 172.28.0.0 dev ipipou1
ip link set ipipou1 up
որտեղ
ipipou* — տեղական թունելի ցանցի ինտերֆեյսի անվանումը
203.0.113.1 - հանրային IP սերվեր
198.51.100.2 - հաճախորդի հանրային IP
192.168.0.2 - հաճախորդի IP-ն նշանակված է ինտերֆեյսի eth0-ին
10001 - տեղական հաճախորդի նավահանգիստ FOU-ի համար
20001 - հանրային հաճախորդի նավահանգիստ FOU-ի համար
10000 - հանրային սերվերի նավահանգիստ FOU-ի համար
encap-csum — UDP ստուգիչ գումար ավելացնելու տարբերակ՝ պարփակված UDP փաթեթներին. կարող է փոխարինվել noencap-csum, էլ չասած, ամբողջականությունն արդեն վերահսկվում է արտաքին պարկուճային շերտով (մինչ փաթեթը գտնվում է թունելի ներսում)
eth0 — տեղական ինտերֆեյս, որին կապվելու է ipip թունելը
172.28.0.1 — Հաճախորդի թունելի ինտերֆեյսի IP (մասնավոր)
172.28.0.0 — IP թունելի սերվերի ինտերֆեյս (մասնավոր)
Քանի UDP կապը կենդանի է, թունելը կլինի աշխատանքային վիճակում, բայց եթե այն կոտրվի, ձեր բախտը կբերի, եթե հաճախորդի IP-ն՝ պորտը մնա նույնը, այն կգործի, եթե փոխվեն՝ կփչանա:
Ամեն ինչ ետ դարձնելու ամենահեշտ ձևը միջուկի մոդուլները բեռնաթափելն է. modprobe -r fou ipip
Նույնիսկ եթե նույնականացում չի պահանջվում, հաճախորդի հանրային IP-ն և պորտը միշտ չէ, որ հայտնի են և հաճախ անկանխատեսելի կամ փոփոխական են (կախված NAT տեսակից): Եթե բաց եք թողնում encap-dport սերվերի կողմից թունելը չի աշխատի, այն բավականաչափ խելացի չէ հեռավոր կապի պորտը վերցնելու համար: Այս դեպքում կարող է օգնել նաև ipipou-ն, կամ WireGuard-ը և դրա նմանները կարող են օգնել ձեզ։
Ինչպես է դա աշխատում.
Հաճախորդը (որը սովորաբար գտնվում է NAT-ի հետևում) բացում է թունել (ինչպես վերը նշված օրինակում) և վավերացման փաթեթ է ուղարկում սերվերին, որպեսզի այն կազմաձևի թունելը իր կողմում: Կախված կարգավորումներից՝ սա կարող է լինել դատարկ փաթեթ (պարզապես, որպեսզի սերվերը կարողանա տեսնել հանրային IP՝ կապի պորտը), կամ տվյալների հետ, որոնց միջոցով սերվերը կարող է նույնականացնել հաճախորդին։ Տվյալները կարող են լինել պարզ տեքստի պարզ անցաբառ (նմանալոգիա HTTP Basic Auth-ի հետ) կամ հատուկ մշակված տվյալներ, որոնք ստորագրված են մասնավոր բանալիով (նման է HTTP Digest Auth-ին միայն ավելի ուժեղ, տես գործառույթը client_auth ծածկագրում):
Սերվերում (հանրային IP-ով այն կողմում), երբ ipipou-ն սկսվում է, այն ստեղծում է nfqueue queue handler և կարգավորում է ցանցի ֆիլտրը, որպեսզի անհրաժեշտ փաթեթներն ուղարկվեն այնտեղ, որտեղ պետք է լինեն. մնացած բոլորը գնում են ուղիղ FOU լսողին:
Նրանց համար, ովքեր չգիտեն, nfqueue (կամ NetfilterQueue) հատուկ բան է այն սիրողականների համար, ովքեր չգիտեն, թե ինչպես մշակել միջուկի մոդուլներ, որոնք օգտագործելով netfilter (nftables/iptables) թույլ են տալիս վերահղել ցանցային փաթեթները դեպի օգտվողի տարածք և մշակել դրանք այնտեղ՝ օգտագործելով: պրիմիտիվ նշանակում է ձեռքի տակ. փոփոխել (ըստ ցանկության) և վերադարձնել այն միջուկին կամ հեռացնել այն:
Ծրագրավորման որոշ լեզուների համար կան nfqueue-ի հետ աշխատելու կապեր, bash-ի համար չկա (հե, զարմանալի չէ), ես ստիպված էի օգտագործել python. ipipou-ն օգտագործում է NetfilterQueue.
Եթե կատարումը կարևոր չէ, ապա օգտագործելով այս բանը, դուք կարող եք համեմատաբար արագ և հեշտությամբ հորինել ձեր սեփական տրամաբանությունը փաթեթների հետ բավականին ցածր մակարդակի վրա աշխատելու համար, օրինակ՝ ստեղծել փորձնական տվյալների փոխանցման արձանագրություններ, կամ թրոլել տեղական և հեռավոր ծառայությունները ոչ ստանդարտ վարքագծով:
Raw sockets-ը աշխատում է ձեռք ձեռքի տված nfqueue-ի հետ, օրինակ, երբ թունելն արդեն կազմաձևված է, և FOU-ը լսում է ցանկալի պորտը, դուք չեք կարողանա փաթեթ ուղարկել նույն նավահանգստից սովորական ձևով. այն զբաղված է, բայց Դուք կարող եք վերցնել և ուղարկել պատահականորեն ստեղծված փաթեթը անմիջապես ցանցի ինտերֆեյսի մեջ՝ օգտագործելով հումքային վարդակից, թեև այդպիսի փաթեթ ստեղծելու համար մի փոքր ավելի շատ կպահանջվի: Ահա թե ինչպես են ստեղծվում վավերացումով փաթեթները ipipou-ում:
Քանի որ ipipou-ն մշակում է կապից միայն առաջին փաթեթները (և նրանք, որոնց հաջողվել է արտահոսել հերթում մինչև կապի հաստատումը), կատարումը գրեթե չի տուժում:
Հենց որ ipipou սերվերը ստանում է վավերացված փաթեթ, ստեղծվում է թունել, և կապի բոլոր հետագա փաթեթներն արդեն մշակվում են միջուկի կողմից՝ շրջանցելով nfqueue-ը: Եթե կապը ձախողվի, ապա հաջորդի առաջին փաթեթը կուղարկվի nfqueue հերթ՝ կախված կարգավորումներից, եթե դա նույնականացումով փաթեթ չէ, այլ վերջին հիշված IP-ից և հաճախորդի պորտից, այն կարող է փոխանցվել կամ վրա կամ դեն նետված: Եթե վավերացված փաթեթը գալիս է նոր IP-ից և նավահանգստից, թունելը վերակազմավորվում է դրանք օգտագործելու համար:
Սովորական IPIP-over-FOU-ն ունի ևս մեկ խնդիր NAT-ի հետ աշխատելիս. անհնար է ստեղծել երկու IPIP թունելներ, որոնք պարփակված են UDP-ով նույն IP-ով, քանի որ FOU և IPIP մոդուլները բավականին մեկուսացված են միմյանցից: Նրանք. նույն հանրային IP-ի հետևում գտնվող զույգ հաճախորդները չեն կարողանա միաժամանակ միանալ նույն սերվերին այս ձևով: Ապագայում, գուցե, այն կլուծվի միջուկի մակարդակով, բայց դա հաստատ չէ։ Միևնույն ժամանակ, NAT-ի խնդիրները կարող են լուծվել NAT-ի միջոցով. եթե պատահի, որ IP հասցեների մի զույգ արդեն զբաղված է մեկ այլ թունելով, ipipou-ն NAT-ը կանի հանրայինից մինչև այլընտրանքային մասնավոր IP, voila: - Դուք կարող եք թունելներ ստեղծել մինչև նավահանգիստները սպառվեն:
Որովհետեւ Կապի մեջ ոչ բոլոր փաթեթներն են ստորագրված, ապա այս պարզ պաշտպանությունը խոցելի է MITM-ի համար, այնպես որ, եթե հաճախորդի և սերվերի միջև թաքնված է չարագործ, որը կարող է լսել տրաֆիկը և շահարկել այն, նա կարող է վերահղել վավերացված փաթեթները: մեկ այլ հասցե և ստեղծեք թունել անվստահելի հյուրընկալողից:
Եթե ինչ-որ մեկը գաղափարներ ունի, թե ինչպես շտկել դա՝ միաժամանակ թողնելով երթևեկի հիմնական մասը միջուկում, մի հապաղեք բարձրաձայնել:
Ի դեպ, encapsulation-ը UDP-ում իրեն շատ լավ է ապացուցել: IP-ով ինկապսուլյացիայի համեմատ, այն շատ ավելի կայուն է և հաճախ ավելի արագ, չնայած UDP վերնագրի լրացուցիչ ծախսերին: Դա պայմանավորված է նրանով, որ ինտերնետում հոսթինգների մեծ մասը լավ է աշխատում միայն երեք ամենահայտնի արձանագրություններով՝ TCP, UDP, ICMP: Շոշափելի մասը կարող է ամբողջությամբ հրաժարվել մնացած ամեն ինչից կամ ավելի դանդաղ մշակել, քանի որ այն օպտիմիզացված է միայն այս երեքի համար։
Օրինակ, սա է պատճառը, որ QUICK-ը, որի վրա հիմնված է HTTP/3-ը, ստեղծվել է UDP-ի, այլ ոչ թե IP-ի վերևում:
Դե, բավական բառեր, ժամանակն է տեսնելու, թե ինչպես է այն աշխատում «իրական աշխարհում»:
Ճակատամարտ
Օգտագործվում է իրական աշխարհը ընդօրինակելու համար iperf3. Իրականությանը մոտ լինելու աստիճանի առումով սա մոտավորապես նույնն է, ինչ իրական աշխարհը ընդօրինակելը Minecraft-ում, բայց առայժմ դա տեղի կունենա:
Մրցույթի մասնակիցներ.
հղում գլխավոր ալիք
այս հոդվածի հերոսը ipipou-ն է
OpenVPN նույնականացումով, բայց առանց կոդավորման
OpenVPN բոլոր ներառական ռեժիմով
WireGuard առանց PresharedKey, MTU=1440-ով (միայն IPv4-ից)
Տեխնիկական տվյալներ գիքերի համար Չափումները վերցվում են հետևյալ հրամաններով.
հաճախորդի վրա.
UDP
CPULOG=NAME.udp.cpu.log; sar 10 6 >"$CPULOG" & iperf3 -c SERVER_IP -4 -t 60 -f m -i 10 -B LOCAL_IP -P 2 -u -b 12M; tail -1 "$CPULOG"
# Где "-b 12M" это пропускная способность основного канала, делённая на число потоков "-P", чтобы лишние пакеты не плодить и не портить производительность.
Խոնավ տգեղ նշան
Սերվերի պրոցեսորի բեռնվածությունը այնքան էլ ցուցիչ չէ, քանի որ... Այնտեղ շատ այլ ծառայություններ կան, որոնք երբեմն խլում են ռեսուրսները.
proto bandwidth[Mbps] CPU_idle_client[%] CPU_idle_server[%]
# 20 Mbps канал с микрокомпьютера (4 core) до VPS (1 core) через Атлантику
# pure
UDP 20.4 99.80 93.34
TCP 19.2 99.67 96.68
ICMP latency min/avg/max/mdev = 198.838/198.997/199.360/0.372 ms
# ipipou
UDP 19.8 98.45 99.47
TCP 18.8 99.56 96.75
ICMP latency min/avg/max/mdev = 199.562/208.919/220.222/7.905 ms
# openvpn0 (auth only, no encryption)
UDP 19.3 99.89 72.90
TCP 16.1 95.95 88.46
ICMP latency min/avg/max/mdev = 191.631/193.538/198.724/2.520 ms
# openvpn (full encryption, auth, etc)
UDP 19.6 99.75 72.35
TCP 17.0 94.47 87.99
ICMP latency min/avg/max/mdev = 202.168/202.377/202.900/0.451 ms
# wireguard
UDP 19.3 91.60 94.78
TCP 17.2 96.76 92.87
ICMP latency min/avg/max/mdev = 217.925/223.601/230.696/3.266 ms
## около-1Gbps канал между VPS Европы и США (1 core)
# pure
UDP 729 73.40 39.93
TCP 363 96.95 90.40
ICMP latency min/avg/max/mdev = 106.867/106.994/107.126/0.066 ms
# ipipou
UDP 714 63.10 23.53
TCP 431 95.65 64.56
ICMP latency min/avg/max/mdev = 107.444/107.523/107.648/0.058 ms
# openvpn0 (auth only, no encryption)
UDP 193 17.51 1.62
TCP 12 95.45 92.80
ICMP latency min/avg/max/mdev = 107.191/107.334/107.559/0.116 ms
# wireguard
UDP 629 22.26 2.62
TCP 198 77.40 55.98
ICMP latency min/avg/max/mdev = 107.616/107.788/108.038/0.128 ms
20 Մբիթ/վրկ ալիք
ալիք 1 լավատեսական Գբիտ/վրկ-ի դիմաց
Բոլոր դեպքերում, ipipou-ն իր կատարողականությամբ բավականին մոտ է բազային ալիքին, ինչը հիանալի է:
Չկոդավորված openvpn թունելն իրեն բավականին տարօրինակ էր պահում երկու դեպքում էլ։
Եթե որեւէ մեկը պատրաստվում է փորձարկել այն, հետաքրքիր կլինի լսել արձագանքները: