ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

Home ติดตั้ง VPN ด้วย WireGuard บน Linux Server

ติดตั้ง VPN ด้วย WireGuard บน Linux Server

WireGuard เป็น VPN รุ่นใหม่ที่อยู่ในเคอร์เนล Linux ตั้งแต่เวอร์ชัน 5.6 ตั้งค่าง่ายกว่า OpenVPN มาก ไฟล์ตั้งค่าสั้น ใช้การเข้ารหัสสมัยใหม่ และเร็ว การยืนยันตัวตนใช้คู่กุญแจ (Public Key / Private Key) แบบเดียวกับ SSH Key ไม่มีรหัสผ่านให้เดา

การใช้งานที่พบบ่อยสำหรับผู้ดูแลเซิร์ฟเวอร์คือ สร้างเครือข่ายส่วนตัวระหว่างเครื่องของผู้ดูแลกับเซิร์ฟเวอร์ แล้วเปิดบริการที่ไม่ควรออกอินเทอร์เน็ต เช่น ฐานข้อมูล, Redis, หน้า Admin หรือ SSH ให้เข้าได้เฉพาะผ่าน VPN บทความนี้ตั้ง WireGuard Server บน Linux และเชื่อมเครื่องลูกข่ายหนึ่งเครื่องแบบ Split Tunnel (เฉพาะทราฟฟิกไปยังเครือข่าย VPN) และมีหัวข้อเสริมสำหรับ Full Tunnel หากคุณใช้ OpenVPN อยู่แล้ว ดู วิธีติดตั้ง VPN Server ด้วย OpenVPN

สิ่งที่ต้องเตรียม

  • เซิร์ฟเวอร์ Ubuntu 22.04/24.04 หรือ AlmaLinux/Rocky Linux 9 ที่มี Public IP (ตัวอย่างใช้ 203.0.113.10) และสิทธิ์ sudo
  • เครื่องลูกข่าย: Linux, Windows, macOS, iOS หรือ Android ที่ติดตั้งโปรแกรม WireGuard จาก wireguard.com/install
  • วางแผน IP ภายใน VPN ที่ไม่ชนกับเครือข่ายของสำนักงาน ตัวอย่างนี้ใช้ 10.8.0.0/24 โดยเซิร์ฟเวอร์เป็น 10.8.0.1 และลูกข่ายเครื่องแรกเป็น 10.8.0.2
  • พอร์ต UDP สำหรับ WireGuard ตัวอย่างใช้ 51820

ขั้นตอนที่ 1: ติดตั้ง WireGuard บนเซิร์ฟเวอร์

# Ubuntu
sudo apt update
sudo apt install -y wireguard

# AlmaLinux / Rocky Linux 9
sudo dnf install -y wireguard-tools

บน AlmaLinux/Rocky 9 โมดูล WireGuard มากับเคอร์เนลแล้ว Red Hat ระบุสถานะ WireGuard ไว้เป็น Technology Preview จึงควรทดสอบให้มั่นใจก่อนใช้กับงานสำคัญ ตรวจว่าโหลดโมดูลได้ด้วย sudo modprobe wireguard && lsmod | grep wireguard

ขั้นตอนที่ 2: สร้างคู่กุญแจของเซิร์ฟเวอร์

sudo -i
cd /etc/wireguard
umask 077
wg genkey | tee server.key | wg pubkey > server.pub
cat server.pub
exit

umask 077 ทำให้ไฟล์ที่สร้างอ่านได้เฉพาะ root server.key คือ Private Key ห้ามคัดลอกออกจากเครื่อง ส่วน server.pub คือ Public Key ที่จะใส่ในเครื่องลูกข่าย

ขั้นตอนที่ 3: สร้างคู่กุญแจของลูกข่าย

วิธีที่ปลอดภัยที่สุดคือสร้างกุญแจบนเครื่องลูกข่ายเอง โปรแกรม WireGuard บน Windows, macOS และมือถือจะสร้าง Private Key ให้อัตโนมัติเมื่อกด Add empty tunnel และแสดง Public Key ให้คัดลอก ถ้าลูกข่ายเป็น Linux ใช้คำสั่งเดียวกับขั้นตอนที่ 2 แล้วเก็บชื่อไฟล์เป็น client1.key และ client1.pub

