Skip to content
Thuan Bui's Blog
Go back

Kết nối dây chuyền 2 mạng Wireguard để chuyển hướng mạng sử dụng Docker

Updated:

Mới đây, mình nhận được 1 yêu cầu hướng dẫn cách cấu hình kết nối dây chuyền 2 mạng Wireguard với nhau để chuyển hướng mạng gián tiếp. Mô hình hoạt động sẽ như hình minh hoạ dưới đây:

Sau khi nghiên cứu, mình đã tìm ra được cách thiết lập chuyển hướng dây chuyền 2 mạng Wireguard để chia sẻ trong bài viết hôm nay.

Bài viết này được dựa trên 2 bài viết mình đã chia sẻ trước đây về Wireguard Docker

I. Yêu cầu chuẩn bị

[Interface]
PrivateKey = sO7U9OS0s5vxxxdfY1aNHzVYXpJhKAaU/HG9MyfaWU=
Address = 10.9.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = 9NknLwkQRaxxxsfNr9wKIC15KsqRvN5eOwUZxuhDFWI=
PresharedKey = xhqj9bnxxxuuFtzbVJ5GJPD6D4YAMHdk6RbL5JVkT+M=
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Endpoint = 252.222.96.107:51822

II. Tạo Wireguard Server (VPS B)

Tạo Wireguard Server trên VPS B theo hướng dẫn ở đây

https://thuanbui.me/wg-easy-wireguard-vpn-server-web-ui/

III. Tạo Docker network (VPS A)

Để 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

Terminal window
docker network create --subnet 10.10.0.0/24 wgnet

Kiểm tra lại thông số của wgnet bằng lệnh docker inspect wgnet

