Tarkibga o'tish

SSH tunneling

scp va rsync maqolasida SSH ulanishi fayllarni ko'chirish uchun ishlatildi, lekin SSH bu bilan cheklanmaydi — shifrlangan kanal o'rnatilgach, u orqali har qanday boshqa TCP trafigini ham yo'naltirish mumkin. Bu imkoniyat SSH tunneling (yoki port forwarding) deb ataladi va odatda faqat ichki tarmoqdan kirish mumkin bo'lgan xizmatlarga — masalan, faqat lokal tarmoqqa bog'langan ma’lumotlar bazasiga — tashqaridan xavfsiz yetib borish uchun ishlatiladi.

Tunnel nega kerak: keng tarqalgan vaziyat

Ko'p production arxitekturalarida ma’lumotlar bazasi yoki ichki admin panel tashqi tarmoqdan ataylab yopilgan bo'ladi va unga faqat serverning o'zidan yoki ichki tarmoqdan (masalan, 127.0.0.1 yoki 10.20.0.0/24) yetib borish mumkin — bu to'g'ri xavfsizlik qarori. Lekin administratorga baribir vaqti-vaqti bilan o'z mashinasidan shu ichki xizmatga yetib borish kerak bo'ladi — masalan, PostgreSQL’ga grafik klient orqali ulanish.

