Masalahnya: Port Kamu Terbuka ke Mana-Mana
Kamu lagi develop webhook handler — katakanlah untuk Midtrans atau Stripe. Service mereka butuh endpoint yang bisa diakses dari internet untuk ngirim notifikasi pembayaran. Solusi paling gampang? Langsung buka port di VPS, atau pakai ngrok free tier yang limitnya bikin frustrasi.
Tapi ada masalah lain yang lebih sering terjadi: kamu kerja di belakang NAT (router kantor, kampus, atau ISP yang nggak kasih IP publik), jadi port forwarding biasa nggak mungkin. Atau kamu punya VPS tapi males setup reverse proxy cuma buat testing.
SSH tunneling adalah solusi yang udah ada sejak lama, built-in di hampir semua sistem, dan gratis. Kalau kamu udah punya VPS atau server remote dengan SSH access, kamu udah punya semua yang dibutuhkan.
Tiga Mode SSH Tunnel yang Perlu Kamu Tahu
Sebelum masuk ke kode, penting buat ngerti perbedaan tiga mode tunneling. Banyak dev bingung karena namanya mirip tapi arahnya beda.
1. Local Port Forwarding (-L)
Traffic dari port lokal kamu diteruskan ke port di remote server (atau host lain yang bisa dijangkau remote server).
Use case: Akses database production yang cuma bisa diakses dari dalam server, tanpa expose port-nya ke internet.
# Format: ssh -L [local_port]:[destination_host]:[destination_port] [user]@[ssh_server]
ssh -L 5432:localhost:5432 deploy@vps.kamu.com
Setelah command ini jalan, kamu bisa connect ke PostgreSQL production via localhost:5432 dari laptop kamu — padahal database itu ada di VPS dan port-nya nggak dibuka ke publik.
2. Remote Port Forwarding (-R)
Ini kebalikannya. Port di remote server diteruskan ke port di mesin lokal kamu.
Use case: Expose local development server kamu ke internet via VPS — ini yang paling relevan buat webhook testing.
# Format: ssh -R [remote_port]:[local_host]:[local_port] [user]@[ssh_server]
ssh -R 8080:localhost:3000 deploy@vps.kamu.com
Setelah ini, siapapun yang akses http://vps.kamu.com:8080 akan diteruskan ke localhost:3000 di laptop kamu. Midtrans bisa kirim webhook ke VPS kamu, dan request-nya nyampe ke local dev server.
3. Dynamic Port Forwarding (-D)
Bikin SOCKS proxy. Semua traffic dari aplikasi yang dikonfigurasi lewat proxy ini akan keluar dari remote server.
ssh -D 1080 deploy@vps.kamu.com
Kemudian set browser atau curl pakai SOCKS5 proxy di localhost:1080. Berguna kalau kamu mau test request yang seolah-olah berasal dari IP VPS kamu.
Setup Remote Port Forwarding untuk Webhook Testing
Ini skenario paling umum: kamu develop webhook handler di local, dan butuh URL publik buat dikasih ke payment gateway atau third-party service.
Langkah 1: Aktifkan GatewayPorts di VPS
By default, remote port forwarding di SSH hanya bisa diakses dari localhost VPS itu sendiri. Untuk expose ke internet, kamu perlu ubah satu config di VPS:
# Di VPS kamu
sudo nano /etc/ssh/sshd_config
Tambahkan atau ubah baris ini:
GatewayPorts yes
Kemudian restart SSH daemon:
sudo systemctl restart sshd
Gotcha: Kalau kamu lupa step ini, tunnel-nya tetap jalan tapi cuma bisa diakses dari dalam VPS (curl localhost:8080), bukan dari luar. Ini bikin bingung karena SSH-nya connect tanpa error.
Langkah 2: Buka Port di Firewall VPS
Kalau VPS kamu pakai UFW:
sudo ufw allow 8080/tcp
Kalau pakai iptables langsung:
sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
Kalau pakai cloud provider (DigitalOcean, AWS, GCP), jangan lupa juga buka port di security group / firewall panel mereka — ini sering kelewat.
Langkah 3: Jalankan Tunnel dari Laptop
Misalnya local dev server kamu jalan di port 3000:
ssh -R 8080:localhost:3000 deploy@vps.kamu.com -N -v
Flag yang dipakai:
-R 8080:localhost:3000— remote forward port 8080 VPS ke localhost:3000 laptop-N— jangan jalankan command apapun, cuma tunnel-v— verbose, berguna buat debug
Sekarang kasih URL http://vps.kamu.com:8080/webhook ke Midtrans atau service apapun, dan request-nya akan nyampe ke local dev server kamu.
Test dulu sebelum kasih ke third-party:
# Dari terminal lain atau mesin lain
curl -X POST http://vps.kamu.com:8080/webhook \
-H "Content-Type: application/json" \
-d '{"order_id": "TEST-001", "status": "success"}'
Biar Tunnel Nggak Putus Sendiri
Problem klasik: SSH tunnel tiba-tiba mati setelah idle beberapa menit karena timeout dari router atau firewall di antara kamu dan server. Ini nyebelin banget pas lagi nunggu webhook masuk.
Ada dua cara handle ini.
Cara 1: SSH Config dengan KeepAlive
Edit ~/.ssh/config di laptop kamu:
Host vps-tunnel
HostName vps.kamu.com
User deploy
ServerAliveInterval 30
ServerAliveCountMax 3
ExitOnForwardFailure yes
RemoteForward 8080 localhost:3000
Sekarang kamu tinggal jalankan:
ssh -N vps-tunnel
ServerAliveInterval 30 bikin SSH kirim keepalive packet setiap 30 detik. ExitOnForwardFailure yes bikin SSH exit kalau port forwarding gagal di-setup — berguna buat auto-restart.
Cara 2: AutoSSH untuk Auto-Reconnect
Install autossh:
# Ubuntu/Debian
sudo apt install autossh
# macOS
brew install autossh
Jalankan tunnel dengan autossh:
autossh -M 0 -N \
-o "ServerAliveInterval=30" \
-o "ServerAliveCountMax=3" \
-R 8080:localhost:3000 \
deploy@vps.kamu.com
-M 0 artinya matikan monitoring port bawaan autossh dan pakai SSH keepalive aja. Kalau koneksi putus, autossh otomatis reconnect.
Local Port Forwarding: Akses Database Tanpa Expose Port
Skenario kedua yang sering gue pakai: akses PostgreSQL atau Redis di production server langsung dari local tanpa buka port ke publik.
Misalnya PostgreSQL di VPS jalan di port 5432 tapi cuma listen di 127.0.0.1 (best practice — jangan pernah expose database port ke 0.0.0.0):
ssh -L 15432:localhost:5432 deploy@vps.kamu.com -N
Gue pakai port 15432 di lokal biar nggak bentrok sama PostgreSQL lokal yang mungkin udah jalan di 5432.
Sekarang connect dari laptop:
psql -h localhost -p 15432 -U myuser -d mydb
Atau dari aplikasi, tinggal ganti connection string:
# Python dengan psycopg2
import psycopg2
conn = psycopg2.connect(
host="localhost",
port=15432,
database="mydb",
user="myuser",
password="secret"
)
Semua traffic antara laptop dan VPS dienkripsi via SSH. Database port-nya sendiri nggak pernah dibuka ke internet.
Gotcha: Kalau kamu pakai pg_hba.conf dengan restriction berdasarkan IP, pastikan connection dari 127.0.0.1 diizinkan — karena dari sisi PostgreSQL, koneksinya datang dari localhost VPS.
Bikin Tunnel Jalan Otomatis Saat Boot (systemd)
Kalau kamu butuh tunnel yang selalu aktif — misalnya buat monitoring atau akses database — jadikan systemd service.
Buat file /etc/systemd/system/ssh-tunnel-db.service:
[Unit]
Description=SSH Tunnel ke Database Production
After=network.target
[Service]
User=kamu
ExecStart=/usr/bin/autossh -M 0 -N \
-o "ServerAliveInterval=30" \
-o "ServerAliveCountMax=3" \
-o "StrictHostKeyChecking=no" \
-L 15432:localhost:5432 \
deploy@vps.kamu.com
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Aktifkan:
sudo systemctl daemon-reload
sudo systemctl enable ssh-tunnel-db
sudo systemctl start ssh-tunnel-db
# Cek status
sudo systemctl status ssh-tunnel-db
Catatan: Pastikan SSH key sudah di-setup tanpa passphrase untuk user yang menjalankan service ini, atau pakai ssh-agent dengan proper setup. Kalau pakai passphrase, service nggak bisa auto-start.
Perbandingan: SSH Tunnel vs ngrok vs Cloudflare Tunnel
Biar kamu bisa pilih yang tepat:
| SSH Tunnel | ngrok Free | Cloudflare Tunnel | |
|---|---|---|---|
| Biaya | Gratis (butuh VPS) | Gratis (limited) | Gratis |
| URL custom | Ya (domain VPS) | Random URL | Ya |
| Bandwidth | Unlimited | Limited | Unlimited |
| Latency | Rendah | Medium | Medium |
| Setup | Manual tapi simpel | Sangat mudah | Perlu domain CF |
| Privacy | Full control | Data lewat ngrok | Data lewat CF |
Kalau kamu udah punya VPS, SSH tunneling adalah pilihan paling masuk akal — nggak ada dependency eksternal, nggak ada data yang lewat pihak ketiga, dan nggak ada limit bandwidth.
ngrok masih worth it buat quick demo atau sharing ke klien yang butuh URL yang lebih "proper". Cloudflare Tunnel bagus kalau kamu udah all-in di ekosistem Cloudflare.
Yang Gue Lakuin Sekarang
Setup gue saat ini untuk SSH tunneling local development:
- SSH config di
~/.ssh/configdengan semua tunnel yang sering dipakai — database staging, Redis, dan satu remote forward untuk webhook testing. - autossh untuk tunnel database yang harus selalu aktif, dijadikan systemd service.
- Remote forward on-demand via command line kalau lagi butuh expose local server untuk webhook atau demo ke klien.
Langkah lanjutan yang bisa kamu coba:
- Kombinasikan dengan
moshkalau koneksi internet kamu sering putus-putus - Setup Nginx di VPS sebagai reverse proxy di depan tunnel port — biar bisa pakai HTTPS dan domain yang proper
- Eksplorasi
sshuttlekalau kamu butuh route seluruh traffic (bukan cuma satu port) lewat SSH — ini basically WordPress object cache berbasis SSH
SSH tunneling bukan teknologi baru, tapi justru itu kelebihannya — battle-tested, ada di mana-mana, dan nggak butuh install tool tambahan di server. Kadang solusi lama memang yang paling reliable.