Mười hai bài xây dựng

Máy chủ WireGuard được bảo mật với IPv6 thực sự định tuyến

Xây dựng một điểm cuối WireGuard cấp cho máy khách địa chỉ v4 riêng và một dải IPv6 được định tuyến thực sự, phía sau chính sách nftables từ chối mọi thứ không được yêu cầu.

Kết quả đạt được

Một instance chạy WireGuard, cấp cho mỗi client một địa chỉ IPv4 riêng, một địa chỉ IPv6 được route từ /48 của bạn, và một resolver nằm trong tunnel để các truy vấn DNS không đi đường khác với phần còn lại của lưu lượng. Tường lửa mặc định drop cả hai chiều. Forwarding chỉ bật cho interface tunnel, và chỉ outbound.

Đã kiểm tra trên R-4 tại AMS-01 với Debian 13. WireGuard là single-flow và chạy ở kernel, nên thêm CPU không giúp gì cho đến khi bạn đẩy nhiều gigabit qua nó. Quan trọng hơn là vị trí: chọn site gần nơi bạn thực sự ở, vì mỗi mili giây thêm vào đây là thêm vào mọi gói tin.

Trước khi bắt đầu

  • Một instance đã triển khai và quyền root qua SSH.
  • Bổ sung IPv6 /48 được kích hoạt trong panel. /64 đi kèm chỉ đủ cho một client, nhưng subnet riêng cho từng client từ một /64 có nghĩa phải proxy neighbour discovery, đó là một sở thích hơn là cấu hình.
  • Một hostname trỏ đến instance. Mọi thứ bên dưới sử dụng vpn.example.com.
  • Mọi địa chỉ 2001:db8: ở đây là không gian tài liệu. Thay tiền tố bằng cái hiển thị trên trang instance của bạn.

1. Gói và cài đặt kernel

apt update && apt full-upgrade -y
apt install -y wireguard-tools nftables unbound qrencode
ip -br link

Lệnh cuối in tên interface hướng ra ngoài của bạn. Trên image KVM của chúng tôi, nó là ens3; nếu khác, thay thế ở mọi nơi bên dưới. Bây giờ là kernel:

cat > /etc/sysctl.d/99-wireguard.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.ens3.accept_ra = 2
net.ipv4.conf.all.rp_filter = 1
EOF
sysctl --system

Dòng accept_ra = 2 là dòng mọi người hay quên. Bật IPv6 forwarding khiến kernel ngừng chấp nhận router advertisement, default route biến mất trong vòng mười phút, và máy tối đen qua v6 trong khi vẫn trả lời qua v4. Đặt giá trị 2 giữ cho việc chấp nhận advertisement trên host forwarding.

2. Khóa

install -d -m 700 /etc/wireguard
umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub
wg genkey | tee /etc/wireguard/laptop.key | wg pubkey > /etc/wireguard/laptop.pub
wg genpsk > /etc/wireguard/laptop.psk

Khóa pre-shared không phải là tùy chọn trong bản build này. Nó không tốn gì, chỉ một dòng trong mỗi config, và là sự khác biệt giữa một tunnel chỉ an toàn hôm nay và một tunnel an toàn trước kẻ thù đang ghi lại lưu lượng bây giờ để giải mã sau này.

3. Interface server

Viết /etc/wireguard/wg0.conf, dán nội dung khóa vào chỗ được đánh dấu:

[Interface]
Address = 10.7.0.1/24, 2001:db8:1a2b:7::1/64
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>
MTU = 1420

[Peer]
# laptop
PublicKey = <contents of /etc/wireguard/laptop.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
AllowedIPs = 10.7.0.2/32, 2001:db8:1a2b:7::2/128

Ở phía server, AllowedIPs là bảng định tuyến, không phải danh sách quyền. Cấp cho mỗi peer chính xác địa chỉ nó sở hữu và không rộng hơn, nếu không hai client sẽ tranh nhau cùng một route và kẻ thua sẽ ngừng nhận gói tin.

chmod 600 /etc/wireguard/wg0.conf

4. Resolver bên trong tunnel

Trỏ client đến một resolver công cộng sẽ phá hỏng ý nghĩa. Unbound đã được cài; cấu hình cho nó /etc/unbound/unbound.conf.d/tunnel.conf:

server:
  interface: 10.7.0.1
  interface: 2001:db8:1a2b:7::1
  access-control: 10.7.0.0/24 allow
  access-control: 2001:db8:1a2b:7::/64 allow
  do-ip6: yes
  prefetch: yes
  hide-identity: yes
  hide-version: yes
  qname-minimisation: yes

Unbound sẽ không khởi động được trước khi tunnel tồn tại, vì các địa chỉ đó chưa lên. Sắp xếp thứ tự đúng thay vì chống lại nó:

systemctl edit unbound
[Unit]
[email protected]
[email protected]

5. Tường lửa

Thay thế toàn bộ /etc/nftables.conf:

flush ruleset

