From d8367ba012930847e07753758489e6d7fb180737 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Sun, 27 Apr 2025 15:28:16 +0800 Subject: [PATCH] feat(vpn-overlay): dynamic Endpoint switching and WireGuard keys generation - Support dynamic AllowedIPs and Endpoint based on enable_vless - Fix wg1 -> wg0 in iptables rules - Update config files - Support dynamic WireGuard keys generation in gen_wireguard_keys.sh --- .../vpn-overlay/wireguard/site/tasks/main.yml | 1 + .../wireguard/site/templates/wg0.conf.j2 | 8 +- config/sit/vpn-keys.yaml | 35 ++++---- config/sit/vpn-overlay.yaml | 13 +-- scripts/gen_wireguard_keys.sh | 83 +++++++++++++++++++ 5 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 scripts/gen_wireguard_keys.sh diff --git a/ansible/playbooks/roles/vhosts/vpn-overlay/wireguard/site/tasks/main.yml b/ansible/playbooks/roles/vhosts/vpn-overlay/wireguard/site/tasks/main.yml index 9c61bf5a..5362c43c 100644 --- a/ansible/playbooks/roles/vhosts/vpn-overlay/wireguard/site/tasks/main.yml +++ b/ansible/playbooks/roles/vhosts/vpn-overlay/wireguard/site/tasks/main.yml @@ -18,6 +18,7 @@ {{ overlay_keys['keys'] | selectattr('name', 'equalto', inventory_hostname) | list | first }} + features: "{{ overlay_data.features }}" - name: 提取对端 peer 节点列表 set_fact: diff --git a/ansible/playbooks/roles/vhosts/vpn-overlay/wireguard/site/templates/wg0.conf.j2 b/ansible/playbooks/roles/vhosts/vpn-overlay/wireguard/site/templates/wg0.conf.j2 index fbc81c00..02372fb5 100644 --- a/ansible/playbooks/roles/vhosts/vpn-overlay/wireguard/site/templates/wg0.conf.j2 +++ b/ansible/playbooks/roles/vhosts/vpn-overlay/wireguard/site/templates/wg0.conf.j2 @@ -6,15 +6,19 @@ DNS = 8.8.8.8 MTU = 1400 PostUp = iptables -I FORWARD -o %i -j ACCEPT -PostUp = iptables -A FORWARD -i wg1 -j ACCEPT +PostUp = iptables -A FORWARD -i wg0 -j ACCEPT PostUp = iptables -t nat -A POSTROUTING -o {{ current_interface }} -j MASQUERADE PostDown = iptables -D FORWARD -o %i -j ACCEPT -PostDown = iptables -D FORWARD -i wg1 -j ACCEPT +PostDown = iptables -D FORWARD -i wg0 -j ACCEPT PostDown = iptables -t nat -D POSTROUTING -o {{ current_interface }} -j MASQUERADE [Peer] PublicKey = {{ peer_public_key }} AllowedIPs = {{ current_allowed_ips }} +{% if features.enable_vless %} +Endpoint = 127.0.0.1:51830 +{% else %} Endpoint = {{ peer_endpoint }} +{% endif %} PersistentKeepalive = 25 diff --git a/config/sit/vpn-keys.yaml b/config/sit/vpn-keys.yaml index 37ffbb15..de7875bb 100644 --- a/config/sit/vpn-keys.yaml +++ b/config/sit/vpn-keys.yaml @@ -1,21 +1,4 @@ keys: - - name: deepflow-demo - private_key: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 66623962303236653931333431393932336164313365656664333636316262343137333933303166 - 3162656332643130353739373531636564336539653561620a323032666662623864656332306130 - 65306165666264633738316563313439316164393030316431663265383634366165333334633131 - 6166623463633836350a356132353939613636336139386165303563383763363164393365383838 - 61393833346334386531316666373438613966313864396462373865393465343236376664643237 - 6364326161363433386431623963623733653736663639373162 - public_key: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 63613935616137343434666164663963333632663266636663386536373264373234616135633631 - 3633393835383231363863346335366463303565373034350a623862393837373830333832336433 - 37323538653962373632623531366130373764313036613637646536663466336661336639393861 - 3561373939393765360a653036303535623865613462666534383930663939646239373435626635 - 64346433343064353835663936366434326262333265363837663632363966356435333363346534 - 6335633637363463653831366438303835633066333062653264 - name: master-1 private_key: !vault | $ANSIBLE_VAULT;1.1;AES256 @@ -63,3 +46,21 @@ keys: - name: global-hub private_key: public_key: + - name: deepflow-demo + private_key: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 36316136663466336564383766626434626338356130626537663163373530326332366335306136 + 3266383533373032623366396139653063626338646237310a353439346238653832646437313663 + 62623239623761326436613833313739386662356263353338666461363438613766663962386162 + 3539343836623936370a313439316335346235306633333333643738333461323963313038313161 + 62376566626335306335623134346361326364346433626234383162616636326265356364313938 + 6534613330643764613733333266313365633635663138636633 + public_key: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 32326461646138373831356335656664643737313032656134663138323439313164353766363134 + 6232303034663064303235303363663661326433313536660a666133616438316436306463303163 + 64646530633639616266396563383362306235313662373565323963633039653931376431303565 + 6136396164346563660a643235646232353061323463396539383266333133343532396139373035 + 39653262653638363930383861353262303030373332313538383362393633663562303566373737 + 3062336434313031613534393033616330333363613863613464 + diff --git a/config/sit/vpn-overlay.yaml b/config/sit/vpn-overlay.yaml index 40f410b4..5bea5532 100644 --- a/config/sit/vpn-overlay.yaml +++ b/config/sit/vpn-overlay.yaml @@ -1,15 +1,15 @@ # 基础网络参数 -wg_network: 172.16.0.0/24 +wg_network: 172.16.0.0/16 bridge_network: 10.253.0.0/16 vxlan_id: 100 hub_port: 51820 # 全局功能开关 features: - enable_vxlan_between_sits: true # 是否开启 vxlan 桥接(站点接入 Hub) - enable_vxlan_between_hubs: true # 是否开启 Hub 之间的 VXLAN Mesh enable_vless: true # 是否通过 VLESS 中转 WG 流量 enable_multi_hub: true # 是否支持多 Hub 架构(false 则为单 Hub star 架构) + enable_vxlan_between_sits: true # 是否开启 vxlan 桥接(站点接入 Hub) + enable_vxlan_between_hubs: true # 是否开启 Hub 之间的 VXLAN Mesh only_wireguard: false # 若为 true,仅使用 WireGuard 点对点,忽略 gretap/vxlan # WireGuard Hub 节点配置 @@ -139,13 +139,14 @@ sites: path: /xray - name: deepflow-demo - interface: eth0 + interface: wlp0s20f3 + public_ip: 172.30.0.10 wg_ip: 172.30.0.10 br_ip: 10.253.253.2 local_ip: 172.30.0.10 remote_ip: 172.30.0.1 - hub: hub2 - public_ip: c.example.com + wireguard_peer: cn-hub + allowed_ips: "172.30.0.0/16" vless: enabled: true endpoint: vless-c.example.com diff --git a/scripts/gen_wireguard_keys.sh b/scripts/gen_wireguard_keys.sh new file mode 100644 index 00000000..bb8ea505 --- /dev/null +++ b/scripts/gen_wireguard_keys.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +# scripts/gen_wireguard_keys.sh +# 支持全量或指定 name 生成 WireGuard 密钥并加密到 keys.yaml + +set -euo pipefail + +VAULT_PASSWORD_FILE="$HOME/.vault_password" # ✅ 正确展开用户目录 +VPN_CONFIG="config/sit/vpn-overlay.yaml" +OUTPUT_FILE="config/sit/vpn-keys.yaml" + +if [[ ! -f "$VAULT_PASSWORD_FILE" ]]; then + echo "ERROR: 未找到 $VAULT_PASSWORD_FILE,请创建 ~/.vault_password 保存 ansible vault 密码。" >&2 + exit 1 +fi + +# 参数 +SPECIFIC_NAME="${1:-}" # 第一个参数,指定name(可选) + +# 读取 hubs 和 sites 的 name +names=($(yq '.hubs[].name' "$VPN_CONFIG") $(yq '.sites[].name' "$VPN_CONFIG")) + +# 检查是否指定 name +if [[ -n "$SPECIFIC_NAME" ]]; then + if ! printf "%s\n" "${names[@]}" | grep -q "^${SPECIFIC_NAME}$"; then + echo "ERROR: 指定的 name \"$SPECIFIC_NAME\" 不在 vpn-overlay.yaml 的 hubs 或 sites 里。" >&2 + exit 1 + fi + names=("$SPECIFIC_NAME") + echo "🔵 只更新指定 name: $SPECIFIC_NAME" +else + echo "🟢 全量生成所有 names: ${names[*]}" + echo "keys:" > "$OUTPUT_FILE" # 只有全量时才清空 output +fi + +for name in "${names[@]}"; do + echo "生成 $name 的 WireGuard 密钥对..." + + tmpdir=$(mktemp -d) + + wg genkey > "$tmpdir/privatekey" + cat "$tmpdir/privatekey" | wg pubkey > "$tmpdir/publickey" + + private_key_encrypted=$(ansible-vault encrypt_string --vault-password-file "$VAULT_PASSWORD_FILE" --encrypt-vault-id default "$(cat "$tmpdir/privatekey")" --name "private_key") + public_key_encrypted=$(ansible-vault encrypt_string --vault-password-file "$VAULT_PASSWORD_FILE" --encrypt-vault-id default "$(cat "$tmpdir/publickey")" --name "public_key") + + if [[ -n "$SPECIFIC_NAME" ]]; then + # 只更新某个 name,需要保留原有 keys.yaml + tmp_keys=$(mktemp) + + # 先去掉原本存在的同名块 + awk -v NAME="$name" ' + BEGIN { skip=0 } + /^ - name: / { + if ($3 == NAME) { skip=1 } + else { skip=0 } + } + skip==0 { print } + ' "$OUTPUT_FILE" > "$tmp_keys" + + # 追加新的 key 块 + { + echo " - name: $name" + echo "$private_key_encrypted" | sed 's/^/ /' + echo "$public_key_encrypted" | sed 's/^/ /' + echo "" + } >> "$tmp_keys" + + mv "$tmp_keys" "$OUTPUT_FILE" + else + # 全量生成直接写 + { + echo " - name: $name" + echo "$private_key_encrypted" | sed 's/^/ /' + echo "$public_key_encrypted" | sed 's/^/ /' + echo "" + } >> "$OUTPUT_FILE" + fi + + rm -rf "$tmpdir" +done + +echo "✅ 完成生成,keys 写入到 $OUTPUT_FILE"