此脚本整合所有配置,支持动态适配多内网场景,无需预设内网地址,执行后仅需添加账号即可实现“接入即互通”。

一键部署脚本(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,按菜单提示操作(支持新增、删除、查看账号,及清理过期内网记录)。

脚本会自动校验账号唯一性和内网段格式,避免配置错误。后续若需要为账号添加“流量限制”或“有效期”功能,要不要我帮你进一步升级这个管理脚本?

标签: L2TP, LIPsec

添加新评论