[
{
"Name": "wgnet",
"Id": "3776c37e5afbac33ccb583122a0d86aade3714c551c6d1770db906e4e54652b0",
"Created": 2023-07-22,
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "10.10.0.0/24",
"Gateway": "10.10.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]

IV. Cấu hình WireGuard server (VPS A)

Tạo Wireguard Server trên VPS A cũng dùng wg-easy tương tự như trên VPS B. Tuy nhiên, cần chú ý thay đổi thông số WG_DEFAULT_ADDRESS khác với subnet đã sử dụng trên VPS B.

Ví dụ:

Nếu hai subnet trùng nhau sẽ khiến phần cấu hình routing table ở phần sau gặp lỗi.

Ngoài ra, cần phải cấu hình cho container này kết nối vào network wgnet bằng cách thêm vào các dòng sau

networks:
default:
name: wgnet
external: true

File docker-compose.yml trên VPS A sẽ tương tự như sau

version: "3.8"
services:
wg-easy:
environment:
# ⚠️ Required:
# Change this to your host's public address
- WG_HOST=22.22.22.22
# Optional:
- PASSWORD=10h30
- WG_PORT=51820
- WG_DEFAULT_ADDRESS=10.8.0.x
# - WG_DEFAULT_DNS=1.1.1.1
# - WG_MTU=1420
# - WG_ALLOWED_IPS=192.168.15.0/24, 10.0.1.0/24
# - WG_PRE_UP=echo "Pre Up" > /etc/wireguard/pre-up.txt
# - WG_POST_UP=echo "Post Up" > /etc/wireguard/post-up.txt
# - WG_PRE_DOWN=echo "Pre Down" > /etc/wireguard/pre-down.txt
# - WG_POST_DOWN=echo "Post Down" > /etc/wireguard/post-down.txt
image: weejewel/wg-easy
container_name: wireguard-server
volumes:
- .:/etc/wireguard
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
networks:
default:
name: wgnet
external: true

Tiếp theo, tại file cấu hình Wireguard client và cài đặt trên máy tính / điện thoại dùng để kết nối.

V. Cấu hình Wireguard client (VPS A)

1. 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 từ VPS B đã được thiết lập bằng wg-easy. 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.9.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = 9NknLwkQRaxxxsfNr9wKIC15KsqRvN5eOwUZxuhDFWI=
PresharedKey = xhqj9bnxxxuuFtzbVJ5GJPD6D4YAMHdk6RbL5JVkT+M=
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Endpoint = 252.222.96.107:51822

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ối 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:

Terminal window
iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE

Để 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 = iptables -t nat -A POSTROUTING -o wg+ -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -o wg+ -j MASQUERADE

Lưu lại cấu hình cuối cùng trong thư mục ~/wireguad-client/config/wg0.conf

Terminal window
mkdir -p ~/wireguard-client/config
nano ~/wireguard-client/config/wg0.conf

Nhập vào nội dung sau và lưu lại

[Interface]
PrivateKey = sO7U9OS0s5vxxxdfY1aNHzVYXpJhKAaU/HG9MyfaWU=
Address = 10.9.0.2/24
DNS = 1.1.1.1
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 = 25
Endpoint = 252.222.96.107:51822

2. Tạo Wireguard client container

Tạo file docker-compose.yml để thiết lập Wireguard Client

Terminal window
cd ~/wireguard-client
nano docker-compose.yml

Nhập vào nội dung sau

services:
wireguard:
image: lscr.io/linuxserver/wireguard
container_name: wireguard-client
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: 10.10.0.2
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
restart: unless-stopped
networks:
default:
name: wgnet
external: true

Các thông số cần chú ý:

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-client. 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

Terminal window
[#] 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
[#] iptables-restore -n
[#] iptables -t nat -A POSTROUTING -o wg+ -j MASQUERADE
[ls.io-init] done.

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

Kiểm tra xem Wireguard-client đã kết nối thành công chưa bằng lệnh

docker exec wireguard-client curl -s ifconfig.me

Nếu thấy kết quả trả về là IP của VPS B nghĩa là Container đã kết nối thành công đến VPS B.

VI. Cấu hình routing table (VPS A)

1. Trước khi chỉnh sửa

Đầu tiên, kiểm tra thông số của mạng wgnet

Terminal window
docker network inspect wgnet

Kết quả sẽ hiện ra 2 container wireguard-client (đang kết nối đến VPS B) và wireguard-server (đang có kết nối từ máy tính ở nhà vào) đang được kết nối vào.

"Containers": {
"689ba546576337de722cf85f286c9fcb01229152a935f6aa41ca5b83b1d6639e": {
"Name": "wireguard-client",
"EndpointID": "7f56478d20d086570d121486e4f84b610387420841dc64cc87a03bff6d38ea8c",
"MacAddress": "02:42:0a:0a:00:02",
"IPv4Address": "10.10.0.2/24",
"IPv6Address": ""
},
"9761f07474eab357e6369c8a69e0b677836699ff3e1519011b70690620e10c56": {
"Name": "wireguard-server",
"EndpointID": "a45ba1746bbc2d7dd94931f4d752bb303caebbfc051875340258373e0fd346f5",
"MacAddress": "02:42:0a:0a:00:03",
"IPv4Address": "10.10.0.3/24",
"IPv6Address": ""
}
},

Kiểm tra IP của máy tính đang kết nối vào VPS A bằng cách truy cập https://ifconfig.me. Nếu đang kết nối thành công, kết quả sẽ hiện ra IP của VPS A 111.111.111.111

2. Chỉnh sửa routing table trên wireguard-server container

Trên VPS A, để chuyển kết nối từ container wireguard-server (IP: 10.10.0.3) đi qua wireguard-client (IP: 10.10.0.2), mình sẽ sửa lại routing table trong container Wireguard-server như sau

docker exec --privileged wireguard-server ip rule add from 10.8.0.0/24 table 120
docker exec --privileged wireguard-server ip route add default via 10.10.0.2 table 120

Giải thích:

  1. Tạo routing table mới với id 120, các truy cập từ subnet 10.8.0.0/24 sẽ đi qua routing table này.

  2. Chuyển hướng kết nối mặc định của routing table 120 sẽ đi qua IP 10.10.0.2, là IP của Wireguard-client.

Chú ý: Mỗi khi khởi động lại container wireguard-server, routing table sẽ tự động bị reset, bạn cần phải chạy lại 2 lệnh trên để thiết lập lại kết nối.

3. Xác nhận kết nối thành công

Trên máy tính đang kết nối vào VPS A, truy cập lại https://ifconfig.me.

Nếu thấy hiện ra IP của VPS B 222.222.222.222 nghĩa là kết nối bắc cầu đã được thực hiện thành công. Từ PC —> VPS A —> VPS B.

Chúc bạn thực hiện thành công


Share this post on:

Previous Post
Simple Cloudflare Turnstile - Plugin tích hợp Turnstile giúp chống spam bots
Next Post
Cập nhật Proxmox VE 7.4 lên 8.0