Հասնել VPN հաճախորդի ծառայությանը՝ հակադարձ թունել, թե՞ DNAT
Հասնել OpenVPN հաճախորդի ծառայությանը առանց պորտի փոխանցման. համեմատեք հակադարձ SSH թունելը սերվերի կողմի DNAT-ի և ընտրությունը որոշող երեք պայմանների հետ։
Նույնիսկ մատակարարի NAT-ի հետևում գտնվող նոութբուքը կարող է սպասարկել գործընկերոջը, քանի դեռ VPN սերվերը հանդես է գալիս որպես հանդիպման կետ։ Այնտեղ տանում են երկու մեխանիզմ՝ հաճախորդը զանգահարում է դուրս և խնդրում սերվերին պահել լսող պորտ, կամ սերվերը հրապարակում է պորտ և այն թարգմանում թունելի մեջ։ Երկուսն էլ լուծում են նույն հասանելիության խնդիրը և տարբեր կերպ են վարվում ձախողման, հսկողության և գրանցման պայմաններում։ Երեք պայման որոշում է, թե որն է պատկանում ձեր կարգավորմանը։
Երկու ձև, մեկ հանդիպման կետ
Առաջին ձևում հաճախորդը դուրս է բացում SSH նստաշրջան և խնդրում սերվերին լսել ընտրված պորտին՝ յուրաքանչյուր կապ հետ ուղարկելով այդ նստաշրջանով։ Սերվերի վրա ոչինչ չի փոխանցվում և փաթեթի թարգմանություն տեղի չի ունենում, ուստի միակ պահանջները SSH հաշիվ, թույլատրված փոխանցում և պորտի համար հրապատի կանոն են։ Ծառայությունը մնում է կապված հաճախորդի loopback-ին, ինչը սովորաբար հենց ցանկալին է։
ssh -N -R 8081:127.0.0.1:8080 -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 [email protected]
Երկրորդ ձևում սերվերն է տիրում հանրային պորտին և վերագրում է յուրաքանչյուր կապը դեպի հաճախորդի թունելի հասցեն։ Դա պահանջում է միացված IP փոխանցում, նպատակակետի թարգմանություն մուտքի ճանապարհին և աղբյուրի թարգմանություն ելքի ճանապարհին, և այն շարունակում է աշխատել, երբ SSH նստաշրջան չկա։ Պորտը պատկանում է սերվերին, ոչ թե նստաշրջանին, և հենց այդ հատկությունն է որոշում իրական դեպքերի մեծ մասը։
Ձևերից ոչ մեկը կառուցվածքով ավելի ապահով չէ։ Երկուսն էլ բացում են մեկ ծառայության պորտ բոլոր նրանց համար, ովքեր կարող են հասնել սերվերի հանրային հասցեին, և երկուսն էլ դեռ կախված են ծառայության սեփական նույնականացումից։
Պայման առաջին. պե՞տք է պորտն ապրի ավելի երկար, քան նստաշրջանը
Հակադարձ փոխանցումն ապրում է ուղիղ այնքան, որքան այն ստեղծած SSH նստաշրջանը։ Երբ կապը կտրվում է, լսողը անհետանում է, և գործընկերը դանդաղ ուղու փոխարեն տեսնում է մերժված կապ։ Հրամանի հսկողությունը systemd միավորով և վերագործարկման քաղաքականությամբ լուծում է դա, և ExitOnForwardFailure=yes անմիջապես տեսանելի է դարձնում ձախողված կապակցումը՝ փոխանցումից զուրկ նստաշրջան թողնելու փոխարեն։
Թարգմանված պորտը գոյատևում է վերագործարկումներից, եթե կանոնները պահվում են, բայց դա կախված է նրանից, որ հաճախորդը պահպանի նույն թունելի հասցեն։ Դինամիկ լողավազանը, որը վերականգնումից հետո նոութբուքին տալիս է այլ հասցե, լուռ ուղղում է կանոնը դեպի ոչինչ։ Նախ վերապահեք թունելի հասցեն, ապա գրեք կանոնը, և երկուսը դիտարկեք որպես մեկ փոփոխություն։
Եթե ծառայությունը պետք է պատասխանի գիշերվա երեքին առանց ոչ ոքի հսկողության, ապա սերվերի հրապարակած պորտով ձևն ունի ավելի քիչ շարժվող մասեր, քանի որ միակ գործընթացը, որը պետք է մնա աշխատող, հենց թունելն է։
Պայման երկրորդ. ումն է հրապատն ու գրանցամատյանները
Հակադարձ ձևը պահում է ամբողջ քաղաքականությունը երկու տեղում։ sshd AllowTcpForwarding-ի միջոցով որոշում է, թե արդյոք հեռավոր փոխանցումներն ընդհանրապես թույլատրված են, իսկ GatewayPorts որոշում է, թե լսողը կապակցվի loopback-ին, թե բոլոր հասցեներին։ Լռելյայն no արժեքով սերվերից դուրս գտնվող գործընկերը չի կարող հասնել պորտին, թեև փոխանցումը հաջողվել է, և դա կոտրված թունել է թվում, մինչդեռ իրականում կապակցման հասցե է։
sudo ss -ltn '( sport = :8081 )'
sudo grep -E '^(GatewayPorts|AllowTcpForwarding)' /etc/ssh/sshd_config
Թարգմանված ձևը պահանջում է միացված փոխանցում և երկու կանոն, և հենց երկրորդ կանոնում են սխալվում բաղադրատոմսերի մեծ մասը։ Աղբյուրի թարգմանությունը conntrack-ի DNAT վիճակով սահմանափակելը նշանակում է, որ վերագրվում են միայն նպատակակետի կանոնով ստեղծված կապերը, այլ ոչ թե յուրաքանչյուր փաթեթ, որը սերվերը ուղարկում է թունել։
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8081 -j DNAT --to-destination 10.88.0.6:8080
sudo iptables -t nat -A POSTROUTING -o tun0 -m conntrack --ctstate DNAT -j SNAT --to-source 10.88.0.1
Այդ վերագրումը ոչնչացնում է նաև հեղինակության վերագրումը։ Դրանից հետո հաճախորդը յուրաքանչյուր զանգահարողի տեսնում է որպես սերվերի թունելի հասցե, ինչը ցանկացած հասցեով սահմանափակում միավորում է մեկ դույլի մեջ և թաքցնում, թե ով ինչ ուղարկեց։ Եթե հեղինակությունը կարևոր է, ավարտեք կապը սերվերի վրա կամ այնտեղ պահեք թույլտվության որոշումը և փոխանցեք ինքնություն այն վերնագրում, որին ծառայությունը վստահում է։ Այս երկու ուղղումների միջև ընտրությունը կախված է նրանից՝ արդյոք ծառայությունն ընդհանրապես կարդում է փոխանցիչի վերնագիր։
Պայման երրորդ. մեկ պորտ, թե շատ, և ումն է անունը
Մեկ պորտի վրա մեկ ծառայությունը այն դեպքն է, երբ հակադարձ փոխանցումը հաղթում է ջանքով։ Ձեզ պետք է մեկ հրաման, մեկ հաշիվ և մեկ հրապատի կանոն, իսկ մաքրումը նստաշրջանը սպանելն է։ Նույն հանրային հասցեի վրա մի քանի ծառայություններ ձեզ մղում են սերվերի հրապարակած ձևին, որովհետև յուրաքանչյուր հակադարձ փոխանցում ունի իր սերվերի պորտը, և բազմությունը աճում է յուրաքանչյուր ծառայության հետ։
Անունները ավելի են բարդացնում։ Հակադարձ փոխանցումը կարող է լինել TCP փոխանցիչի հետևում, որը երթուղավորում է ըստ SNI-ի, մինչդեռ թարգմանված պորտը սովորաբար մեկ պորտ է յուրաքանչյուր ծառայության համար։ Եթե ծառայությունն ինքն է ավարտում TLS-ը և պահանջում է բնօրինակ հոսթի անունը, փոխանցիչի մոտեցումը պահպանում է այն, իսկ DNAT մոտեցումը պահպանում է այն միայն այն դեպքում, երբ ծառայությունն ընդունում է այդ անունը այդ պորտի վրա։
Գրեք, թե երեք պայմաններից ո՛րն է որոշել ձևը։ Հակառակ դեպքում երկրորդ ծառայություն ավելացնող հաջորդ մարդը նույն համեմատությունը կրկին կբացի ավելի քիչ համատեքստով։
Որոշեք, ապա փորձարկեք դրսից
Փորձարկեք ուղին ցանցից, որը նոութբուք տանող ոչ մի երթուղի չունի, և դիտեք սերվերի հաշվիչները, քանի դեռ հարցումը ընթանում է։ Սերվերից իր իսկ հանրային հասցեին ուղղված փորձարկումը այստեղ ոչինչ չի ապացուցում, քանի որ փաթեթը ստեղծվում է տեղական և երբեք չի հասնում մուտքային թարգմանության կեռիկին, ուստի փորձարկումը կարող է անցնել, մինչդեռ իրական ուղին կոտրված է։
sudo iptables -t nat -L PREROUTING -n -v
sudo tcpdump -ni any 'tcp port 8081' -c 20
Անշարժ մնացող հաշվիչները նշանակում են, որ փաթեթը երբեք չի հասել կանոնին, ինչը մատնանշում է մատակարարին կամ հոսթի հրապատին։ Հաշվիչները, որոնք շարժվում են, մինչ ծառայությունը մերժում է, մատնանշում են հաճախորդի սեփական հրապատը կամ այն հասցեն, որի վրա ծառայությունը լսում է։Թունելը, որը կրում է փաթեթը, բայց ոչինչ չի վերադարձնում, երթուղու կամ հակադարձ ուղու խնդիր է և այս երեք ելքերից ոչ մեկը չպետք է ախտորոշվի հաճախորդի ադապտերը խմբագրելով։ Գրեք, թե որ հաշվիչը շարժվեց, նախքան որևէ բան փոխելը, քանի որ հաջորդ փորձարկմանը պետք է այդ հիմնագիծը։
Երբ ձևն աշխատում է, գրանցեք պորտը, սեփականատիրոջը և հսկողության եղանակը թունելի կարգավորման կողքին։ Միայն ինչ-որ մեկի shell-ի պատմության մեջ գոյություն ունեցող հասանելիության ուղղումը մեկ վերագործարկում հեռու է կրկնվող միջադեպից։