问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

基于WireGuard实现的云组网

创作时间:
作者:
@小白创作中心

基于WireGuard实现的云组网

引用
1
来源
1.
https://blog.nipx.cn/pages/509bb6/

本文将详细介绍如何使用WireGuard实现家庭网络、出租屋网络、手机网络和云服务的互联互通。通过配置WireGuard,可以实现有公网设备直连,无公网设备经云服务器转发的网络架构。文章将从需求分析、拓扑设计、安装配置到常见问题解决,提供全面的技术指导。

需求分析

  • 实现家庭网络、出租屋网络、手机网络、云服务互联互通
  • 家庭网络拥有公网 IP,在访问家庭网络时直连,而不经过云服务器中转
  • 内网 DNS,由于很多服务都带有端口号,并不好记

拓扑图

  • 访问有公网设备时直连
  • 访问无公网设备时经云服务器转发

安装配置

Linux平台

基本安装

在Ubuntu系统上,可以通过以下命令安装WireGuard:

apt install wireguard

作为中转服务器时,需要配置流量转发:

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf

常见命令

# 启动
systemctl start wg-quick@wg0
# 重启
systemctl restart wg-quick@wg0
# 查看连接状态
wg
# 伪装 NAT
iptables -t nat -A POSTROUTING -o enp1s0(网卡) -j MASQUERADE
# 接受来自wg0网卡的转发
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A FORWARD -i wg0 -o enp1s0 -j ACCEPT
# wg-quick
wg-quick up wg0
wg-quick down wg0

Padavan平台

安装步骤

  1. 下载文件:https://nip.lanzoul.com/iZ8Wv0ykwyne 密码:h7rj
  2. tunsafe_mipsel 文件移动并重命名:
    /etc/storage/tunsafe
    
  3. 添加可执行权限:
    chmod a+x tunsafe
    
  4. 创建 wg0.conf 文件到 /etc/storage/wg0.conf

启动与管理

# 启动
/etc/storage/tunsafe start -n wg0 /etc/storage/wg0.conf &
# 停止
/etc/storage/tunsafe stop
# 状态查看
/etc/storage/tunsafe show

OpenWrt平台

以 iStoreOS 为例:

  1. 软件包管理,安装 luci-i18n-wireguard-zh-cn
  2. 网络 - 接口 - 添加新接口,名称:cloud_network,协议:WireGuard VPN
  3. 常规设置,填写:
  • 秘钥(点击生成新的密钥对)
  • 公钥(感觉可以不填,可能是用来复制生成的密钥对里的公钥)
  • IP 地址,如 192.168.1.0/24
  • 防火墙
  • 选择:lan
  1. 对端,添加对端:
  • 公钥
  • 允许的 IP
  • 路由允许的 IP:勾选
  • 端点主机
  • 端点端口
  • 持续 Keep-Alive:25

保存并应用,重启。

配置方法

生成密钥对

在配置之前,需要先生成用于连接的密钥对:

#生成私钥
wg genkey > example.key
# 生成公钥
wg pubkey < example.key > example.key.pub
# 同时输出 私钥+公钥
wg genkey | tee >(wg pubkey)
# 通过私钥字符串得到公钥
echo "公钥字符串" | wg pubkey

wg0.conf配置

  • /etc/wireguard/wg0.conf
[Interface]
# Name = node1.example.tld
Address = 192.0.2.3/32 
ListenPort = 51820
MTU = 1280
PrivateKey = localPrivateKeyAbcAbcAbc=
[Peer]
# Name = node2-node.example.tld
AllowedIPs = 192.0.2.1/24
Endpoint = node1.example.tld:51820
PublicKey = remotePublicKeyAbcAbcAbc=
PersistentKeepalive = 25
  • [Interface]:当前节点配置

  • Address:虚拟网卡网卡地址

  • ListenPort:当前节点会监听这个端口,供其他节点连接

  • PrivateKey:当前节点的私钥

  • MTU:1280,使用 1500、1420 有可能丢包。具体值参考坑 3

  • Table:默认auto,会根据 Peer 的 AllowedIPs 配置到主路由表,当存在冲突时,需要自定义路由表,参考坑 2.

  • [Peer]:对等节点

  • AllowedIPs:允许从此节点发来的数据报,源 IP 地址范围,同时也是当前节点发送时的路由表规则。

  • Endpoint:与此节点连接的 IP 地址和端口

  • PublicKey:此节点的公钥

  • PersistentKeepalive:心跳包间隔时长,通常为25

配置示例

  1. NAT 背后节点
[Interface]
PrivateKey = xxxx
MTU = 1280
[Peer]
# 中转节点
PublicKey = xxx
AllowedIPs = 192.168.0.0/16 # 路由到此节点的目标地址段,同时也是允许他发来的源地址段
Endpoint = x.x.x.x:51820 # 此节点的端点
PersistentKeepalive = 25
  1. 中转节点
