Port Forwarding

Membuat tunnel SSH untuk mengakses layanan lokal di server jarak jauh.

Daftar isi

Port forwarding menjadikan koneksi SSH sebagai terowongan (tunnel) bagi koneksi TCP lain, sehingga layanan yang tidak diekspos ke jaringan tetap dapat dijangkau dari mesin lokal. Topik ini membahas pembuatan tunnel lokal dengan opsi -L, arah sebaliknya dengan -R, proxy dinamis dengan -D, beserta kesalahan yang lazim ditemui ketika tunnel tidak berjalan.

Konsep tunnel SSH#

Selain sesi terminal, koneksi SSH dapat mengangkut koneksi TCP lain di dalam kanal terenkripsinya. Pada tunnel lokal (local forwarding), klien ssh membuka port di mesin lokal, dan setiap koneksi yang masuk ke port itu diteruskan melalui tunnel menuju tujuan yang dijangkau dari sisi server. Tujuannya tidak harus mesin server itu sendiri, melainkan apa pun yang dapat dijangkau dari server, termasuk layanan pada jaringan privat di belakangnya.

Kegunaan khasnya adalah menjangkau layanan yang sengaja tidak dibuka ke publik. Aplikasi web di server misalnya dapat dikonfigurasi untuk hanya mendengarkan pada localhost:3000, sehingga tidak bisa dibuka dari luar, tetapi tetap bisa dijelajahi dari mesin lokal melalui tunnel. Diagram berikut mengikuti perjalanan satu permintaan pada susunan semacam itu.

Mesin lokalbrowserlocalhost:8080Server 198.51.100.20sshdport 22aplikasi weblocalhost:3000hanya mendengarkan di servertunnel SSH terenkripsi
Tunnel lokal: permintaan browser diteruskan ke aplikasi yang hanya mendengarkan di server

Cakupan tunnel ini sebatas port-port yang dideklarasikan pada opsi, sehingga tunnel bukan pengganti VPN yang meneruskan seluruh lalu lintas jaringan. Kelebihannya justru pada keterbatasan itu, karena port yang dibuka hanya sedikit, seluruhnya tercatat jelas pada perintahnya, dan hilang begitu proses ssh-nya diakhiri.

Membuat tunnel dengan -L#

Bentuk opsi -L adalah -L port-lokal:tujuan:port-tujuan, dan perintah lengkapnya ditulis seperti berikut.

bash
# tidak-dijalankan
# klien ssh tidak terpasang di sandbox, sehingga tunnel dicoba pada mesin dengan OpenSSH
# membuka localhost:8080 di mesin lokal menuju localhost:3000 di sisi server
ssh -L 8080:localhost:3000 [email protected] -N

Angka 8080 adalah port yang dibuka di mesin lokal, sedangkan localhost:3000 dinilai dari sisi server, sehingga yang dimaksud adalah port 3000 pada server itu sendiri. Opsi -N menyatakan bahwa sesi ini tidak menjalankan perintah jarak jauh apa pun, sehingga tidak ada prompt terminal yang terbuka dan tunnel berhenti segera setelah Ctrl-C ditekan. Selama proses ssh itu berjalan, browser yang membuka http://localhost:8080 sebenarnya sedang terhubung ke aplikasi di server.

bash
# tidak-dijalankan
# dijalankan pada terminal lain selama sesi tunnel masih terbuka
curl -I http://localhost:8080

Klien mengikat port lokal pada 127.0.0.1 secara default, sehingga tunnel hanya dapat dipakai dari mesin yang sama. Menuliskan bind address secara eksplisit seperti -L 0.0.0.0:8080:localhost:3000 membuka tunnel bagi mesin lain di jaringan, dan keputusan semacam itu harus disertai kesadaran bahwa semua orang di jaringan tersebut ikut mendapat jalan masuk. Opsi -f menempatkan proses ssh ke latar belakang setelah autentikasi, sehingga tunnel dapat berjalan tanpa menempati terminal.