ขั้นตอนที่ 4: เขียนไฟล์ตั้งค่าเซิร์ฟเวอร์

sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = ใส่เนื้อหาของ server.key

[Peer]
# client1: โน้ตบุ๊กผู้ดูแลระบบ
PublicKey = ใส่ Public Key ของ client1
AllowedIPs = 10.8.0.2/32

AllowedIPs ฝั่งเซิร์ฟเวอร์มีสองความหมายพร้อมกัน คือ แพ็กเก็ตจาก Peer นี้ต้องมาจาก IP นี้เท่านั้น และแพ็กเก็ตที่ส่งไปยัง IP นี้จะถูกส่งผ่าน Peer นี้ แต่ละ Peer จึงต้องมี IP ไม่ซ้ำกัน และใช้ /32

sudo chmod 600 /etc/wireguard/wg0.conf

ขั้นตอนที่ 5: เปิด Firewall และเริ่ม Service

# Ubuntu (UFW)
sudo ufw allow 51820/udp

# AlmaLinux / Rocky Linux (firewalld)
sudo firewall-cmd --permanent --add-port=51820/udp
sudo firewall-cmd --reload

หากเซิร์ฟเวอร์มี Security Group หรือ Firewall ภายนอกจากฝั่งผู้ให้บริการ ให้เปิดพอร์ต UDP 51820 เพิ่มด้วย จากนั้นเริ่ม Interface และตั้งให้เริ่มเมื่อบูต:

sudo systemctl enable --now wg-quick@wg0
sudo wg show

ผลลัพธ์ควรแสดง interface: wg0, listening port: 51820 และ Peer ที่ใส่ไว้

ขั้นตอนที่ 6: ตั้งค่าเครื่องลูกข่าย

ในโปรแกรม WireGuard ของลูกข่าย แก้ไข Tunnel ให้เป็นดังนี้ (บน Linux บันทึกเป็น /etc/wireguard/wg0.conf ของเครื่องลูกข่าย):

[Interface]
PrivateKey = Private Key ของ client1 (โปรแกรมใส่ให้แล้ว)
Address = 10.8.0.2/32

[Peer]
PublicKey = ใส่เนื้อหาของ server.pub
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25
  • AllowedIPs = 10.8.0.0/24 ฝั่งลูกข่าย คือ Split Tunnel ส่งเฉพาะทราฟฟิกที่ไปยังเครือข่าย VPN ผ่านอุโมงค์ ส่วนการท่องเว็บทั่วไปยังออกทางอินเทอร์เน็ตปกติ
  • PersistentKeepalive = 25 ส่งแพ็กเก็ตทุก 25 วินาทีเพื่อไม่ให้ Router หรือ NAT ของสำนักงานตัดการเชื่อมต่อที่เงียบไป

กด Activate บนโปรแกรม หรือบน Linux ใช้ sudo wg-quick up wg0

ตรวจสอบผลลัพธ์

จากเครื่องลูกข่าย:

ping 10.8.0.1

บนเซิร์ฟเวอร์:

sudo wg show

ควรเห็นบรรทัด latest handshake: ... seconds ago และตัวเลข transfer ทั้งรับและส่งเพิ่มขึ้น ถ้าไม่มีบรรทัด handshake เลย แปลว่าแพ็กเก็ตยังไม่ถึงกันหรือกุญแจไม่ตรง

ใช้ VPN ป้องกันบริการภายใน

เมื่อ VPN ทำงาน คุณสามารถจำกัดบริการให้รับเฉพาะเครือข่าย VPN ได้ ตัวอย่างการอนุญาต SSH เฉพาะจาก VPN ด้วย UFW:

sudo ufw allow in on wg0 to any port 22 proto tcp

ก่อนลบกฎที่อนุญาต SSH จากอินเทอร์เน็ต ให้เปิด SSH Session เดิมค้างไว้ แล้วทดสอบเข้าผ่าน VPN ด้วยหน้าต่างใหม่ (ssh ผู้ใช้@10.8.0.1) ให้สำเร็จก่อน และควรมีช่องทาง Console สำรองเสมอ เพราะถ้า VPN มีปัญหา คุณจะเข้า SSH ไม่ได้เลย บริการอย่าง Redis หรือ MySQL สามารถ Bind ที่ 10.8.0.1 เพิ่มจาก 127.0.0.1 ได้ (ดู เปิดให้เชื่อมต่อ MySQL/MariaDB จากภายนอกอย่างปลอดภัย)