[Interface]
PrivateKey = xxxx
MTU = 1280
ListenPort = 51820 # 与其他节点建立连接的端口
[Peer]
# 节点1
PublicKey = xxx
AllowedIPs = 192.168.1.0/24 # 路由到此节点的目标地址段,同时也是允许他发来的源地址段
PersistentKeepalive = 25
[Peer]
# 节点2
PublicKey = xxx
AllowedIPs = 192.168.2.0/24 # 路由到此节点的目标地址段,同时也是允许他发来的源地址段
PersistentKeepalive = 25
  1. 无外网节点
[Interface]
PrivateKey = xxxx
MTU = 1280
Table = 1234 # 避免与k8s隧道冲突
[Peer]
# 节点1
PublicKey = xxx
AllowedIPs = 0.0.0.0/0 # 把所有流量转发到此节点
PersistentKeepalive = 25
# 192.168.0.0/16 使用 1234 表
ip rule add to 192.168.0.0/16 table 1234
ip rule add ipproto tcp dport 80 table 1234
ip rule add ipproto tcp dport 443 table 1234

wg-quick 重启脚本

#!/bin/bash
# Set the path to your WireGuard configuration file
CONF_FILE="/etc/wireguard/wg0.conf"
# Bring the interface down
sudo wg-quick down "$CONF_FILE"
# Bring the interface up with the new configuration
sudo wg-quick up "$CONF_FILE"
# Print a message to indicate that the configuration has been reloaded
echo "WireGuard configuration reloaded!"
chmod +x wg-quick-restart.sh

限制目的 IP

在实践中发现,一个节点配置,把路由到中转节点的 AllowedIPs 改为 0.0.0.0/0 就可以通过中转节点访问互联网,而这并不是期望的,只希望它处理内网 IP 的路由。需要通过防火墙 iptables 来限制。

wireguard over TCP(基于 Phantun 实现)

安装

wget https://github.com/dndx/phantun/releases/download/v0.7.0/phantun_x86_64-unknown-linux-musl.zip
unzip phantun_x86_64-unknown-linux-musl.zip
mv phantun_client phantun_server /usr/local/bin/
# 服务端
# 在client端运行:
./udp2raw_amd64 -c -l0.0.0.0:3333  -r44.55.66.77:4096 -k "passwd" --raw-mode faketcp   --cipher-mode xor  -a

服务端 wg0.conf

MTU = 1200
ListenPort = 51820
PreUp = sudo udp2raw -s -l 0.0.0.0:4096 -r 127.0.0.1:51820 -k "your-password" --raw-mode faketcp -a --log-level 0 --cipher-mode xor &
Postdown = pkill -f "udp2raw.*:4097"

客户端 wg0.conf

MTU = 1200
PreUp = udp2raw -c -l 127.0.0.1:51820 -r YOUR-SERVER-IP:4096 -k "your-password" --raw-mode faketcp -a --log-level 0 --cipher-mode xor &
Postdown = pkill -f "udp2raw.*:51820"
# peer的ip写 127.0.0.1:51820

常见问题及解决方案

  1. 腾讯云轻量服务器不能通过静态路由到其他内网服务器
  • 最终选择在每一台服务器上部署 WireGuard 互联
  1. 与 k8s 隧道路由表冲突
  • 使用 Table 指定 wg0 的路由表,再通过 ip rule 来配置哪些流量经过此路由表转发。
  1. MTU1280 不是真理
  • 经过测试发现此台服务器最佳 MTU 为 1252。
  1. 客户端无法重连问题排除
  • 通过抓包发现,客户端一直在向服务端发送报文,而服务端始终未收到报文。
  • 重启脚本解决:
    #!/bin/bash
    ip="10.0.0.1"    # 将ip地址替换为你要ping的目标IP
    count=0          # 初始化计数器
    while true; do
        if ping -c 1 -W 1 "$ip" >/dev/null 2>&1; then
            logger -t "wg-monitor" "ping success: $ip"
            count=0
            break
        else
            logger -t "wg-monitor" "ping fail: $ip"
            count=
        fi
        if [ "$count" -eq 5 ]; then
            logger -t "wg-monitor" "reboot WireGuard"
            ifup cloud_network  # 重启 WireGuard
            break
        fi
        sleep 5  # 等待5秒后再次ping
    done
    
  1. 与 mihomo 不兼容问题
  • 由于需要和境外服务器组网,而 udp 数据包出境丢包严重,因此加了一层 TLS 隧道来优化稳定,在连接两个 Peer 时发现两个

总结

WireGuard 确实十分轻量,也因为轻量所以似乎不那么聪明。他适用于云组网,IP 地址很少改变的场景。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号