Các bài viết về cách thiết lập WireGuard VPN bằng Docker trước đây của mình như wg-easy, wirehole-ui đều dùng cho mục đích tạo WireGuard VPN Server. Rồi sau đó sẽ dùng WireGuard client trên Windows, Linux hay iOS để kết nối vào WireGuard VPN Server.
Bài viết này mình sẽ hướng dẫn cách thiết lập WireGuard client trên máy chủ Linux sử dụng Docker và chuyển hướng kết nối mạng của máy chủ đi qua WireGuard VPN.
Mục Lục
I. Yêu cầu chuẩn bị
- Một máy chủ đã được cài đặt sẵn Docker và Docker Compose.
- Một máy chủ đã được thiết lập sẵn WireGuard VPN Server: có thể sử dụng wg-easy hoặc Wirehole-UI để thiết lập.
- File cấu hình WireGuard client được tạo ra bởi WireGuard Server, có dạng như dưới đây
[Interface]
PrivateKey = sO7U9OS0s5vxxxdfY1aNHzVYXpJhKAaU/HG9MyfaWU=
Address = 10.6.0.8/24
DNS = 10.2.0.100
[Peer]
PublicKey = 9NknLwkQRaxxxsfNr9wKIC15KsqRvN5eOwUZxuhDFWI=
PresharedKey = xhqj9bnxxxuuFtzbVJ5GJPD6D4YAMHdk6RbL5JVkT+M=
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 0
Endpoint = 222.222.96.107:51822
Code language: YAML (yaml)
II. Chuyển hướng mạng của máy chủ đi qua WireGuard VPN
Thứ tự công việc cần làm:
- Thiết lập WireGuard client sử dụng image WireGuard của Linuxserver
- Chỉnh sửa Routing Table để điều hướng mạng đi qua IP của WireGuard client container.
In order to route via routing tables, we’ll use the container’s IP address, therefore it is best that it has a static IP in a defined subnet. Let’s first make sure we create a docker bridge network called wgnet
with a defined subnet via the following command:
1. Tạo Docker network
Để có thể điều hướng mạng bằng routing table, container Wireguard client cần sử dụng IP tĩnh để tránh rắc rối về sau. Mình sẽ tạo 1 mạng docker bridge mới với tên gọi wgnet
bằng lệnh
docker network create --subnet 172.30.0.0/24 wgnet
Code language: YAML (yaml)
Kiểm tra lại thông số của wgnet
bằng lệnh docker inspect wgnet
[
{
"Name": "wgnet",
"Id": "395281362a007244f03d8b8008a12c55ecea141410143d970376029564d5a02c",
"Created": "2022-09-28T21:40:39.761479649+07:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.30.0.0/24"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
Code language: JSON / JSON with Comments (json)
Kiểm tra Routing Table hiện tại bằng lệnh ip route show
default via 192.168.0.1 dev ens18
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-3e6bd5841382 proto kernel scope link src 172.18.0.1
172.20.0.0/16 dev br-aadab51557e3 proto kernel scope link src 172.20.0.1
172.22.0.0/16 dev br-31493810cb58 proto kernel scope link src 172.22.0.1
172.24.0.0/16 dev br-e6e5decbac26 proto kernel scope link src 172.24.0.1
172.30.0.0/24 dev br-395281362a00 proto kernel scope link src 172.30.0.1 linkdown
192.168.0.0/24 dev ens18 proto kernel scope link src 192.168.0.138
Code language: YAML (yaml)
Có thể thấy mạng 172.30.0.0/24
đã được tạo và hiện ra trong routing table của máy chủ. Tuy nhiên nó đang có trạng thái linkdown
vì chưa có container nào kết nối vào mạng này.
Hiện tại tất cả kết nối ra Internet đều được điều hướng qua LAN gateway 192.168.0.1
, được cấu hình qua mục default via 192.168.0.1 dev ens18
Chúng ta cần phải chỉnh sửa lại routing table này sau khi đã thiết lập thành công Wireguard container, để cho kết nối mạng sẽ đi qua WireGuard chứ không phải qua LAN Gateway.
2. Tạo file cấu hình wg0.conf
Trong bài này mình sẽ lấy file cấu hình từ Wireguad VPN Server được thiết lập bằng Wirehole-UI. Truy cập vào dashboard của wg-easy, tạo client mới và tải file cấu hình về, có nội dung tương tự như dưới đây
[Interface]
PrivateKey = sO7U9OS0s5vxxxdfY1aNHzVYXpJhKAaU/HG9MyfaWU=
Address = 10.6.0.8/24
DNS = 10.2.0.100
[Peer]
PublicKey = 9NknLwkQRaxxxsfNr9wKIC15KsqRvN5eOwUZxuhDFWI=
PresharedKey = xhqj9bnxxxuuFtzbVJ5GJPD6D4YAMHdk6RbL5JVkT+M=
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 0
Endpoint = 222.222.96.107:51822
Code language: YAML (yaml)
Với cấu hình này, một đường truyền tunnel sẽ được tạo ra và tất cả kết nố bên trong WireGuard container sẽ đi qua tunnel này. Tuy nhiên, chúng ta muốn còn kết nối của máy chủ, nằm ngoài container đi qua Wireguard Tunnel. Do đó, cần phải cấu hình NAT để kết nối đi đúng hướng bằng lệnh sau:
iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
Code language: Nginx (nginx)
Để thiết lập tự động, mình sẽ dùng thông số PostUp
và PreDown
trong file cấu hình của WireGuard.
- PostUp: lệnh sẽ chạy sau khi WireGuard tunnel được tạo.
- PostDown: lệnh sẽ chạy trước khi WireGuard tunnel bị hủy.
PostUp = iptables -t nat -A POSTROUTING -o wg+ -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -o wg+ -j MASQUERADE
Code language: Nginx (nginx)
Lưu lại cấu hình cuối cùng trong thư mục /home/thuanbui/wireguad-client/config/wg0.conf
mkdir -p /home/thuanbui/wireguard-client/config
nano /home/thuanbui/wireguard-client/config/wg0.conf
Code language: Nginx (nginx)
Nhập vào nội dung sau và lưu lại
[Interface]
PrivateKey = sO7U9OS0s5vxxxdfY1aNHzVYXpJhKAaU/HG9MyfaWU=
Address = 10.6.0.8/24
DNS = 10.2.0.100
PostUp = iptables -t nat -A POSTROUTING -o wg+ -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -o wg+ -j MASQUERADE
[Peer]
PublicKey = 9NknLwkQRaxxxsfNr9wKIC15KsqRvN5eOwUZxuhDFWI=
PresharedKey = xhqj9bnxxxuuFtzbVJ5GJPD6D4YAMHdk6RbL5JVkT+M=
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 0
Endpoint = 222.222.96.107:51822
Code language: YAML (yaml)
3. Tạo Wireguard client container
Tạo file docker-compose.yml
để thiết lập Wireguard Client
cd /home/thuanbui/wireguard-client
nano docker-compose.yml
Code language: Bash (bash)
Nhập vào nội dung sau
services:
wireguard:
image: lscr.io/linuxserver/wireguard
container_name: wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Ho_Chi_Minh
volumes:
- ./config:/config
- /lib/modules:/lib/modules
networks:
default:
ipv4_address: 172.30.0.50
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
restart: unless-stopped
networks:
default:
name: wgnet
external: true
Code language: YAML (yaml)
Các thông số cần chú ý:
- Phần
networks
được cấu hình để WireGuard container kết nối vào Docker netwokwgnet
đã tạo trước đó. - Dòng 17: cấu hình IP tĩnh cho container
172.30.0.50
Kích hoạt Docker container bằng lệnh docker-compose up -d
.
Để bảo đảm WireGuard Tunnel đã được tạo thành công, kiểm tra lại logs bằng lệnh docker logs wireguard
. Nếu thấy nó kết thúc với nội dung như dưới đây nghĩa là Tunnel đã được tạo thành công
s6-rc: info: service 99-ci-service-check successfully started
Warning: `/config/wg0.conf' is world accessible
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.6.0.8/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] resolvconf -a wg0 -m 0 -x
[#] wg set wg0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
sysctl: setting key "net.ipv4.conf.all.src_valid_mark", ignoring: Read-only file system
[#] iptables-restore -n
[#] iptables -t nat -A POSTROUTING -o wg+ -j MASQUERADE
Code language: YAML (yaml)
Nếu trong logs hiện ra lỗi như dưới đây, bạn cần chỉnh sửa lại dòng AllowedIPs
trong file wg0.conf, xóa ::/0
và chỉ chừa lại 0.0.0.0/0
. Sau đó khởi động lại container.
Error: IPv6 is disabled on nexthop device.
[#] resolvconf -d wg0 -f
[#] ip link delete dev wg0
Code language: Python (python)
Kiểm tra lại routing table bằng lệnh ip route show
default via 192.168.0.1 dev ens18
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-3e6bd5841382 proto kernel scope link src 172.18.0.1
172.20.0.0/16 dev br-aadab51557e3 proto kernel scope link src 172.20.0.1
172.22.0.0/16 dev br-31493810cb58 proto kernel scope link src 172.22.0.1
172.24.0.0/16 dev br-e6e5decbac26 proto kernel scope link src 172.24.0.1
172.30.0.0/24 dev br-395281362a00 proto kernel scope link src 172.30.0.1
192.168.0.0/24 dev ens18 proto kernel scope link src 192.168.0.138
Code language: YAML (yaml)
Có thể thấy mạng 172.130.0.0/24
giờ đã được kích hoạt vì đã có WireGuard kết nối vào, không còn trạng thái linkdown nữa.
Tuy nhiên lúc này, kết nối ra ngoài của máy chủ vẫn chưa chạy qua WireGuard Tunnel, kiểm tra bằng lệnh curl ifconfig.me
.
115.xxx.xxx.xx
Code language: CSS (css)
Kết quả trả về là Public IP của máy chủ nghĩa là kết nối vẫn chưa đi qua WireGuard tunnel.
4. Chỉnh sửa routing table
Sử dụng lệnh sau để chỉnh sửa lại Routing table
sudo ip route del default
sudo ip route add 222.222.96.107 via 192.168.0.1
sudo ip route add default via 172.30.0.50
Code language: CSS (css)
- Dòng 1: xóa routing mặc định
- Dòng 2:
222.222.96.107
là IP của WireGuard VPN, cần phải được đi qua LAN Gateway để tránh bị vòng lặp - Dòng 3: tạo routing mặc định cho mọi kết nối đi qua IP của WireGuard container
172.30.0.50
Kiểm tra lại ip route show
sẽ thấy kết nối ra ngoài được điều hướng đi qua 172.30.0.50
default via 172.30.0.50 dev br-395281362a00
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-3e6bd5841382 proto kernel scope link src 172.18.0.1
172.20.0.0/16 dev br-aadab51557e3 proto kernel scope link src 172.20.0.1
172.22.0.0/16 dev br-31493810cb58 proto kernel scope link src 172.22.0.1
172.24.0.0/16 dev br-e6e5decbac26 proto kernel scope link src 172.24.0.1
172.30.0.0/24 dev br-395281362a00 proto kernel scope link src 172.30.0.1
192.168.0.0/24 dev ens18 proto kernel scope link src 192.168.0.138
222.222.96.107 via 192.168.0.1 dev ens18
Code language: YAML (yaml)
Kiểm tra lại IP của máy chủ bằng lệnh curl ifconfig.me
222.222.96.107
Code language: CSS (css)
Kết quả trả về bây giờ là IP của WireGuard Server. Nghĩa là chúng ta đã cấu hình thành công cho kết nối của máy chủ đi qua WireGuard Tunnel. Hura!
5. Thiết lập System Service
Routing table của máy chủ sẽ quay lại mặc định mỗi khi khởi động lại máy, khiến cho các thông số vừa mới chỉnh không còn hiệu lực. Để cấu hình cho kết nối mạng của máy chủ luôn luôn đi qua WireGuard Tunnel, chúng ta sẽ tạo 1 system service để nó tự động chỉnh sửa routing table mỗi khi khởi động
sudo nano /lib/systemd/system/iproute.service
Code language: Nginx (nginx)
Nhập vào nội dung sau
[Unit]
Description=Route everything through WireGuard
After=docker.service
[Service]
Type=oneshot
Restart=on-failure
ExecStart=ip route del default
ExecStart=ip route add 222.222.96.107 via 192.168.0.1
ExecStart=ip route add default via 172.30.0.50
[Install]
WantedBy=multi-user.target
Code language: YAML (yaml)
Kích hoạt service
sudo systemctl enable iproute.service
Code language: Bash (bash)
Vậy là xong. Máy chủ sẽ luôn tự động kết nối thông qua WireGuard Tunnel mỗi khi khởi động lại.
Chúc bạn thực hiện thành công!
Nguồn tham khảo: https://www.linuxserver.io/blog/routing-docker-host-and-container-traffic-through-wireguard
[convertkit form=7087807]
Cái này cái lên Nas synology được không anh? Để Nas thành client chạy wireguard.
Mình chưa có điều kiện dùng qua Synology nên không rành nhé. Lo ngại ở cái phần Routing không biết nó có thực hiện được hay không. Nếu bạn làm được thì chia sẻ nhé.
Cho mình hỏi là nếu mình lấy file conf từ dịch vụ vpn của mullvad thì phần cấu hình file conf ở bước thứ 2 sẽ như thế nào bạn.
Cám ơn bạn!
Nếu đã có file conf của mullvad thì bạn đổi tên nó thành wg0.conf và lưu lại, sau đó thao tác tiếp.
Bạn có thể hướng dẫn xray + wire guard ko?
CẢM ƠN
E có một cái VPS làm VPN Server (wireguard), a có thể hướng dẫn em sử dụng Xpenology làm Wireguard Client để kết nối tới VPN server trên con VPS được ko ạ