เพิ่ม Peer ใหม่โดยไม่ตัดการเชื่อมต่อเดิม

เพิ่มบล็อก [Peer] ใหม่ใน /etc/wireguard/wg0.conf ด้วย IP ถัดไป เช่น 10.8.0.3/32 แล้วโหลดค่าใหม่โดยไม่ต้องหยุด Interface:

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'

ทางเลือก: Full Tunnel ให้ทราฟฟิกทั้งหมดออกผ่านเซิร์ฟเวอร์

ถ้าต้องการให้ลูกข่ายออกอินเทอร์เน็ตด้วย IP ของเซิร์ฟเวอร์ (เช่น เพื่อเข้าระบบที่ Whitelist IP ไว้) ต้องเปิด IP Forwarding และ NAT บนเซิร์ฟเวอร์ ตรวจชื่อ Network Interface หลักก่อนด้วย ip route | grep default (ตัวอย่างใช้ eth0)

echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

บน Ubuntu เพิ่มบรรทัดนี้ในส่วน [Interface] ของเซิร์ฟเวอร์ (แก้ eth0 ให้ตรงกับเครื่องของคุณ) แล้วรีสตาร์ตด้วย sudo systemctl restart wg-quick@wg0:

PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

ถ้าเปิด UFW อยู่ด้วย UFW จะบล็อกการ Forward ตามค่าเริ่มต้น ให้อนุญาตเพิ่มด้วย sudo ufw route allow in on wg0 out on eth0 บน AlmaLinux/Rocky ที่ใช้ firewalld ให้ใช้ Masquerade ของ firewalld แทน PostUp:

sudo firewall-cmd --permanent --zone=public --add-masquerade
sudo firewall-cmd --permanent --zone=trusted --add-interface=wg0
sudo firewall-cmd --reload

การใส่ wg0 ในโซน trusted ทำให้ลูกข่าย VPN เข้าถึงทุกบริการบนเซิร์ฟเวอร์ได้ ถ้าต้องการจำกัด ให้สร้างโซนแยกสำหรับ wg0 แทน จากนั้นแก้ AllowedIPs = 0.0.0.0/0 และเพิ่ม DNS = 1.1.1.1 (หรือ DNS ที่องค์กรใช้) ในส่วน [Interface] ของลูกข่าย

ปัญหาที่พบบ่อย

ไม่มี latest handshake เลย

ตรวจตามลำดับ: พอร์ต UDP 51820 เปิดทั้ง Firewall ในเครื่องและภายนอกหรือยัง, Endpoint ถูก IP และพอร์ตหรือไม่, และ Public Key ที่ใส่สลับกันถูกฝั่งหรือไม่ (เซิร์ฟเวอร์ใส่ Public Key ของลูกข่าย ลูกข่ายใส่ Public Key ของเซิร์ฟเวอร์) เครือข่ายบางแห่งบล็อก UDP ขาออก ให้ลองจากเครือข่ายมือถือเพื่อเทียบ

Handshake สำเร็จ แต่ ping ไม่ได้

มักเป็นเรื่อง AllowedIPs ไม่ครอบคลุม IP ที่ใช้ หรือ Firewall บนเซิร์ฟเวอร์บล็อกทราฟฟิกที่เข้ามาทาง wg0 ทดสอบด้วย sudo ufw allow in on wg0 ชั่วคราว

Full Tunnel เชื่อมต่อได้แต่ออกเว็บไม่ได้

ยังไม่ได้เปิด ip_forward, ชื่อ Interface ในกฎ NAT ไม่ตรงกับเครื่อง หรือ UFW บล็อกการ Forward ตรวจด้วย sysctl net.ipv4.ip_forward ต้องได้ 1

wg-quick แจ้ง resolvconf: command not found บน Ubuntu

เกิดเมื่อใส่ DNS = ในไฟล์ของลูกข่ายที่เป็น Ubuntu ติดตั้งด้วย sudo apt install -y openresolv หรือลบบรรทัด DNS ออกถ้าไม่ต้องการเปลี่ยน DNS

หากต้องการออกแบบเครือข่าย VPN ระหว่างหลายเซิร์ฟเวอร์หรือหลายสาขา ติดต่อทีมซัพพอร์ต THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security