多内网动态互通 L2TP/IPsec 一键部署脚本
此脚本整合所有配置,支持动态适配多内网场景,无需预设内网地址,执行后仅需添加账号即可实现“接入即互通”。
一键部署脚本(root权限执行)
!/bin/bash
clear
echo "=== 多内网动态互通 L2TP/IPsec 一键部署脚本 ==="
-------------------------- 1. 基础配置(需手动修改以下3项)--------------------------
SERVER_PUBLIC_IP="你的服务器公网IP" # 替换为中继服务器公网IP
VPN_PSK="123456abc" # 自定义IPsec预共享密钥(如123@VPN2024)
VPN_VIRTUAL_SUBNET="10.0.0.0/24" # VPN虚拟网段(避免与内网冲突,默认无需改)
VPN_IP_RANGE="10.0.0.10-10.0.0.50" # 分配给客户端的虚拟IP范围
-------------------------------------------------------------------------------------
echo "1. 环境初始化..."
关闭防火墙与SELinux
systemctl stop firewalld && systemctl disable firewalld >/dev/null 2>&1
setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config >/dev/null 2>&1
安装依赖
yum install -y libreswan xl2tpd ppp iptables-services >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "依赖安装失败,请检查yum源!"
exit 1
fi
echo "2. 配置 IPsec (libreswan)..."
写入IPsec主配置
cat > /etc/ipsec.conf << EOF
version 2.0
config setup
protostack=netkey
nat_traversal=yes
virtual_private=%v4:${VPN_VIRTUAL_SUBNET%,*}
conn L2TP-IPsec
auto=add
left=${SERVER_PUBLIC_IP}
leftid=${SERVER_PUBLIC_IP}
leftsubnet=0.0.0.0/0
right=%any
rightsubnet=${VPN_VIRTUAL_SUBNET}
rightprotoport=17/1701
authby=secret
pfs=no
type=transport
ike=aes256-sha1
phase2alg=aes256-sha1
EOF
写入预共享密钥
echo "${SERVER_PUBLIC_IP} %any : PSK \"${VPN_PSK}\"" > /etc/ipsec.secrets
echo "3. 配置 L2TP (xl2tpd)..."
写入xl2tpd主配置
cat > /etc/xl2tpd/xl2tpd.conf << EOF
[global]
ipsec saref = yes
[lns default]
ip range = ${VPN_IP_RANGE}
local ip = ${VPN_VIRTUAL_SUBNET%.*}.1
require chap = yes
refuse pap = yes
require authentication = yes
name = L2TP-Server
pppoptfile = /etc/ppp/options.xl2tpd
EOF
写入PPP配置
cat > /etc/ppp/options.xl2tpd << EOF
ms-dns 8.8.8.8
ms-dns 114.114.114.114
auth
crtscts
mtu 1400
mru 1400
lock
connect-delay 5000
EOF
echo "4. 创建动态内网转发脚本..."
动态记录内网段并配置转发的脚本
cat > /etc/ppp/ip-up.d/record-subnet << EOF
!/bin/bash
记录客户端VPN IP与绑定的内网段
CLIENT_VPN_IP=$4
CLIENT_SUBNET=$PEER_SUBNET
if [ -z "$CLIENT_SUBNET" ]; then
echo "警告:客户端未绑定内网段,无法互通!"
exit 0
fi
存储映射关系(去重)
grep -q "$CLIENT_SUBNET" /etc/ppp/client-subnets.txt || echo "$CLIENT_VPN_IP $CLIENT_SUBNET" >> /etc/ppp/client-subnets.txt
动态添加互通转发规则
for SUBNET in $(awk '{print $2}' /etc/ppp/client-subnets.txt); do
iptables -C FORWARD -s \$CLIENT_SUBNET -d \$SUBNET -j ACCEPT 2>/dev/null || iptables -A FORWARD -s \$CLIENT_SUBNET -d \$SUBNET -j ACCEPT
iptables -C FORWARD -s \$SUBNET -d \$CLIENT_SUBNET -j ACCEPT 2>/dev/null || iptables -A FORWARD -s \$SUBNET -d \$CLIENT_SUBNET -j ACCEPT
done
EOF
赋予脚本权限
chmod +x /etc/ppp/ip-up.d/record-subnet
touch /etc/ppp/client-subnets.txt # 初始化内网段存储文件
echo "5. 配置 iptables 与路由转发..."
开启路由转发
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p >/dev/null 2>&1
配置iptables规则
iptables -F && iptables -t nat -F
允许VPN基础流量
iptables -A INPUT -p udp --dport 500 -j ACCEPT
iptables -A INPUT -p udp --dport 4500 -j ACCEPT
iptables -A INPUT -p udp --dport 1701 -j ACCEPT
允许访问服务器自身
iptables -A FORWARD -d ${SERVER_PUBLIC_IP} -j ACCEPT
iptables -A FORWARD -s ${SERVER_PUBLIC_IP} -j ACCEPT
保存规则并启动iptables
service iptables save >/dev/null 2>&1
systemctl start iptables && systemctl enable iptables >/dev/null 2>&1
echo "6. 启动服务并验证..."
启动服务
systemctl start ipsec && systemctl enable ipsec >/dev/null 2>&1
systemctl start xl2tpd && systemctl enable xl2tpd >/dev/null 2>&1
验证服务状态
IPSEC_STATUS=$(ipsec status | grep "ESTABLISHED" | wc -l)
XL2TPD_STATUS=$(systemctl is-active xl2tpd)
if [ ${IPSEC_STATUS} -ge 0 ] && [ "${XL2TPD_STATUS}" = "active" ]; then
echo -e "\n=== 部署成功!==="
echo "1. 基础信息:"
echo " - 服务器公网IP:${SERVER_PUBLIC_IP}"
echo " - IPsec预共享密钥:${VPN_PSK}"
echo " - VPN虚拟网段:${VPN_VIRTUAL_SUBNET}"
echo -e "\n2. 添加客户端账号(示例):"
echo ' echo "vpn-user * user-pass * \"PEER_SUBNET=客户端内网段/24\"" >> /etc/ppp/chap-secrets'
echo " (替换 vpn-user/user-pass/客户端内网段 为实际信息,每个客户端一行)"
echo -e "\n3. 查看已接入内网段:cat /etc/ppp/client-subnets.txt"
else
echo -e "\n部署失败!请检查服务状态:"
echo "ipsec status && systemctl status xl2tpd"
exit 1
fi
使用说明
1. 脚本修改:复制脚本到服务器后,先修改开头“基础配置”部分的3个参数(服务器公网IP、PSK密钥、虚拟网段,虚拟网段默认无需改)。
2. 执行脚本:赋予权限并执行 chmod +x l2tp-multi-subnet.sh && ./l2tp-multi-subnet.sh。
3. 添加客户端:按脚本输出的示例,执行命令添加账号(关键是绑定PEER_SUBNET为客户端内网段,如192.168.3.0/24)。
部署后,客户端拨号成功即会自动与其他已接入的内网互通,且访问外网时使用自有公网IP。需要我帮你生成一个“客户端账号管理脚本”吗?支持一键添加、删除和查看账号,更方便后续维护。
L2TP客户端账号管理脚本(一键添加/删除/查看)
该脚本可快速管理L2TP账号,自动校验内网段格式,避免手动修改配置文件出错,适配多内网动态互通场景。
账号管理脚本(保存为 vpn-account-manager.sh)
!/bin/bash
clear
CHAP_SECRETS="/etc/ppp/chap-secrets"
CLIENT_SUBNETS="/etc/ppp/client-subnets.txt"
显示菜单
show_menu() {
echo "=== L2TP客户端账号管理工具 ==="
echo "1. 新增账号(需绑定内网段)"
echo "2. 删除账号"
echo "3. 查看所有账号"
echo "4. 清空过期内网段记录"
echo "5. 退出"
echo -n "请选择操作(1-5):"
read OPTION
}
1. 新增账号
add_account() {
echo -e "\n--- 新增L2TP账号 ---"
echo -n "输入账号名:"
read USERNAME
# 校验账号是否已存在
if grep -q "^${USERNAME}\s" ${CHAP_SECRETS}; then
echo "错误:账号 ${USERNAME} 已存在!"
return 1
fi
echo -n "输入账号密码:"
read -s PASSWORD
echo -n -e "\n输入客户端内网段(如192.168.1.0/24):"
read SUBNET
# 校验内网段格式(简单正则,匹配x.x.x.x/x)
if ! echo ${SUBNET} | grep -qE '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$'; then
echo "错误:内网段格式无效!正确格式如192.168.1.0/24"
return 1
fi
# 写入账号配置
echo "${USERNAME} * ${PASSWORD} * \"PEER_SUBNET=${SUBNET}\"" >> ${CHAP_SECRETS}
echo -e "\n账号 ${USERNAME} 新增成功!"
echo "绑定内网段:${SUBNET}(客户端拨号后自动互通)"
}
2. 删除账号
delete_account() {
echo -e "\n--- 删除L2TP账号 ---"
echo "当前所有账号:"
grep -v "^#" ${CHAP_SECRETS} | awk '{print "账号:"$1" | 绑定内网段:"$5}' | sed 's/"PEER_SUBNET=//;s/"//'
if [ $? -ne 0 ]; then
echo "暂无账号!"
return 1
fi
echo -n -e "\n输入要删除的账号名:"
read USERNAME
if ! grep -q "^${USERNAME}\s" ${CHAP_SECRETS}; then
echo "错误:账号 ${USERNAME} 不存在!"
return 1
fi
# 删除账号(保留文件原有格式)
sed -i "/^${USERNAME}\s/d" ${CHAP_SECRETS}
# (可选)删除对应内网段记录(若需彻底清理)
SUBNET=$(grep -o "\"PEER_SUBNET=.*\"" ${CHAP_SECRETS} | grep -B1 "${USERNAME}" | sed 's/"PEER_SUBNET=//;s/"//' 2>/dev/null)
if [ -n "${SUBNET}" ]; then
sed -i "/${SUBNET}/d" ${CLIENT_SUBNETS}
fi
echo "账号 ${USERNAME} 删除成功!"
}
3. 查看所有账号
list_accounts() {
echo -e "\n--- 所有L2TP账号信息 ---"
echo "=================================================="
echo "账号名 | 绑定内网段 | 状态(是否在线)"
echo "=================================================="
# 遍历所有账号,显示信息并判断是否在线(通过VPN虚拟IP)
while read LINE; do
USER=$(echo ${LINE} | awk '{print $1}')
SUBNET=$(echo ${LINE} | awk '{print $5}' | sed 's/"PEER_SUBNET=//;s/"//')
# 检查是否在线(VPN虚拟IP是否存在)
VPN_IP=$(grep "${SUBNET}" ${CLIENT_SUBNETS} | awk '{print $1}' 2>/dev/null)
STATUS="离线"
if [ -n "${VPN_IP}" ] && ip addr | grep -q "${VPN_IP}"; then
STATUS="在线(${VPN_IP})"
fi
# 格式化输出(对齐显示)
printf "%-12s| %-16s| %s\n" "${USER}" "${SUBNET}" "${STATUS}"
done < <(grep -v "^#" ${CHAP_SECRETS})
echo "=================================================="
}
4. 清空过期内网段记录
clean_subnets() {
echo -e "\n--- 清空过期内网段记录 ---"
echo "当前已记录的内网段:"
cat ${CLIENT_SUBNETS} | awk '{print "内网段:"$2"(VPN IP:"$1")"}'
if [ ! -s ${CLIENT_SUBNETS} ]; then
echo "无过期记录可清理!"
return 1
fi
echo -n "确认清空所有内网段记录?(y/n):"
read CONFIRM
if [ "${CONFIRM}" = "y" ] || [ "${CONFIRM}" = "Y" ]; then
> ${CLIENT_SUBNETS} # 清空文件
echo "清空成功!下次客户端拨号会重新记录有效内网段"
else
echo "取消操作!"
fi
}
主逻辑
while true; do
show_menu
case ${OPTION} in
1) add_account ;;
2) delete_account ;;
3) list_accounts ;;
4) clean_subnets ;;
5) echo -e "\n退出管理工具!"; exit 0 ;;
*) echo "无效选项,请重新选择!" ;;
esac
echo -e "\n按任意键返回菜单..."
read -n 1
clear
done
使用方法
1. 脚本部署:将上述代码复制到服务器,保存为 vpn-account-manager.sh。
2. 赋予权限:执行 chmod +x vpn-account-manager.sh。
3. 运行管理:执行 ./vpn-account-manager.sh,按菜单提示操作(支持新增、删除、查看账号,及清理过期内网记录)。
脚本会自动校验账号唯一性和内网段格式,避免配置错误。后续若需要为账号添加“流量限制”或“有效期”功能,要不要我帮你进一步升级这个管理脚本?