mirror of
https://github.com/TheyCallMeSecond/sing-box-manager.git
synced 2024-11-16 19:56:10 +08:00
505 lines
14 KiB
Plaintext
505 lines
14 KiB
Plaintext
# 函数:根据系统版本自动安装依赖
|
||
install_dependencies() {
|
||
local os_version
|
||
os_version=$(lsb_release -si 2>/dev/null)
|
||
|
||
local dependencies
|
||
local common_dependencies="wget tar socat jq git openssl"
|
||
|
||
case "$os_version" in
|
||
Debian|Ubuntu)
|
||
dependencies="$common_dependencies uuid-runtime build-essential zlib1g-dev libssl-dev libevent-dev"
|
||
;;
|
||
CentOS)
|
||
dependencies="$common_dependencies util-linux gcc-c++ zlib-devel openssl-devel libevent-devel"
|
||
;;
|
||
*)
|
||
echo "不支持的操作系统: $os_version"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
if ! command -v apt-get &> /dev/null && ! command -v dnf &> /dev/null && ! command -v yum &> /dev/null; then
|
||
echo "不支持的包管理器,无法继续安装依赖。"
|
||
exit 1
|
||
fi
|
||
|
||
echo "更新软件包列表..."
|
||
if command -v apt-get &> /dev/null; then
|
||
apt-get update
|
||
elif command -v dnf &> /dev/null; then
|
||
dnf makecache
|
||
elif command -v yum &> /dev/null; then
|
||
yum makecache
|
||
fi
|
||
|
||
echo "下载并安装依赖..."
|
||
if command -v apt-get &> /dev/null; then
|
||
apt-get install -y $dependencies
|
||
elif command -v dnf &> /dev/null; then
|
||
dnf install -y $dependencies
|
||
elif command -v yum &> /dev/null; then
|
||
yum install -y $dependencies
|
||
fi
|
||
|
||
echo "依赖已安装。"
|
||
}
|
||
|
||
|
||
|
||
# 检查防火墙配置
|
||
function check_firewall_configuration() {
|
||
local os_name=$(uname -s)
|
||
local firewall
|
||
|
||
if [[ $os_name == "Linux" ]]; then
|
||
if command -v ufw >/dev/null 2>&1 && ufw status | grep -q "Status: active"; then
|
||
firewall="ufw"
|
||
elif command -v iptables >/dev/null 2>&1 && iptables -S | grep -q "INPUT -j DROP"; then
|
||
firewall="iptables"
|
||
elif command -v firewalld >/dev/null 2>&1 && firewall-cmd --state | grep -q "running"; then
|
||
firewall="firewalld"
|
||
fi
|
||
fi
|
||
|
||
if [[ -z $firewall ]]; then
|
||
echo "未检测到防火墙配置或防火墙未启用,跳过配置防火墙。"
|
||
return
|
||
fi
|
||
|
||
echo "检查防火墙配置..."
|
||
|
||
case $firewall in
|
||
ufw)
|
||
if ! ufw status | grep -q "Status: active"; then
|
||
ufw enable
|
||
fi
|
||
|
||
if ! ufw status | grep -q " $listen_port"; then
|
||
ufw allow "$listen_port"
|
||
fi
|
||
|
||
if ! ufw status | grep -q " $override_port"; then
|
||
ufw allow "$override_port"
|
||
fi
|
||
|
||
if ! ufw status | grep -q " 80"; then
|
||
ufw allow 80
|
||
fi
|
||
|
||
echo "防火墙配置已更新。"
|
||
;;
|
||
iptables)
|
||
if ! iptables -C INPUT -p tcp --dport "$listen_port" -j ACCEPT >/dev/null 2>&1; then
|
||
iptables -A INPUT -p tcp --dport "$listen_port" -j ACCEPT
|
||
fi
|
||
|
||
if ! iptables -C INPUT -p udp --dport "$listen_port" -j ACCEPT >/dev/null 2>&1; then
|
||
iptables -A INPUT -p udp --dport "$listen_port" -j ACCEPT
|
||
fi
|
||
|
||
if ! iptables -C INPUT -p tcp --dport "$override_port" -j ACCEPT >/dev/null 2>&1; then
|
||
iptables -A INPUT -p tcp --dport "$override_port" -j ACCEPT
|
||
fi
|
||
|
||
if ! iptables -C INPUT -p udp --dport "$override_port" -j ACCEPT >/dev/null 2>&1; then
|
||
iptables -A INPUT -p udp --dport "$override_port" -j ACCEPT
|
||
fi
|
||
|
||
if ! iptables -C INPUT -p tcp --dport 80 -j ACCEPT >/dev/null 2>&1; then
|
||
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
|
||
fi
|
||
|
||
if ! iptables -C INPUT -p udp --dport 80 -j ACCEPT >/dev/null 2>&1; then
|
||
iptables -A INPUT -p udp --dport 80 -j ACCEPT
|
||
fi
|
||
|
||
iptables-save > /etc/sysconfig/iptables
|
||
|
||
echo "iptables防火墙配置已更新。"
|
||
;;
|
||
firewalld)
|
||
if ! firewall-cmd --zone=public --list-ports | grep -q "$listen_port/tcp"; then
|
||
firewall-cmd --zone=public --add-port="$listen_port/tcp" --permanent
|
||
fi
|
||
|
||
if ! firewall-cmd --zone=public --list-ports | grep -q "$listen_port/udp"; then
|
||
firewall-cmd --zone=public --add-port="$listen_port/udp" --permanent
|
||
fi
|
||
|
||
if ! firewall-cmd --zone=public --list-ports | grep -q "$override_port/tcp"; then
|
||
firewall-cmd --zone=public --add-port="$override_port/tcp" --permanent
|
||
fi
|
||
|
||
if ! firewall-cmd --zone=public --list-ports | grep -q "$override_port/udp"; then
|
||
firewall-cmd --zone=public --add-port="$override_port/udp" --permanent
|
||
fi
|
||
|
||
if ! firewall-cmd --zone=public --list-ports | grep -q "80/tcp"; then
|
||
firewall-cmd --zone=public --add-port=80/tcp --permanent
|
||
fi
|
||
|
||
if ! firewall-cmd --zone=public --list-ports | grep -q "80/udp"; then
|
||
firewall-cmd --zone=public --add-port=80/udp --permanent
|
||
fi
|
||
|
||
firewall-cmd --reload
|
||
|
||
echo "firewalld防火墙配置已更新。"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# 检查 sing-box 文件夹是否存在,如果不存在则创建
|
||
function check_sing_box_folder() {
|
||
local folder="/usr/local/etc/sing-box"
|
||
if [[ ! -d "$folder" ]]; then
|
||
mkdir -p "$folder"
|
||
fi
|
||
}
|
||
|
||
# 函数:开启 BBR
|
||
enable_bbr() {
|
||
if ! grep -q "net.core.default_qdisc=fq" /etc/sysctl.conf; then
|
||
echo "开启 BBR..."
|
||
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
|
||
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
|
||
sysctl -p
|
||
echo "BBR 已开启"
|
||
else
|
||
echo "BBR 已经开启,跳过配置。"
|
||
fi
|
||
}
|
||
|
||
# 选择安装方式
|
||
function select_sing_box_install_option() {
|
||
while true; do
|
||
echo "请选择 sing-box 的安装方式:"
|
||
echo " [1]. 编译安装sing-box(支持全部功能)"
|
||
echo " [2]. 下载安装sing-box(支持部分功能)"
|
||
|
||
local install_option
|
||
read -p "请选择 [1-2]: " install_option
|
||
|
||
case $install_option in
|
||
1)
|
||
install_go
|
||
compile_install_sing_box
|
||
break
|
||
;;
|
||
2)
|
||
install_latest_sing_box
|
||
break
|
||
;;
|
||
*)
|
||
echo "无效的选择,请重新输入。"
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# 函数:检查并安装 Go
|
||
install_go() {
|
||
if ! command -v go &> /dev/null; then
|
||
echo "下载并安装 Go..."
|
||
local go_arch
|
||
case $(uname -m) in
|
||
x86_64)
|
||
go_arch="amd64"
|
||
;;
|
||
i686)
|
||
go_arch="386"
|
||
;;
|
||
aarch64)
|
||
go_arch="arm64"
|
||
;;
|
||
armv6l)
|
||
go_arch="armv6l"
|
||
;;
|
||
*)
|
||
echo "不支持的架构: $(uname -m)"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
# 获取最新版本的 Go 下载链接
|
||
local go_version
|
||
go_version=$(curl -sL "https://golang.org/VERSION?m=text")
|
||
local go_download_url="https://go.dev/dl/$go_version.linux-$go_arch.tar.gz"
|
||
|
||
# 假定 wget 已经安装,直接下载安装包
|
||
wget -c "$go_download_url" -O - | tar -xz -C /usr/local
|
||
echo 'export PATH=$PATH:/usr/local/go/bin' | tee -a /etc/profile
|
||
source /etc/profile
|
||
go version
|
||
|
||
echo "Go 已安装"
|
||
else
|
||
echo "Go 已经安装,跳过安装步骤。"
|
||
fi
|
||
}
|
||
|
||
#编译安装sing-box
|
||
function compile_install_sing_box() {
|
||
local go_install_command="go install -v -tags \
|
||
with_quic,\
|
||
with_grpc,\
|
||
with_dhcp,\
|
||
with_wireguard,\
|
||
with_shadowsocksr,\
|
||
with_ech,\
|
||
with_utls,\
|
||
with_reality_server,\
|
||
with_acme,\
|
||
with_clash_api,\
|
||
with_v2ray_api,\
|
||
with_gvisor,\
|
||
with_lwip \
|
||
github.com/sagernet/sing-box/cmd/sing-box@latest"
|
||
|
||
echo "正在编译安装 sing-box,请稍候..."
|
||
$go_install_command
|
||
|
||
if [[ $? -eq 0 ]]; then
|
||
mv ~/go/bin/sing-box /usr/local/bin/
|
||
chmod +x /usr/local/bin/sing-box
|
||
echo "sing-box 编译安装成功"
|
||
else
|
||
echo "sing-box 编译安装失败"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 下载并安装最新的 Sing-Box 版本
|
||
function install_latest_sing_box() {
|
||
local arch=$(uname -m)
|
||
local url="https://api.github.com/repos/SagerNet/sing-box/releases/latest"
|
||
local download_url
|
||
|
||
# 根据 VPS 架构确定合适的下载 URL
|
||
case $arch in
|
||
x86_64)
|
||
download_url=$(curl -s $url | grep -o "https://github.com[^\"']*linux-amd64.tar.gz")
|
||
;;
|
||
armv7l)
|
||
download_url=$(curl -s $url | grep -o "https://github.com[^\"']*linux-armv7.tar.gz")
|
||
;;
|
||
aarch64)
|
||
download_url=$(curl -s $url | grep -o "https://github.com[^\"']*linux-arm64.tar.gz")
|
||
;;
|
||
amd64v3)
|
||
download_url=$(curl -s $url | grep -o "https://github.com[^\"']*linux-amd64v3.tar.gz")
|
||
;;
|
||
*)
|
||
echo -e "${RED}不支持的架构:$arch${NC}"
|
||
return 1
|
||
;;
|
||
esac
|
||
|
||
# 下载并安装 Sing-Box
|
||
if [ -n "$download_url" ]; then
|
||
echo "正在下载 Sing-Box..."
|
||
curl -L -o sing-box.tar.gz "$download_url"
|
||
tar -xzf sing-box.tar.gz -C /usr/local/bin --strip-components=1
|
||
rm sing-box.tar.gz
|
||
|
||
# 赋予可执行权限
|
||
chmod +x /usr/local/bin/sing-box
|
||
|
||
echo "Sing-Box 安装成功!"
|
||
else
|
||
echo -e "${RED}无法获取 Sing-Box 的下载 URL。${NC}"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 配置 sing-box 开机自启服务
|
||
function configure_sing_box_service() {
|
||
echo "配置 sing-box 开机自启服务..."
|
||
local service_file="/etc/systemd/system/sing-box.service"
|
||
|
||
if [[ -f $service_file ]]; then
|
||
rm "$service_file"
|
||
fi
|
||
|
||
local service_config='[Unit]
|
||
Description=sing-box service
|
||
Documentation=https://sing-box.sagernet.org
|
||
After=network.target nss-lookup.target
|
||
|
||
[Service]
|
||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
||
ExecStart=/usr/local/bin/sing-box run -c /usr/local/etc/sing-box/config.json
|
||
Restart=on-failure
|
||
RestartSec=1800s
|
||
LimitNOFILE=infinity
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target'
|
||
|
||
echo "$service_config" >"$service_file"
|
||
echo "sing-box 开机自启动服务已配置。"
|
||
systemctl daemon-reload
|
||
}
|
||
|
||
|
||
# 函数:读取上行速度
|
||
function read_up_speed() {
|
||
while true; do
|
||
read -p "请输入上行速度 (默认100 Mbps): " up_speed
|
||
up_speed=${up_speed:-100}
|
||
|
||
if [[ $up_speed =~ ^[0-9]+$ ]]; then
|
||
echo "上行速度设置成功:${up_speed} Mbps"
|
||
break
|
||
else
|
||
echo "错误:请输入一个有效的数字。"
|
||
fi
|
||
done
|
||
}
|
||
|
||
# 函数:读取下行速度
|
||
function read_down_speed() {
|
||
while true; do
|
||
read -p "请输入下行速度 (默认100 Mbps): " down_speed
|
||
down_speed=${down_speed:-100}
|
||
|
||
if [[ $down_speed =~ ^[0-9]+$ ]]; then
|
||
echo "下行速度设置成功:${down_speed} Mbps"
|
||
break
|
||
else
|
||
echo "错误:请输入一个有效的数字。"
|
||
fi
|
||
done
|
||
}
|
||
|
||
# 函数:读取认证密码
|
||
function read_auth_password() {
|
||
read -p "请输入认证密码 (留空表示随机生成): " auth_password
|
||
|
||
if [[ -z "$auth_password" ]]; then
|
||
auth_password=$(openssl rand -base64 32)
|
||
echo "随机生成的认证密码为:${auth_password}"
|
||
fi
|
||
}
|
||
|
||
# 函数:读取多用户信息
|
||
function read_multi_users() {
|
||
local users=()
|
||
|
||
while true; do
|
||
read -p "是否继续添加用户?(Y/N): " add_multiple_users
|
||
|
||
if [[ "$add_multiple_users" == "Y" || "$add_multiple_users" == "y" ]]; then
|
||
read -p "请输入认证密码: " auth_password
|
||
|
||
if [[ -z "$auth_password" ]]; then
|
||
auth_password=$(openssl rand -base64 32)
|
||
echo "随机生成的认证密码为:${auth_password}"
|
||
fi
|
||
|
||
users+=("{\"auth_str\": \"$auth_password\"}")
|
||
elif [[ "$add_multiple_users" == "N" || "$add_multiple_users" == "n" ]]; then
|
||
break
|
||
fi
|
||
done
|
||
|
||
echo "多用户设置成功。"
|
||
echo "${users[@]}"
|
||
}
|
||
|
||
# 函数:读取域名并检查是否绑定本机IP
|
||
function read_and_validate_domain() {
|
||
while true; do
|
||
read -p "请输入域名: " domain
|
||
|
||
if ping -c 1 "$domain" &>/dev/null; then
|
||
break
|
||
else
|
||
echo "错误:域名未解析或输入错误,请重新输入。"
|
||
fi
|
||
done
|
||
|
||
echo "域名设置成功:${domain}"
|
||
}
|
||
|
||
# 函数:读取证书和私钥路径
|
||
function read_certificate_paths() {
|
||
read -p "请输入证书路径 (默认/etc/ssl/private/cert.crt): " certificate_path
|
||
certificate_path=${certificate_path:-/etc/ssl/private/cert.crt}
|
||
|
||
read -p "请输入私钥路径 (默认/etc/ssl/private/private.key): " private_key_path
|
||
private_key_path=${private_key_path:-/etc/ssl/private/private.key}
|
||
|
||
echo "证书路径:${certificate_path}"
|
||
echo "私钥路径:${private_key_path}"
|
||
}
|
||
|
||
# 函数:生成sing-box配置文件
|
||
function generate_sing_box_config() {
|
||
local config_file="/usr/local/etc/sing-box/config.json"
|
||
|
||
read_listen_port
|
||
read_up_speed
|
||
read_down_speed
|
||
read_auth_password
|
||
local users=$(read_multi_users) # Get users data from the function
|
||
read_and_validate_domain
|
||
read_certificate_paths
|
||
|
||
echo "生成sing-box配置文件..."
|
||
echo "{
|
||
\"log\": {
|
||
\"disabled\": false,
|
||
\"level\": \"info\",
|
||
\"timestamp\": true
|
||
},
|
||
\"inbounds\": [
|
||
{
|
||
\"type\": \"hysteria\",
|
||
\"tag\": \"hysteria-in\",
|
||
\"listen\": \"::\",
|
||
\"listen_port\": $listen_port,
|
||
\"sniff\": true,
|
||
\"sniff_override_destination\": true,
|
||
\"up_mbps\": $up_speed,
|
||
\"down_mbps\": $down_speed,
|
||
\"obfs\": \"obfs123\",
|
||
\"users\": [$users],
|
||
\"tls\": {
|
||
\"enabled\": true,
|
||
\"server_name\": \"$domain\",
|
||
\"alpn\": [
|
||
\"h3\"
|
||
],
|
||
\"min_version\": \"1.2\",
|
||
\"max_version\": \"1.3\",
|
||
\"certificate_path\": \"$certificate_path\",
|
||
\"key_path\": \"$private_key_path\"
|
||
}
|
||
}
|
||
],
|
||
\"outbounds\": [
|
||
{
|
||
\"type\": \"direct\",
|
||
\"tag\": \"direct\"
|
||
},
|
||
{
|
||
\"type\": \"block\",
|
||
\"tag\": \"block\"
|
||
}
|
||
]
|
||
}" > "$config_file"
|
||
|
||
echo "配置文件 $config_file 创建成功。"
|
||
}
|
||
|
||
# 主函数
|
||
function main() {
|
||
generate_sing_box_config
|
||
}
|
||
|
||
main
|
||
|