NoctisNode
← PanduanJaringan2026-10-239 menit

Reverse Proxy TCP dan Proxy SSH Caddy dengan caddy-l4

Caddy inti hanya mem-proxy HTTP. Untuk TCP mentah dan SSH, build Caddy dengan app layer4 caddy-l4, teruskan port, atau bagi port 443 antara SSH dan HTTPS berdasarkan protokol.

Singkatnya: Caddy standar tidak bisa mem-proxy TCP mentah atau SSH, karena `reverse_proxy` miliknya hanya berbicara HTTP. Untuk meneruskan TCP, Anda membangun Caddy dengan modul caddy-l4 (github.com/mholt/caddy-l4) menggunakan xcaddy, lalu mengonfigurasi app `layer4`-nya untuk listen di sebuah port dan mem-proxy koneksi, dengan opsi memilih upstream berdasarkan protokol, sehingga SSH dan HTTPS bisa berbagi port 443.

caddy-l4 adalah modul terpisah, bukan bagian dari distribusi Caddy default, dan README-nya masih menyebutnya sebagai pekerjaan yang sedang berjalan yang konfigurasinya bisa berubah antarversi. Panduan ini memakai konfigurasi JSON, yang langsung memetakan ke struktur modul yang terdokumentasi. Jika Anda hanya butuh proxy HTTP atau HTTPS, panduan reverse proxy Caddy sudah cukup.

Mengapa Caddy inti hanya untuk HTTP

App bawaan Caddy adalah `http`, `tls`, dan `pki`. Handler `reverse_proxy` berada di dalam app HTTP, sehingga membutuhkan request HTTP yang sudah di-parse sebelum bisa merutekan apa pun. Klien SSH, klien PostgreSQL, atau protokol game tidak pernah mengirimkannya, sehingga Caddy akan menjawab dengan error TLS atau HTTP.

caddy-l4 menambahkan app `layer4` terpisah yang bekerja pada koneksi mentah. App ini dapat mencocokkan byte pertama sebuah koneksi (banner SSH, TLS ClientHello dengan SNI, baris request HTTP, startup PostgreSQL, dan lainnya), lalu mem-proxy, mengakhiri TLS, atau menyerahkan stream ke handler lain. Karena merupakan app seperti `http`, keduanya bisa berjalan dalam proses yang sama.

KebutuhanCaddy intiCaddy + caddy-l4
Reverse proxy HTTPS dengan auto TLSYaYa
Port forwarding TCP biasaTidakYa (handler `proxy`)
Penerusan UDPTidakYa (listen di `udp/:port`)
TLS passthrough berdasarkan SNITidakYa (matcher `tls` dengan `sni`)
SSH dan HTTPS di port yang samaTidakYa (matcher `ssh` dan `tls`)
Dukungan CaddyfilePenuhSebagian; JSON adalah format referensi

Build Caddy dengan modul layer4

xcaddy mengompilasi Caddy dengan modul tambahan. Sebagai alternatif, pilih `mholt/caddy-l4` di halaman unduhan resmi Caddy dan unduh binary siap pakai. Cara mana pun, verifikasi dengan `list-modules` bahwa modul `layer4` tercantum sebelum menulis konfigurasi.

# Current Caddy needs a recent Go toolchain; distro golang-go packages are
# often too old, so install the latest release from https://go.dev/dl/
# and make sure /usr/local/go/bin is in PATH, then:
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

# Build Caddy with the layer4 app
~/go/bin/xcaddy build --with github.com/mholt/caddy-l4

# Confirm the modules are present
./caddy list-modules | grep layer4

Ganti binary bawaan paket dengan aman

Jika Caddy dipasang dari repositori apt resmi, cara terdokumentasi untuk menggantinya dengan build kustom adalah `dpkg-divert` plus `update-alternatives`, agar upgrade paket tidak menimpa binary Anda. Ingat bahwa sekarang Anda harus build ulang untuk mendapatkan pembaruan Caddy.

sudo dpkg-divert --divert /usr/bin/caddy.default --rename /usr/bin/caddy
sudo mv ./caddy /usr/bin/caddy.custom
sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.default 10
sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.custom 50
sudo systemctl restart caddy

Contoh 1: reverse proxy TCP biasa

Konfigurasi ini listen di port 5432 dan meneruskan setiap koneksi ke server PostgreSQL di alamat privat, misalnya ujung lain dari tunnel WireGuard. Tanpa matcher berarti setiap koneksi mengambil rute tersebut. Upstream menerima beberapa alamat `dial` untuk failover, dan handler `proxy` mendukung load balancing dan health check serupa dengan `reverse_proxy` HTTP.

Backend melihat IP Caddy, bukan IP klien. Jika backend memahami PROXY protocol, set `"proxy_protocol": "v2"` pada handler proxy untuk meneruskan alamat aslinya.

{
  "apps": {
    "layer4": {
      "servers": {
        "postgres": {
          "listen": [":5432"],
          "routes": [
            {
              "handle": [
                {
                  "handler": "proxy",
                  "upstreams": [{"dial": ["10.8.0.2:5432"]}]
                }
              ]
            }
          ]
        }
      }
    }
  }
}

Contoh 2: SSH dan HTTPS di-multiplex pada port 443

