> "$SINGBOX_LOG" 2>&1 log() { echo "[$(date)] $1" >> "$FIREWALL_LOG" } log "Starting Sing-box with config: $CONFIG_FILE" log "Restarting firewall..." /etc/init.d/firewall restart sleep 2 if command -v fw4 > /dev/null; then log "FW4 Detected. Starting nftables." nft flush ruleset nft -f - <<'NFTABLES' flush ruleset table inet singbox { set local_ipv4 { type ipv4_addr flags interval elements = { 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, 240.0.0.0/4 } } set local_ipv6 { type ipv6_addr flags interval elements = { ::ffff:0.0.0.0/96, 64:ff9b::/96, 100::/64, 2001::/32, 2001:10::/28, 2001:20::/28, 2001:db8::/32, 2002::/16, fc00::/7, fe80::/10 } } chain singbox-tproxy { fib daddr type { unspec, local, anycast, multicast } return ip daddr @local_ipv4 return ip6 daddr @local_ipv6 return udp dport { 123 } return meta l4proto { tcp, udp } meta mark set 1 tproxy to :9888 accept } chain singbox-mark { fib daddr type { unspec, local, anycast, multicast } return ip daddr @local_ipv4 return ip6 daddr @local_ipv6 return udp dport { 123 } return meta mark set 1 } chain mangle-output { type route hook output priority mangle; policy accept; meta l4proto { tcp, udp } skgid != 1 ct direction original goto singbox-mark } chain mangle-prerouting { type filter hook prerouting priority mangle; policy accept; iifname { lo, eth0 } meta l4proto { tcp, udp } ct direction original goto singbox-tproxy } } NFTABLES elif command -v fw3 > /dev/null; then log "FW3 Detected. Starting iptables." iptables -t mangle -F iptables -t mangle -X iptables -t mangle -N singbox-mark iptables -t mangle -A singbox-mark -m addrtype --dst-type UNSPEC,LOCAL,ANYCAST,MULTICAST -j RETURN iptables -t mangle -A singbox-mark -d 10.0.0.0/8 -j RETURN iptables -t mangle -A singbox-mark -d 127.0.0.0/8 -j RETURN iptables -t mangle -A singbox-mark -d 169.254.0.0/16 -j RETURN iptables -t mangle -A singbox-mark -d 172.16.0.0/12 -j RETURN iptables -t mangle -A singbox-mark -d 192.168.0.0/16 -j RETURN iptables -t mangle -A singbox-mark -d 240.0.0.0/4 -j RETURN iptables -t mangle -A singbox-mark -p udp --dport 123 -j RETURN iptables -t mangle -A singbox-mark -j MARK --set-mark 1 iptables -t mangle -N singbox-tproxy iptables -t mangle -A singbox-tproxy -m addrtype --dst-type UNSPEC,LOCAL,ANYCAST,MULTICAST -j RETURN iptables -t mangle -A singbox-tproxy -d 10.0.0.0/8 -j RETURN iptables -t mangle -A singbox-tproxy -d 127.0.0.0/8 -j RETURN iptables -t mangle -A singbox-tproxy -d 169.254.0.0/16 -j RETURN iptables -t mangle -A singbox-tproxy -d 172.16.0.0/12 -j RETURN iptables -t mangle -A singbox-tproxy -d 192.168.0.0/16 -j RETURN iptables -t mangle -A singbox-tproxy -d 240.0.0.0/4 -j RETURN iptables -t mangle -A singbox-tproxy -p udp --dport 123 -j RETURN iptables -t mangle -A singbox-tproxy -p tcp -j TPROXY --tproxy-mark 0x1/0x1 --on-port 9888 iptables -t mangle -A singbox-tproxy -p udp -j TPROXY --tproxy-mark 0x1/0x1 --on-port 9888 iptables -t mangle -A OUTPUT -p tcp -m cgroup ! --cgroup 1 -j singbox-mark iptables -t mangle -A OUTPUT -p udp -m cgroup ! --cgroup 1 -j singbox-mark iptables -t mangle -A PREROUTING -i lo -p tcp -j singbox-tproxy iptables -t mangle -A PREROUTING -i lo -p udp -j singbox-tproxy iptables -t mangle -A PREROUTING -i eth0 -p tcp -j singbox-tproxy iptables -t mangle -A PREROUTING -i eth0 -p udp -j singbox-tproxy ip6tables -t mangle -N singbox-mark ip6tables -t mangle -A singbox-mark -m addrtype --dst-type UNSPEC,LOCAL,ANYCAST,MULTICAST -j RETURN ip6tables -t mangle -A singbox-mark -d ::ffff:0.0.0.0/96 -j RETURN ip6tables -t mangle -A singbox-mark -d 64:ff9b::/96 -j RETURN ip6tables -t mangle -A singbox-mark -d 100::/64 -j RETURN ip6tables -t mangle -A singbox-mark -d 2001::/32 -j RETURN ip6tables -t mangle -A singbox-mark -d 2001:10::/28 -j RETURN ip6tables -t mangle -A singbox-mark -d 2001:20::/28 -j RETURN ip6tables -t mangle -A singbox-mark -d 2001:db8::/32 -j RETURN ip6tables -t mangle -A singbox-mark -d 2002::/16 -j RETURN ip6tables -t mangle -A singbox-mark -d fc00::/7 -j RETURN ip6tables -t mangle -A singbox-mark -d fe80::/10 -j RETURN ip6tables -t mangle -A singbox-mark -p udp --dport 123 -j RETURN ip6tables -t mangle -A singbox-mark -j MARK --set-mark 1 ip6tables -t mangle -N singbox-tproxy ip6tables -t mangle -A singbox-tproxy -m addrtype --dst-type UNSPEC,LOCAL,ANYCAST,MULTICAST -j RETURN ip6tables -t mangle -A singbox-tproxy -d ::ffff:0.0.0.0/96 -j RETURN ip6tables -t mangle -A singbox-tproxy -d 64:ff9b::/96 -j RETURN ip6tables -t mangle -A singbox-tproxy -d 100::/64 -j RETURN ip6tables -t mangle -A singbox-tproxy -d 2001::/32 -j RETURN ip6tables -t mangle -A singbox-tproxy -d 2001:10::/28 -j RETURN ip6tables -t mangle -A singbox-tproxy -d 2001:20::/28 -j RETURN ip6tables -t mangle -A singbox-tproxy -d 2001:db8::/32 -j RETURN ip6tables -t mangle -A singbox-tproxy -d 2002::/16 -j RETURN ip6tables -t mangle -A singbox-tproxy -d fc00::/7 -j RETURN ip6tables -t mangle -A singbox-tproxy -d fe80::/10 -j RETURN ip6tables -t mangle -A singbox-tproxy -p udp --dport 123 -j RETURN ip6tables -t mangle -A singbox-tproxy -p tcp -j TPROXY --tproxy-mark 0x1/0x1 --on-port 9888 ip6tables -t mangle -A singbox-tproxy -p udp -j TPROXY --tproxy-mark 0x1/0x1 --on-port 9888 ip6tables -t mangle -A OUTPUT -p tcp -m cgroup ! --cgroup 1 -j singbox-mark ip6tables -t mangle -A OUTPUT -p udp -m cgroup ! --cgroup 1 -j singbox-mark ip6tables -t mangle -A PREROUTING -i lo -p tcp -j singbox-tproxy ip6tables -t mangle -A PREROUTING -i lo -p udp -j singbox-tproxy ip6tables -t mangle -A PREROUTING -i eth0 -p tcp -j singbox-tproxy ip6tables -t mangle -A PREROUTING -i eth0 -p udp -j singbox-tproxy else log "Neither fw3 nor fw4 detected, unable to configure firewall rules." exit 1 fi log "Firewall rules applied successfully" log "Starting sing-box with config: $CONFIG_FILE" exec "$SINGBOX_BIN" run -c "$CONFIG_FILE" EOF; function createStartScript($configFile) { global $start_script_template, $singbox_bin, $singbox_log, $log; $script = sprintf($start_script_template, $singbox_log, $configFile, $singbox_bin, $log); $dir = dirname('/etc/neko/core/start.sh'); if (!file_exists($dir)) { mkdir($dir, 0755, true); } file_put_contents('/etc/neko/core/start.sh', $script); chmod('/etc/neko/core/start.sh', 0755); writeToLog("Created start script with config: $configFile"); writeToLog("Singbox binary: $singbox_bin"); writeToLog("Log file: $singbox_log"); writeToLog("Firewall log file: $log"); } function writeToLog($message) { global $log; $dateTime = new DateTime(); $dateTime->modify('+8 hours'); $time = $dateTime->format('H:i:s'); $logMessage = "[ $time ] $message\n"; if (file_put_contents($log, $logMessage, FILE_APPEND) === false) { error_log("Failed to write to log file: $log"); } } function rotateLogs($logFile, $maxSize = 1048576) { if (file_exists($logFile) && filesize($logFile) > $maxSize) { rename($logFile, $logFile . '.old'); touch($logFile); chmod($logFile, 0644); } } function isSingboxRunning() { global $singbox_bin; $command = "pgrep -f " . escapeshellarg($singbox_bin); exec($command, $output); return !empty($output); } function isNekoBoxRunning() { global $neko_dir; $pid = trim(shell_exec("cat $neko_dir/tmp/neko.pid 2>/dev/null")); return !empty($pid) && file_exists("/proc/$pid"); } function getSingboxPID() { global $singbox_bin; $command = "pgrep -f " . escapeshellarg($singbox_bin); exec($command, $output); return isset($output[0]) ? $output[0] : null; } function getRunningConfigFile() { global $singbox_bin; $command = "ps w | grep '$singbox_bin' | grep -v grep"; exec($command, $output); foreach ($output as $line) { if (strpos($line, '-c') !== false) { $parts = explode('-c', $line); if (isset($parts[1])) { $configPath = trim(explode(' ', trim($parts[1]))[0]); return $configPath; } } } return null; } function getAvailableConfigFiles() { global $singbox_config_dir; return glob("$singbox_config_dir/*.json"); } $availableConfigs = getAvailableConfigFiles(); writeToLog("Script started"); if(isset($_POST['neko'])){ $dt = $_POST['neko']; writeToLog("Received neko action: $dt"); if ($dt == 'start') { if (isSingboxRunning()) { writeToLog("Cannot start NekoBox: Sing-box is running"); } else { shell_exec("$neko_dir/core/neko -s"); writeToLog("NekoBox started successfully"); } } if ($dt == 'disable') { shell_exec("$neko_dir/core/neko -k"); writeToLog("NekoBox stopped"); } if ($dt == 'restart') { if (isSingboxRunning()) { writeToLog("Cannot restart NekoBox: Sing-box is running"); } else { shell_exec("$neko_dir/core/neko -r"); writeToLog("NekoBox restarted successfully"); } } if ($dt == 'clear') { shell_exec("echo \"Logs has been cleared...\" > $neko_dir/tmp/neko_log.txt"); writeToLog("NekoBox logs cleared"); } writeToLog("Neko action completed: $dt"); } if (isset($_POST['singbox'])) { $action = $_POST['singbox']; $config_file = isset($_POST['config_file']) ? $_POST['config_file'] : ''; writeToLog("Received singbox action: $action"); writeToLog("Config file: $config_file"); switch ($action) { case 'start': if (isNekoBoxRunning()) { writeToLog("Cannot start Sing-box: NekoBox is running"); } else { writeToLog("Starting Sing-box"); $singbox_version = trim(shell_exec("$singbox_bin version")); writeToLog("Sing-box version: $singbox_version"); shell_exec("mkdir -p " . dirname($singbox_log)); shell_exec("touch $singbox_log && chmod 644 $singbox_log"); rotateLogs($singbox_log); createStartScript($config_file); $output = shell_exec("sh $start_script_path >> $singbox_log 2>&1 &"); writeToLog("Shell output: " . ($output ?: "No output")); sleep(1); $pid = getSingboxPID(); if ($pid) { writeToLog("Sing-box Started successfully. PID: $pid"); } else { writeToLog("Failed to start Sing-box"); } } break; case 'disable': writeToLog("Stopping Sing-box"); $pid = getSingboxPID(); if ($pid) { writeToLog("Killing Sing-box PID: $pid"); shell_exec("kill $pid"); if (file_exists('/usr/sbin/fw4')) { shell_exec("nft flush ruleset"); } else { shell_exec("iptables -t mangle -F"); shell_exec("iptables -t mangle -X"); } shell_exec("/etc/init.d/firewall restart"); writeToLog("Cleared firewall rules and restarted firewall"); sleep(1); if (!isSingboxRunning()) { writeToLog("Sing-box has been stopped successfully"); } else { writeToLog("Force killing Sing-box"); shell_exec("kill -9 $pid"); writeToLog("Sing-box has been force stopped"); } } else { writeToLog("Sing-box is not running"); } break; case 'restart': if (isNekoBoxRunning()) { writeToLog("Cannot restart Sing-box: NekoBox is running"); } else { writeToLog("Restarting Sing-box"); $pid = getSingboxPID(); if ($pid) { writeToLog("Killing Sing-box PID: $pid"); shell_exec("kill $pid"); sleep(1); } shell_exec("mkdir -p " . dirname($singbox_log)); shell_exec("touch $singbox_log && chmod 644 $singbox_log"); rotateLogs($singbox_log); createStartScript($config_file); shell_exec("sh $start_script_path >> $singbox_log 2>&1 &"); sleep(1); $new_pid = getSingboxPID(); if ($new_pid) { writeToLog("Sing-box Restarted successfully. New PID: $new_pid"); } else { writeToLog("Failed to restart Sing-box"); } } break; } sleep(2); $singbox_status = isSingboxRunning() ? '1' : '0'; exec("uci set neko.cfg.singbox_enabled='$singbox_status'"); exec("uci commit neko"); writeToLog("Singbox status set to: $singbox_status"); } if (isset($_POST['clear_singbox_log'])) { file_put_contents($singbox_log, ''); writeToLog("Singbox log cleared"); } if (isset($_POST['clear_plugin_log'])) { $plugin_log_file = "$neko_dir/tmp/log.txt"; file_put_contents($plugin_log_file, ''); writeToLog("NeKoBox log cleared"); } $neko_status = exec("uci -q get neko.cfg.enabled"); $singbox_status = isSingboxRunning() ? '1' : '0'; exec("uci set neko.cfg.singbox_enabled='$singbox_status'"); exec("uci commit neko"); writeToLog("Final neko status: $neko_status"); writeToLog("Final singbox status: $singbox_status"); if ($singbox_status == '1') { $runningConfigFile = getRunningConfigFile(); if ($runningConfigFile) { $str_cfg = htmlspecialchars(basename($runningConfigFile)); writeToLog("Running config file: $str_cfg"); } else { $str_cfg = 'Sing-box 配置文件:未找到运行中的配置文件'; writeToLog("No running config file found"); } } function readRecentLogLines($filePath, $lines = 1000) { if (!file_exists($filePath)) { return "日志文件不存在: $filePath"; } if (!is_readable($filePath)) { return "无法读取日志文件: $filePath"; } $command = "tail -n $lines " . escapeshellarg($filePath); $output = shell_exec($command); return $output ?: "日志为空"; } function readLogFile($filePath) { if (file_exists($filePath)) { return nl2br(htmlspecialchars(readRecentLogLines($filePath, 1000), ENT_NOQUOTES)); } else { return '日志文件不存在。'; } } $neko_log_content = readLogFile("$neko_dir/tmp/neko_log.txt"); $singbox_log_content = readLogFile($singbox_log); ?> "$devices - $fullOSInfo", 'ramUsage' => "$ramUsage/$ramTotal MB", 'cpuLoad' => "$cpuLoadAvg1Min $cpuLoadAvg5Min $cpuLoadAvg15Min", 'uptime' => "{$days}天 {$hours}小时 {$minutes}分钟 {$seconds}秒", 'cpuLoadAvg1Min' => $cpuLoadAvg1Min, 'ramTotal' => $ramTotal, 'ramUsageOnly' => $ramUsage, ]); exit; } ?> Home - Neko
🏠 首页 📊 面板 ⚙️ 配置 📦 订阅 🛠️ 设定

NekoBox

状态
Mihomo 运行中\n"; } else { echo "\n"; } echo "\n"; if ($singbox_status == 1) { echo "\n"; } else { echo "\n"; } ?>
控制
运行模式

系统状态

系统信息
内存
平均负载
运行时间

CPU

N/A

内存

N/A

交换空间

N/A

下载-总计 上传-总计
- -

日志

NeKoBox 日志


                

Mihomo 日志


                

Sing-box 日志


            
alert('时区已更新成功!');"; } else { echo ""; } } ?>