feat: Add VXLAN over WireGuard support with site automation
- Enabled VXLAN over L3 via WireGuard tunnel; - Standardized Ansible role structure for `vpn-overlay`; - Integrated systemd service management via `vxlan-setup.service`; - Configured per-site VXLAN overlay in `config/sit/vpn-overlay.yaml`;
This commit is contained in:
parent
cb8dda4fed
commit
d38c4770ac
@ -2,4 +2,4 @@
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y vim inetutils-ping
|
||||
sudo apt-get install -y vim iputils-ping rsync
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Default VXLAN settings for site nodes
|
||||
vxlan_dev_if: wg0
|
||||
vxlan_vni: 100
|
||||
vxlan_cidr_suffix: 16
|
||||
overlay_config_path: config/sit/vpn-overlay.yaml
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
# 安全增强版 VXLAN Overlay 脚本(支持 wg0 作为通道设备)
|
||||
# 用法: ./setup_sit_vxlan.sh <dev_if> <local_ip> <remote_ip> <br0_ip> [cidr_suffix] [vxlan_id] [mtu]
|
||||
|
||||
set -e
|
||||
|
||||
DEV_IF="$1"
|
||||
LOCAL_IP="$2"
|
||||
REMOTE_IP="$3"
|
||||
BRIDGE_IP="$4"
|
||||
CIDR_SUFFIX="${5:-16}"
|
||||
VNI="${6:-100}"
|
||||
MTU="${7:-1400}"
|
||||
|
||||
if [[ -z "$DEV_IF" || -z "$LOCAL_IP" || -z "$REMOTE_IP" || -z "$BRIDGE_IP" ]]; then
|
||||
echo "Usage: $0 <dev_if> <local_ip> <remote_ip> <br0_ip> [cidr_suffix] [vxlan_id] [mtu]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VXLAN_IF="vxlan${VNI}"
|
||||
BR_IF="br0"
|
||||
BRIDGE_CIDR="${BRIDGE_IP}/${CIDR_SUFFIX}"
|
||||
SUBNET="$(echo "$BRIDGE_IP" | cut -d. -f1-2).0.0/${CIDR_SUFFIX}"
|
||||
|
||||
# 自动判断 dev 是否能用于 VXLAN(需支持广播)
|
||||
function is_vxlan_dev_usable() {
|
||||
[[ -d "/sys/class/net/$1" ]] && grep -q "broadcast" "/sys/class/net/$1/flags"
|
||||
}
|
||||
|
||||
echo "🔍 检查 $DEV_IF 是否可用于 VXLAN..."
|
||||
USE_DEV_PARAM=true
|
||||
if ! is_vxlan_dev_usable "$DEV_IF"; then
|
||||
echo "⚠️ $DEV_IF 不支持广播,将省略 dev 参数(通过路由走隧道)"
|
||||
USE_DEV_PARAM=false
|
||||
fi
|
||||
|
||||
# 清理旧接口
|
||||
for iface in "$VXLAN_IF" "$BR_IF"; do
|
||||
ip link show "$iface" &>/dev/null && ip link set "$iface" down && ip link del "$iface"
|
||||
done
|
||||
|
||||
# 创建 VXLAN 接口
|
||||
echo "🛠️ 创建 VXLAN 接口 $VXLAN_IF ..."
|
||||
if $USE_DEV_PARAM; then
|
||||
ip link add "$VXLAN_IF" type vxlan id "$VNI" dstport 4789 local "$LOCAL_IP" remote "$REMOTE_IP" dev "$DEV_IF"
|
||||
else
|
||||
ip link add "$VXLAN_IF" type vxlan id "$VNI" dstport 4789 local "$LOCAL_IP" remote "$REMOTE_IP"
|
||||
fi
|
||||
ip link set "$VXLAN_IF" mtu "$MTU"
|
||||
ip link set "$VXLAN_IF" up
|
||||
|
||||
# 创建 br0 桥
|
||||
ip link add "$BR_IF" type bridge
|
||||
ip link set "$BR_IF" mtu "$MTU"
|
||||
ip link set "$VXLAN_IF" master "$BR_IF"
|
||||
ip link set "$BR_IF" up
|
||||
|
||||
# 配置 IP
|
||||
ip addr add "$BRIDGE_CIDR" dev "$BR_IF"
|
||||
|
||||
# 启用转发 + SNAT(仅主机出网时)
|
||||
sysctl -w net.ipv4.ip_forward=1
|
||||
iptables -t nat -C POSTROUTING -s "$SUBNET" -o "$DEV_IF" -j MASQUERADE 2>/dev/null || \
|
||||
iptables -t nat -A POSTROUTING -s "$SUBNET" -o "$DEV_IF" -j MASQUERADE
|
||||
|
||||
# 尝试激活邻居学习
|
||||
REMOTE_BR_IP="172.16.0.$(( $(echo "$BRIDGE_IP" | awk -F. '{print $4}') == 2 ? 3 : 2 ))"
|
||||
ping -c 1 "$REMOTE_BR_IP" || true
|
||||
|
||||
# 展示结果
|
||||
echo ""
|
||||
echo "✅ VXLAN Overlay 已建立"
|
||||
echo " - bridge: $BR_IF ($BRIDGE_CIDR)"
|
||||
echo " - vxlan: $VXLAN_IF ($LOCAL_IP ⇄ $REMOTE_IP, id=$VNI, mtu=$MTU)"
|
||||
echo " - SNAT: $SUBNET → $DEV_IF"
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
---
|
||||
- name: Load site overlay config
|
||||
set_fact:
|
||||
overlay_data: "{{ lookup('file', overlay_config_path) | from_yaml }}"
|
||||
|
||||
- name: Select current site from config
|
||||
set_fact:
|
||||
current_site: "{{ overlay_data.sites | selectattr('name', 'equalto', inventory_hostname) | list | first }}"
|
||||
|
||||
- name: Fail if no matching site found
|
||||
fail:
|
||||
msg: "当前主机 {{ inventory_hostname }} 未在 config 中定义"
|
||||
when: current_site is not defined
|
||||
|
||||
- name: Select first hub as default
|
||||
set_fact:
|
||||
selected_hub: "{{ overlay_data.hubs[0] }}"
|
||||
|
||||
- name: Set VXLAN parameters
|
||||
set_fact:
|
||||
vxlan_dev_if: "{{ current_site.interface}}"
|
||||
vxlan_local_ip: "{{ current_site.local_ip }}"
|
||||
vxlan_remote_ip: "{{ current_site.remote_ip }}"
|
||||
vxlan_br_ip: "{{ current_site.br_ip }}"
|
||||
vxlan_cidr_suffix: "{{ overlay_data.vxlan_cidr_suffix | default(16) }}"
|
||||
vxlan_vni: "{{ overlay_data.vxlan_id | default(100) }}"
|
||||
|
||||
- name: 使用 rsync 分发 VXLAN 脚本
|
||||
synchronize:
|
||||
src: "files/setup_sit_vxlan.sh"
|
||||
dest: /tmp/setup_sit_vxlan.sh
|
||||
mode: push
|
||||
|
||||
- name: 移动脚本并赋权到 /usr/local/bin
|
||||
shell: |
|
||||
mv /tmp/setup_sit_vxlan.sh /usr/local/bin/setup_sit_vxlan.sh
|
||||
chmod +x /usr/local/bin/setup_sit_vxlan.sh
|
||||
become: true
|
||||
|
||||
- name: Render systemd unit for VXLAN
|
||||
template:
|
||||
src: vxlan-setup.service.j2
|
||||
dest: /etc/systemd/system/vxlan-setup.service
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload systemd daemon
|
||||
systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Enable and start VXLAN overlay setup
|
||||
systemd:
|
||||
name: vxlan-setup
|
||||
enabled: true
|
||||
state: started
|
||||
@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=VXLAN Overlay Setup for {{ inventory_hostname }}
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/setup_sit_vxlan.sh {{ vxlan_dev_if }} {{ vxlan_local_ip }} {{ vxlan_remote_ip }} {{ vxlan_br_ip }} {{ vxlan_cidr_suffix }} {{ vxlan_vni }}
|
||||
RemainAfterExit=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
8
ansible/playbooks/vpn-overlay.yaml
Normal file
8
ansible/playbooks/vpn-overlay.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
- name: Run infrastructure setup
|
||||
hosts: all
|
||||
become: yes
|
||||
gather_facts: yes
|
||||
vars:
|
||||
overlay_config_path: "{{ playbook_dir }}/../../config/sit/vpn-overlay.yaml"
|
||||
roles:
|
||||
- vhosts/vpn-overlay/vxlan/site
|
||||
@ -1,16 +1,16 @@
|
||||
# 基础网络参数
|
||||
wg_network: 10.100.0.0/24
|
||||
bridge_network: 172.16.0.0/16
|
||||
wg_network: 172.16.0.0/24
|
||||
bridge_network: 10.253.0.0/16
|
||||
vxlan_id: 100
|
||||
hub_port: 51820
|
||||
|
||||
# 全局功能开关
|
||||
features:
|
||||
enable_gretap: true # 是否开启 gretap 桥接(站点接入 Hub)
|
||||
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 架构)
|
||||
only_wireguard: false # 若为 true,仅使用 WireGuard 点对点,忽略 gretap/vxlan
|
||||
enable_vless: true # 是否通过 VLESS 中转 WG 流量
|
||||
enable_multi_hub: true # 是否支持多 Hub 架构(false 则为单 Hub star 架构)
|
||||
only_wireguard: false # 若为 true,仅使用 WireGuard 点对点,忽略 gretap/vxlan
|
||||
|
||||
# WireGuard Hub 节点配置
|
||||
hubs:
|
||||
@ -26,24 +26,23 @@ hubs:
|
||||
|
||||
# 各个站点定义
|
||||
sites:
|
||||
- name: site_a
|
||||
wg_ip: 10.100.0.2
|
||||
br_ip: 172.16.0.2
|
||||
hub: hub1
|
||||
public_ip: a.example.com
|
||||
- name: master-1
|
||||
interface: ens5
|
||||
br_ip: 10.253.253.2
|
||||
local_ip: 10.255.0.200
|
||||
remote_ip: 10.255.0.100
|
||||
vless:
|
||||
enabled: true
|
||||
endpoint: vless-a.example.com
|
||||
enabled: false
|
||||
uuid: "11111111-1111-1111-1111-111111111111"
|
||||
transport: ws
|
||||
tls: true
|
||||
path: /wg
|
||||
|
||||
- name: site_b
|
||||
wg_ip: 10.100.0.3
|
||||
br_ip: 172.16.0.3
|
||||
hub: hub1
|
||||
public_ip: b.example.com
|
||||
- name: slave-1
|
||||
interface: ens5
|
||||
br_ip: 10.253.253.3
|
||||
local_ip: 10.255.0.100
|
||||
remote_ip: 10.255.0.200
|
||||
vless:
|
||||
enabled: false # 此节点不通过 VLESS,直接访问 Hub
|
||||
|
||||
Loading…
Reference in New Issue
Block a user