Klien SSH mengirim banner versinya (`SSH-2.0-...`) begitu terhubung, sehingga caddy-l4 dapat mengenali SSH sebelum ada respons dari server. Konfigurasi di bawah mengirim SSH ke sshd lokal, TLS untuk `git.example.com` ke layanan yang mengakhiri TLS-nya sendiri, dan semua TLS lainnya ke app HTTP Caddy yang listen di 8443. Karena layer4 kini memegang port 443, app HTTP tidak boleh ikut bind ke port itu: set `https_port 8443` di opsi global Caddyfile, atau alamat `listen` yang setara di JSON, dan biarkan port 80 terbuka untuk challenge HTTP-01. Dengan `https_port 8443`, pengalihan otomatis HTTP ke HTTPS milik Caddy akan mengarah ke port 8443, jadi set `auto_https disable_redirects` dan tambahkan situs `http:// { redir https://{host}{uri} permanent }` Anda sendiri.

Protokol tempat server berbicara lebih dulu, seperti SMTP, FTP, atau MySQL, tidak dapat dideteksi dengan cara ini, karena klien menunggu tanpa mengirim apa pun. Berikan port tersendiri untuk protokol tersebut.

{
  "apps": {
    "layer4": {
      "servers": {
        "mux443": {
          "listen": [":443"],
          "routes": [
            {
              "match": [{"ssh": {}}],
              "handle": [
                {"handler": "proxy", "upstreams": [{"dial": ["127.0.0.1:22"]}]}
              ]
            },
            {
              "match": [{"tls": {"sni": ["git.example.com"]}}],
              "handle": [
                {"handler": "proxy", "upstreams": [{"dial": ["127.0.0.1:3443"]}]}
              ]
            },
            {
              "match": [{"tls": {}}],
              "handle": [
                {"handler": "proxy", "upstreams": [{"dial": ["127.0.0.1:8443"]}]}
              ]
            }
          ]
        }
      }
    }
  }
}

Jalankan dan uji

  1. 01.Simpan JSON sebagai `/etc/caddy/caddy.json` dan validasi.
  2. 02.Hentikan layanan dan jalankan Caddy di foreground untuk memantau log saat Anda terhubung.
  3. 03.Arahkan unit systemd ke file JSON dengan drop-in override, lalu `sudo systemctl daemon-reload` dan `sudo systemctl start caddy`.
  4. 04.Hubungkan dengan `ssh -p 443` dan buka situs HTTPS di browser untuk memastikan kedua rute berfungsi.
# Validate and test in the foreground first
sudo caddy validate --config /etc/caddy/caddy.json
sudo systemctl stop caddy
sudo caddy run --config /etc/caddy/caddy.json

# Make the service use the JSON file: sudo systemctl edit caddy
[Service]
ExecStart=
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/caddy.json
ExecReload=
ExecReload=/usr/bin/caddy reload --config /etc/caddy/caddy.json --force

# Client side
ssh -p 443 [email protected]

Kapan sebaiknya memakai HAProxy atau sslh

caddy-l4 cocok jika Anda sudah menjalankan Caddy dan menginginkan satu proses untuk HTTPS dan beberapa rute TCP. Untuk setup yang didominasi TCP, alternatif matang di repositori Debian dan Ubuntu mungkin lebih mudah dioperasikan: HAProxy dalam `mode tcp` merutekan berdasarkan SNI dengan `req.ssl_sni` dan memiliki statistik serta health check yang mendetail, sedangkan sslh adalah daemon kecil yang dibuat khusus untuk berbagi satu port antara SSH, TLS, OpenVPN, dan lainnya. Keduanya dipasang dengan apt dan diperbarui bersama sistem, tanpa build kustom yang perlu dipelihara.

Mengekspos SSH di 443 membantu di jaringan yang hanya mengizinkan port web, tetapi itu bukan fitur keamanan. Tetap gunakan autentikasi khusus kunci dari panduan hardening SSH. Di VPS NoctisNode Anda punya root penuh, sehingga tool mana pun bisa bind ke port yang Anda butuhkan; untuk perilaku sertifikat di sisi HTTPS lihat HTTPS otomatis Caddy dan, untuk container, Caddy sebagai reverse proxy Docker.

ToolKelebihanKekurangan
Caddy + caddy-l4Satu proses untuk HTTPS otomatis dan TCP, matcher protokol, API JSONBuild kustom, modul masih berkembang
HAProxyProxy TCP/HTTP yang matang, routing SNI, health check dan statistik lengkapKonfigurasi lebih banyak, tanpa klien ACME bawaan
sslhSangat kecil, khusus untuk berbagi port SSH/TLS/VPNHanya multiplexing; tanpa terminasi TLS atau load balancing

FAQ

QBisakah Caddy mem-proxy trafik TCP?

ATidak secara bawaan. Caddy inti hanya mem-proxy HTTP; untuk TCP atau UDP mentah Anda membutuhkan build Caddy yang menyertakan modul pihak ketiga caddy-l4 (layer4).

QBagaimana cara mem-proxy SSH melalui Caddy?

ABuild Caddy dengan caddy-l4, tambahkan server layer4 yang mencocokkan `ssh` dan mem-proxy ke `127.0.0.1:22`, lalu hubungkan dengan `ssh -p <port>`. Di port 443 Anda bisa menggabungkannya dengan rute `tls` agar HTTPS tetap berfungsi.

QBisakah SSH dan HTTPS berbagi port 443?

ABisa. caddy-l4, sslh, dan HAProxy semuanya dapat memeriksa byte pertama koneksi dan merutekan SSH serta TLS ke backend berbeda di port yang sama.

QApakah caddy-l4 mendukung Caddyfile?

AAda dukungan Caddyfile melalui opsi global `layer4`, tetapi JSON tetap menjadi format yang paling lengkap dan terdokumentasi dengan baik. Periksa README modul untuk versi yang Anda build.

Reverse Proxy TCP dan Proxy SSH Caddy dengan caddy-l4 · NoctisNode