Cara Membuat VPN WireGuard di VPS Linux Sendiri
Panduan WireGuard di VPS Linux: buat kunci dan wg0.conf, aktifkan forwarding serta NAT, pahami AllowedIPs, DNS, dan error handshake yang sering muncul.
Yang Anda bangun
VPN WireGuard pada server yang Anda miliki memerlukan sekitar empat puluh baris konfigurasi: satu pasangan kunci, satu file antarmuka, satu sysctl, satu aturan NAT, dan satu celah pada firewall. Instalasinya sederhana, sehingga sebagian besar panduan ini membahas hal-hal yang dapat gagal, izin kunci, AllowedIPs, forwarding, dan DNS.
WireGuard adalah tunnel Layer 3 di kernel dan telah menjadi bagian dari mainline sejak Linux 5.6. Karena itu, Ubuntu 24.04 dan Debian 13 menyertakannya tanpa modul eksternal. Tidak ada negosiasi cipher, certificate authority, atau langkah username/password: peer terdiri atas kunci publik dan alamat IP yang boleh digunakan oleh kunci tersebut. Paket yang gagal dalam pemeriksaan MAC akan dibuang tanpa balasan, sehingga port tidak merespons pemindaian. Konsekuensinya, tidak ada server autentikasi. Untuk mencabut akses, hapus peer pada server.
Periksa virtualisasi terlebih dahulu
WireGuard memerlukan kernel yang dapat dimuati modul. Pada VPS KVM, WireGuard dapat langsung digunakan. Pada virtualisasi berbasis container yang berbagi kernel host, seperti OpenVZ dan LXC, perintah pertama gagal dengan RTNETLINK answers: Operation not supported. Gunakan implementasi userspace wireguard-go sebagai alternatif. Periksa terlebih dahulu dengan sudo modprobe wireguard && echo ok.
Membuat key tanpa membocorkannya
/etc/wireguard/server.key yang dapat dibaca semua pengguna sama saja dengan tidak memiliki VPN. Perintah umask 077 && wg genkey | sudo tee ... yang umum memang berfungsi: kecuali sudoers menetapkan umask_override, yang secara default tidak aktif, sudo menggabungkan umask Anda dengan nilai defaultnya, yaitu 0022, dan tidak pernah membuatnya lebih longgar, sehingga file yang dibuat oleh tee memiliki mode 600. Key dapat bocor jika pipe tersebut dijalankan tanpa umask 077, dengan umask normal 022, atau pada sistem yang mengaktifkan umask_override melalui sudoers. Tetapkan mode secara eksplisit agar hal tersebut tidak lagi berpengaruh.
sudo apt update && sudo apt install -y wireguard nftables
sudo install -d -m 700 /etc/wireguard
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server.key'
sudo sh -c 'wg pubkey < /etc/wireguard/server.key > /etc/wireguard/server.pub'
sudo chmod 600 /etc/wireguard/server.keyBuat pasangan client dengan cara yang sama. wg genpsk menambahkan pre-shared key opsional, satu baris pada setiap konfigurasi.
Antarmuka server: /etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>
[Peer]
PublicKey = <laptop public key>
PresharedKey = <psk, optional>
AllowedIPs = 10.8.0.2/32chmod 600; peringatan saat startup yang menyatakan bahwa file dapat diakses oleh semua pengguna berarti Anda melewatkan langkah tersebut. Address adalah alamat server di dalam tunnel, dengan mask seluruh subnet VPN. Pilih rentang yang tidak akan bertabrakan dengan jaringan yang digunakan di luar, karena 192.168.1.0/24 bertabrakan dengan banyak router rumahan yang digunakan klien Anda. Akibatnya, tunnel kalah secara diam-diam terhadap rute lokal.
AllowedIPs milik peer di sisi server adalah /32, yaitu satu-satunya alamat tunnel yang dimiliki klien tersebut. Jika dua peer diberi allowed IP yang sama, alamat itu berpindah ke peer yang dikonfigurasi terakhir. Peer pertama berhenti menerima trafik tanpa pesan error apa pun. Biarkan SaveConfig tidak disetel, atau wg-quick down akan menulis ulang file ini berdasarkan status aktif.
Ubah server menjadi router
Server Linux membuang paket yang tidak ditujukan kepadanya. Forwarding dan source NAT tidak aktif secara default.
printf 'net.ipv4.ip_forward = 1\nnet.ipv6.conf.all.forwarding = 1\n' \
| sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sysctl net.ipv4.ip_forwardsysctl -w polos berfungsi sampai reboot berikutnya, lalu berhenti tanpa pesan. NAT memerlukan interface egress, yaitu NIC yang terhubung ke Internet, bukan wg0. Jangan mengasumsikan eth0; ambil nama interface Anda dari ip route show default, karena image saat ini menggunakan nama seperti enp1s0 atau ens3.
Firewall: port dan jalur penerusan
Satu file nftables mencakup filter dan NAT. Tulis /etc/nftables.conf untuk mengosongkan ruleset yang ada, jadi jangan jalankan ini pada server yang sudah dikelola oleh ufw atau Docker.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
iif lo accept
tcp dport 22 accept
udp dport 51820 accept
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname "wg0" oifname "enp1s0" accept
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.8.0.0/24 oifname "enp1s0" masquerade
}
}Terapkan dengan sudo systemctl enable --now nftables dan biarkan sesi SSH kedua tetap terbuka: policy drop ditambah kesalahan ketik pada aturan SSH dapat mengunci Anda dari server sendiri. Perhatikan hal yang tidak diizinkan oleh forward chain, yaitu wg0 ke wg0. Peer dapat mengakses Internet, tetapi tidak dapat saling mengakses; tambahkan iifname "wg0" oifname "wg0" accept untuk VPN peer-to-peer. Akses peer ke server itu sendiri bukan tugas chain ini: paket yang ditujukan ke server melewati input hook, bukan forward, sehingga input chain yang menentukan. Dalam konfigurasi ini, peer dapat mengakses SSH dan tidak ada yang lain, bahkan tidak dapat melakukan ping ke 10.8.0.1. Tambahkan iifname "wg0" icmp type echo-request accept di sana, serta satu aturan iifname "wg0" untuk setiap service yang ingin dapat diakses hanya melalui tunnel. Hal ini penting ketika server juga digunakan sebagai server pengembangan jarak jauh yang menjalankan Claude Code di tmux dan Anda tidak ingin mengekspos bagian tersebut ke publik.
Pada server yang menggunakan ufw: ufw allow 51820/udp, DEFAULT_FORWARD_POLICY="ACCEPT" di /etc/default/ufw, dan aturan POSTROUTING MASQUERADE *nat di bagian atas /etc/ufw/before.rules.
Menjalankannya dengan systemd
sudo systemctl enable --now wg-quick@wg0
sudo wg showwg-quick membuat interface, menambahkan alamat, dan memasang rute yang diturunkan dari AllowedIPs. enable --now adalah bagian pentingnya: wg-quick up wg0 yang dijalankan manual akan hilang setelah reboot berikutnya, dan pembaruan kernel mengharuskan reboot. Unit yang gagal berjalan kembali setelah salah satu reboot tersebut tidak akan menampilkan indikasi apa pun sampai seseorang mencoba terhubung. Karena itu, drop-in OnFailure= pada wg-quick@wg0 yang diarahkan ke server ntfy Anda sendiri adalah cara termurah untuk menerima pemberitahuan di ponsel, bukan mengetahuinya dari pengguna yang tidak dapat login.
Konfigurasi client dan pengaturan yang sering disalahpahami
[Interface]
PrivateKey = <laptop private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1
[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25AllowedIPs menjalankan dua fungsi yang berbeda sekaligus. Mencampurkan kedua fungsi ini menjadi penyebab sebagian besar kebingungan tentang WireGuard.
Untuk trafik keluar, pengaturan ini berfungsi sebagai tabel routing. Paket yang tujuan-nya cocok dengan AllowedIPs milik sebuah peer akan dienkripsi dan dikirim ke peer tersebut. 0.0.0.0/0, ::/0 mengirimkan semua trafik melalui tunnel, yaitu full tunnel dengan server sebagai default route. Split tunnel menggunakan daftar yang lebih sempit: AllowedIPs = 10.8.0.0/24, 10.20.0.0/16 membawa trafik VPN serta satu jaringan privat di belakang server, sedangkan trafik lainnya tetap menggunakan route lokalnya. Daftar yang lebih sempit ini memungkinkan Anda sepenuhnya menjauhkan layanan dari Internet publik. Contohnya, instance Nextcloud privat pada VPS yang terikat pada alamat tunnel, atau VM lab nested virtualisation yang berjalan pada mesin yang sama, tetap dapat diakses oleh peer dan tidak terlihat oleh pihak lain.
Untuk trafik masuk, pengaturan ini berfungsi sebagai daftar kontrol akses. Paket yang telah didekripsi dari sebuah peer akan dibuang jika alamat sumbernya tidak termasuk dalam AllowedIPs milik peer tersebut. Karena itu, server mencantumkan 10.8.0.2/32 untuk laptop. Entri 0.0.0.0/0 di sana akan memungkinkan client tersebut melakukan spoofing terhadap alamat apa pun di dalam tunnel.
PersistentKeepalive digunakan untuk client di belakang NAT, ketika router hanya mempertahankan pemetaan UDP selama ada paket yang mengalir. Setelah pemetaan tersebut kedaluwarsa, server tidak dapat lagi menjangkau client. PersistentKeepalive = 25 mempertahankan pemetaan tetap aktif. Atur pengaturan ini pada client, bukan pada server yang memiliki alamat IP publik.
DNS dan kebocoran yang tidak disadari
Dengan AllowedIPs = 0.0.0.0/0 dan tanpa baris DNS =, client tetap menggunakan resolver yang diperolehnya dari jaringan lokal, yaitu router kafe pada 192.168.1.1. Rute tersebut lebih spesifik daripada rute default, sehingga kueri DNS keluar melalui link lokal dalam bentuk plaintext, sementara trafik lainnya ditunnelkan. Trafiknya privat, tetapi daftar nama yang diakses tidak.
Ada 2 opsi yang jelas. Arahkan DNS ke resolver publik (DNS = 9.9.9.9), sehingga kueri melewati tunnel dan keluar dari server Anda, meskipun resolver tersebut tetap dapat melihatnya. Atau jalankan unbound atau dnsmasq yang terikat pada 10.8.0.1, tetapkan DNS = 10.8.0.1, dan tambahkan udp dport 53 iifname "wg0" accept ke input chain. Tetapkan baris tersebut lalu abaikan resolver, dan tidak ada apa pun yang dapat di-resolve.
Pada client Linux, wg-quick menerapkan DNS melalui resolvconf; jika tidak ada, Anda mendapatkan resolvconf: command not found. Instal openresolv, atau tetapkan PostUp = resolvectl dns %i 10.8.0.1 pada client systemd-resolved.
Menambahkan dan menghapus peer tanpa memutus tunnel
Memulai ulang interface untuk menambahkan pengguna akan memutus semua koneksi yang sedang aktif. Tambahkan blok [Peer] ke wg0.conf, lalu muat ulang kumpulan peer tanpa memutus koneksi.
sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'wg-quick strip menampilkan konfigurasi tanpa kunci khusus wg-quick (Address, DNS, PostUp), sedangkan syncconf menerapkan perbedaannya saat tunnel tetap aktif. Perintah ini hanya memperbarui peer: perubahan pada Address tetap memerlukan proses down/up penuh. Cabut akses dengan sudo wg set wg0 peer <public key> remove, lalu hapus blok tersebut dari file. Jika tidak, blok akan muncul kembali pada pemuatan ulang berikutnya.
Mode kegagalan dan string yang akan Anda lihat
Handshake tidak pernah selesai. wg show mencantumkan peer tanpa latest handshake, dan log client menunjukkan:
Handshake for peer 1 (10.0.0.10:51820) did not complete after 5 seconds, retrying (try 2)Tidak ada paket yang masuk, atau tidak ada paket yang diterima. Periksa secara berurutan: apakah UDP 51820 terbuka pada firewall VPS dan firewall jaringan provider Anda, yang biasanya merupakan pengaturan terpisah pada sebagian besar panel; apakah alamat dan port Endpoint sudah benar; apakah key tertukar. Key dalam blok [Peer] milik client harus berupa public key server, dan sebaliknya. Menempelkan private key atau public key milik client sendiri menimbulkan gejala yang sama persis. sudo tcpdump -ni any udp port 51820 pada server menunjukkan apakah paket masuk sama sekali. Modul kernel tidak mencatat apa pun secara default. Pesan WireGuard baru muncul di dmesg setelah Anda mengaktifkan dynamic debug (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control). Setelah diaktifkan, ketidakcocokan key muncul sebagai penolakan invalid-MAC.
Handshake berhasil, tetapi tidak ada Internet. ping 10.8.0.1 berhasil, tetapi ping 1.1.1.1 timeout: forwarding atau NAT belum dikonfigurasi. Pastikan sysctl net.ipv4.ip_forward berisi 1, lalu pantau counter saat client melakukan ping menggunakan sudo nft list ruleset atau sudo iptables -t nat -L POSTROUTING -n -v. Tidak adanya paket pada aturan masquerade berarti nama interface egress salah. Counter yang meningkat tanpa balasan menunjukkan masalah pada kebijakan forward chain.
Internet berfungsi, tetapi nama tidak dapat di-resolve. ping 1.1.1.1 berhasil dan curl https://example.com mengembalikan Could not resolve host. Baris DNS tidak ada, atau baris tersebut menyebut resolver yang tidak dapat dijangkau dari dalam tunnel.
Beberapa situs HTTPS berhenti merespons. SSH dan ping berfungsi, tetapi halaman besar berhenti dimuat. Penyebabnya adalah path MTU: tunnel menambahkan overhead, dan link tertentu di tengah jalur membuang paket yang terlalu besar tanpa mengirim pesan ICMP kembali. Atur MTU pada [Interface] milik client. Pada link biasa dengan ukuran 1500 byte, wg-quick sudah memilih 1420 (1500 dikurangi overhead sebesar 80 byte), sehingga menulis 1420 tidak mengubah apa pun. Coba 1380, lalu 1280. Jika menurunkan MTU mengatasi halaman yang berhenti dimuat, tetapi throughput masih tidak memuaskan, jangan terus menebak nilai bulat. Ikuti cara menemukan path MTU sebenarnya dengan bisection dan membatasi TCP MSS. Langkah ini juga membantu menyingkirkan penyebab yang sama sekali tidak berkaitan dengan tunnel.
Interface menolak untuk start. Address already in use berarti proses lain sedang menggunakan UDP 51820. Cannot find device wg0 setelah up gagal biasanya berarti konfigurasi ditolak. Baca journalctl -u wg-quick@wg0 -n 50.
Migrasi dari Streisand atau OpenVPN
Streisand tidak lagi dipelihara dan repositorinya telah diarsipkan. Menjalankan VPN dengan otomatisasi yang ditinggalkan menimbulkan masalah keamanan yang berkembang secara perlahan. Tidak ada pemutakhiran langsung di tempat, dan PKI OpenVPN tidak dapat dikonversi. WireGuard tidak menggunakan sertifikat, CA, atau masa berlaku. Karena itu, setiap klien harus mendapatkan pasangan kunci baru.
Lakukan migrasi secara paralel. WireGuard pada UDP 51820 dapat berjalan berdampingan dengan OpenVPN pada 1194 di server yang sama. Siapkan wg0, pindahkan klien satu per satu, lalu hentikan service lama. Model nama pengguna/password dan pencabutan akses OpenVPN tidak dapat dipindahkan. Jika Anda memerlukan akun atau jejak audit, tambahkan lapisan tersebut di atas WireGuard.
Backup, upgrade, dan hal-hal yang membebani pada skala besar
/etc/wireguard adalah server tersebut. Cadangkan file ini (sudo tar czf wg-backup.tgz -C /etc wireguard, mode 600, simpan di luar server), sehingga Anda dapat membangun ulang pada VPS baru dalam hitungan menit. Jika private key server hilang, semua konfigurasi client harus diterbitkan ulang karena client menyimpan public key server untuk verifikasi. Upgrade cukup dilakukan dengan apt upgrade biasa, ditambah reboot untuk pembaruan kernel, dan wg-quick@wg0 akan aktif kembali secara otomatis jika Anda mengaktifkannya.
State per-peer berukuran kecil dan kriptografi berjalan di kernel. Karena itu, batasnya ditentukan oleh CPU dan bandwidth VPS, bukan oleh konfigurasi ini. Ukur batas tersebut dengan iperf3 melalui tunnel, bukan dengan mengandalkan angka yang dipublikasikan. Hal yang membebani pada skala besar adalah operasional. Setiap peer memerlukan IP tunnel yang unik. Mengedit enam puluh blok [Peer] secara manual dapat menyebabkan AllowedIPs duplikat. Buat konfigurasi tersebut dari sebuah script. Satu server berarti satu endpoint UDP dan satu titik kegagalan. WireGuard tidak memiliki clustering. Redundansi berarti menggunakan server kedua dengan key-nya sendiri. Rotasi key tetap dilakukan secara manual. Karena itu, catat siapa yang memegang setiap key dan cara mencabut salah satunya. Jika pencatatan tersebut sudah melampaui kemampuan sebuah file teks, solusi yang umum adalah menggunakan control plane di atas data plane kernel yang sama. server NetBird yang di-host sendiri menangani alokasi alamat, distribusi peer, dan setup key yang sebelumnya harus Anda lakukan secara manual. Jika menjalankan control plane sendiri berarti harus mengelola satu server tambahan, Tailscale dapat meng-host control plane tersebut untuk Anda. Paket Personal gratisnya mencakup enam user dengan jumlah perangkat user yang tidak terbatas dan, pada tahap awal, hingga 50 resource bertag seperti server, sehingga sebagian besar fleet pribadi tidak perlu membayar. Setelah melewati batas tersebut, biaya ditentukan oleh jumlah orang, bukan jumlah mesin. Jadi, biaya yang sebenarnya dibayar rumah tangga atau tim kecil bergantung pada jumlah manusia yang memiliki login, bukan jumlah peer yang harus Anda tambahkan secara manual ke wg0.conf. Dalam model tersebut, pencatatan AllowedIPs untuk split tunnel digantikan oleh pengumuman private range dari subnet router. Pengumuman dilakukan satu kali dari satu VPS dan disetujui secara terpusat, bukan ditempelkan ke setiap file client. Apakah perubahan ini layak dilakukan bergantung pada resource yang benar-benar dapat dijangkau oleh control plane ter-host. Control plane tersebut tidak pernah menyimpan key yang mengenkripsi trafik Anda, tetapi menentukan peer mana yang dapat saling mengetahui.
Semua ini memerlukan box Linux yang Anda kendalikan, IP publik, kernel yang dapat memuat module, dan firewall yang Anda kelola dari ujung ke ujung.
FAQ
Mengapa handshake WireGuard tidak pernah selesai?
wg show yang menampilkan peer tanpa latest handshake berarti paket tidak tiba atau tidak diterima. Periksa UDP 51820 pada firewall VPS dan firewall jaringan terpisah milik penyedia Anda. Pastikan host dan port Endpoint sudah benar. Kemudian periksa agar key tidak tertukar. Blok [Peer] milik client harus berisi public key server. sudo tcpdump -ni any udp port 51820 pada server menunjukkan apakah paket tiba sama sekali. dmesg hanya melaporkan kegagalan handshake WireGuard setelah Anda mengaktifkan debug dinamis (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control). Setelah itu, ketidakcocokan key muncul sebagai pembuangan invalid-MAC.
Tunnel tersambung, tetapi saya tidak memiliki akses Internet. Apa yang kurang?
ping 10.8.0.1 yang berfungsi sementara ping 1.1.1.1 mengalami timeout menunjukkan masalah pada forwarding atau NAT. Pastikan sysctl net.ipv4.ip_forward berisi 1 dan nilai tersebut ditetapkan dalam /etc/sysctl.d/, bukan hanya melalui sysctl -w yang hilang setelah reboot. Kemudian periksa apakah rule masquerade menggunakan nama interface egress yang sebenarnya dari ip route show default. Nama tersebut dapat berupa enp1s0 atau ens3, dan lebih jarang eth0.
Apakah saya memerlukan baris DNS = dalam konfigurasi client?
Dengan full tunnel dan tanpa baris DNS =, client tetap menggunakan resolver yang diperoleh dari jaringan lokal. Query tersebut keluar tanpa enkripsi melalui link lokal, sedangkan semua trafik lainnya diteruskan melalui tunnel. Arahkan DNS ke resolver publik, atau jalankan unbound/dnsmasq yang terikat pada 10.8.0.1 dan buka udp dport 53 iifname "wg0" pada input chain.
Apa yang sebenarnya dikendalikan oleh AllowedIPs?
AllowedIPs memiliki dua fungsi. Untuk trafik keluar, parameter ini merupakan tabel routing: trafik yang cocok dengan AllowedIPs milik peer akan dienkripsi dan dikirim ke peer tersebut. Untuk trafik masuk, parameter ini merupakan access-control list: paket yang telah didekripsi dan sumbernya berada di luar AllowedIPs peer tersebut akan dibuang. Karena itu, sisi server mencantumkan /32 untuk setiap client, sedangkan sisi client dapat mencantumkan 0.0.0.0/0.
Apakah WireGuard dapat berjalan pada VPS apa pun?
Pada VPS KVM, WireGuard berjalan dengan module in-kernel tanpa konfigurasi tambahan. Pada virtualisasi berbasis container yang berbagi kernel host, seperti OpenVZ atau LXC, modprobe wireguard gagal dengan Operation not supported. Alternatifnya adalah implementasi userspace wireguard-go. Jalankan sudo modprobe wireguard && echo ok sebelum melakukan hal lain.