Satu koneksi boleh membawa beberapa tunnel sekaligus dengan menuliskan opsi -L berulang, misalnya untuk membuka aplikasi web dan basis data dalam satu login.

bash
# tidak-dijalankan
# dua tunnel pada satu koneksi: aplikasi web dan basis data
ssh -L 8080:localhost:3000 -L 5433:localhost:5432 [email protected] -N

Setiap port lokal yang dibuka tunduk pada aturan bind address yang sama, dan seluruhnya berhenti bersamaan ketika proses ssh diakhiri.

Arah sebaliknya dan proxy dinamis#

Opsi -R membalik arah, yaitu klien meminta server membuka port, dan koneksi yang masuk ke port tersebut diteruskan menuju tujuan di sisi klien. Bentuk ini dipakai untuk memperlihatkan layanan mesin lokal kepada server, misalnya ketika aplikasi yang sedang dikembangkan perlu dijangkau oleh layanan webhook yang hanya menjangkau server. Secara default, port yang dibuka -R di sisi server terikat pada 127.0.0.1 server itu sendiri, sehingga hanya dapat diakses dari server tersebut. Membukanya bagi pihak lain menuntut opsi GatewayPorts pada sshd. Opsi -D membuka proxy SOCKS lokal yang merutekan koneksi sesuai permintaan aplikasi, bukan menuju satu tujuan tetap. Opsi -N dan -f bekerja dengan cara yang sama pada ketiganya, sehingga pola penggunaan dan pengakhirannya tidak perlu dipelajari ulang.

OpsiPort dibuka diTujuan dinilai dariKegunaan khas
-Lmesin lokalsisi servermenjangkau layanan yang tidak diekspos
-Rserversisi klienmemperlihatkan layanan lokal ke server
-Dmesin lokalsesuai permintaan aplikasiproxy SOCKS untuk banyak tujuan
bash
# tidak-dijalankan
# memperlihatkan localhost:8000 mesin lokal sebagai localhost:9000 di server
ssh -R 9000:localhost:8000 [email protected] -N
# membuka proxy SOCKS pada port 1080 mesin lokal
ssh -D 1080 [email protected] -N

Kesalahan umum#

  • Memilih port lokal yang sudah dipakai. Klien melaporkan bind [127.0.0.1]:8080: Address already in use dan tunnel tidak terbentuk, sehingga solusinya adalah memilih port lain atau menghentikan proses yang memakainya.
  • Mengira localhost pada -L 8080:localhost:3000 berarti mesin lokal. Bagian tujuan selalu dinilai dari sisi server, sehingga layanan yang dituju harus benar-benar berjalan di server.
  • Mengira tunnel tetap hidup setelah sesi ditutup. Tunnel berjalan selama proses ssh-nya berjalan, dan -f hanya memindahkannya ke latar belakang, bukan memisahkannya dari sesi.
  • Menyalahkan firewall ketika halaman tidak terbuka. Apabila port lokal sudah terbuka tetapi halaman gagal dimuat, periksa dahulu apakah layanan di server memang berjalan dan mendengarkan pada port yang dituju.
  • Kehilangan jejak proses tunnel latar belakang. Proses yang diluncurkan dengan -f tidak meninggalkan jendela terminal, sehingga pencariannya memakai pgrep -af 'ssh -L' dan pengakhirannya memakai kill atas PID yang ditemukan.

Ringkasan#

  • ssh -L 8080:localhost:3000 server -N meneruskan koneksi lokal menuju tujuan yang dinilai dari sisi server, di dalam satu kanal terenkripsi.
  • Tujuan tunnel boleh berupa mesin lain yang dijangkau server, dan bind address default 127.0.0.1 menjaga tunnel tetap lokal.
  • Opsi -R membalik arah untuk memperlihatkan layanan lokal ke server, sedangkan -D membuka proxy SOCKS.
  • Tunnel berhenti ketika proses ssh-nya dihentikan, dan opsi -f memindahkannya ke latar belakang.

Referensi#