table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    ct state invalid drop
    iif lo accept
    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept
    tcp dport 22 accept
    udp dport 51820 accept
    iifname "wg0" udp dport 53 accept
    iifname "wg0" tcp dport 53 accept
  }
  chain forward {
    type filter hook forward priority filter; policy drop;
    ct state established,related accept
    iifname "wg0" oifname "ens3" accept
    iifname "wg0" oifname "wg0" drop
  }
  chain output {
    type filter hook output priority filter; policy accept;
  }
}

table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 10.7.0.0/24 oifname "ens3" masquerade
  }
}

Lưu ý điều gì vắng mặt: không có bảng NAT cho IPv6. Client đi ra với địa chỉ riêng của chúng từ /48 của bạn, đó là toàn bộ lý do lấy /48. Dòng iifname "wg0" oifname "wg0" drop ngăn các peer truy cập lẫn nhau, điều bạn muốn trừ khi bạn cố tình xây dựng mesh.

systemctl enable --now nftables
nft list ruleset | head -20

6. Khởi động

systemctl enable --now wg-quick@wg0
systemctl restart unbound
wg show wg0

7. Client

[Interface]
PrivateKey = <contents of /etc/wireguard/laptop.key>
Address = 10.7.0.2/24, 2001:db8:1a2b:7::2/64
DNS = 10.7.0.1
MTU = 1420

[Peer]
PublicKey = <contents of /etc/wireguard/server.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

Đối với điện thoại, biến nó thành mã QR trên server và chụp màn hình terminal:

qrencode -t ansiutf8 < /root/laptop.conf

Trên client Debian hoặc Ubuntu, dòng DNS = cần openresolv được cài, nếu không wg-quick in cảnh báo và âm thầm giữ resolver cũ của bạn. Đó là nguyên nhân phổ biến nhất của một tunnel hoạt động hoàn hảo nhưng rò rỉ mọi truy vấn.

Xác minh

Bốn kiểm tra, theo thứ tự. Bất kỳ kiểm tra nào thất bại sẽ chỉ cho bạn bước cần quay lại.

# on the server, after connecting the client
wg show wg0 latest-handshakes
wg show wg0 transfer

Dấu thời gian bắt tay trong vòng hai phút gần đây và các bộ đếm khác không ở cả hai chiều nghĩa là mật mã và định tuyến đều ổn.

# on the client
ping -c3 10.7.0.1
ping -c3 2001:db8:1a2b:7::1
dig @10.7.0.1 paragonvps.com AAAA +short

Lệnh thứ ba chứng minh resolver tunnel đang trả lời. Nếu hết thời gian, unbound đã khởi động trước khi wg0 tồn tại; hãy khởi động lại nó.

Kiểm tra cuối là kiểm tra duy nhất chứng minh lưu lượng của bạn đi ra từ nơi bạn nghĩ, và nó cần một máy thứ hai. Bất kỳ instance nào khác trong hạm đội đều được, ở bất kỳ thành phố nào:

# on the second instance
nc -lv 9101

# on the client, tunnel up
curl -m5 -4 http://second.example.com:9101/
curl -m5 -6 http://second.example.com:9101/

Trình nghe in địa chỉ nguồn của mỗi kết nối. Kết nối v4 của bạn nên đến từ server WireGuard, vì nó đã bị masquerade. Kết nối v6 nên đến từ địa chỉ tunnel riêng của client trong /48 của bạn, không thay đổi, đó là ý nghĩa của routed và proxy không có.

Khi gặp sự cố

Triệu chứngNguyên nhânCách khắc phục
Bắt tay thành công, không có lưu lượng đi quaForwarding tắt, hoặc chuỗi forward dropsysctl net.ipv4.ip_forward, sau đó đọc lại chuỗi forward
Yêu cầu nhỏ ổn, tải xuống lớn treoMTU và path discoveryGiảm cả hai config xuống MTU = 1380 và thử lại
IPv6 chết khoảng mười phút sau khi khởi độngForwarding giết router advertisementaccept_ra = 2 trên interface hướng ra ngoài
DNS phân giải bên ngoài tunnelClient bỏ qua DNS =Cài openresolv trên client
Mọi thứ biến mất sau khi khởi động lạiUnits chưa được bậtsystemctl enable wg-quick@wg0 nftables unbound

Từ đây, các bước tiếp theo hợp lý là một endpoint thứ hai ở vùng khác và một hệ thống giám sát cho bạn biết khi một trong số chúng ngừng trả lời. Cả hai đều được trình bày trong các hướng dẫn; trang mạng giải thích những gì edge làm với lưu lượng của bạn trước khi nó đến bạn.

Sẵn sàng khi bạn cần

Chọn thành phố. Chọn kích thước. Thanh toán bằng coin.

Không có biểu mẫu về bạn là ai, không chờ đợi con người phê duyệt, không gọi điện thoại để xác minh bất cứ điều gì. Hóa đơn được thanh toán và thông tin đăng nhập sẽ vào hộp thư của bạn.