CentOS 7 部署 WireGuard(RPM 安装 + 分流不影响互联网 + 一键新增用户脚本)
1)目标与原则
目标
CentOS 7 上跑 WireGuard 服务器(wg0)
Windows / Linux 客户端接入
只让指定网段走隧道(Split Tunnel),不影响正常上网
核心原则(分流)
客户端配置里 AllowedIPs 写什么,就只路由什么
不想影响互联网:不要写
0.0.0.0/0
2)准备:确认系统与内核
cat /etc/redhat-release uname -r
CentOS7 上 WireGuard 的 kmod 模块经常是“按内核版本编译”的,所以 uname -r 要记住。
3)安装:从 3 个 RPM 包开始(推荐本地安装)
3.1 创建目录
mkdir -p /root/wg_rpm cd /root/wg_rpm
3.2 下载 3 个包
这 3 个是常用的最小组合:
wireguard-tools:wg / wg-quick 工具kmod-wireguard:元包(壳)wireguard:noarch(提供 common 依赖)
# wireguard-tools(工具) curl -LO "https://mirrors.aliyun.com/elrepo/elrepo/el7/x86_64/RPMS/wireguard-tools-1.0.20210914-1.el7.x86_64.rpm" # kmod 元包(依赖壳) curl -LO "https://mirrors.aliyun.com/rpmfusion/free/el/updates/7/x86_64/k/kmod-wireguard-1.0.20201221-1.el7.x86_64.rpm" # wireguard noarch(common 依赖) curl -LO "https://mirrors.aliyun.com/rpmfusion/free/el/updates/7/x86_64/w/wireguard-1.0.20201221-1.el7.noarch.rpm"
3.3 关键:下载“内核绑定模块包”
你 uname -r 如果是 3.10.0-1160.el7.x86_64,就下载:
curl -LO "https://mirrors.aliyun.com/rpmfusion/free/el/updates/7/x86_64/k/kmod-wireguard-3.10.0-1160.el7.x86_64-1.0.20201221-1.el7.x86_64.rpm"
如果不是 1160,把文件名里的 3.10.0-1160.el7.x86_64 换成你实际内核版本。
你之前报错“需要:kmod-wireguard-3.10.0-1160...”就是因为只装了元包,没有装这个“内核绑定包”。
3.4 一次性安装
yum localinstall -y ./*.rpm
3.5 验证
modprobe wireguard lsmod | grep wireguard || echo "wireguard module not loaded" wg --version
4)服务端配置(CentOS7)
下面以一个简单网段为例:
WireGuard 虚拟网段:
10.66.66.0/24服务器 wg0:
10.66.66.1第 1 个客户端:
10.66.66.2
4.1 生成密钥(务必分清 .key / .pub)
mkdir -p /etc/wireguard cd /etc/wireguard umask 077 wg genkey | tee server.key | wg pubkey > server.pub wg genkey | tee client.key | wg pubkey > client.pub echo "=== server.key(私钥) ==="; cat server.key echo "=== server.pub(公钥) ==="; cat server.pub echo "=== client.key(私钥) ==="; cat client.key echo "=== client.pub(公钥) ==="; cat client.pub
只记一句:
PrivateKey填.keyPublicKey填.pub
4.2 写服务端 /etc/wireguard/wg0.conf
vim /etc/wireguard/wg0.conf
内容:
[Interface] Address = 10.66.66.1/24 ListenPort = 51820 PrivateKey = <填 server.key 内容> [Peer] PublicKey = <填 client.pub 内容> AllowedIPs = 10.66.66.2/32
建议不要写
SaveConfig = true,容易出现“文件改了但运行态还是旧 peer”的坑。
4.3 启动与开机自启
wg-quick up wg0 systemctl enable wg-quick@wg0
验证:
ip addr show wg0 ss -lunp | grep 51820 wg show wg0
4.4 放行 UDP 51820
firewalld:
firewall-cmd --add-port=51820/udp --permanent firewall-cmd --reload
如果你用 iptables,测试先粗放(后面再细化):
iptables -I INPUT -p udp --dport 51820 -j ACCEPT iptables -I INPUT -i wg0 -j ACCEPT iptables -I INPUT -i wg0 -p icmp -j ACCEPT
5)客户端配置(Windows / Linux)
Windows WireGuard 新建 tunnel,粘贴(示例):
[Interface] PrivateKey = <填 client.key 内容> Address = 10.66.66.2/24 [Peer] PublicKey = <填 server.pub 内容> Endpoint = 你的服务器公网IP:51820 PersistentKeepalive = 25 # 分流:只走 10.66.66.0/24,不影响互联网 AllowedIPs = 10.66.66.0/24
验证:
Windows:
ping 10.66.66.1服务器:
wg show wg0看latest handshake与transfer
6)一键新增用户脚本(自动分配 IP + 生成客户端配置 + 热加载)
把下面脚本保存为:/root/add_wg_user.sh
#!/usr/bin/env bash
set -euo pipefail
WG_IF="wg0"
WG_DIR="/etc/wireguard"
WG_CONF="${WG_DIR}/${WG_IF}.conf"
NET_PREFIX="10.66.66"
CIDR="24"
SERVER_IP_LAST="1"
DEFAULT_ALLOWED_IPS="${NET_PREFIX}.0/${CIDR}"
DEFAULT_ENDPOINT="110.42.98.59:51820"
usage() {
cat <<EOF
用法:
$0 <username> [--ip-last N] [--endpoint IP:PORT] [--allowed "10.66.66.0/24,192.168.10.0/24"]
示例:
$0 user3
$0 user4 --ip-last 10
$0 user5 --allowed "10.66.66.0/24,192.168.10.0/24"
$0 user6 --endpoint "1.2.3.4:51820"
EOF
}
die() { echo "ERROR: $*" >&2; exit 1; }
[[ $# -lt 1 ]] && usage && exit 1
NAME="$1"; shift
[[ "$NAME" =~ ^[a-zA-Z0-9._-]+$ ]] || die "username 只能包含字母数字 . _ -"
IP_LAST=""
ENDPOINT="$DEFAULT_ENDPOINT"
ALLOWED_IPS="$DEFAULT_ALLOWED_IPS"
while [[ $# -gt 0 ]]; do
case "$1" in
--ip-last) IP_LAST="${2:-}"; shift 2 ;;
--endpoint) ENDPOINT="${2:-}"; shift 2 ;;
--allowed) ALLOWED_IPS="${2:-}"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*) die "未知参数:$1(用 -h 查看帮助)" ;;
esac
done
[[ -f "$WG_CONF" ]] || die "找不到 $WG_CONF"
# 读取服务器公钥(优先用 server.pub)
SERVER_PUB=""
if [[ -f "${WG_DIR}/server.pub" ]]; then
SERVER_PUB="$(tr -d '\r\n' < "${WG_DIR}/server.pub")"
else
if ip link show "$WG_IF" >/dev/null 2>&1; then
SERVER_PUB="$(wg show "$WG_IF" public-key 2>/dev/null || true)"
fi
fi
[[ -n "$SERVER_PUB" ]] || die "读取服务器公钥失败(建议放 ${WG_DIR}/server.pub)"
# 自动分配下一个可用 IP
if [[ -z "$IP_LAST" ]]; then
USED_LASTS="$(grep -Eo "${NET_PREFIX}\.[0-9]{1,3}/32" "$WG_CONF" \
| awk -F'[./]' '{print $4}' \
| sort -n | uniq || true)"
for n in $(seq 2 254); do
[[ "$n" == "$SERVER_IP_LAST" ]] && continue
echo "$USED_LASTS" | grep -qx "$n" && continue
IP_LAST="$n"
break
done
fi
[[ -n "$IP_LAST" ]] || die "没有可用 IP 了(10.66.66.2~254 都被占用)"
[[ "$IP_LAST" =~ ^[0-9]+$ ]] || die "--ip-last 必须是数字"
(( IP_LAST >= 2 && IP_LAST <= 254 )) || die "--ip-last 必须在 2~254"
CLIENT_IP="${NET_PREFIX}.${IP_LAST}/${CIDR}"
CLIENT_ALLOWED_IP="${NET_PREFIX}.${IP_LAST}/32"
umask 077
CLIENTS_DIR="${WG_DIR}/clients"
mkdir -p "$CLIENTS_DIR"
CLIENT_KEY_FILE="${CLIENTS_DIR}/${NAME}.key"
CLIENT_PUB_FILE="${CLIENTS_DIR}/${NAME}.pub"
CLIENT_CONF_FILE="${CLIENTS_DIR}/${NAME}.conf"
[[ -f "$CLIENT_KEY_FILE" || -f "$CLIENT_CONF_FILE" ]] && die "用户文件已存在,换名或先备份删除"
wg genkey | tee "$CLIENT_KEY_FILE" | wg pubkey > "$CLIENT_PUB_FILE"
CLIENT_PUB="$(tr -d '\r\n' < "$CLIENT_PUB_FILE")"
CLIENT_KEY="$(tr -d '\r\n' < "$CLIENT_KEY_FILE")"
cat > "$CLIENT_CONF_FILE" <<EOF
[Interface]
PrivateKey = ${CLIENT_KEY}
Address = ${CLIENT_IP}
[Peer]
PublicKey = ${SERVER_PUB}
Endpoint = ${ENDPOINT}
PersistentKeepalive = 25
AllowedIPs = ${ALLOWED_IPS}
EOF
TS="$(date '+%F_%H%M%S')"
BK="${WG_CONF}.bak.${TS}"
cp -a "$WG_CONF" "$BK"
grep -qF "$CLIENT_PUB" "$WG_CONF" && die "wg0.conf 已存在该公钥,备份在:$BK"
{
echo ""
echo "# ${NAME} added ${TS}"
echo "[Peer]"
echo "PublicKey = ${CLIENT_PUB}"
echo "AllowedIPs = ${CLIENT_ALLOWED_IP}"
} >> "$WG_CONF"
# 热加载(不中断现有连接)
if ip link show "$WG_IF" >/dev/null 2>&1; then
wg set "$WG_IF" peer "$CLIENT_PUB" allowed-ips "$CLIENT_ALLOWED_IP" || true
fi
echo "OK: 已新增用户:${NAME}"
echo " - 分配 IP:${CLIENT_IP}"
echo " - 服务器配置已更新:${WG_CONF}"
echo " - 服务器配置备份:${BK}"
echo " - 客户端配置文件:${CLIENT_CONF_FILE}"
echo ""
echo "把这个文件发给用户导入即可:"
echo " ${CLIENT_CONF_FILE}"给执行权限:
chmod +x /root/add_wg_user.sh
6.1 新增用户示例
自动分配下一个 IP:
/root/add_wg_user.sh user2
指定 IP 最后一段:
/root/add_wg_user.sh user2 --ip-last 3
让用户额外能访问内网段(仍然分流,不影响互联网):
/root/add_wg_user.sh user2 --allowed "10.66.66.0/24,192.168.10.0/24"
脚本输出里会给你:
分配的 IP
生成的客户端配置路径:
/etc/wireguard/clients/user2.conf
把这个文件发给用户导入 WireGuard 客户端即可。
7)排障最有效的两条命令
7.1 看握手(服务端)
wg show wg0
看有没有:
latest handshaketransfer是否在涨
7.2 抓包判断“端口通不通 / 服务端回不回”
tcpdump -ni any udp port 51820
只有入站,没有回包:通常是 peer key 不匹配/服务端没认出客户端
双向都有:再看防火墙/路由/ICMP
8)子网互通怎么做(继续分流,不影响互联网)
当你需要让客户端访问远端内网(例如 192.168.10.0/24):
客户端 AllowedIPs 加上:
AllowedIPs = 10.66.66.0/24, 192.168.10.0/24
然后“远端内网回程”通常有两种方式:
给内网网关加静态路由(标准方案)
服务器做 NAT(省事方案)
这一段跟你的实际网卡/网关有关,确定后再上最终配置就行。
已有10位网友发表了看法:
发表评论