Bu yerda ikkita yoqimsiz variant bor: xizmatni tashqi tarmoqqa ochish (xavfsizlikni zaiflashtiradi) yoki har safar SSH orqali serverga kirib, butunlay terminal ichida ishlash (grafik vositalardan foydalanish imkoniyatini yo'qotadi). SSH tunneling uchinchi, yaxshiroq yo'lni taklif qiladi: masofaviy portni mavjud SSH ulanishi orqali lokal mashinada mavjuddek ko'rsatish — xizmatning o'zi hech qachon tashqariga ochilmaydi; unga faqat sizning SSH sessiyangiz "yo'l" ochadi.

Local forwarding (-L): masofaviy portni lokalda ochish

Eng ko'p ishlatiladigan tunnel turi. Sintaksis:

ssh -L <local_port>:<target_host>:<target_port> <ssh_user>@<ssh_server>

Masalan, db-server dagi faqat 127.0.0.1:5432 ni tinglayotgan PostgreSQL’ga ulanish:

ssh -L 5432:127.0.0.1:5432 alice@db-server

Bu buyruq ishlab turgan paytda lokal mashinangizdagi localhost:5432 ga yuborilgan har qanday so'rov avtomatik ravishda SSH tunneli orqali db-server ning 127.0.0.1:5432 iga yo'naltiriladi. Boshqa terminaldan:

psql -h 127.0.0.1 -p 5432 -U appuser -d production

Bu yerdagi target_host — SSH serverning o'zi emas, balki SSH server nuqtai nazaridan ko'rinadigan manzil. Agar maqsadli xizmat SSH serverning o'zida ishlasa, bu 127.0.0.1; agar u SSH server orqali yetib boriladigan boshqa ichki hostda bo'lsa, buning o'rniga o'sha hostning ichki IP’si ishlatiladi:

ssh -L 5432:10.20.0.30:5432 alice@bastion-server

Bu yerda bastion-server shunchaki "oraliq bekat" vazifasini bajaradi, haqiqiy ma’lumotlar bazasi esa 10.20.0.30 da turadi — bu tunnel faqat bastion’ning o'ziga emas, bastion’dan ko'rinadigan istalgan hostga yetib bora olishini ko'rsatadi.

Tunnelni fonda ishga tushirish

Terminalni band qilib qo'ymaslik uchun:

ssh -f -N -L 5432:127.0.0.1:5432 alice@db-server
  • -f — autentifikatsiya muvaffaqiyatli o'tgach, SSH ulanishini fonga o'tkazadi;
  • -N — hech qanday masofaviy buyruq ishga tushirilmasligini bildiradi (ulanish faqat port forwarding uchun mavjud; shell ochish shart emas).

Warning

ssh -f -N forward hech qachon bog'lanmagan bo'lsa ham muvaffaqiyat qaytaradi va fonga o'tadi — masalan, lokal port allaqachon band bo'lganda. Shunda sizda ishlayotgan SSH ulanishi qoladi, lekin ishlaydigan tunnel bo'lmaydi va nosozlik faqat keyinroq lokal portda chalkash "connection refused" sifatida yuzaga chiqadi. Forward’ni sozlab bo'lmaganda fondagi ssh darhol chiqib ketishi uchun -o ExitOnForwardFailure=yes ni qo'shing — bu jim nosozlikni aniq ko'rinadiganiga aylantiradi:

ssh -f -N -o ExitOnForwardFailure=yes -L 5432:127.0.0.1:5432 alice@db-server

Tunnelni to'xtatish uchun mos ssh jarayonini topib, uni o'ldirish kerak:

ps aux | grep "5432:127.0.0.1:5432"
kill <PID>

Remote forwarding (-R): lokal xizmatni masofada ochish

Yo'nalish teskari: lokal mashinangizda ishlayotgan xizmat masofaviy serverdan yetib boriladigan bo'ladi.

ssh -R 8080:127.0.0.1:3000 alice@public-server

Bu lokal mashinangizdagi 3000 portida ishlayotgan xizmatni public-server ning 8080 portida "ko'rinadigan" qiladi — public-server ga ulangan har kim (yoki serverning o'zi) localhost:8080 orqali lokal 3000 portingizga yetib bora oladi.

Odatiy foydalanish holati: ishlab chiqish jarayonida lokal ishlayotgan veb-ilovani o'z tarmog'ingizda hech narsa ochmasdan tashqi dunyoga vaqtincha ko'rsatish — masalan, webhook’ni sinash uchun.

Warning

Sukut bo'yicha sshd_config da GatewayPorts no o'rnatilgan, ya’ni remote forward’ga tashqi tarmoqdan emas, faqat public-server ning o'zidan (127.0.0.1) yetib borish mumkin. Uni butun tarmoqqa ochish (GatewayPorts yes) xavfsizlik oqibatlarini puxta o'ylab ko'rishni talab qiladi, chunki bu lokal xizmatingizni butun internetdan yetib boriladigan qilib qo'yishi mumkin.

Dynamic forwarding (-D): SOCKS proxy

Local va remote forwarding har biri bitta muayyan portga qaratilgan bo'lsa, dynamic forwarding butun bir SOCKS proxy yaratadi — u orqali oldindan alohida belgilanmagan istalgan sondagi xizmatlarga SSH server nuqtai nazaridan yetib borish mumkin bo'ladi:

ssh -D 1080 -N alice@bastion-server

Brauzer yoki boshqa ilovaning tarmoq sozlamalarida 127.0.0.1:1080 ni SOCKS5 proxy sifatida belgilash o'sha ilovaning barcha tarmoq so'rovlarini bastion-server orqali, go'yo so'rovlarni shu serverning o'zidan yuborayotgandek yo'naltiradi. Faqat ichkaridan ko'rinadigan bir nechta veb-xizmatlarni (admin panellar, monitoring dashboard’lari) birin-ketin ko'zdan kechirishda bu har bir xizmat uchun alohida -L yozishdan qulayroq.

Tunnel turlarini solishtirish

Flag Yo'nalish Odatiy foydalanish
-L Lokal port → masofaviy manzil Lokal mashinadan ichki DB yoki admin panelga yetib borish
-R Masofaviy port → lokal manzil Lokal ishlayotgan xizmatni tashqariga vaqtincha ochish
-D SOCKS proxy Bir nechta ichki xizmatga har birini ro'yxatlamasdan bitta umumiy proxy orqali yetib borish

Amaliy vaziyat: faqat ichkaridan ko'rinadigan admin panelga yetib borish

Muammo: monitoring.internal:9090 dagi monitoring dashboard’i faqat serverning ichki tarmog'idan (10.20.0.0/24) ko'rinadi, lekin unga shaxsiy noutbukdagi brauzerdan kirish kerak.

1-qadam — mavjud kirish yo'lini aniqlash: bastion-server ga SSH orqali yetib borish mumkin va u ichki tarmoqqa ulangan.

2-qadam — local forwarding tunnelini ochish:

ssh -f -N -L 9090:monitoring.internal:9090 alice@bastion-server

3-qadam — tunnel ishlayotganini tasdiqlash:

ss -tlnp | grep 9090
LISTEN 0  128  127.0.0.1:9090  0.0.0.0:*  users:(("ssh",pid=5210,fd=6))

Lokal 9090 port ssh jarayonining o'zi tomonidan band qilinganini ko'rsatadi.

4-qadam — brauzerda tekshirish: http://127.0.0.1:9090 ga o'tish dashboard’ni ochishi kerak — brauzer to'g'ridan-to'g'ri monitoring.internal bilan emas, lokal SSH tunneli bilan muloqot qilyapti.

5-qadam — ish tugagach tunnelni yopish:

ps aux | grep "9090:monitoring.internal"
kill <PID>

6-qadam — natija va hujjatlashtirish: monitoring xizmati hech qachon tashqi tarmoqqa ochilmadi; unga faqat vaqtinchalik, aniq ishga tushirilgan SSH tunneli orqali kirildi.

Keng tarqalgan xatolar

-L sintaksisining uch qismini adashtirish

local_port:target_host:target_port da target_host odatda SSH serverning o'zi emas, SSH server nuqtai nazaridan ko'rinadigan host ekanini unutish — tunnelning o'z manzil manzili yoziladigan joyda ko'pincha 127.0.0.1 to'g'ri qiymat bo'ladi.

Fonda ishlayotgan tunnelni qanday to'xtatishni unutish

-f bilan ishga tushirilgan tunnel terminal yopilgandan keyin ham ishlashda davom etadi. Mos ssh jarayonini qanday topib, to'xtatishni bilmaslik vaqt o'tishi bilan ishlatilmaydigan, unutilgan tunnellarning to'planib qolishiga olib keladi.

Remote forwarding sukut bo'yicha butun tarmoqqa ochiladi deb kutish

Sukut bo'yicha remote forward’ga faqat serverning o'zidan yetib borish mumkin. Uni tashqaridan yetib boriladigan qilish alohida, ataylab kiritilgan konfiguratsiya o'zgarishini talab qiladi.

Tunnel ortidagi xizmatni "yetarlicha xavfsiz" deb hisoblab, uni uzoq vaqtga unutish

Tunnelning o'zi xavfsiz kanal, lekin uning ortidagi xizmatning o'z autentifikatsiyasi zaif bo'lsa (masalan, sukut bo'yicha parol), tunnel muammoni hal qilmasdan faqat yashiradi.

Mashqlar

  1. Laboratoriya serveringizda faqat 127.0.0.1 ga bog'langan oddiy HTTP xizmatini ishga tushiring (masalan, python3 -m http.server 8000 --bind 127.0.0.1), so'ng uni -L yordamida lokal brauzeringizda oching.
  2. Yuqoridagi tunnelni -f -N bilan ishga tushiring, jarayonni ps aux bilan toping va uni kill bilan to'xtating.
  3. -D 1080 bilan SOCKS tunnelini oching va uni brauzer proxy sozlamalarida sinab, ichki tarmoqdagi biror narsaga ulaning.
  4. -L ni ataylab mavjud bo'lmagan maqsadli hostga yo'naltiring va natijada chiqadigan xatoni kuzating.

Mashqni bajardim deyish uchun: 1-mashqda xizmatga serverning o'z IP manzili orqali to'g'ridan-to'g'ri ulanib bo'lmasligi kerak (bu u hali ham faqat 127.0.0.1 ga bog'langanini tasdiqlaydi), mashinangizdagi http://127.0.0.1:<local_port> orqali, tunnel yordamida esa u to'g'ri ochilishi kerak.

Manbalar