Dựng WireGuard server trên OpenWrt bằng UCI và kiểm tra tunnel
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 packagesopkg updateopkg install wireguard-tools# Configuration parametersVPN_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 keysumask go=wg genkey | tee wgserver.key | wg pubkey > wgserver.pubwg genkey | tee wgclient.key | wg pubkey > wgclient.pubwg genpsk > wgclient.psk# Server private keyVPN_KEY="$(cat wgserver.key)"# Pre-shared keyVPN_PSK="$(cat wgclient.psk)"# Client public keyVPN_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 firewalluci 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.wguci 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 firewallservice 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 networkuci -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 peersuci -q delete network.wgclientuci 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 networkservice 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.orgtraceroute6 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 servicesservice log restart; service network restart; sleep 10# Log and statuslogread -e vpn; netstat -l -n -p | grep -e "^udp\s.*\s-$"# Runtime configurationpgrep -f -a wg; wg show; wg showconf vpnip address show; ip route show table allip rule show; ip -6 rule show; nft list ruleset# Persistent configurationuci 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
Footnotes
-
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. ↩ ↩2 ↩3
Bình Luận & Thảo Luận
Góp ý, hỏi đáp và chia sẻ suy nghĩ của bạn