Files
shell/proxy/l2tp.sh
2025-12-17 19:36:30 +08:00

458 lines
13 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
Red="\033[31m" # 红色
Green="\033[32m" # 绿色
Yellow="\033[33m" # 黄色
Blue="\033[34m" # 蓝色
Nc="\033[0m" # 重置颜色
Red_globa="\033[41;37m" # 红底白字
Green_globa="\033[42;37m" # 绿底白字
Yellow_globa="\033[43;37m" # 黄底白字
Blue_globa="\033[44;37m" # 蓝底白字
Info="${Green}[信息]${Nc}"
Error="${Red}[错误]${Nc}"
Tip="${Yellow}[提示]${Nc}"
# 检查是否为root用户
check_root(){
if [ -d "/proc/vz" ]; then
echo -e "${Error} 警告: 你的VPS基于OpenVZ内核可能不支持IPSec。"
echo -e "${Tip} L2TP安装已取消。"
exit 1
fi
if [ "$(id -u)" != "0" ]; then
echo -e "${Error} 当前非root用户(或没有root权限)无法继续操作请更换root用户或使用 ${Green_globa}sudo -i${Nc} 命令获取临时root权限。"
exit 1
fi
if [ ! -c "/dev/ppp" ]; then
echo -e "${Error} 警告: 当前内核不支持PPP无法安装L2TP。"
echo -e "${Tip} 当前内核版本: $(uname -r)"
echo -e "${Tip} 请更换为支持PPP的标准Linux内核。"
exit 1
fi
}
check_release(){
if [[ -e /etc/os-release ]]; then
. /etc/os-release
release=$ID
elif [[ -e /usr/lib/os-release ]]; then
. /usr/lib/os-release
release=$ID
fi
os_version=$(echo $VERSION_ID | cut -d. -f1,2)
if [[ "${release}" == "ol" ]]; then
release=oracle
elif [[ ! "${release}" =~ ^(kali|centos|ubuntu|fedora|debian|almalinux|rocky|alpine)$ ]]; then
echo -e "${Error} 抱歉,此脚本不支持您的操作系统。"
echo -e "${Info} 请确保您使用的是以下支持的操作系统之一:"
echo -e "-${Red} Ubuntu ${Nc}"
echo -e "-${Red} Debian ${Nc}"
echo -e "-${Red} CentOS ${Nc}"
echo -e "-${Red} Fedora ${Nc}"
echo -e "-${Red} Kali ${Nc}"
echo -e "-${Red} AlmaLinux ${Nc}"
echo -e "-${Red} Rocky Linux ${Nc}"
echo -e "-${Red} Oracle Linux ${Nc}"
echo -e "-${Red} Alpine Linux ${Nc}"
exit 1
fi
}
check_pmc(){
check_release
if [[ "$release" == "debian" || "$release" == "ubuntu" || "$release" == "kali" ]]; then
updates="apt update -y"
installs="apt install -y"
apps=("curl" "xl2tpd" "strongswan" "pptpd" "nftables")
elif [[ "$release" == "alpine" ]]; then
updates="apk update -f"
installs="apk add -f"
apps=("curl" "xl2tpd" "strongswan" "pptpd" "nftables")
elif [[ "$release" == "almalinux" || "$release" == "rocky" || "$release" == "oracle" ]]; then
updates="dnf update -y"
installs="dnf install -y"
check_install="dnf list installed"
apps=("curl" "xl2tpd" "strongswan" "pptpd" "nftables")
elif [[ "$release" == "centos" ]]; then
updates="yum update -y"
installs="yum install -y"
apps=("curl" "xl2tpd" "strongswan" "pptpd" "nftables")
elif [[ "$release" == "fedora" ]]; then
updates="dnf update -y"
installs="dnf install -y"
apps=("curl" "xl2tpd" "strongswan" "pptpd" "nftables")
fi
}
install_base(){
check_pmc
cmds=("curl" "xl2tpd" "ipsec" "pptpd" "nft")
echo -e "${Info} 你的系统是${Red} $release $os_version ${Nc}"
echo
for i in "${!cmds[@]}"; do
if ! which "${cmds[i]}" &>/dev/null; then
APPS+=("${apps[i]}")
fi
done
if [ ${#APPS[@]} -gt 0 ]; then
echo -e "${Tip} 正在安装依赖:${Green}${APPS[*]}${Nc} 请稍后..."
$updates &>/dev/null
$installs "${APPS[@]}" &>/dev/null
$installs ppp &>/dev/null
else
echo -e "${Info} 所有依赖已存在,不需要额外安装。"
fi
}
rand(){
local length=${1:-10}
local chars=({a..z} {A..Z} {0..9})
local str=""
for i in $(seq 1 $length); do
str+="${chars[$RANDOM%62]}"
done
echo "$str"
}
get_public_ip(){
InFaces=($(ls /sys/class/net | grep -E '^(eth|ens|eno|esp|enp|vif)'))
IP_API=(
"api64.ipify.org"
"4.ipw.cn"
"ip.sb"
"checkip.amazonaws.com"
"icanhazip.com"
"ipinfo.io/ip"
)
for iface in "${InFaces[@]}"; do
for ip_api in "${IP_API[@]}"; do
IPv4=$(curl -s4 --max-time 2 --interface "$iface" "$ip_api")
if [[ -n "$IPv4" ]]; then
inface="$iface"
break 2
fi
done
done
}
install_vpn(){
get_public_ip
set_conf
cat > /etc/ipsec.conf<<EOF
config setup
charondebug="ike 2, knl 2, cfg 2"
uniqueids=no
conn %default
keyexchange=ikev1
authby=secret
ike=aes256-sha1-modp1024,aes128-sha1-modp1024,3des-sha1-modp1024!
esp=aes256-sha1,aes128-sha1,3des-sha1!
keyingtries=3
ikelifetime=8h
lifetime=1h
dpdaction=clear
dpddelay=30s
dpdtimeout=120s
rekey=no
forceencaps=yes
fragmentation=yes
conn L2TP-PSK
left=%any
leftid=${IPv4}
leftfirewall=yes
leftprotoport=17/${l2tpport}
right=%any
rightprotoport=17/%any
type=transport
auto=add
also=%default
EOF
cat > /etc/ipsec.secrets<<EOF
%any %any : PSK "${l2tppsk}"
EOF
cat > /etc/xl2tpd/xl2tpd.conf<<EOF
[global]
port = ${l2tpport}
[lns default]
ip range = ${l2tplocip}.11-${l2tplocip}.255
local ip = ${l2tplocip}.1
require chap = yes
refuse pap = yes
require authentication = yes
name = l2tpd
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
EOF
cat > /etc/ppp/options.xl2tpd<<EOF
ipcp-accept-local
ipcp-accept-remote
require-mschap-v2
ms-dns 8.8.8.8
ms-dns 114.114.114.114
noccp
auth
hide-password
idle 1800
mtu 1410
mru 1410
nodefaultroute
debug
proxyarp
connect-delay 5000
EOF
cat > /etc/pptpd.conf<<EOF
option /etc/ppp/pptpd-options
debug
localip ${pptplocip}.1
remoteip ${pptplocip}.11-255
EOF
cat > /etc/ppp/pptpd-options<<EOF
name pptpd
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
require-mppe-128
ms-dns 8.8.8.8
ms-dns 114.114.114.114
proxyarp
lock
nobsdcomp
novj
novjccomp
nologfd
EOF
cat > /etc/ppp/chap-secrets <<EOF
# Secrets for authentication using CHAP
# client server secret IP addresses
EOF
for num in $(seq 11 255); do
echo "${l2tpuser}${num} l2tpd ${l2tppass}${num} ${l2tplocip}.${num}" >> /etc/ppp/chap-secrets
done
for num in $(seq 11 255); do
echo "${pptpuser}${num} pptpd ${pptppass}${num} ${pptplocip}.${num}" >> /etc/ppp/chap-secrets
done
set_icmp
set_nftables
}
set_icmp(){
seticmp1="net.ipv4.ip_forward=1"
seticmp2="net.ipv4.conf.all.send_redirects=0"
seticmp3="net.ipv4.conf.default.send_redirects=0"
seticmp4="net.ipv4.conf.all.accept_redirects=0"
seticmp5="net.ipv4.conf.default.accept_redirects=0"
for seticmp in "$seticmp1" "$seticmp2" "$seticmp3" "$seticmp4" "$seticmp5"; do
if grep -qE "^\s*${seticmp%=*}\s*=" /etc/sysctl.conf; then
sed -i "s|^\s*${seticmp%=*}\s*=.*|${seticmp}|g" /etc/sysctl.conf
else
echo "$seticmp" >> /etc/sysctl.conf
fi
done
sysctl -p &> /dev/null
}
set_nftables(){
[ -f /etc/nftables.conf ] && cp -pf /etc/nftables.conf /etc/nftables.conf.old.`date +%Y%m%d`
cat > /etc/nftables.conf <<EOF
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
ct state established,related accept
ip protocol icmp accept
iif lo accept
udp dport {500,4500,${l2tpport},${pptpport}} accept
accept
}
chain forward {
type filter hook forward priority 0;
ct state established,related accept
ip saddr ${l2tplocip}.0/24 accept
ip saddr ${pptplocip}.0/24 accept
accept
}
chain output {
type filter hook output priority 0;
accept
}
}
table ip nat {
chain prerouting {
type nat hook prerouting priority 0;
accept
}
chain postrouting {
type nat hook postrouting priority 100;
oif "${inface}" masquerade
}
chain output {
type nat hook output priority 0;
accept
}
}
EOF
systemctl daemon-reload
systemctl enable nftables
systemctl restart nftables
}
vpn_start(){
systemctl daemon-reload
systemctl enable ipsec
systemctl enable xl2tpd
systemctl enable pptpd
echo 1 > /proc/sys/net/ipv4/ip_forward
systemctl restart ipsec
systemctl restart xl2tpd
systemctl restart pptpd
}
set_conf(){
echo
# L2tp
echo -e "${Tip} 请输入L2tpIP范围:"
read -p "(默认范围: 10.10.10):" l2tplocip
[ -z "${l2tplocip}" ] && l2tplocip="10.10.10"
echo -e "${Tip} 请输入L2tp端口:"
read -p "(默认端口: 1701):" l2tpport
[ -z "${l2tpport}" ] && l2tpport=1701
# 端口范围检查
while ! [[ "$l2tpport" =~ ^[0-9]+$ ]] || [ "$l2tpport" -lt 1000 ] || [ "$l2tpport" -gt 65535 ]; do
echo -e "${Error} 端口必须为1000-65535之间的数字"
read -p "请重新输入端口 (1000-65535):" l2tpport
[ -z "${l2tpport}" ] && l2tpport=1701
done
l2tpuser=$(rand 5)
echo -e "${Tip} 请输入L2tp用户名:"
read -p "(默认用户名: ${l2tpuser}):" tmpl2tpuser
[ -n "${tmpl2tpuser}" ] && l2tpuser="${tmpl2tpuser}"
l2tppass=$(rand 7)
echo -e "${Tip} 请输入 ${l2tpuser} 的密码:"
read -p "(默认密码: ${l2tppass}):" tmpl2tppass
[ -n "${tmpl2tppass}" ] && l2tppass="${tmpl2tppass}"
l2tppsk=$(rand 20)
echo -e "${Tip} 请输入L2tp PSK密钥:"
read -p "(默认PSK: ${l2tppsk}):" tmppsk
[ -n "${tmppsk}" ] && l2tppsk="${tmppsk}"
# Pptp
echo -e "${Tip} 请输入Pptp IP范围:"
read -p "(默认范围: 192.168.30):" pptplocip
[ -z "${pptplocip}" ] && pptplocip="192.168.30"
echo -e "${Tip} 请输入Pptp端口:"
read -p "(默认端口: 1723):" pptpport
[ -z "${pptpport}" ] && pptpport=1723
# 端口范围检查
while ! [[ "$pptpport" =~ ^[0-9]+$ ]] || [ "$pptpport" -lt 1000 ] || [ "$pptpport" -gt 65535 ]; do
echo -e "${Error} 端口必须为1000-65535之间的数字"
read -p "请重新输入端口 (1000-65535):" l2tpport
[ -z "${pptpport}" ] && pptpport=1723
done
pptpuser=$(rand 5)
echo -e "${Tip} 请输入Pptp用户名:"
read -p "(默认用户名: ${pptpuser}):" tmppptpuser
[ -n "${tmppptpuser}" ] && pptpuser="${tmppptpuser}"
pptppass=$(rand 7)
echo -e "${Tip} 请输入 ${pptpuser} 的密码:"
read -p "(默认密码: ${pptppass}):" tmppptppass
[ -n "${tmppptppass}" ] && pptppass="${tmppptppass}"
echo
echo -e "${Info} L2tp服务器本地IP: ${Green}${l2tplocip}.1${Nc}"
echo -e "${Info} L2tp客户端IP范围: ${Green}${l2tplocip}.11-${l2tplocip}.255${Nc}"
echo -e "${Info} L2tp端口 : ${Green}${l2tpport}${Nc}"
echo -e "${Info} L2tp用户名 : ${Green}${l2tpuser}${Nc}"
echo -e "${Info} L2tp密码 : ${Green}${l2tppass}${Nc}"
echo -e "${Info} L2tpPSK密钥 : ${Green}${l2tppsk}${Nc}"
echo
echo -e "${Info} Pptp服务器本地IP: ${Green}${pptplocip}.1${Nc}"
echo -e "${Info} Pptp客户端IP范围: ${Green}${pptplocip}.11-${pptplocip}.255${Nc}"
echo -e "${Info} Pttp端口 : ${Green}${pptpport}${Nc}"
echo -e "${Info} Pttp用户名 : ${Green}${pptpuser}${Nc}"
echo -e "${Info} Pttp密码 : ${Green}${pptppass}${Nc}"
echo
}
finally(){
echo "请稍候..."
sleep 3
vpn_start
echo
echo "###############################################################"
echo "# VPN 安装脚本 #"
echo "###############################################################"
echo
echo -e "${Info} 默认用户名和密码如下:"
echo
echo -e "${Info} 服务器IP: ${Green}${IPv4}${Nc}"
echo
echo -e "${Info} L2tp端口 : ${Green}${l2tpport}${Nc}"
echo -e "${Info} L2tp用户名 : ${Green}${l2tpuser}${Nc}"
echo -e "${Info} L2tp密码 : ${Green}${l2tppass}${Nc}"
echo -e "${Info} L2tpPSK密钥 : ${Green}${l2tppsk}${Nc}"
echo
echo -e "${Info} Pttp端口 : ${Green}${pptpport}${Nc}"
echo -e "${Info} Pttp用户名 : ${Green}${pptpuser}${Nc}"
echo -e "${Info} Pttp密码 : ${Green}${pptppass}${Nc}"
echo
echo -e "${Info} 完整的用户配置请查看 ${Green}/etc/ppp/chap-secrets${Nc} 文件"
echo
}
vpn(){
clear
echo
echo "###############################################################"
echo "# VPN 安装脚本 #"
echo "###############################################################"
echo
check_root
install_base
install_vpn
finally
}
vpn