返回

WireGuard客户端自动配置生成脚本

介绍 WireGuard 客户端配置生成脚本的用途和特点,适合自动化为 WireGuard 服务器批量添加新 Peer 与客户端配置
2024-06-13
4711 字 · 约 12 分钟阅读

该脚本可用于自动为 WireGuard 服务器生成新的客户端(Peer)配置,并将必要的 Peer 信息自动追加到服务端配置文件

主要:

  • 交互式参数输入,支持参数记忆,方便重复操作
  • 自动分配唯一客户端虚拟 IP,避免 IP 冲突
  • 自动生成并保存客户端密钥,服务端公钥和预共享密钥
  • 自动将新 Peer 信息追加到服务端配置文件
  • 客户端配置输出到指定目录,便于统一管理和分发
  • 检测到 qrencode 程序时自动输出二维码,方便手机扫码导入 WireGuard 配置

适用场景:

  • 批量为 WireGuard 服务器添加新客户端(如公司员工、多个移动设备等)
  • 需要便捷地生成客户端配置文件和二维码,提升 WireGuard 运维效率
#!/bin/bash
set -e

# =========================
#     WireGuard 客户端生成器
# =========================

INI_FILE="./wg-client-gen.ini"
declare -A ini_defaults

# 1. 读取 ini 配置(如果存在)
if [[ -f "$INI_FILE" ]]; then
  echo "🔎 检测到默认参数文件: $INI_FILE"
  while IFS='=' read -r key value; do
    key=$(echo "$key" | sed 's/^[ \t]*//;s/[ \t]*$//')
    value=$(echo "$value" | sed 's/^[ \t]*//;s/[ \t]*$//')
    [[ -z "$key" || "$key" == \#* ]] && continue
    ini_defaults["$key"]="$value"
  done < "$INI_FILE"
fi

# 2. 交互式输入参数,并支持 ini 默认值
echo "========= WireGuard 客户端配置生成 ========="

read -rp "请输入 WireGuard 服务端配置文件路径 (如 /etc/wireguard/wg0.conf) [${ini_defaults[WG_CONF]}]: " WG_CONF
WG_CONF="${WG_CONF:-${ini_defaults[WG_CONF]}}"
while [[ -z "$WG_CONF" || ! -f "$WG_CONF" ]]; do
  echo "❌ 配置文件无效,请重新输入"
  read -rp "请输入 WireGuard 服务端配置文件路径 (如 /etc/wireguard/wg0.conf): " WG_CONF
done

read -rp "请输入服务端 Endpoint (如 1.1.1.1:11820) [${ini_defaults[ENDPOINT]}]: " ENDPOINT
ENDPOINT="${ENDPOINT:-${ini_defaults[ENDPOINT]}}"
while [[ -z "$ENDPOINT" ]]; do
  echo "❌ Endpoint 不能为空"
  read -rp "请输入服务端 Endpoint (如 1.1.1.1:11820): " ENDPOINT
done

read -rp "请输入客户端名称(李明) [${ini_defaults[CLIENT_NAME]}]: " CLIENT_NAME
CLIENT_NAME="${CLIENT_NAME:-${ini_defaults[CLIENT_NAME]}}"
while [[ -z "$CLIENT_NAME" ]]; do
  echo "❌ 客户端名称不能为空"
  read -rp "请输入客户端名称(李明): " CLIENT_NAME
done

# 输出目录默认值为“服务端配置文件名去扩展名-client”
CFG_BASENAME=$(basename "$WG_CONF" .conf)
DEFAULT_OUTPUT_DIR="${CFG_BASENAME}-client"
read -rp "请输入输出目录 (留空则使用默认: ${DEFAULT_OUTPUT_DIR}) [${ini_defaults[OUTPUT_DIR]}]: " OUTPUT_DIR
OUTPUT_DIR="${OUTPUT_DIR:-${ini_defaults[OUTPUT_DIR]}}"
OUTPUT_DIR="${OUTPUT_DIR:-${DEFAULT_OUTPUT_DIR}}"
mkdir -p "$OUTPUT_DIR"

# AllowedIPs 获取,默认 0.0.0.0/0,支持记忆和交互
DEFAULT_ALLOWEDIPS="${ini_defaults[ALLOWEDIPS]:-0.0.0.0/0}"
read -rp "请输入本客户端的 AllowedIPs (如 0.0.0.0/0 或 10.8.0.2/32) [${DEFAULT_ALLOWEDIPS}]: " ALLOWEDIPS
ALLOWEDIPS="${ALLOWEDIPS:-${DEFAULT_ALLOWEDIPS}}"
while [[ -z "$ALLOWEDIPS" ]]; do
  echo "❌ AllowedIPs 不能为空"
  read -rp "请输入本客户端的 AllowedIPs (如 0.0.0.0/0 或 10.8.0.2/32): " ALLOWEDIPS
done

# 获取服务端 IP 网段(如 10.9.0.x)
SERVER_ADDRESS=$(grep -m1 '^Address' "$WG_CONF" | cut -d '=' -f2 | tr -d '[:space:]' | cut -d'/' -f1)
SUBNET=$(echo "$SERVER_ADDRESS" | awk -F. '{print $1"."$2"."$3}')
USED_IPS=$(grep -oP 'AllowedIPs\s*=\s*\K([0-9\.]+)' "$WG_CONF"; grep -oP 'Address\s*=\s*\K([0-9\.]+)' "$WG_CONF")

# 查找可用 IP
for i in $(seq 2 254); do
  CANDIDATE="$SUBNET.$i"
  if ! echo "$USED_IPS" | grep -qw "$CANDIDATE"; then
    CLIENT_IP="$CANDIDATE"
    break
  fi
done

if [[ -z "$CLIENT_IP" ]]; then
  echo "❌ 没有可用 IP 地址,请检查配置"
  exit 1
fi

# 生成密钥
CLIENT_PRIVATE_KEY=$(wg genkey)
CLIENT_PUBLIC_KEY=$(echo "$CLIENT_PRIVATE_KEY" | wg pubkey)
PRESHARED_KEY=$(wg genpsk)

# 获取服务端 public key
SERVER_PRIVATE_KEY=$(grep -m1 '^PrivateKey' "$WG_CONF" | awk -F '= ' '{print $2}' | tr -d ' ')
SERVER_PUBLIC_KEY=$(echo "$SERVER_PRIVATE_KEY" | wg pubkey)

# 获取服务端端口
SERVER_PORT=$(grep -m1 '^ListenPort' "$WG_CONF" | awk -F '= ' '{print $2}' | tr -d ' ')

# 用户确认
echo "📋 即将生成新的 WireGuard 客户端配置:"
echo "➡ 客户端名称:     $CLIENT_NAME"
echo "➡ 分配地址:       $CLIENT_IP/32"
echo "➡ 服务端 Endpoint: $ENDPOINT"
echo "➡ 输出目录:       $OUTPUT_DIR"
echo "➡ 服务端端口:     $SERVER_PORT"
echo "➡ AllowedIPs:     $ALLOWEDIPS"
read -rp "✅ 确认继续?(y/N): " CONFIRM
[[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]] && echo "🚫 已取消" && exit 0

# 追加到服务端配置
cat <<EOF >> "$WG_CONF"

# === Auto-generated Peer: $CLIENT_NAME ===
[Peer]
# $CLIENT_NAME
PublicKey = $CLIENT_PUBLIC_KEY
PresharedKey = $PRESHARED_KEY
AllowedIPs = $CLIENT_IP/32
EOF

echo "✅ 已添加到服务端配置:$WG_CONF"

# 生成客户端配置
CLIENT_CONF_PATH="$OUTPUT_DIR/$CLIENT_IP.conf"
cat <<EOF > "$CLIENT_CONF_PATH"
# WireGuard 客户端配置 - $CLIENT_NAME
[Interface]
PrivateKey = $CLIENT_PRIVATE_KEY
Address = $CLIENT_IP/32
# Client: $CLIENT_NAME

[Peer]
# Server
PublicKey = $SERVER_PUBLIC_KEY
PresharedKey = $PRESHARED_KEY
Endpoint = $ENDPOINT
AllowedIPs = $ALLOWEDIPS
PersistentKeepalive = 25
EOF

echo "✅ 客户端配置文件生成成功:$CLIENT_CONF_PATH"

# 3. 记录交互参数到固定 ini(当前执行目录)
cat <<EOF > "$INI_FILE"
WG_CONF=$WG_CONF
ENDPOINT=$ENDPOINT
CLIENT_NAME=$CLIENT_NAME
OUTPUT_DIR=$OUTPUT_DIR
ALLOWEDIPS=$ALLOWEDIPS
EOF
echo "🔖 此次交互参数已写入: $INI_FILE"

# 4. 检测 qrencode 并输出二维码
if command -v qrencode >/dev/null 2>&1; then
  echo "ℹ️  检测到 qrencode,生成二维码如下(可直接扫码导入 WireGuard 客户端):"
  qrencode -t ansiutf8 < "$CLIENT_CONF_PATH"
  # 也可以输出为图片文件:
  # qrencode -o "$OUTPUT_DIR/client-$CLIENT_NAME-$CLIENT_IP.png" < "$CLIENT_CONF_PATH"
else
  echo "⚠️  未检测到 qrencode,跳过二维码生成"
fi

留言

发表留言