#!/bin/bash red='\e[31m' yellow='\e[33m' green='\e[32m' none='\e[0m' config_file="/usr/local/etc/xray/config.json" default_config=' { "inbounds": [ { "listen": "127.0.0.1", "port": 9999, "protocol": "vmess", "settings": { "clients": [ { "id": "sky22333" } ] }, "streamSettings": { "network": "ws", "security": "none", "wsSettings": { "path": "/sky22333" } }, "tag": "inbound0" } ], "outbounds": [ { "protocol": "socks", "settings": { "servers": [ { "address": "127.0.0.2", "port": 2222, "users": [ { "user": "admin123", "pass": "admin333" } ] } ] }, "tag": "outbound0" } ], "routing": { "rules": [ { "type": "field", "inboundTag": ["inbound0"], "outboundTag": "outbound0" } ] } } ' # 检查并安装curl check_and_install_curl() { if ! type curl &>/dev/null; then echo -e "${yellow}正在安装curl...${none}" apt-get update && apt-get install -yq curl fi } # 检查并安装jq check_and_install_jq() { if ! type jq &>/dev/null; then echo -e "${yellow}正在安装jq...${none}" apt-get update && apt-get install -yq jq fi } # 检查并安装uuid-runtime check_and_install_uuid_runtime() { if ! type uuidgen &>/dev/null; then echo -e "${yellow}正在安装 uuid-runtime...${none}" apt-get update && apt-get install -yq uuid-runtime fi } # 检查并安装xray check_and_install_xray() { if ! type xray &>/dev/null; then echo -e "${yellow}正在安装 xray...${none}" bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install fi } # 检查是否已存在入站配置 check_existing_inbound_config() { if grep -q '"tag":' "$config_file"; then return 0 # 已存在入站配置 else return 1 # 不存在入站配置 fi } # 创建默认配置文件 create_default_config() { if ! check_existing_inbound_config; then echo "$default_config" > "$config_file" echo -e "${green}已创建默认配置文件。${none}" else echo -e "${yellow}入站配置已存在,跳过创建默认配置文件。${none}" fi } # 获取本机公网 IP get_local_ip() { local ip=$(curl -s http://ipinfo.io/ip) if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "$ip" else echo "无法自动获取公网IP地址,请手动输入。" read -p "请输入您的公网IP地址: " manual_ip if [[ $manual_ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "$manual_ip" else echo "输入的IP地址格式不正确,请重新运行脚本并输入有效的公网IP地址。" exit 1 fi fi } # 显示所有入站配置和 Vmess 链接以及对应的出站配置(出战只显示地址、端口、用户名和密码) show_inbound_configs() { local local_ip=$(get_local_ip) # 获取本机IP local config=$(jq '.inbounds | map(select(.port != 9999))' "$config_file") local outbounds=$(jq '.outbounds' "$config_file") echo -e "${green}入站节点配置:${none}" local length=$(jq '. | length' <<< "$config") for ((i = 0; i < length; i++)); do local port=$(jq -r ".[$i].port" <<< "$config") local id=$(jq -r ".[$i].settings.clients[0].id" <<< "$config") local path=$(jq -r ".[$i].streamSettings.wsSettings.path" <<< "$config") # 将节点地址设置为本机IP local node_address="$local_ip" local vmess_link="vmess://$(echo -n "{\"v\":\"2\",\"ps\":\"节点$(($i + 1))\",\"add\":\"$node_address\",\"port\":$port,\"id\":\"$id\",\"aid\":0,\"net\":\"ws\",\"path\":\"$path\",\"type\":\"none\"}" | base64 -w 0)" echo -e "${yellow}节点: $(($i + 1))${none} - 端口: ${port}, Vmess 链接: ${vmess_link}" # 构造出站配置的标签 local outbound_tag="outbound$port" # 根据构造的标签查找对应的出站配置 local outbound_config=$(jq --arg tag "$outbound_tag" '.[] | select(.tag == $tag) | .settings.servers[] | {address, port, user: .users[0].user, pass: .users[0].pass}' <<< "$outbounds") if [[ ! -z $outbound_config ]]; then echo -e "${green}出站配置:${none} 地址: $(jq -r '.address' <<< "$outbound_config"), 端口: $(jq -r '.port' <<< "$outbound_config"), 用户名: $(jq -r '.user' <<< "$outbound_config"), 密码: $(jq -r '.pass' <<< "$outbound_config")" else echo -e "${red}未找到对应的出站配置。${none}" fi done } # 添加新节点 add_new_nodes() { read -p "请输入要添加的节点数量: " num_nodes if ! [[ $num_nodes =~ ^[0-9]+$ ]]; then echo -e "${red}错误!${none} 请输入有效的数量。\n" return fi local max_port=$(jq '[.inbounds[].port] | max // 10000' "$config_file") local start_port=$((max_port+1)) for ((i=0; i "$config_file.tmp" && mv "$config_file.tmp" "$config_file" # 添加出站配置 jq --arg tag "$new_outbound_tag" --arg addr "$outbound_addr" --argjson port "$outbound_port" --arg user "$outbound_user" --arg pass "$outbound_pass" ' .outbounds += [{ protocol: "socks", settings: { servers: [{ address: $addr, port: $port, users: [{ user: $user, pass: $pass }] }] }, tag: $tag }]' "$config_file" > "$config_file.tmp" && mv "$config_file.tmp" "$config_file" # 添加路由规则 jq --arg inTag "$new_tag" --arg outTag "$new_outbound_tag" ' .routing.rules += [{ type: "field", inboundTag: [$inTag], outboundTag: $outTag }] ' "$config_file" > "$config_file.tmp" && mv "$config_file.tmp" "$config_file" done echo -e "${green}已成功添加 $num_nodes 个节点。${none}" systemctl restart xray echo -e "${green}Xray 服务已重新启动。${none}" } # 删除特定端口号的节点 delete_node_by_port() { read -p "请输入要删除的vmess节点端口号: " port_to_delete if ! [[ $port_to_delete =~ ^[0-9]+$ ]]; then echo -e "${red}错误!${none} 请输入有效的端口号。\n" return fi local inbound_tag="inbound$port_to_delete" local outbound_tag="outbound$port_to_delete" # 删除入站配置 jq --argjson port "$port_to_delete" 'del(.inbounds[] | select(.port == $port))' "$config_file" > "$config_file.tmp" && mv "$config_file.tmp" "$config_file" # 删除出站配置 jq --arg tag "$outbound_tag" 'del(.outbounds[] | select(.tag == $tag))' "$config_file" > "$config_file.tmp" && mv "$config_file.tmp" "$config_file" # 删除路由规则 jq --arg inTag "$inbound_tag" --arg outTag "$outbound_tag" 'del(.routing.rules[] | select(.inboundTag[] == $inTag and .outboundTag == $outTag))' "$config_file" > "$config_file.tmp" && mv "$config_file.tmp" "$config_file" echo -e "${green}已成功删除端口号为 $port_to_delete 的节点。${none}" systemctl restart xray echo -e "${green}Xray 服务已重新启动。${none}" } # 主菜单 main_menu() { while true; do echo -e "\n${green}sky22333-快速批量搭建二级代理脚本-管理菜单:${none}" echo "1. 查看所有节点" echo "2. 新增vmess入站sk5出站" echo "3. 删除节点" echo "4. 退出" read -p "请输入选项: " choice case $choice in 1) show_inbound_configs ;; 2) add_new_nodes ;; 3) delete_node_by_port ;; 4) break ;; *) echo -e "${red}无效的选项,请重新选择。${none}" ;; esac done } # 调用主菜单函数 check_and_install_curl check_and_install_jq check_and_install_uuid_runtime check_and_install_xray create_default_config get_local_ip main_menu