456 lines
13 KiB
Bash
456 lines
13 KiB
Bash
#!/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
|
||
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
|
||
proxyarp
|
||
lock
|
||
nobsdcomp
|
||
novj
|
||
novjccomp
|
||
nologfd
|
||
|
||
EOF
|
||
|
||
cat > /etc/ppp/chap-secrets <<EOF
|
||
# Secrets for authentication using CHAP
|
||
# client server secret IP addresses
|
||
${l2tpuser} l2tpd ${l2tppass} ${l2tplocip}.10
|
||
${pptpuser} pptpd ${pptppass} ${pptplocip}.10
|
||
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
|