Dựng WireGuard server trên OpenWrt bằng UCI và kiểm tra tunnel
MỤC LỤC BÀI VIẾT (Nhấn để xem)
WireGuard server trên OpenWrt có ba ranh giới mình phải giữ rõ: key của server/client, firewall cho UDP listen port và interface VPN nằm trong zone nào. Bài dưới dùng chính tên/địa chỉ của mẫu nguồn; private key, PSK và password chỉ được sinh trên máy thật, không ghi vào Markdown.1
Mục tiêu và giả định
Nguồn hướng tới VPN mã hóa, truy cập LAN từ xa, split/full tunnel và tránh leak ở client. Mình giả định router đã có WAN hoạt động, client có thể tạo key, và đã chuẩn bị đường port-forward UDP từ Internet vào VPN_PORT nếu router nằm sau modem. Bài này không thay thế phần cấu hình client; sau khi server xong, đối chiếu thêm tài liệu WireGuard client/extras.
1. Preparation
Cài package và đặt tham số. VPN_IF, VPN_PORT, IPv4 /24 và ULA IPv6 /64 là đúng chuỗi của nguồn; nếu đổi thì đổi nhất quán ở firewall, network và client:1
# Install packages
opkg update
opkg install wireguard-tools
# Configuration parameters
VPN_IF="vpn"
VPN_PORT="51820"
VPN_ADDR="192.168.9.1/24"
VPN_ADDR6="fd00:9::1/64"
2. Key management
Tạo private/public key của server và client cùng PSK. Các file wgserver.key, wgserver.pub, wgclient.key, wgclient.pub, wgclient.psk phải được lưu ngoài repo với permission chặt; chỉ public key mới được đưa sang peer kia.
# Generate keys
umask go=
wg genkey | tee wgserver.key | wg pubkey > wgserver.pub
wg genkey | tee wgclient.key | wg pubkey > wgclient.pub
wg genpsk > wgclient.psk
# Server private key
VPN_KEY="$(cat wgserver.key)"
# Pre-shared key
VPN_PSK="$(cat wgclient.psk)"
# Client public key
VPN_PUB="$(cat wgclient.pub)"
umask go= là chuỗi lệnh được giữ nguyên từ nguồn; mình kiểm tra shell/release thực tế trước khi chạy. Không dán giá trị private key hoặc PSK vào log, chat hay Git.
3. Firewall
Nguồn đưa interface VPN vào LAN zone để giảm số rule nội bộ, rồi mở UDP VPN_PORT từ WAN:
# Configure firewall
uci rename firewall.@zone[0]="lan"
uci rename firewall.@zone[1]="wan"
uci del_list firewall.lan.network="${VPN_IF}"
uci add_list firewall.lan.network="${VPN_IF}"
uci -q delete firewall.wg
uci set firewall.wg="rule"
uci set firewall.wg.name="Allow-WireGuard"
uci set firewall.wg.src="wan"
uci set firewall.wg.dest_port="${VPN_PORT}"
uci set firewall.wg.proto="udp"
uci set firewall.wg.target="ACCEPT"
uci commit firewall
service firewall restart
Đây là lựa chọn policy, không phải mặc định an toàn cho mọi LAN. Nếu VPN client chỉ cần một VLAN/service, mình tạo zone riêng và forward tối thiểu thay vì cho toàn bộ VPN vào LAN.
4. Network và peer
Tạo interface WireGuard với private key/listen port/addresses, sau đó thêm client peer với public key, PSK và allowed IP /32 + /128 của client:1
# Configure network
uci -q delete network.${VPN_IF}
uci set network.${VPN_IF}="interface"
uci set network.${VPN_IF}.proto="wireguard"
uci set network.${VPN_IF}.private_key="${VPN_KEY}"
uci set network.${VPN_IF}.listen_port="${VPN_PORT}"
uci add_list network.${VPN_IF}.addresses="${VPN_ADDR}"
uci add_list network.${VPN_IF}.addresses="${VPN_ADDR6}"
# Add VPN peers
uci -q delete network.wgclient
uci set network.wgclient="wireguard_${VPN_IF}"
uci set network.wgclient.public_key="${VPN_PUB}"
uci set network.wgclient.preshared_key="${VPN_PSK}"
uci add_list network.wgclient.allowed_ips="${VPN_ADDR%.*}.2/32"
uci add_list network.wgclient.allowed_ips="${VPN_ADDR6%:*}:2/128"
uci commit network
service network restart
Ở code trên, ${VPN_ADDR%.*}.2/32 và ${VPN_ADDR6%:*}:2/128 là phép suy ra địa chỉ client từ biến server. Mình xác nhận kết quả thực tế bằng uci show network trước khi restart.
Testing
Kiểm tra cả IPv4 và IPv6 bằng traceroute:
traceroute openwrt.org
traceroute6 openwrt.org
Sau khi client handshake, kiểm tra log, cổng UDP, runtime WireGuard, bảng route/rule, nftables và cấu hình lưu trong UCI:
# Restart services
service log restart; service network restart; sleep 10
# Log and status
logread -e vpn; netstat -l -n -p | grep -e "^udp\s.*\s-$"
# Runtime configuration
pgrep -f -a wg; wg show; wg showconf vpn
ip address show; ip route show table all
ip rule show; ip -6 rule show; nft list ruleset
# Persistent configuration
uci show network; uci show firewall; crontab -l
Troubleshooting
Nếu không handshake, kiểm tra lần lượt public key của peer, PSK, endpoint/port-forward UDP, listen port, clock, allowed_ips và firewall. Nếu handshake có nhưng không đi LAN, kiểm tra zone/forwarding, địa chỉ 192.168.9.0/24, route IPv6 và nft list ruleset. Nếu full tunnel làm mất truy cập endpoint, phải có route ngoại lệ tới endpoint trước khi ép default route.
Kiểm tra an toàn và rollback
Chụp uci show network và uci show firewall trước thay đổi. Khi rollback, xóa đúng network.vpn, network.wgclient và rule firewall do bài tạo, commit rồi restart; không xóa nhầm zone đang phục vụ WAN/LAN. Private key bị lộ phải tạo key mới và cập nhật toàn bộ peer.
Nguồn
https://openwrt.org/docs/guide-user/services/vpn/wireguard/server — OpenWrt Wiki – WireGuard server. Cập nhật: 2023-11-05; key/PSK được sinh cục bộ khi triển khai. ↩︎ ↩︎ ↩︎
OpenWRT
- Chia sẻ ổ USB qua Samba trên OpenWrt: cấu hình, firewall và xử lý lỗi
- DNS over TLS trên OpenWrt với Unbound: cấu hình và kiểm tra rò rỉ DNS
- Dùng USB làm bộ nhớ ngoài cho OpenWrt: driver, phân vùng và automount
- LuCI essentials trên OpenWrt: cài đặt, HTTPS, port thay thế và offline
- Sao lưu và khôi phục cấu hình OpenWrt bằng LuCI và SSH
Bình luận & Thảo luận 0
Chia sẻ thắc mắc, phản hồi hoặc kinh nghiệm thực chiến của bạn