วิธีติดตั้ง WireGuard VPN บน Linux VPS ด้วยตัวเอง
เรียนรู้วิธีตั้งค่า WireGuard VPN บน VPS ของคุณเอง ตั้งแต่การสร้างกุญแจ การตั้งค่า wg0.conf การทำ IP forwarding และ NAT ไปจนถึงการแก้ไขปัญหา Handshake failed ที่พบบ่อย
สิ่งที่คุณกำลังสร้าง
การทำ WireGuard VPN บนเซิร์ฟเวอร์ที่คุณเป็นเจ้าของใช้การตั้งค่าเพียงประมาณ 40 บรรทัด ได้แก่: หนึ่งคู่กุญแจ, หนึ่งไฟล์อินเทอร์เฟซ, หนึ่ง sysctl, หนึ่งกฎ NAT และหนึ่งช่องเปิดไฟร์วอลล์ การติดตั้งนั้นทำได้ง่ายมาก ดังนั้นเนื้อหาส่วนใหญ่ในคู่มือนี้จึงครอบคลุมถึงสิ่งที่มักจะเกิดข้อผิดพลาด, สิทธิ์ของกุญแจ, AllowedIPs, การส่งต่อข้อมูล (forwarding) และ DNS
WireGuard เป็นอุโมงค์ Layer 3 ในระดับเคอร์เนล ซึ่งรวมอยู่ใน mainline ตั้งแต่ Linux 5.6 เป็นต้นมา ดังนั้น Ubuntu 24.04 และ Debian 13 จึงมาพร้อมกับฟีเจอร์นี้โดยไม่ต้องติดตั้งโมดูลภายนอก ไม่มีการเจรจา cipher, ไม่มีการใช้ certificate authority และไม่มีขั้นตอนการใช้ชื่อผู้ใช้/รหัสผ่าน: peer หนึ่งตัวประกอบด้วยกุญแจสาธารณะ (public key) และที่อยู่ IP ที่กุญแจนั้นได้รับอนุญาตให้ใช้งาน แพ็กเก็ตที่ผ่านการตรวจสอบ MAC ไม่สำเร็จจะถูกทิ้งโดยไม่มีการตอบกลับ ดังนั้นพอร์ตจะไม่ตอบสนองต่อการสแกน ในทางกลับกัน เนื่องจากไม่มีเซิร์ฟเวอร์ตรวจสอบสิทธิ์ การเพิกถอนสิทธิ์การเข้าถึงจึงต้องทำโดยการลบ peer ออกจากเครื่องโดยตรง
ตรวจสอบระบบเวอร์ชวลไลเซชันก่อน
WireGuard ต้องการเคอร์เนลที่สามารถโหลดโมดูลเข้าไปได้ ซึ่งบน KVM VPS จะใช้งานได้ทันที แต่สำหรับการทำเวอร์ชวลไลเซชันแบบคอนเทนเนอร์ที่ใช้เคอร์เนลร่วมกับโฮสต์ เช่น OpenVZ หรือ LXC คำสั่งแรกจะล้มเหลวด้วย RTNETLINK answers: Operation not supported และต้องใช้ wireguard-go ซึ่งเป็นอิมพลีเมนต์ระดับ userspace แทน ให้ตรวจสอบด้วย sudo modprobe wireguard && echo ok ก่อนเสมอ
การสร้างคีย์โดยไม่ให้ข้อมูลรั่วไหล
ไฟล์ /etc/wireguard/server.key ที่ทุกคนในระบบอ่านได้นั้นมีค่าเท่ากับการไม่มี VPN เลย บรรทัด umask 077 && wg genkey | sudo tee ... ที่ใช้กันทั่วไปนั้นไม่น่าเชื่อถือ เนื่องจาก sudo จะใช้ umask ของตนเองกับไฟล์ที่ tee สร้างขึ้น ดังนั้นควรตั้งค่าโหมดการเข้าถึงไฟล์ให้ชัดเจน
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.keyสร้างคู่คีย์สำหรับไคลเอนต์ด้วยวิธีเดียวกัน wg genpsk จะเพิ่ม pre-shared key ซึ่งเป็นตัวเลือกเสริม โดยระบุไว้หนึ่งบรรทัดในไฟล์คอนฟิกของแต่ละฝั่ง
อินเทอร์เฟซของเซิร์ฟเวอร์: /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 หากมีคำเตือนขณะเริ่มทำงานว่าไฟล์นี้อนุญาตให้ทุกคนเข้าถึงได้ แสดงว่าคุณข้ามขั้นตอนการตั้งค่าสิทธิ์ไป Address คือที่อยู่ของเซิร์ฟเวอร์ภายในอุโมงค์เครือข่าย โดยระบุ subnet mask ของ VPN ทั้งหมด ให้เลือกช่วง IP ที่ไม่ซ้ำกับเครือข่ายภายนอก เพราะ 192.168.1.0/24 มักจะชนกับ IP ของเราเตอร์ตามบ้านส่วนใหญ่ที่ไคลเอนต์ใช้งานอยู่ ซึ่งจะทำให้การรับส่งข้อมูลผ่านอุโมงค์ล้มเหลวโดยไม่มีการแจ้งเตือน
AllowedIPs ของ peer ในฝั่ง เซิร์ฟเวอร์ คือ /32 ซึ่งเป็นที่อยู่ภายในอุโมงค์ที่ไคลเอนต์นั้นเป็นเจ้าของ หากกำหนด AllowedIPs ซ้ำกันให้กับ peer สองราย การรับส่งข้อมูลจะถูกส่งไปยัง peer ที่ถูกตั้งค่าล่าสุดแทน และ peer รายแรกจะหยุดรับข้อมูลโดยไม่มีข้อความแสดงข้อผิดพลาดปรากฏขึ้นที่ใดเลย อย่าปล่อยให้ SaveConfig ไม่ได้ตั้งค่าไว้ มิฉะนั้น wg-quick down จะเขียนไฟล์นี้ทับด้วยสถานะปัจจุบันของระบบ
เปลี่ยนเซิร์ฟเวอร์ให้เป็นเราเตอร์
โดยปกติ Linux server จะทิ้งแพ็กเก็ตที่ไม่ได้ส่งถึงตัวมันเอง เนื่องจากค่าเริ่มต้นไม่ได้เปิดใช้งานการส่งต่อข้อมูล (forwarding) และ source NAT
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_forwardการใช้ sysctl -w เพียงอย่างเดียวจะใช้งานได้จนกว่าจะรีบูตเครื่อง หลังจากนั้นจะหยุดทำงานโดยไม่มีการแจ้งเตือน การทำ NAT จำเป็นต้องระบุอินเทอร์เฟซขาออก (egress interface) ซึ่งก็คือ NIC ที่เชื่อมต่อกับอินเทอร์เน็ต ไม่ใช่ wg0 อย่าทึกทักเอาเองว่าเป็น eth0 ให้ตรวจสอบชื่ออินเทอร์เฟซของคุณจาก ip route show default เนื่องจากอิมเมจปัจจุบันมักใช้ชื่ออย่าง enp1s0 หรือ ens3
ไฟร์วอลล์: พอร์ตและเส้นทางการส่งต่อ (forward path)
ไฟล์ nftables หนึ่งไฟล์ครอบคลุมทั้งการกรอง (filter) และ NAT เขียน /etc/nftables.conf ซึ่งจะ ล้าง กฎที่มีอยู่เดิมทั้งหมด ดังนั้นให้ข้ามขั้นตอนนี้หากเซิร์ฟเวอร์ของคุณมีการจัดการด้วย ufw หรือ 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
}
}ใช้คำสั่ง sudo systemctl enable --now nftables เพื่อนำกฎไปใช้ โดยต้องเปิดเซสชัน SSH สำรองไว้อีกหนึ่งช่องทางเสมอ เพราะ policy drop หากพิมพ์กฎ SSH ผิดพลาดเพียงตัวอักษรเดียวจะทำให้คุณถูกล็อกออกจากเซิร์ฟเวอร์ทันที โปรดสังเกตว่า chain การส่งต่อ (forward chain) ไม่อนุญาตให้ทำสิ่งใดบ้าง โดยดูจาก wg0 ถึง wg0 โดยปกติแล้ว peer จะเข้าถึงอินเทอร์เน็ตได้แต่ไม่สามารถเข้าถึงกันเองได้ หากต้องการให้ peer เชื่อมต่อกันเองได้ให้เพิ่ม iifname "wg0" oifname "wg0" accept กฎชุดเดียวกันนี้ยังควบคุมสิ่งที่ peer สามารถเข้าถึงได้บนตัวเซิร์ฟเวอร์เอง ซึ่งมีความสำคัญเมื่อเซิร์ฟเวอร์ทำหน้าที่เป็น เซิร์ฟเวอร์สำหรับการพัฒนาทางไกลที่รัน Claude Code ใน tmux และคุณไม่ต้องการเปิดเผยส่วนนั้นสู่สาธารณะ
สำหรับเซิร์ฟเวอร์ที่ใช้ ufw: ให้ใช้ ufw allow 51820/udp, เพิ่ม DEFAULT_FORWARD_POLICY="ACCEPT" ใน /etc/default/ufw และเพิ่มกฎ POSTROUTING MASQUERADE ด้วย *nat ไว้ที่ส่วนบนสุดของ /etc/ufw/before.rules
การเปิดใช้งานภายใต้ systemd
sudo systemctl enable --now wg-quick@wg0
sudo wg showwg-quick จะสร้างอินเทอร์เฟซ เพิ่มที่อยู่ IP และติดตั้งเส้นทางเครือข่ายที่ได้มาจาก AllowedIPs ส่วน enable --now คือส่วนสำคัญที่ต้องทำ: การรัน wg-quick up wg0 ด้วยตนเองจะหายไปหลังจากรีบูตเครื่อง และการอัปเกรดเคอร์เนลจำเป็นต้องมีการรีบูต หาก unit ไม่สามารถกลับมาทำงานได้หลังจากรีบูต มันจะเงียบไปจนกว่าจะมีคนพยายามเชื่อมต่อ ดังนั้นการใช้ OnFailure= แบบ drop-in ที่ wg-quick@wg0 โดยชี้ไปยัง เซิร์ฟเวอร์ ntfy ของคุณเอง จึงเป็นวิธีที่ประหยัดที่สุดในการรับการแจ้งเตือนบนโทรศัพท์ของคุณ แทนที่จะรอรับแจ้งจากผู้ใช้ที่เข้าใช้งานไม่ได้
การตั้งค่าฝั่งไคลเอนต์ และจุดที่ทุกคนมักเข้าใจผิด
[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 ทำหน้าที่สองอย่างพร้อมกัน และการนำสองหน้าที่นี้มาปนกันคือสาเหตุหลักของความสับสนในการใช้งาน WireGuard
ในขาออก มันคือตารางเส้นทาง (routing table) แพ็กเก็ตที่มีปลายทางตรงกับ AllowedIPs ของ peer จะถูกเข้ารหัสและส่งไปยัง peer นั้น 0.0.0.0/0, ::/0 จะส่งทุกอย่างผ่านอุโมงค์ (full tunnel) โดยให้เซิร์ฟเวอร์เป็น default route ส่วน split tunnel จะเป็นรายการที่แคบกว่า เช่น AllowedIPs = 10.8.0.0/24, 10.20.0.0/16 ที่ส่งเฉพาะทราฟฟิก VPN และเครือข่ายส่วนตัวหนึ่งวงที่อยู่หลังเซิร์ฟเวอร์ ส่วนทราฟฟิกอื่นยังคงใช้เส้นทางเดิมในเครื่อง รายการที่จำกัดนี้เองที่ช่วยให้คุณเก็บเซอร์วิสต่างๆ ไว้ไม่ให้เข้าถึงได้จากอินเทอร์เน็ตสาธารณะ เช่น อินสแตนซ์ Nextcloud ส่วนตัวบน VPS ที่ผูกไว้กับ tunnel address หรือ VM ในห้องแล็บแบบ nested-virtualisation ที่รันบนเครื่องเดียวกัน ซึ่งจะยังคงเข้าถึงได้เฉพาะ peer เท่านั้นและมองไม่เห็นจากภายนอก
ในขาเข้า มันคือรายการควบคุมการเข้าถึง (access-control list) แพ็กเก็ตที่ถอดรหัสแล้วจาก peer ซึ่งมีที่อยู่ต้นทางไม่อยู่ใน AllowedIPs ของ peer นั้นจะถูกทิ้ง นี่คือเหตุผลที่เซิร์ฟเวอร์ระบุ 10.8.0.2/32 สำหรับแล็ปท็อป หากตั้งค่าเป็น 0.0.0.0/0 ในส่วนนั้น จะทำให้ไคลเอนต์สามารถปลอมแปลงที่อยู่ใดก็ได้ในอุโมงค์
PersistentKeepalive มีไว้สำหรับไคลเอนต์ที่อยู่หลัง NAT ซึ่งเราเตอร์จะเปิดการแมป UDP ไว้เฉพาะช่วงที่มีแพ็กเก็ตวิ่งผ่านเท่านั้น เมื่อหมดเวลา เซิร์ฟเวอร์จะไม่สามารถติดต่อไคลเอนต์ได้ PersistentKeepalive = 25 จะช่วยรักษาการแมปนี้ไว้ ให้ตั้งค่านี้ที่ฝั่งไคลเอนต์ ไม่ใช่บนเซิร์ฟเวอร์ที่มี Public IP
DNS และการรั่วไหลที่ไม่มีใครสังเกตเห็น
เมื่อใช้ AllowedIPs = 0.0.0.0/0 และไม่มีบรรทัด DNS = ไคลเอนต์จะยังคงใช้ตัวแก้ไข (resolver) ที่ได้รับมาจากเครือข่ายท้องถิ่น ซึ่งก็คือเราเตอร์ของร้านกาแฟที่ 192.168.1.1 เส้นทางดังกล่าวมีความเฉพาะเจาะจงมากกว่าเส้นทางเริ่มต้น (default route) ดังนั้นคำขอ DNS จึงถูกส่งออกผ่านลิงก์ท้องถิ่นในรูปแบบข้อความธรรมดา (cleartext) ในขณะที่ข้อมูลอื่นทั้งหมดถูกส่งผ่านอุโมงค์ (tunnel) แม้ว่าทราฟฟิกจะมีความเป็นส่วนตัว แต่รายการชื่อโดเมนที่เรียกใช้งานนั้นไม่เป็นความลับ
มีทางเลือกที่ตรงไปตรงมาสองทาง คือกำหนดให้ DNS ชี้ไปยังตัวแก้ไขสาธารณะ (DNS = 9.9.9.9) ซึ่งจะทำให้คำขอวิ่งผ่านอุโมงค์และออกไปจากเซิร์ฟเวอร์ของคุณ แม้ว่าตัวแก้ไขนั้นจะยังคงเห็นคำขอของคุณอยู่ หรือเรียกใช้งาน unbound หรือ dnsmasq โดยผูกไว้ที่ 10.8.0.1, ตั้งค่า DNS = 10.8.0.1 และเพิ่ม udp dport 53 iifname "wg0" accept เข้าไปใน input chain จากนั้นตั้งค่าบรรทัดดังกล่าวแล้วไม่ต้องสนใจตัวแก้ไขอีกต่อไป ซึ่งจะส่งผลให้ไม่มีการแก้ไขชื่อใดๆ ได้เลย
บนไคลเอนต์ Linux นั้น wg-quick จะใช้ DNS ผ่านทาง resolvconf หากไม่มีการตั้งค่าดังกล่าว คุณจะได้รับ resolvconf: command not found ให้ติดตั้ง openresolv หรือตั้งค่า PostUp = resolvectl dns %i 10.8.0.1 บนไคลเอนต์ที่ใช้ systemd-resolved
การเพิ่มและลบ peer โดยไม่ทำให้ tunnel หลุด
การรีสตาร์ทอินเทอร์เฟซเพื่อเพิ่มผู้ใช้จะทำให้ทุกคนที่เชื่อมต่ออยู่หลุดออกไป ให้ผนวกบล็อก [Peer] เข้าไปใน wg0.conf จากนั้นจึงโหลดชุด peer ใหม่โดยไม่ต้องปิดการเชื่อมต่อ
sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'wg-quick strip จะแสดงค่าคอนฟิกโดยไม่มีคีย์เฉพาะของ wg-quick (Address, DNS, PostUp) และ syncconf จะนำการเปลี่ยนแปลงไปใช้ในขณะที่เซสชันปัจจุบันยังคงทำงานอยู่ คำสั่งนี้จะอัปเดตเฉพาะ peer เท่านั้น หากมีการเปลี่ยนแปลง Address ยังคงจำเป็นต้องสั่ง down/up ใหม่ทั้งหมด หากต้องการเพิกถอนสิทธิ์ให้ใช้ sudo wg set wg0 peer <public key> remove จากนั้นให้ลบบล็อกดังกล่าวออกจากไฟล์ มิฉะนั้นค่าเดิมจะกลับมาอีกครั้งในการโหลดครั้งถัดไป
รูปแบบความล้มเหลวและข้อความที่คุณจะพบ
Handshake ไม่สำเร็จ wg show แสดงรายการ peer โดยไม่มี latest handshake และฝั่ง client จะบันทึก log ดังนี้:
Handshake for peer 1 (10.0.0.10:51820) did not complete after 5 seconds, retrying (try 2)ไม่มีข้อมูลส่งมาถึง หรือไม่มีข้อมูลใดถูกยอมรับ ให้ตรวจสอบตามลำดับดังนี้: พอร์ต UDP 51820 เปิดอยู่บน firewall ของ VPS และ บน network firewall ของผู้ให้บริการ (ซึ่งมักเป็นส่วนควบคุมแยกต่างหากในแผงควบคุมส่วนใหญ่) หรือไม่, ที่อยู่ Endpoint และพอร์ตถูกต้องหรือไม่, และมีการสลับกุญแจกันหรือไม่ กุญแจในบล็อก [Peer] ของ client จะต้องเป็น public key ของ server และในทางกลับกัน หากนำ private key หรือ public key ของ client เองมาใส่ จะทำให้เกิดอาการนี้โดยตรง sudo tcpdump -ni any udp port 51820 บน server จะแสดงให้เห็นว่ามีแพ็กเก็ตส่งมาถึงหรือไม่ โดยปกติ kernel module จะไม่บันทึก log ใดๆ ข้อความของ WireGuard จะปรากฏใน dmesg ก็ต่อเมื่อคุณเปิดใช้งาน dynamic debug (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control) แล้วเท่านั้น ซึ่งหากเปิดใช้งานแล้ว ความผิดพลาดของกุญแจจะแสดงผลเป็นการทิ้งแพ็กเก็ตเนื่องจาก invalid-MAC
Handshake สำเร็จ แต่ใช้งานอินเทอร์เน็ตไม่ได้ ping 10.8.0.1 ทำงานสำเร็จ แต่ ping 1.1.1.1 หมดเวลา (timeout): แสดงว่าขาดการตั้งค่า forwarding หรือ NAT ให้ตรวจสอบว่า sysctl net.ipv4.ip_forward มีค่าเป็น 1 จากนั้นให้สังเกตตัวนับ (counter) ขณะที่ client ทำการ ping โดยใช้ sudo nft list ruleset หรือ sudo iptables -t nat -L POSTROUTING -n -v หากตัวนับบนกฎ masquerade เป็นศูนย์ แสดงว่าชื่อ interface ขาออก (egress interface) ไม่ถูกต้อง หากตัวนับเพิ่มขึ้นเรื่อยๆ แต่ไม่มีการตอบกลับ แสดงว่าเป็นปัญหาที่นโยบายของ forward chain
ใช้งานอินเทอร์เน็ตได้ แต่แก้ชื่อโดเมน (DNS) ไม่ได้ ping 1.1.1.1 ทำงานสำเร็จ แต่ curl https://example.com ส่งค่ากลับเป็น Could not resolve host แสดงว่าบรรทัด DNS หายไป หรือระบุตัว resolver ที่ไม่สามารถเข้าถึงได้จากภายใน tunnel
เว็บไซต์ HTTPS บางแห่งค้าง SSH และ ping ใช้งานได้ปกติ แต่หน้าเว็บที่มีขนาดใหญ่โหลดไม่ขึ้น: นี่คือปัญหา path MTU เนื่องจาก tunnel มี overhead เพิ่มเติม และมีลิงก์บางจุดระหว่างทางทิ้งแพ็กเก็ตที่มีขนาดใหญ่เกินไปโดยไม่มีการส่งข้อความ ICMP กลับมา ให้ลดค่า MTU ในส่วน [Interface] ของ client โดยลองตั้งค่าเป็น 1420, 1380 หรือ 1280 หากการลดค่า MTU ช่วยแก้ปัญหาการค้างได้ แต่ความเร็วในการรับส่งข้อมูลยังไม่น่าพอใจ ให้เลิกเดาตัวเลขกลมๆ แล้วทำตามขั้นตอน การหาค่า path MTU ที่แท้จริงด้วยวิธี bisection และการทำ TCP MSS clamping ซึ่งจะช่วยคัดกรองสาเหตุที่ไม่ได้เกิดจาก tunnel ออกไปได้ด้วย
Interface ไม่ยอมเริ่มทำงาน Address already in use หมายความว่ามี process อื่นใช้งานพอร์ต UDP 51820 อยู่ Cannot find device wg0 หลังจากที่ up ล้มเหลว มักหมายความว่าไฟล์ config ถูกปฏิเสธ ให้ตรวจสอบ journalctl -u wg-quick@wg0 -n 50
การย้ายจาก Streisand หรือ OpenVPN
Streisand ไม่ได้รับการดูแลรักษาแล้วและ repository ถูกเก็บถาวร การรัน VPN บนระบบอัตโนมัติที่ถูกทิ้งร้างเป็นปัญหาด้านความปลอดภัยที่สะสมไปเรื่อยๆ ไม่สามารถทำการอัปเกรดแบบ in-place ได้ และ PKI ของ OpenVPN ก็ไม่สามารถแปลงรูปแบบได้ เนื่องจาก WireGuard ไม่มีใบรับรอง ไม่มี CA และไม่มีวันหมดอายุ ดังนั้นไคลเอนต์แต่ละเครื่องจึงต้องสร้างคู่กุญแจ (key pair) ใหม่ทั้งหมด
ให้ทำการย้ายแบบขนาน โดย WireGuard บน UDP 51820 สามารถทำงานร่วมกับ OpenVPN บนพอร์ต 1194 บนเซิร์ฟเวอร์เดียวกันได้ ให้ติดตั้ง wg0 แล้วย้ายไคลเอนต์ทีละเครื่อง จากนั้นจึงหยุดการทำงานของบริการเดิม รูปแบบการใช้งานชื่อผู้ใช้/รหัสผ่านและการเพิกถอนสิทธิ์ของ OpenVPN ไม่สามารถนำมาใช้กับ WireGuard ได้ หากคุณต้องการระบบบัญชีผู้ใช้หรือบันทึกการตรวจสอบ (audit trail) ให้สร้างเลเยอร์ดังกล่าวครอบทับบน WireGuard อีกชั้นหนึ่ง
การสำรองข้อมูล การอัปเกรด และข้อจำกัดเมื่อขยายระบบ
/etc/wireguard คือตัวเซิร์ฟเวอร์ ให้สำรองข้อมูลไว้ (sudo tar czf wg-backup.tgz -C /etc wireguard, โหมด 600, เก็บไว้ภายนอกเครื่อง) แล้วคุณจะสามารถกู้คืนระบบบน VPS เครื่องใหม่ได้ภายในไม่กี่นาที หากทำ private key ของเซิร์ฟเวอร์หาย คุณจะต้องออก config ให้ไคลเอนต์ใหม่ทั้งหมด เนื่องจากไคลเอนต์มีการทำ public key pinning ไว้ การอัปเกรดเป็นเพียงการรัน apt upgrade ตามปกติแล้วรีบูตหากมีการอัปเดต kernel และ wg-quick@wg0 จะกลับมาทำงานเองหากคุณเปิดใช้งานไว้
สถานะของแต่ละ peer มีขนาดเล็กและการเข้ารหัสทำงานในระดับ kernel ดังนั้นขีดจำกัดจึงอยู่ที่ CPU และ bandwidth ของ VPS ไม่ใช่ที่ตัว config นี้ ให้วัดประสิทธิภาพด้วย iperf3 ผ่านอุโมงค์แทนการเชื่อตัวเลขที่ระบุไว้ สิ่งที่กลายเป็นภาระเมื่อขยายระบบคือการดูแลรักษา ทุก peer ต้องการ IP สำหรับอุโมงค์ที่ไม่ซ้ำกัน และการแก้ไขบล็อก [Peer] จำนวน 60 ชุดด้วยมือมักทำให้เกิด AllowedIPs ซ้ำซ้อนโดยไม่ตั้งใจ ควรสร้าง config จากสคริปต์แทน เซิร์ฟเวอร์หนึ่งเครื่องคือหนึ่ง UDP endpoint และเป็นจุดเดียวที่อาจเกิดความล้มเหลว (single point of failure) และ WireGuard ไม่มีระบบ clustering: การทำ redundancy หมายถึงการมีเซิร์ฟเวอร์เครื่องที่สองพร้อมกุญแจของตัวเอง การหมุนเวียนกุญแจ (key rotation) ยังคงต้องทำด้วยมือ ดังนั้นควรจดบันทึกว่าใครถือกุญแจชุดไหนและจะเพิกถอนอย่างไร เมื่อการจดบันทึกเกินกว่าจะจัดการด้วยไฟล์ข้อความ คำตอบทั่วไปคือการใช้ control plane ครอบทับบน kernel data plane เดิม และ เซิร์ฟเวอร์ NetBird ที่โฮสต์เอง จะช่วยจัดการการจัดสรรที่อยู่ การกระจาย peer และ setup keys ที่คุณต้องทำด้วยมือ หากการรัน control plane เองเป็นภาระเกินไป Tailscale มีบริการโฮสต์ให้คุณ และ แผนฟรีรองรับผู้ใช้ 6 คนพร้อมอุปกรณ์ไม่จำกัด ซึ่งเพียงพอสำหรับผู้ใช้ส่วนใหญ่ หลังจากจุดนั้นไป ค่าใช้จ่ายจะคิดตามจำนวนคนไม่ใช่จำนวนเครื่อง ดังนั้น ค่าใช้จ่ายสำหรับครัวเรือนหรือทีมขนาดเล็ก จะขึ้นอยู่กับจำนวนผู้ใช้งานจริง ไม่ใช่จำนวน peer ที่คุณต้องคอยแก้ไขใน wg0.conf ในแง่นั้น การจัดการ AllowedIPs แบบ split-tunnel จะกลายเป็นการ ประกาศช่วง IP ภายในของคุณจาก subnet router ซึ่งประกาศเพียงครั้งเดียวจาก VPS เครื่องเดียวและอนุมัติจากศูนย์กลาง แทนการคัดลอกไปวางในไฟล์ของไคลเอนต์ทุกเครื่อง ความคุ้มค่าของการแลกเปลี่ยนนี้ขึ้นอยู่กับว่า control plane ที่โฮสต์ไว้เข้าถึงอะไรได้บ้าง และ มันไม่เคยถือครองกุญแจที่ใช้เข้ารหัสทราฟฟิกของคุณ แม้ว่ามันจะตัดสินใจว่า peer ใดจะรู้จักกันก็ตาม
ทั้งหมดนี้ต้องการเครื่อง Linux ที่คุณควบคุมได้, IP สาธารณะ, kernel ที่สามารถโหลดโมดูลได้ และ firewall ที่คุณจัดการได้เองทั้งหมด
FAQ
Why does the WireGuard handshake never complete?
wg show listing a peer with no latest handshake means packets are not arriving or not being accepted. Check UDP 51820 on both the VPS firewall and your provider's separate network firewall, confirm the Endpoint host and port, then check the keys are not crossed, the client's [Peer] block must hold the server's public key. sudo tcpdump -ni any udp port 51820 on the server shows whether packets arrive at all; dmesg only reports WireGuard's handshake failures after you enable dynamic debug (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control), and then a key mismatch appears as an invalid-MAC drop.
The tunnel connects but I have no internet. What is missing?
ping 10.8.0.1 working while ping 1.1.1.1 times out points at forwarding or NAT. Confirm sysctl net.ipv4.ip_forward reads 1 and that it is set in /etc/sysctl.d/, not just with a sysctl -w that dies at reboot. Then check the masquerade rule names your real egress interface from ip route show default, enp1s0 or ens3, rarely eth0.
Do I need the DNS = line in my client config?
With a full tunnel and no DNS = line, the client keeps the resolver it learned from the local network, and those queries leave in cleartext over the local link while everything else is tunnelled. Point DNS at a public resolver, or run unbound/dnsmasq bound to 10.8.0.1 and open udp dport 53 iifname "wg0" in the input chain.
What does AllowedIPs actually control?
It does two jobs. Outbound it is a routing table: traffic matching a peer's AllowedIPs is encrypted and sent to that peer. Inbound it is an access-control list: a decrypted packet whose source is outside that peer's AllowedIPs is dropped. That is why the server side lists a /32 per client while the client side may list 0.0.0.0/0.
Will WireGuard run on any VPS?
On a KVM VPS it works with the in-kernel module and no extra setup. On container virtualisation that shares the host kernel, such as OpenVZ or LXC, modprobe wireguard fails with Operation not supported and the fallback is the wireguard-go userspace implementation. Run sudo modprobe wireguard && echo ok before anything else.