From e6516c80d8eec33ecb986d7e473536198c47696d Mon Sep 17 00:00:00 2001 From: taamarin Date: Tue, 27 Jun 2023 13:07:21 +0700 Subject: [PATCH] Adapting the Scripts --- box/scripts/box.inotify | 2 +- box/scripts/box.iptables | 264 +++++++++++----------- box/scripts/box.service | 464 +++++++++++++++++++++------------------ box/scripts/box.tool | 401 ++++++++++++++++----------------- box/scripts/start.sh | 27 ++- box/settings.ini | 39 ++-- box/sing-box/config.json | 2 +- 7 files changed, 618 insertions(+), 581 deletions(-) diff --git a/box/scripts/box.inotify b/box/scripts/box.inotify index d317ed8..060c7c1 100755 --- a/box/scripts/box.inotify +++ b/box/scripts/box.inotify @@ -7,7 +7,7 @@ service_path="/data/adb/box/scripts/box.service" iptables_path="/data/adb/box/scripts/box.iptables" data_box="/data/adb/box" run_path="/data/adb/box/run" -now=$(date +"%R") +now=$(date +"%I:%M %p") events=$1 monitor_dir=$2 diff --git a/box/scripts/box.iptables b/box/scripts/box.iptables index 27499c8..4511adb 100755 --- a/box/scripts/box.iptables +++ b/box/scripts/box.iptables @@ -5,17 +5,17 @@ scripts_dir=$(dirname "${scripts}") source /data/adb/box/settings.ini # Variabel yang digunakan -table="223" -fwmark="223" -pref="100" +table='0x69' +fwmark='0x69' +pref='0x64' # disable / enable quic using iptables rules quic="enable" # Looking for value from "fake-ip-range: / listen: / enhanced-mode: / tun-device:" block in YAML / JSON configuration file case "${bin_name}" in "clash") - clash_fake_ip_range=$(busybox awk '!/^ *#/ && /fake-ip-range:/ { print $2; found=1; exit } END { if (!found) print "198.18.0.1/16" }' "${clash_config}" 2>/dev/null) clash_enhanced_mode=$(busybox awk '!/^ *#/ && /enhanced-mode: / { print $2;found=1; exit } END{ if(!found) print "fake-ip" }' "${clash_config}" 2>/dev/null) + fake_ip_range=$(busybox awk '!/^ *#/ && /fake-ip-range:/ { print $2; found=1; exit } END { if (!found) print "198.18.0.1/16" }' "${clash_config}" 2>/dev/null) clash_dns_port=$(busybox awk '!/^ *#/ && /listen:/ { split($0, arr, ":"); print arr[3]; found=1; exit } END{ if(!found) print "1053" }' "${clash_config}" 2>/dev/null) if [[ "${network_mode}" == "mixed" || "${proxy_mode}" == "tun" ]]; then tun_device=$(busybox awk '!/^ *#/ && /device: / { print $2;found=1; exit } END{ if(!found) print "utun" }' "${clash_config}" 2>/dev/null) @@ -28,15 +28,17 @@ case "${bin_name}" in tun_device="tun0" fi fi + fake_ip_range=$(find ${box_dir}/sing-box/ -type f -name "*.json" -exec busybox awk -F'"' '/inet4_range/ {print $4}' {} \;) + fake_ip6_range=$(find ${box_dir}/sing-box/ -type f -name "*.json" -exec busybox awk -F'"' '/inet6_range/ {print $4}' {} \;) ;; "xray" | "v2fly") if [[ "${network_mode}" == "mixed" || "${proxy_mode}" == "tun" ]]; then - log error "$bin_name does not support proxy_mode: tun or network_mode: mixed" + log Error "$bin_name does not support proxy_mode: tun or network_mode: mixed" exit 1 fi ;; *) - log error "<${bin_name}> unknown binary." + log Error "<${bin_name}> unknown binary." exit 1 ;; esac @@ -44,12 +46,15 @@ esac misc_info() { case "${bin_name}" in clash) - log debug "enhanced-mode: $clash_enhanced_mode, fake-ip-range: $clash_fake_ip_range, listen-port: $clash_dns_port" + log Debug "enhanced-mode: $clash_enhanced_mode, fake-ip-range: $fake_ip_range, listen-port: $clash_dns_port" ;; clash|sing-box) if [[ "${network_mode}" == "mixed" || "${proxy_mode}" == "tun" ]]; then - log info "tun_device: $tun_device" + log Info "tun_device: $tun_device" fi + [ -n "${fake_ip_range}" ] && { + log Debug "fakeip inet4(6)_range: ${fake_ip_range}, ${fake_ip6_range}" + } ;; *) true @@ -58,11 +63,10 @@ misc_info() { } box_sync_port() { - sleep 0.5 if [[ "${network_mode}" == "tproxy" && "${proxy_mode}" != "tun" ]]; then - netstat -tnulp | grep -q "${tproxy_port}" || log warn "tproxy_port: ${tproxy_port} out of sync with config" + netstat -tnulp | grep -q "${tproxy_port}" || log Warning "tproxy_port: ${tproxy_port} out of sync with config" elif [[ "${network_mode}" == "mixed" || "${proxy_mode}" == "tun" ]]; then - ifconfig | grep -q "${tun_device}" || log warn "tun_device: '${tun_device}' not found" + ifconfig | grep -q "${tun_device}" || log Warning "tun_device: '${tun_device}' not found" fi } @@ -74,9 +78,9 @@ find_packages_uid() { } probe_user_group() { - if bin_pid=$(busybox pidof ${bin_name}) ; then - box_user=$(stat -c %U /proc/"${bin_pid}") - box_group=$(stat -c %G /proc/"${bin_pid}") + if PID=$(busybox pidof ${bin_name}) ; then + box_user=$(stat -c %U /proc/$PID) + box_group=$(stat -c %G /proc/$PID) return 0 else IFS=':' read -r box_user box_group <<< "${box_user_group}" @@ -152,14 +156,20 @@ start_redirect() { if [ "${bin_name}" = "clash" ]; then ${iptables} -t nat -A BOX_EXTERNAL -p udp --dport 53 -j REDIRECT --to-ports "${clash_dns_port}" ${iptables} -t nat -A BOX_LOCAL -p udp --dport 53 -j REDIRECT --to-ports "${clash_dns_port}" - if [ "${clash_enhanced_mode}" = "fake-ip" ] ; then - ${iptables} -t nat -A BOX_EXTERNAL -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 - ${iptables} -t nat -A BOX_LOCAL -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 - fi - # else - # Other types of inbound should be added here to receive DNS traffic instead of sniffing - # ${iptables} -t nat -A BOX_EXTERNAL -p udp --dport 53 -j REDIRECT --to-ports "${redir_port}" - # ${iptables} -t nat -A BOX_LOCAL -p udp --dport 53 -j REDIRECT --to-ports "${redir_port}" + + # Other types of inbound should be added here to receive DNS traffic instead of sniffing + # ${iptables} -t nat -A BOX_EXTERNAL -p udp --dport 53 -j REDIRECT --to-ports "${redir_port}" + # ${iptables} -t nat -A BOX_LOCAL -p udp --dport 53 -j REDIRECT --to-ports "${redir_port}" + fi + + # Fix ICMP (ping) + # This does not guarantee that the ping result is valid + # Just that it returns a result + # "--to-destination" can be set to a reachable address. + + if [ -n "${fake_ip_range}" ]; then + ${iptables} -t nat -A BOX_EXTERNAL -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + ${iptables} -t nat -A BOX_LOCAL -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 fi # Allow access to intranet subnets @@ -174,7 +184,7 @@ start_redirect() { for ap in "${ap_list[@]}"; do ${iptables} -t nat -A BOX_EXTERNAL -p tcp -i "${ap}" -j REDIRECT --to-ports "${redir_port}" done - log info "${ap_list[*]} transparent proxy." + log Info "${ap_list[*]} transparent proxy." fi ${iptables} -t nat -I PREROUTING -j BOX_EXTERNAL @@ -185,7 +195,7 @@ start_redirect() { for ignore in "${ignore_out_list[@]}"; do ${iptables} -t nat -I BOX_LOCAL -o "${ignore}" -j RETURN done - log info "${ignore_out_list[*]} ignore transparent proxy." + log Info "${ignore_out_list[*]} ignore transparent proxy." fi fi @@ -197,7 +207,7 @@ start_redirect() { if [ -z "$(cat "${uid_list[@]}")" ] ; then # Route Everything ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports "${redir_port}" - log info "Transparent proxy for all apps." + log Info "Transparent proxy for all apps." else # Bypass apps # loop through the UID list @@ -211,13 +221,13 @@ start_redirect() { # Allow !app ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports "${redir_port}" - log info "proxy-mode: ${proxy_mode} < [ ${packages_list[*]} ] no transparent proxy." + log Info "proxy-mode: ${proxy_mode} < [ ${packages_list[*]} ] no transparent proxy." fi elif [ "${proxy_mode}" = "whitelist" ]; then if [ -z "$(cat "${uid_list[@]}")" ] ; then # Route Everything ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports "${redir_port}" - log info "Transparent proxy for all apps." + log Info "Transparent proxy for all apps." else # Route apps to Box # loop through the UID list @@ -231,12 +241,12 @@ start_redirect() { ${iptables} -t nat -A BOX_LOCAL -p tcp -m owner --uid-owner 0 -j REDIRECT --to-ports "${redir_port}" ${iptables} -t nat -A BOX_LOCAL -p tcp -m owner --uid-owner 1052 -j REDIRECT --to-ports "${redir_port}" - log info "proxy-mode: ${proxy_mode} < [ ${packages_list[*]} ] transparent proxy." + log Info "proxy-mode: ${proxy_mode} < [ ${packages_list[*]} ] transparent proxy." fi else - log warn "proxy-mode: ${proxy_mode} < error." + log Warning "proxy-mode: ${proxy_mode} < error." ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports "${redir_port}" - log info "Transparent proxy for all apps." + log Info "Transparent proxy for all apps." fi fi @@ -266,8 +276,10 @@ stop_redirect() { fi if [ "${iptables}" != "ip6tables -w 64" ]; then - ${iptables} -t nat -D BOX_EXTERNAL -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 - ${iptables} -t nat -D BOX_LOCAL -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + if [ -n "${fake_ip_range}" ]; then + ${iptables} -t nat -D BOX_EXTERNAL -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + ${iptables} -t nat -D BOX_LOCAL -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + fi ${iptables} -t nat -F BOX_EXTERNAL ${iptables} -t nat -X BOX_EXTERNAL @@ -340,7 +352,7 @@ start_tproxy() { # add iptables rules for UDP traffic ${iptables} -t mangle -A BOX_EXTERNAL -p udp -i "${ap}" -j TPROXY --on-port "${tproxy_port}" --tproxy-mark "${fwmark}" done - [ "${iptables}" != "ip6tables -w 64" ] && log info "${ap_list[*]} transparent proxy." + [ "${iptables}" != "ip6tables -w 64" ] && log Info "${ap_list[*]} transparent proxy." fi ${iptables} -t mangle -I PREROUTING -j BOX_EXTERNAL @@ -352,7 +364,7 @@ start_tproxy() { for ignore in ${ignore_out_list[@]} ; do ${iptables} -t mangle -I BOX_LOCAL -o "${ignore}" -j RETURN done - [ "${iptables}" != "ip6tables -w 64" ] && log info "${ignore_out_list[*]} ignore transparent proxy." + [ "${iptables}" != "ip6tables -w 64" ] && log Info "${ignore_out_list[*]} ignore transparent proxy." fi # Bypass intranet Clash @@ -393,7 +405,7 @@ start_tproxy() { # Route Everything ${iptables} -t mangle -A BOX_LOCAL -p tcp -j MARK --set-mark "${fwmark}" ${iptables} -t mangle -A BOX_LOCAL -p udp -j MARK --set-mark "${fwmark}" - [ "${iptables}" != "ip6tables -w 64" ] && log info "transparent proxy for all apps." + [ "${iptables}" != "ip6tables -w 64" ] && log Info "transparent proxy for all apps." else # Bypass apps @@ -407,7 +419,7 @@ start_tproxy() { # Allow !app ${iptables} -t mangle -A BOX_LOCAL -p tcp -j MARK --set-mark "${fwmark}" ${iptables} -t mangle -A BOX_LOCAL -p udp -j MARK --set-mark "${fwmark}" - [ "${iptables}" != "ip6tables -w 64" ] && log info "proxy-mode: ${proxy_mode} < [ ${packages_list[*]} ] no transparent proxy." + [ "${iptables}" != "ip6tables -w 64" ] && log Info "proxy-mode: ${proxy_mode} < [ ${packages_list[*]} ] no transparent proxy." fi elif [ "${proxy_mode}" = "whitelist" ]; then @@ -415,7 +427,7 @@ start_tproxy() { # Route Everything ${iptables} -t mangle -A BOX_LOCAL -p tcp -j MARK --set-mark "${fwmark}" ${iptables} -t mangle -A BOX_LOCAL -p udp -j MARK --set-mark "${fwmark}" - [ "${iptables}" != "ip6tables -w 64" ] && log info "transparent proxy for all apps." + [ "${iptables}" != "ip6tables -w 64" ] && log Info "transparent proxy for all apps." else # Route apps to Box # loop through uid list and add iptables rule @@ -434,13 +446,13 @@ start_tproxy() { ${iptables} -t mangle -A BOX_LOCAL -p udp -m owner --uid-owner 1052 -j MARK --set-mark "${fwmark}" # Route DNS request to Box [ "${bin_name}" != "clash" ] && ${iptables} -t mangle -A BOX_LOCAL -p udp --dport 53 -j MARK --set-mark "${fwmark}" - [ "${iptables}" != "ip6tables -w 64" ] && log info "proxy-mode: ${proxy_mode} < [ ${packages_list[*]} ] transparent proxy." + [ "${iptables}" != "ip6tables -w 64" ] && log Info "proxy-mode: ${proxy_mode} < [ ${packages_list[*]} ] transparent proxy." fi else - log debug "proxy-mode: ${proxy_mode} < error" + log Debug "proxy-mode: ${proxy_mode} < error" ${iptables} -t mangle -A BOX_LOCAL -p tcp -j MARK --set-mark "${fwmark}" ${iptables} -t mangle -A BOX_LOCAL -p udp -j MARK --set-mark "${fwmark}" - [ "${iptables}" != "ip6tables -w 64" ] && log info "transparent proxy for all apps." + [ "${iptables}" != "ip6tables -w 64" ] && log Info "transparent proxy for all apps." fi ${iptables} -t mangle -I OUTPUT -j BOX_LOCAL @@ -457,7 +469,7 @@ start_tproxy() { ${iptables} -A OUTPUT -p udp --dport 443 -j REJECT ${iptables} -A OUTPUT -p udp --dport 80 -j REJECT # ${iptables} -A OUTPUT -p udp -m multiport --dport 443,80 -j REJECT - [ "${iptables}" != "ip6tables -w 64" ] && log warn "disable QUIC" + [ "${iptables}" != "ip6tables -w 64" ] && log Warning "disable QUIC" fi # This rule blocks local access to tproxy-port to prevent traffic loopback. @@ -481,16 +493,17 @@ start_tproxy() { ${iptables} -t nat -A CLASH_DNS_LOCAL -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -j RETURN ${iptables} -t nat -A CLASH_DNS_LOCAL -p udp --dport 53 -j REDIRECT --to-ports "${clash_dns_port}" ${iptables} -t nat -I OUTPUT -j CLASH_DNS_LOCAL - - # Fix ICMP (ping) - # This does not guarantee that the ping result is valid - # Just that it returns a result - # "--to-destination" can be set to a reachable address. - if [ "${clash_enhanced_mode}" = "fake-ip" ] ; then - ${iptables} -t nat -I OUTPUT -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 - ${iptables} -t nat -I PREROUTING -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 - fi fi + # Fix ICMP (ping) + # This does not guarantee that the ping result is valid + # Just that it returns a result + # "--to-destination" can be set to a reachable address. + + if [ -n "${fake_ip_range}" ]; then + ${iptables} -t nat -I OUTPUT -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + ${iptables} -t nat -I PREROUTING -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + fi + fi } @@ -546,10 +559,13 @@ stop_tproxy() { ${iptables} -t nat -F CLASH_DNS_LOCAL ${iptables} -t nat -X CLASH_DNS_LOCAL - ${iptables} -t nat -D OUTPUT -p icmp -d "${clash_fake_ip_range}" -j DNAT --to-destination 127.0.0.1 - ${iptables} -t nat -D PREROUTING -p icmp -d "${clash_fake_ip_range}" -j DNAT --to-destination 127.0.0.1 - # ${iptables} -t nat -D OUTPUT -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 - # ${iptables} -t nat -D PREROUTING -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + if [ -n "${fake_ip_range}" ]; then + ${iptables} -t nat -D OUTPUT -p icmp -d "${fake_ip_range}" -j DNAT --to-destination 127.0.0.1 + ${iptables} -t nat -D PREROUTING -p icmp -d "${fake_ip_range}" -j DNAT --to-destination 127.0.0.1 + fi + + # ${iptables} -t nat -D OUTPUT -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + # ${iptables} -t nat -D PREROUTING -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 fi } @@ -557,7 +573,7 @@ if [ "${proxy_mode}" != "tun" ]; then case "$1" in enable) misc_info - probe_user_group || log error "failed to check BOX user group, please make sure ${bin_name} kernel is started." + probe_user_group || log Error "failed to check BOX user group, please make sure ${bin_name} kernel is started." #ipv4 iptables="iptables -w 64" && { stop_tproxy @@ -574,70 +590,69 @@ if [ "${proxy_mode}" != "tun" ]; then find_packages_uid case "${network_mode}" in tproxy) - log info "use TPROXY: TCP + UDP." - log info "creating iptables transparent proxy rules." + log Info "use TPROXY: TCP + UDP." + log Info "creating iptables transparent proxy rules." iptables="iptables -w 64" intranet+=($(ip address | busybox awk '/inet / && !/127\.0\.0\.1/ {print $2}')) - start_tproxy && log info "create iptables transparent proxy rules done." || { log error "create iptables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } + start_tproxy && log Info "create iptables transparent proxy rules done." || { log Error "create iptables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } if [ "${ipv6}" = "true" ]; then - log debug "use IPv6." + log Debug "use IPv6." ipv6_enable iptables="ip6tables -w 64" intranet6+=($(ip address | busybox awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) - start_tproxy && log info "create ip(6)tables transparent proxy rules done." || { log error "create ip(6)tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } + start_tproxy && log Info "create ip(6)tables transparent proxy rules done." || { log Error "create ip(6)tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } else disable_ipv6 - log warn "disable IPv6." + log Warning "disable IPv6." fi ;; redirect) - log info "use REDIRECT: TCP ONLY" - log info "creating iptables transparent proxy rules." + log Info "use REDIRECT: TCP ONLY" + log Info "creating iptables transparent proxy rules." iptables="iptables -w 64" intranet+=($(ip address | busybox awk '/inet / && !/127\.0\.0\.1/ {print $2}')) - start_redirect && log info "create iptables transparent proxy rules done." || { log error "create iptables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } + start_redirect && log Info "create iptables transparent proxy rules done." || { log Error "create iptables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } if [ "${ipv6}" = "true" ]; then - log debug "use IPv6." + log Debug "use IPv6." ipv6_enable iptables="ip6tables -w 64" intranet6+=($(ip address | busybox awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) - start_redirect && log info "create ip(6)tables transparent proxy rules done." || { log error "create ip(6)tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } + start_redirect && log Info "create ip(6)tables transparent proxy rules done." || { log Error "create ip(6)tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } else disable_ipv6 - log warn "disable IPv6." + log Warning "disable IPv6." fi ;; mixed) - log info "use MIXED: TCP + TUN" - log info "creating iptables transparent proxy rules." + log Info "use MIXED: TCP + TUN" + log Info "creating iptables transparent proxy rules." iptables="iptables -w 64" forward -I || forward -D >> /dev/null 2>&1 intranet+=($(ip address | busybox awk '/inet / && !/127\.0\.0\.1/ {print $2}')) - start_redirect && log info "create iptables transparent proxy rules done." || (log error "create iptables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1) + start_redirect && log Info "create iptables transparent proxy rules done." || (log Error "create iptables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1) if [ "${ipv6}" = "true" ]; then - log debug "use IPv6." + log Debug "use IPv6." ipv6_enable iptables="ip6tables -w 64" intranet6+=($(ip address | busybox awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) forward -I || forward -D >> /dev/null 2>&1 - start_redirect && log info "create ip(6)tables transparent proxy rules done." || (log error "create ip(6)tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1) + start_redirect && log Info "create ip(6)tables transparent proxy rules done." || (log Error "create ip(6)tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1) else disable_ipv6 - log warn "disable IPv6." + log Warning "disable IPv6." fi ;; *) - log error "network_mode: ${network_mode}, unknown" + log Error "network_mode: ${network_mode}, unknown" exit 1 ;; esac box_sync_port - log info "${bin_name} connected." + log Info "${bin_name} connected." ;; renew) - misc_info - probe_user_group || log error "failed to check BOX user group, please make sure ${bin_name} kernel is started." - log warn "cleaning up iptables transparent proxy rules." + probe_user_group || log Error "failed to check BOX user group, please make sure ${bin_name} kernel is started." + log Warning "cleaning up iptables transparent proxy rules." iptables="iptables -w 64" && { stop_tproxy stop_redirect @@ -648,75 +663,76 @@ if [ "${proxy_mode}" != "tun" ]; then stop_redirect forward -D } >> /dev/null 2>&1 - log warn "clean up iptables transparent proxy rules done." + log Warning "clean up iptables transparent proxy rules done." + misc_info find_packages_uid case "${network_mode}" in tproxy) - log info "use TPROXY: TCP + UDP." - log info "creating iptables transparent proxy rules." + log Info "use TPROXY: TCP + UDP." + log Info "creating iptables transparent proxy rules." iptables="iptables -w 64" intranet+=($(ip address | busybox awk '/inet / && !/127\.0\.0\.1/ {print $2}')) - start_tproxy && log info "create iptables transparent proxy rules done." || { log error "create iptables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } + start_tproxy && log Info "create iptables transparent proxy rules done." || { log Error "create iptables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } if [ "${ipv6}" = "true" ]; then - log debug "use IPv6." + log Debug "use IPv6." ipv6_enable iptables="ip6tables -w 64" intranet6+=($(ip address | busybox awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) - start_tproxy && log info "create ip(6)tables transparent proxy rules done." || { log error "create ip(6)tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } + start_tproxy && log Info "create ip(6)tables transparent proxy rules done." || { log Error "create ip(6)tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } else disable_ipv6 - log warn "disable IPv6." + log Warning "disable IPv6." fi ;; redirect) - log info "use REDIRECT: TCP ONLY" - log info "creating iptables transparent proxy rules." + log Info "use REDIRECT: TCP ONLY" + log Info "creating iptables transparent proxy rules." iptables="iptables -w 64" intranet+=($(ip address | busybox awk '/inet / && !/127\.0\.0\.1/ {print $2}')) - start_redirect && log info "create iptables transparent proxy rules done." || { log error "create iptables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } + start_redirect && log Info "create iptables transparent proxy rules done." || { log Error "create iptables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } if [ "${ipv6}" = "true" ]; then - log debug "use IPv6." + log Debug "use IPv6." ipv6_enable iptables="ip6tables -w 64" intranet6+=($(ip address | busybox awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) - start_redirect && log info "create ip(6)tables transparent proxy rules done." || { log error "create ip(6)tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } + start_redirect && log Info "create ip(6)tables transparent proxy rules done." || { log Error "create ip(6)tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } else disable_ipv6 - log warn "disable IPv6." + log Warning "disable IPv6." fi ;; mixed) - log info "use MIXED: TCP + TUN" - log info "creating iptables transparent proxy rules." + log Info "use MIXED: TCP + TUN" + log Info "creating iptables transparent proxy rules." iptables="iptables -w 64" forward -I || forward -D >> /dev/null 2>&1 intranet+=($(ip address | busybox awk '/inet / && !/127\.0\.0\.1/ {print $2}')) - start_redirect && log info "create iptables transparent proxy rules done." || { log error "create iptables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } + start_redirect && log Info "create iptables transparent proxy rules done." || { log Error "create iptables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } if [ "${ipv6}" = "true" ]; then - log debug "use IPv6." + log Debug "use IPv6." ipv6_enable iptables="ip6tables -w 64" intranet6+=($(ip address | busybox awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) forward -I || forward -D >> /dev/null 2>&1 - start_redirect && log info "create ip(6)tables transparent proxy rules done." || { log error "create ip(6)tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } + start_redirect && log Info "create ip(6)tables transparent proxy rules done." || { log Error "create ip(6)tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } else disable_ipv6 - log warn "disable IPv6." + log Warning "disable IPv6." fi ;; *) - log error "network_mode: ${network_mode}, unknown" + log Error "network_mode: ${network_mode}, unknown" exit 1 ;; esac box_sync_port - log info "restart iptables transparent proxy rules done." - log info "${bin_name} connected." + log Info "restart iptables transparent proxy rules done." + log Info "${bin_name} connected." ;; disable) ipv6_enable - probe_user_group || log error "failed to check BOX user group, please make sure ${bin_name} kernel is started." - log warn "clean up iptables transparent proxy rules." + probe_user_group || log Error "failed to check BOX user group, please make sure ${bin_name} kernel is started." + log Warning "clean up iptables transparent proxy rules." #ipv4 iptables="iptables -w 64" && { stop_tproxy @@ -729,7 +745,7 @@ if [ "${proxy_mode}" != "tun" ]; then stop_redirect forward -D } >> /dev/null 2>&1 - log warn "clean up iptables transparent proxy rules done." + log Warning "clean up iptables transparent proxy rules done." ;; *) echo "${red}$0 $1 no found${normal}" @@ -740,8 +756,8 @@ else case "$1" in enable) misc_info - log info "use TUN: TCP + UDP" - probe_user_group || log error "failed to check BOX user group, please make sure ${bin_name} kernel is started." + log Info "use TUN: TCP + UDP" + probe_user_group || log Error "failed to check BOX user group, please make sure ${bin_name} kernel is started." #ipv4 iptables="iptables -w 64" && { stop_tproxy @@ -755,24 +771,23 @@ else forward -D } >> /dev/null 2>&1 iptables="iptables -w 64" - forward -I && log info "create iptables tun rules done." || { log error "create iptables tun rules failed." && forward -D >> /dev/null 2>&1; } + forward -I && log Info "create iptables tun rules done." || { log Error "create iptables tun rules failed." && forward -D >> /dev/null 2>&1; } if [ "${ipv6}" = "true" ]; then - log debug "use IPv6." + log Debug "use IPv6." ipv6_enable iptables="ip6tables -w 64" - forward -I && log info "create ip(6)tables tun rules done." || { log error "create ip(6)tables tun rules failed." && forward -D >> /dev/null 2>&1; } + forward -I && log Info "create ip(6)tables tun rules done." || { log Error "create ip(6)tables tun rules failed." && forward -D >> /dev/null 2>&1; } else disable_ipv6 - log warn "disable IPv6." + log Warning "disable IPv6." fi box_sync_port - log info "${bin_name} connected." + log Info "${bin_name} connected." ;; renew) - misc_info - log info "use TUN: TCP + UDP" - probe_user_group || log error "failed to check BOX user group, please make sure ${bin_name} kernel is started." - log warn "cleaning up tun rules." + log Info "use TUN: TCP + UDP" + probe_user_group || log Error "failed to check BOX user group, please make sure ${bin_name} kernel is started." + log Warning "cleaning up tun rules." #ipv4 iptables="iptables -w 64" && { stop_tproxy @@ -785,26 +800,27 @@ else stop_redirect forward -D } >> /dev/null 2>&1 - log warn "clean up tun rules done." + log Warning "clean up tun rules done." + misc_info iptables="iptables -w 64" - forward -I && log info "create iptables tun rules done." || { log error "create iptables tun rules failed." && forward -D >> /dev/null 2>&1; } + forward -I && log Info "create iptables tun rules done." || { log Error "create iptables tun rules failed." && forward -D >> /dev/null 2>&1; } if [ "${ipv6}" = "true" ]; then - log debug "use IPv6." + log Debug "use IPv6." ipv6_enable iptables="ip6tables -w 64" - forward -I && log info "create ip(6)tables tun rules done." || { log error "create ip(6)tables tun rules failed." && forward -D >> /dev/null 2>&1; } + forward -I && log Info "create ip(6)tables tun rules done." || { log Error "create ip(6)tables tun rules failed." && forward -D >> /dev/null 2>&1; } else disable_ipv6 - log warn "disable IPv6." + log Warning "disable IPv6." fi box_sync_port - log info "restart iptables tun rules done." - log info "${bin_name} connected." + log Info "restart iptables tun rules done." + log Info "${bin_name} connected." ;; disable) ipv6_enable - probe_user_group || log error "failed to check BOX user group, please make sure ${bin_name} kernel is started." - log warn "cleaning up tun rules." + probe_user_group || log Error "failed to check BOX user group, please make sure ${bin_name} kernel is started." + log Warning "cleaning up tun rules." #ipv4 iptables="iptables -w 64" && { stop_tproxy @@ -817,7 +833,7 @@ else stop_redirect forward -D } >> /dev/null 2>&1 - log warn "clean up tun rules done." + log Warning "clean up tun rules done." ;; *) echo "${red}$0 $1 no found${normal}" diff --git a/box/scripts/box.service b/box/scripts/box.service index 8408810..a46b6af 100755 --- a/box/scripts/box.service +++ b/box/scripts/box.service @@ -6,30 +6,33 @@ source /data/adb/box/settings.ini box_check_logs() { # Delete logs for each bin in the list - log info "deleting and backing up logs for ${bin_list[*]}" + log Info "deleting and backup logs" for bin in "${bin_list[@]}"; do if [ -f "${box_run}/${bin}.log" ]; then mv "${box_run}/${bin}.log" "${box_run}/${bin}-$(date +%Y-%m-%d-%H-%M-%S).log" fi done # Delete other log files - find "${box_run}" -type f \( -name "root" -o -name "*.yaml" -o -name "*.list" -o -name "*.inotify.log" \) -exec rm -f {} \; || log warn "Error deleting other log files" + find "${box_run}" -type f \( -name "root" -o -name "*.list" -o -name "*.inotify.log" \) -exec rm -f {} \; # Delete logs that are three days old or older - find "${box_run}" -type f -name "*.log" -mtime +2 -exec rm -f {} \; || log warn "Error deleting old logs" + find "${box_run}" -type f -name "*.log" -mtime +2 -exec rm -f {} \; } box_bin_alive() { - sleep 1.5 - pid=$(busybox pidof ${bin_name} 2>/dev/null) - if ! kill -0 "${pid}" 2>/dev/null; then - log error "${bin_name} service is not running." - log error "Please check ${bin_name}.log for more information." - log error "Killing stale pid ${pid}" + local PID=$(<"${box_pid}" 2>/dev/null) + if ! kill -0 "$PID" 2>/dev/null; then + log Error "$(<"${box_run}/${bin_name}.log")" + log Error "${bin_name} service is not running." + log Error "please check ${bin_name}.log for more information." + log Error "killing stale pid $PID" for bin in "${bin_list[@]}"; do killall -15 "${bin}" >/dev/null 2>&1 || busybox pkill -15 "${bin}" >/dev/null 2>&1 done - ${scripts_dir}/box.iptables disable >/dev/null 2>&1 - exit 1 + "${scripts_dir}/box.iptables" disable >/dev/null 2>&1 + [ -f "${box_pid}" ] && rm -f "${box_pid}" + return 1 + else + return 0 fi } @@ -42,29 +45,21 @@ box_run_crontab() { chmod 0755 "${box_run}/root" if [ "${run_crontab}" = "true" ]; then - log debug "Cron job enabled" + log Debug "Cron job enabled" echo "${interva_update} ${scripts_dir}/box.tool geosub" >> "${box_run}/root" - log debug "Interval crontab geox and subs: ${interva_update}." - log info "${bin_name} geox updates: ${update_geo}." + log Debug "Interval crontab geox and subs: ${interva_update}." + log Info "${bin_name} geox updates: ${update_geo}." if [[ "${bin_name}" == @(clash|sing-box) ]]; then - log info "${bin_name} subscription update: ${update_subscription}." + log Info "${bin_name} subscription update: ${update_subscription}." fi else - log info "Cron Job disabled" - log info "Crontab geox and subscription is disabled." - fi -} - -box_detected_port() { - if [ "${port_detect}" = "true" ]; then - ${scripts_dir}/box.tool port - else - log info "${bin_name} skipped port detection." + log Info "Cron Job disabled" + log Info "Crontab geox and subscription is disabled." fi } box_permission() { - if [[ "${box_user_group}" = "root:net_admin" || "${box_user_group}" = "0:3005" ]] && [ -f "${bin_path}" ]; then + if [[ "${box_user_group}" == @(root:net_admin|0:3005) && -f "${bin_path}" ]]; then # Set ownership and permission of kernel directory chown ${box_user_group} ${bin_path} chmod 6755 ${bin_path} @@ -72,7 +67,7 @@ box_permission() { chmod 0755 "${box_dir}/bin/yq" # Set ownership of data directory chown -R ${box_user_group} ${box_dir} - log info "Use the kernel located in '${bin_path}'." + log Info "Use the kernel located in '${bin_path}'." elif which ${bin_name} | grep -q "/system/bin/"; then box_user=$(echo ${box_user_group} | busybox awk -F ':' '{print $1}') box_group=$(echo ${box_user_group} | busybox awk -F ':' '{print $2}') @@ -80,7 +75,7 @@ box_permission() { box_group_id=$(id -g ${box_group}) # Check if box_user and box_group exist if ! [[ ${box_user_id} && ${box_group_id} ]]; then - log error "${box_user_group} error, use root:net_admin instead." + log Error "${box_user_group} error, use root:net_admin instead." box_user_group="root:net_admin" fi bin_path=$(which ${bin_name}) @@ -92,62 +87,51 @@ box_permission() { # Check if user is not root and group is not net_admin if [[ "${box_user_id}" != "0" || "${box_group_id}" != "3005" ]]; then # Set capability of kernel directory - if ! setcap 'cap_net_admin,cap_net_raw,cap_net_bind_service+ep' "${bin_path}"; then log error "setcap authorization failed, you may need libcap package."; fi + if ! setcap 'cap_net_admin,cap_net_raw,cap_net_bind_service+ep' "${bin_path}"; then log Error "setcap authorization failed, you may need libcap package."; fi fi # Set ownership of data directory box_user_group="root:net_admin" - log info "Using kernel directory ${bin_name} in ${bin_path}" + log Info "Using kernel directory ${bin_name} in ${bin_path}" chown -R ${box_user_group} ${box_dir} else sed -i "s/box_user_group=.*/box_user_group=\"root:net_admin\"/g" ${settings} - log error "Kernel <${bin_name}> is missing." - log error "Please download the <${bin_name}> kernel and place it in the ${bin_dir}/ directory." - log debug "or executed: su -c /data/adb/box/scripts/box.tool upcore ." + log Error "Kernel <${bin_name}> is missing." + log Error "Please download the <${bin_name}> kernel and place it in the ${bin_dir}/ directory." + log Debug "or executed: su -c /data/adb/box/scripts/box.tool upcore ." exit 1 fi } box_check_bin() { - if ! command -v "${bin_path}" >/dev/null 2>&1; then - log error "${bin_path} not found or not executable." - exit 1 - elif [ ! -x "${bin_path}" ]; then - log error "${bin_path} is not executable." - exit 1 - elif [ ! -f "${bin_path}" ]; then - log error "${bin_path} is not a regular file." + if [ ! -x "${bin_path}" ]; then + log Error "${bin_path} is not executable." exit 1 fi case "${bin_name}" in clash) - if ! "${bin_path}" -v >/dev/null 2>&1; then - log error "${bin_name} version information not available." + if ! version_output=$("${bin_path}" -v) >/dev/null 2>&1; then + log Error "${bin_name} version information not available." exit 1 - else - version_output="$(${bin_path} -v)" - log info "${version_output}" fi ;; *) - if ! "${bin_path}" version >/dev/null 2>&1; then - log error "${bin_name} version information not available." + if ! version_output=$("${bin_path}" version) >/dev/null 2>&1; then + log Error "${bin_name} version information not available." exit 1 - else - version_output="$(${bin_path} version)" - log info "${version_output}" fi ;; esac + log Info "${version_output}" } box_create_tun() { # Creates a symlink for /dev/tun if it doesn't already exist if [ ! -c "/dev/net/tun" ]; then if ! mkdir -p /dev/net || ! mknod /dev/net/tun c 10 200; then - log warn "Cannot create /dev/net/tun. Possible reasons:" - log warn "This script is not executed as root user." - log warn "Your system does not support the TUN/TAP driver." - log warn "Your system kernel version is not compatible with the TUN/TAP driver." + log Warning "Cannot create /dev/net/tun. Possible reasons:" + log Warning "This script is not executed as root user." + log Warning "Your system does not support the TUN/TAP driver." + log Warning "Your system kernel version is not compatible with the TUN/TAP driver." exit 1 fi fi @@ -155,12 +139,17 @@ box_create_tun() { prepare_singbox() { # check configuration file - if ! [ -f "${sing_config}" ]; then log error "configuration file ${clash_config} not found";exit 1; fi + if ! [ -f "${sing_config}" ]; then + log Error "configuration file ${sing_config} not found" + exit 1 + else + log Info "config ${sing_config}" + fi yq_cmd="yq" if ! command -v yq &>/dev/null; then if [ ! -e "${box_dir}/bin/yq" ]; then - log debug "yq file not found, start to download from github" + log Debug "yq file not found, start to download from github" ${scripts_dir}/box.tool upyq fi yq_cmd="${box_dir}/bin/yq" @@ -169,35 +158,48 @@ prepare_singbox() { sed -i '/\/\*/,/\*\//d; /^[[:space:]]*\/\//d; /^( *\/\/|\/\*.*\*\/)$/d' "${box_dir}/sing-box/"*.json if [[ "${network_mode}" == "mixed" || "${proxy_mode}" == "tun" ]]; then if grep -q '"type": "tproxy"' "${sing_config}"; then - "${yq_cmd}" eval 'del(.inbounds[] | select(.type == "tproxy"))' -i --output-format=json "${sing_config}" + "${yq_cmd}" 'del(.inbounds[] | select(.type == "tproxy"))' -i --output-format=json "${sing_config}" fi # Checks if "type" is "tun" in configuration if grep -q '"type": "tun"' "${sing_config}"; then - log info "type 'tun' already exists in ${sing_config}" + log Info "type 'tun' already exists in ${sing_config}" else # Add "tun" configuration if missing - "${yq_cmd}" eval '.inbounds += [{"type": "tun","tag": "tun-in","interface_name": "tun3","inet4_address": "172.19.0.1/30","inet6_address": "fdfe:dcba:9876::1/126","mtu": 9000,"stack": "system","auto_route": true,"strict_route": false,"sniff": true,"sniff_override_destination": true,"include_android_user": [0,10],"include_package": [],"exclude_package": []}]' -i --output-format=json "${sing_config}" - log debug "'tun' configuration has been added to ${sing_config}" + "${yq_cmd}" '.inbounds += [{"type": "tun","tag": "tun-in","interface_name": "tun3","inet4_address": "172.19.0.1/30","inet6_address": "fdfe:dcba:9876::1/126","mtu": 9000,"stack": "system","auto_route": true,"strict_route": false,"sniff": true,"sniff_override_destination": true,"include_android_user": [0,10],"include_package": [],"exclude_package": []}]' -i --output-format=json "${sing_config}" + log Debug "'tun' configuration has been added to ${sing_config}" + fi + if [ "${network_mode}" = "mixed" ]; then + # Checks if "type" is "redirect" in configuration + if grep -q '"type": "redirect"' "${sing_config}"; then + log Info "type 'redirect' already exists in ${sing_config}" + else + # Add "redirect" configuration if missing + "${yq_cmd}" '.inbounds += [{"type": "redirect","tag": "redirect-in","listen": "::","listen_port": '"${redir_port}"',"sniff": true,"sniff_override_destination": true}]' -i --output-format=json "${sing_config}" + log Debug "'redirect' configuration has been added to ${sing_config}" + fi fi sed -i 's/"auto_detect_interface": false/"auto_detect_interface": true/g' "${box_dir}/sing-box/"*.json sed -i 's/auto_route": false/auto_route": true/g' "${box_dir}/sing-box/"*.json else if grep -q '"type": "tun"' "${sing_config}"; then - "${yq_cmd}" eval 'del(.inbounds[] | select(.type == "tun"))' -i --output-format=json "${sing_config}" + "${yq_cmd}" 'del(.inbounds[] | select(.type == "tun"))' -i --output-format=json "${sing_config}" + fi + if grep -q '"type": "redirect"' "${sing_config}"; then + "${yq_cmd}" 'del(.inbounds[] | select(.type == "redirect"))' -i --output-format=json "${sing_config}" fi # Checks if "type" is "tproxy" in configuration if grep -q '"type": "tproxy"' "${sing_config}"; then - log info "type 'tproxy' already exists in ${sing_config}" + log Info "type 'tproxy' already exists in ${sing_config}" else # Add "tproxy" configuration if missing - "${yq_cmd}" eval '.inbounds += [{"type": "tproxy", "tag": "tproxy-in", "listen": "::", "listen_port": '"${tproxy_port}"', "sniff": true, "sniff_override_destination": true}]' -i --output-format=json "${sing_config}" - log debug "'tproxy' configuration has been added to ${sing_config}" + "${yq_cmd}" '.inbounds += [{"type": "tproxy", "tag": "tproxy-in", "listen": "::", "listen_port": '"${tproxy_port}"', "sniff": true, "sniff_override_destination": true}]' -i --output-format=json "${sing_config}" + log Debug "'tproxy' configuration has been added to ${sing_config}" fi # sync tproxy port sing-box, Looping through each JSON file in the directory for file in "${box_dir}/sing-box/"*.json; do tproxy=$(sed -n 's/.*"type": "\(tproxy\)".*/\1/p' "${file}") - if [[ -n "${tproxy}" ]]; then - "${yq_cmd}" -o=json eval "(.inbounds[]? | select(.type == \"tproxy\") | .listen_port) = ${tproxy_port}" -i --output-format=json "${file}" + if [ -n "${tproxy}" ]; then + "${yq_cmd}" -o=json "(.inbounds[]? | select(.type == \"tproxy\") | .listen_port) = ${tproxy_port}" -i --output-format=json "${file}" fi done sed -i 's/"auto_detect_interface": true/"auto_detect_interface": false/g' "${box_dir}/sing-box/"*.json @@ -207,7 +209,13 @@ prepare_singbox() { prepare_clash() { # check configuration file - if ! [ -f "${clash_config}" ]; then log error "configuration file ${clash_config} not found";exit 1; fi + if ! [ -f "${clash_config}" ]; then + log Error "configuration file ${clash_config} not found" + exit 1 + else + temp_clash_config_file + log Info "config ${clash_config}" + fi # ipv6=$(busybox awk '/ipv6:/ { print $2; found=1; exit } END{ if(!found) print "false" }' "${clash_config}" | head -n 1 2>/dev/null) # sed -i "s/ipv6:.*/ipv6: ${ipv6}/g" "${clash_config}" @@ -251,9 +259,9 @@ prepare_clash() { ' auto-detect-interface: true' \ ' include-android-user: [0, 10]' \ ' exclude-package: []' \ >> "${clash_config}" - log debug "'tun' configuration has been added to ${sing_config}" + log Debug "'tun' configuration has been added to ${sing_config}" else - log info "type 'tun' already exists in ${clash_config}" + log Info "type 'tun' already exists in ${clash_config}" fi sed -i "/tun:/ {n;s/enable: false/enable: true/}" "${clash_config}" else @@ -265,6 +273,7 @@ prepare_clash() { if [ "${clash_tun_status}" != "true" ]; then # sync tproxy port sed -i -E "s/(tproxy-port: )[0-9]+/\1${tproxy_port}/" "${clash_config}" + sed -i -E "s/(redir-port: )[0-9]+/\1${redir_port}/" "${clash_config}" else [ "${proxy_mode}" != "tun" ] && sed -i 's/network_mode=.*/network_mode="mixed"/g' "${settings}" # remove tproxy port >>> 0 @@ -274,36 +283,49 @@ prepare_clash() { fi } +temp_clash_config_file() { + clash_template="/data/adb/box/clash/template" + temp_clash_config_file="${clash_config}" + + if [ -f "${clash_template}" ]; then + log debug "use template configuration" + cp -f "${clash_template}" "${temp_clash_config_file}.temp" && echo "\n" >> "${temp_clash_config_file}.temp" + sed -n -E '/^proxies:$/,$p' "${clash_config}" >> "${temp_clash_config_file}.temp" + sed -i '/^[[:space:]]*$/d' "${temp_clash_config_file}.temp" + if mv "${temp_clash_config_file}.temp" "${clash_config}"; then + log Info "The merging of the $clash_config and $clash_template files is complete." + fi + fi +} + box_run_bin() { - log info "client-list: [ ${bin_list[*]} ]" - log info "choose: ${bin_name}, start the service." + log Info "client-list: [ ${bin_list[*]} ]" + log Info "choose: ${bin_name}, start the service." ulimit -SHn 65535 case "${bin_name}" in sing-box) prepare_singbox - nohup busybox setuidgid "${box_user_group}" "${bin_path}" run -D "${box_dir}/${bin_name}" --config-directory "${box_dir}/${bin_name}" > "${box_run}/${bin_name}.log" 2>&1 & - PID=$! - echo -n $PID > "${box_pid}" - sleep 0.1 - - if ! busybox pidof "${bin_name}" >/dev/null; then - MESSAGE=$(cat "${box_run}/${bin_name}.log") - log error "Message: $MESSAGE" - log error "Configuration failed. Please check the ${box_run}/${bin_name}.log file." + if ${bin_path} check -D "${box_dir}/${bin_name}" --config-directory "${box_dir}/${bin_name}" > "${box_run}/${bin_name}.log" 2>&1; then + nohup busybox setuidgid "${box_user_group}" "${bin_path}" run -D "${box_dir}/${bin_name}" --config-directory "${box_dir}/${bin_name}" > "${box_run}/${bin_name}.log" 2>&1 & + PID=$! + echo -n $PID > "${box_pid}" + sleep 0.5 + else + log Error "$(<"${box_run}/${bin_name}.log")" + log Error "configuration failed. Please check the ${box_run}/${bin_name}.log file." exit 1 fi ;; clash) prepare_clash - nohup busybox setuidgid "${box_user_group}" "${bin_path}" -d "${box_dir}/${bin_name}" -f "${clash_config}" > "${box_run}/${bin_name}.log" 2>&1 & - PID=$! - echo -n $PID > "${box_pid}" - sleep 0.1 - - if ! busybox pidof "${bin_name}" >/dev/null; then - MESSAGE=$(cat "${box_run}/${bin_name}.log") - log error "Message: $MESSAGE" - log error "Configuration failed. Please check the ${box_run}/${bin_name}.log file." + if ${bin_path} -t -d "${box_dir}/${bin_name}" -f "${clash_config}" > "${box_run}/${bin_name}.log" 2>&1; then + nohup busybox setuidgid "${box_user_group}" "${bin_path}" -d "${box_dir}/${bin_name}" -f "${clash_config}" > "${box_run}/${bin_name}.log" 2>&1 & + PID=$! + echo -n $PID > "${box_pid}" + sleep 0.5 + else + log Error "$(<"${box_run}/${bin_name}.log")" + log Error "configuration failed. Please check the ${box_run}/${bin_name}.log file." exit 1 fi ;; @@ -312,23 +334,29 @@ box_run_bin() { sed -i 's/\(network_mode=\)\"[^\"]*\"/\1"tproxy"/g' ${settings} [ "${proxy_mode}" = "tun" ] && sed -i 's/\(proxy_mode=\)\"[^\"]*\"/\1"blacklist"/g' ${settings} + # sync port + # sed -i "s/port = [0-9]*\.[0-9]*/port = ${tproxy_port}.0/" ${box_dir}/$bin_name/config.toml + # check configuration file if ! [ -f "${box_dir}/${bin_name}/config.toml" ] && ! [ -f "${box_dir}/${bin_name}/config.json" ]; then - log error "configuration file not found: ${box_dir}/${bin_name}/config.toml or config.json" + log Error "configuration file not found: ${box_dir}/${bin_name}/config.toml or config.json" + rm -f "${box_pid}" exit 1 + else + # Displays a configuration xray" + log Info "config ${box_dir}/${bin_name}/*.json, or *.toml" fi # run xray export XRAY_LOCATION_ASSET="${box_dir}/${bin_name}" - nohup busybox setuidgid "${box_user_group}" "${bin_path}" run -confdir "${box_dir}/${bin_name}" > "${box_run}/${bin_name}.log" 2>&1 & - PID=$! - echo -n $PID > "${box_pid}" - sleep 0.1 - - if ! busybox pidof "${bin_name}" >/dev/null; then - MESSAGE=$(cat "${box_run}/${bin_name}.log") - log error "Message: $MESSAGE" - log error "Configuration failed. Please check the ${box_run}/${bin_name}.log file." + if ${bin_path} -test -confdir "${box_dir}/${bin_name}" > "${box_run}/${bin_name}.log" 2>&1; then + nohup busybox setuidgid "${box_user_group}" "${bin_path}" run -confdir "${box_dir}/${bin_name}" > "${box_run}/${bin_name}.log" 2>&1 & + PID=$! + echo -n $PID > "${box_pid}" + sleep 0.5 + else + log Error "$(<"${box_run}/${bin_name}.log")" + log Error "configuration failed. Please check the ${box_run}/${bin_name}.log file." exit 1 fi ;; @@ -337,28 +365,33 @@ box_run_bin() { sed -i 's/\(network_mode=\)\"[^\"]*\"/\1"tproxy"/g' ${settings} [ "${proxy_mode}" = "tun" ] && sed -i 's/\(proxy_mode=\)\"[^\"]*\"/\1"blacklist"/g' ${settings} + # sync port + # sed -i "s/port = [0-9]*\.[0-9]*/port = ${tproxy_port}.0/" ${box_dir}/$bin_name/config.toml + # check configuration file if ! [ -f "${box_dir}/${bin_name}/config.toml" ] && ! [ -f "${box_dir}/${bin_name}/config.json" ]; then - log error "configuration file not found: ${box_dir}/${bin_name}/config.toml or config.json" + log Error "configuration file not found: ${box_dir}/${bin_name}/config.toml or config.json" exit 1 + else + # Displays a configuration v2fly" + log Info "config ${box_dir}/${bin_name}/*.json, or *.toml" fi # run v2ray export V2RAY_LOCATION_ASSET="${box_dir}/${bin_name}" - nohup busybox setuidgid "${box_user_group}" "${bin_path}" run -d "${box_dir}/${bin_name}" > "${box_run}/${bin_name}.log" 2>&1 & - PID=$! - echo -n $PID > "${box_pid}" - sleep 0.1 - - if ! busybox pidof "${bin_name}" >/dev/null; then - MESSAGE=$(cat "${box_run}/${bin_name}.log") - log error "Message: $MESSAGE" - log error "Configuration failed. Please check the ${box_run}/${bin_name}.log file." + if ${bin_path} test -confdir "${box_dir}/${bin_name}" > "${box_run}/${bin_name}.log" 2>&1; then + nohup busybox setuidgid "${box_user_group}" "${bin_path}" run -d "${box_dir}/${bin_name}" > "${box_run}/${bin_name}.log" 2>&1 & + PID=$! + echo -n $PID > "${box_pid}" + sleep 0.5 + else + log Error "$(<"${box_run}/${bin_name}.log")" + log Error "configuration failed. Please check the ${box_run}/${bin_name}.log file." exit 1 fi ;; *) - log error "<${bin_name}> unknown binary." + log Error "<${bin_name}> unknown binary." exit 1 ;; esac @@ -367,173 +400,151 @@ box_run_bin() { box_cgroup() { if [ "${cgroup_memory}" = "true" ]; then if ${scripts_dir}/box.tool cgroup; then - log info "cgroup limit: ${cgroup_memory_limit}." + log Info "cgroup limit: ${cgroup_memory_limit}." else - log warn "failed to enable cgroup for ${bin_name}." - log warn "cgroups is turned off" + log Warning "failed to enable cgroup for ${bin_name}." + log Warning "cgroups is turned off" sed -i -E "/cgroup_memory/ s/(true)/false/" "${settings}" fi else - log info "${bin_name} cgroup: disabled." + log Info "${bin_name} cgroup: disabled." fi } # Function to display the usage of a binary # This script retrieves information about a running binary process and logs it to a log file. - box_bin_status() { # Get the process ID of the binary - bin_pid=$(busybox pidof ${bin_name}) + local PID=$(busybox pidof ${bin_name}) - if [ -z "${bin_pid}" ]; then - log error "${bin_name} is not running." + if [ -z "$PID" ]; then + log Error "${bin_name} is not running." return 1 fi + log Info "${bin_name}($PID) service is running." + log Info "proxy_mode: ${proxy_mode}, $(if [ "${proxy_mode}" != "tun" ]; then echo network_mode: ${network_mode}; fi)" + # Get the memory usage of the binary - rss=$(grep VmRSS /proc/${bin_pid}/status | busybox awk '{ print $2 }') + rss=$(grep VmRSS /proc/$PID/status | busybox awk '{ print $2 }') [ "${rss}" -ge 1024 ] && bin_rss="$(expr ${rss} / 1024) MB" || bin_rss="${rss} KB" - swap=$(grep VmSwap /proc/${bin_pid}/status | busybox awk '{ print $2 }') + swap=$(grep VmSwap /proc/$PID/status | busybox awk '{ print $2 }') [ "${swap}" -ge 1024 ] && bin_swap="$(expr ${swap} / 1024) MB" || bin_swap="${swap} KB" # Get the state of the binary - state=$(grep State /proc/${bin_pid}/status | busybox awk '{ print $2" "$3 }') + state=$(grep State /proc/$PID/status | busybox awk '{ print $2" "$3 }') # Get the user and group of the binary - user_group=$(stat -c %U:%G /proc/${bin_pid}) + user_group=$(stat -c %U:%G /proc/$PID) # Log the information - log info "${bin_name} has started with the '${user_group}' user group." - log info "${bin_name} status: ${state} (PID: ${bin_pid})" - log info "${bin_name} memory usage: ${bin_rss}, swap: ${bin_swap}" + log Info "${bin_name} has started with the '${user_group}' user group." + log Info "${bin_name} status: ${state} (PID: $PID)" + log Info "${bin_name} memory usage: ${bin_rss}, swap: ${bin_swap}" # Get the CPU usage of the binary - cpu=$(ps -p ${bin_pid} -o %cpu | busybox awk 'NR==2{print $1}' 2> /dev/null) + cpu=$(ps -p $PID -o %cpu | busybox awk 'NR==2{print $1}' 2> /dev/null) if [ -n "${cpu}" ]; then - log info "${bin_name} CPU usage: ${cpu}%" + log Info "${bin_name} CPU usage: ${cpu}%" else - log info "${bin_name} CPU usage: not available" + log Info "${bin_name} CPU usage: not available" fi # Get the running time of the binary - running_time=$(ps -p ${bin_pid} -o etime | busybox awk 'NR==2{print $1}' 2> /dev/null) + running_time=$(ps -p $PID -o etime | busybox awk 'NR==2{print $1}' 2> /dev/null) if [ -n "${running_time}" ]; then - log info "${bin_name} running time: ${running_time}" + log Info "${bin_name} running time: ${running_time}" else - log info "${bin_name} running time: not available." + log Info "${bin_name} running time: not available." fi # Save the process ID to the pid file - echo -n "${bin_pid}" > "${box_pid}" + [ -n "$PID" ] && echo -n "$PID" > "${box_pid}" } start_box() { # Clear the log file and add the timestamp and delimiter echo -n "" > "${box_log}" - # Check whether busybox is installed or not on the system using command -v - if ! command -v busybox &> /dev/null; then - log error "busybox command not found." - exit 1 - fi - # Check if the script is being run in interactive mode or not and display the appropriate message - time_zone=$(getprop persist.sys.timezone) - sim_operator=$(getprop gsm.sim.operator.alpha) - network_type=$(getprop gsm.network.type) if [ -t 1 ]; then - echo -e "${yellow}${time_zone}${normal}" - echo -e "${yellow}${sim_operator} / ${network_type}${normal}" + echo -e "${yellow}$(getprop persist.sys.timezone)${normal}" + echo -e "${yellow}$(getprop gsm.sim.operator.alpha) / $(getprop gsm.network.type)${normal}" echo -e "${yellow}$(date)${normal}" echo -e "${white}--------------------------------------------${normal}" else echo "$(getprop persist.sys.timezone)" | tee -a "${box_log}" > /dev/null 2>&1 - echo "${sim_operator} / ${network_type}" | tee -a "${box_log}" > /dev/null 2>&1 + echo "$(getprop gsm.sim.operator.alpha) / $(getprop gsm.network.type)" | tee -a "${box_log}" > /dev/null 2>&1 echo "$(date)" | tee -a "${box_log}" > /dev/null 2>&1 echo "--------------------------------------------" | tee -a "${box_log}" > /dev/null 2>&1 fi + # Update iptables if bin_name is still running - local pid=$(cat ${box_pid} 2>/dev/null) - if kill -0 "${pid}" > /dev/null 2>&1 || busybox pidof "${bin_name}" > /dev/null 2>&1; then - log debug "${bin_name} service is still running, auto restart box." + PIDS=("clash" "xray" "sing-box" "v2fly") + PID="" + i=0 + while [ -z "$PID" ] && [ "$i" -lt "${#PIDS[@]}" ]; do + PID=$(busybox pidof "${PIDS[$i]}") + i=$((i+1)) + done + + if [ -n "$PID" ]; then + pid_name="/data/adb/box/run/pid_name.txt" + ps -p $PID -o comm= > "${pid_name}" + sed -i '/^[[:space:]]*$/d' "${pid_name}" + log Debug "$(<"${pid_name}") (PID: $PID) service is still running, auto restart BOX." + rm -f "${pid_name}" stop_box - start_box - ${scripts_dir}/box.iptables renew || ${scripts_dir}/box.iptables disable + start_box && "${scripts_dir}/box.iptables" renew exit 1 fi + + # Checks if bin_name is defined case "${bin_name}" in "xray" | "sing-box" | "clash" | "v2fly") - log info "Good day 🐻" + log Info "Good day 🐱" ;; *) - log error "bin_name: <${bin_name}> unknown not defined." + log Error "bin_name: <..${bin_name}..> unknown not defined." exit 1 ;; esac + # Check permissions, check for bin existence, delete old logs, create a TUN if necessary, run box, and wait for 1 second box_permission box_check_bin box_check_logs + # Enable IP forwarding if ! sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 || ! sysctl -w net.ipv6.conf.all.forwarding=1 >/dev/null 2>&1; then - echo "Cannot enable IP forwarding." + log Debug "Cannot enable IP forwarding." fi - box_create_tun - box_run_bin - sleep 1 - # Displays a configuration message if bin_name is "clash|xray|sing-box|v2fly" - case "${bin_name}" in - "clash") - log info "config ${clash_config}" - ;; - "sing-box") - log info "config ${box_dir}/${bin_name}/*.json" - ;; - "xray" | "v2fly") - log info "config ${box_dir}/${bin_name}/*.json, or *.toml" - ;; - *) - log error "bin_name: <${bin_name}> unknown not defined." - exit 1 - ;; - esac + + # Execute the box_create_tun functions + if [[ "${network_mode}" == "mixed" || "${proxy_mode}" == "tun" ]]; then + box_create_tun + fi + # Execute box_run_crontab if run_crontab is not equal to "false" - if [ "${run_crontab}" != "false" ]; then - box_run_crontab - else - log info "crontab: disabled." - fi - # Execute the box_cgroup, box_detected_port, box_bin_alive functions + [ "${run_crontab}" != "false" ] && box_run_crontab || log Info "crontab disabled." + + # Execute the box_cgroup, box_run_bin, box_detected_port, box_bin_alive,box_bin_status functions + box_run_bin box_cgroup - box_detected_port - box_bin_alive - # Checks if bin_name is defined - if [ -z "${bin_name}" ]; then - log error "bin_name: <${bin_name}> unknown not defined." - exit 1 - fi - # Look up the PID of bin_name - bin_pid=$(busybox pidof "${bin_name}") - # Checks if bin_name is running - if [ -n "${bin_pid}" ]; then - # If so, prints a message and calls the box_bin_status function - log info "${bin_name} service is running. (PID: ${bin_pid})." - log info "proxy_mode: $proxy_mode $(if [ "${proxy_mode}" != "tun" ]; then echo / network_mode: $network_mode; fi)" - box_bin_status - else - # Otherwise, it prints a message and returns status 1 - log warn "${bin_name} service is stopped." - exit 1 - fi + # $bin_name detected port + if [ "${port_detect}" = "true" ]; then "${scripts_dir}/box.tool" port; else log Info "${bin_name} skipped port detection."; fi + count=0 + while [ $count -le 10 ]; do + sleep 0.15 + box_bin_alive || break + count=$((count + 1)) + done + box_bin_status + # open the yacd in browser open_yacd } stop_box() { - # Find cronjob PID using `pgrep` - cronkill=$(busybox pgrep -f "crond -c ${box_run}") - for cron in ${cronkill[@]}; do - # kill cronjob - kill -15 "${cron}" - done + stop_cron # Kill each binary using a loop for bin in "${bin_list[@]}"; do # Check if the binary is running using pgrep @@ -546,6 +557,7 @@ stop_box() { fi fi done + # Check if the binary has stopped sleep 0.5 if ! busybox pidof "${bin_name}" >/dev/null 2>&1; then @@ -553,17 +565,27 @@ stop_box() { if [ -f "${box_pid}" ]; then rm -f "${box_pid}" fi - log warn "${bin_name} service is stopped." - log warn "${bin_name} disconnected." + log Warning "${bin_name} service is stopped." + log Warning "${bin_name} disconnected." + [ -t 1 ] && echo -e "${white}--------------------------------------------${normal}" else - log warn "${bin_name} Not stopped; may still be shutting down or failed to shut down." + log Warning "${bin_name} Not stopped; may still be shutting down or failed to shut down." force_stop fi } +stop_cron() { + # Find cronjob PID using `pgrep` + cronkill=$(busybox pgrep -f "crond -c ${box_run}") + for cron in ${cronkill[@]}; do + # kill cronjob + kill -15 "${cron}" + done +} + force_stop() { # try forcing it to shut down. - log warn "try forcing it to shut down." + log Warning "try forcing it to shut down." for bin in "${bin_list[@]}"; do # Use `busybox pkill` to kill the binary with signal 9, otherwise use `killall`. if busybox pkill -9 "${bin}"; then @@ -578,11 +600,17 @@ force_stop() { done sleep 0.5 if ! busybox pidof "${bin_name}" >/dev/null 2>&1; then - log warn "done, YOU can sleep peacefully." + log Warning "done, YOU can sleep peacefully." rm -f "${box_pid}" fi } +# Check whether busybox is installed or not on the system using command -v +if ! command -v busybox &> /dev/null; then + log Error "busybox command not found." + exit 1 +fi + case "$1" in start) stop_box >> /dev/null 2>&1 @@ -593,7 +621,7 @@ case "$1" in ;; restart) "${scripts_dir}/box.iptables" disable && stop_box - sleep 1 + sleep 0.5 start_box && "${scripts_dir}/box.iptables" renew ;; status) @@ -603,24 +631,22 @@ case "$1" in clash) echo "${yellow}$("${bin_path}" -v)${normal}";; *) echo "${yellow}$("${bin_path}" version)${normal}";; esac - log info "proxy_mode: $proxy_mode $(if [ "${proxy_mode}" != "tun" ]; then echo / network_mode: $network_mode; fi)" box_bin_status else - log warn "${bin_name} service is stopped." + log Warning "${bin_name} service is stopped." fi ;; cron) run_crontab="true" - cronkill=$(busybox pgrep -f "crond -c ${box_run}") - for cron in ${cronkill[@]}; do - # kill cronjob - kill -15 "${cron}" - done - sleep 0.2 + stop_cron + sleep 0.5 box_run_crontab ;; + kcron) + stop_cron + ;; *) echo "${red}$0 $1 no found${normal}" - echo "${yellow}usage${normal}: ${green}$0${normal} {${yellow}start|stop|restart|status${normal}}" + echo "${yellow}usage${normal}: ${green}$0${normal} {${yellow}start|stop|restart|status|cron|kcron${normal}}" ;; esac \ No newline at end of file diff --git a/box/scripts/box.tool b/box/scripts/box.tool index d0ff376..4f63313 100755 --- a/box/scripts/box.tool +++ b/box/scripts/box.tool @@ -15,29 +15,22 @@ singbox_releases=false # whether use ghproxy to accelerate github download use_ghproxy=true -# Check if a binary is running by checking the pid file -probe_bin_alive() { - if [ ! -f "${box_pid}" ]; then - log error "pid file not found, binary is not alive" - return 1 - fi - sleep 0.5 - if ! busybox pidof "${bin_name}" >/dev/null; then - log error "binary is not alive" - return 1 - fi - return 0 # binary is alive -} - # Restart the binary, after stopping and running again restart_box() { - ${scripts_dir}/box.service restart - sleep 0.5 - if probe_bin_alive ; then - # ${scripts_dir}/box.iptables renew - log debug "$(date +"%F %R") || ${bin_name} finished restarting." + "${scripts_dir}/box.service" restart + # PIDS=("clash" "xray" "sing-box" "v2fly") + PIDS=(${bin_name}) + PID="" + i=0 + while [ -z "$PID" ] && [ "$i" -lt "${#PIDS[@]}" ]; do + PID=$(busybox pidof "${PIDS[$i]}") + i=$((i+1)) + done + + if [ -n "$PID" ]; then + log Debug "${bin_name} Restart complete [$(date +"%F %R")]" else - log error "Failed to restart ${bin_name}." + log Error "Failed to restart ${bin_name}." ${scripts_dir}/box.iptables disable >/dev/null 2>&1 fi } @@ -51,7 +44,7 @@ update_file() { mv "${file}" "${file_bak}" || return 1 fi # Use ghproxy - if [[ "${use_ghproxy}" == true ]] && [[ "${update_url}" == @(https://github.com/*|https://raw.githubusercontent.com/*|https://gist.github.com/*|https://gist.githubusercontent.com/*) ]]; then + if [ "${use_ghproxy}" == true ] && [[ "${update_url}" == @(https://github.com/*|https://raw.githubusercontent.com/*|https://gist.github.com/*|https://gist.githubusercontent.com/*) ]]; then update_url="https://ghproxy.com/${update_url}" fi # request @@ -65,7 +58,7 @@ update_file() { if [ -f "${file_bak}" ]; then mv "${file_bak}" "${file}" || true fi - log error "Download ${request} ${orange}failed${normal}" + log Error "Download ${request} ${orange}failed${normal}" return 1 } return 0 @@ -79,13 +72,13 @@ update_yq() { "armv7l"|"armv8l") arch="arm"; platform="android" ;; "i686") arch="386"; platform="android" ;; "x86_64") arch="amd64"; platform="android" ;; - *) log warn "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; + *) log Warning "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; esac # If you use yq_linux, an error will occur (cmd: mkdir /tmp permission denied) when using a cron job. # download_link="https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${arch}" download_link="https://github.com/taamarin/yq/releases/download/prerelease/yq_${platform}_${arch}" - log debug "Download ${download_link}" + log Debug "Download ${download_link}" update_file "${box_dir}/bin/yq" "${download_link}" chown "${box_user_group}" "${box_dir}/bin/yq" chmod 0755 "${box_dir}/bin/yq" @@ -116,12 +109,12 @@ update_geox() { geosite_url="https://github.com/MetaCubeX/meta-rules-dat/raw/release/geosite.dat" ;; esac - if [ "${update_geo}" = "true" ] && { log info "daily updates geox" && log debug "Downloading ${geoip_url}"; } && update_file "${geoip_file}" "${geoip_url}" && { log debug "Downloading ${geosite_url}" && update_file "${geosite_file}" "${geosite_url}"; }; then + if [ "${update_geo}" = "true" ] && { log Info "daily updates geox" && log Debug "Downloading ${geoip_url}"; } && update_file "${geoip_file}" "${geoip_url}" && { log Debug "Downloading ${geosite_url}" && update_file "${geosite_file}" "${geosite_url}"; }; then find "${box_dir}/${bin_name}" -type f -name "*.db.bak" -delete find "${box_dir}/${bin_name}" -type f -name "*.dat.bak" -delete find "${box_dir}/${bin_name}" -type f -name "*.mmdb.bak" -delete - log debug "Update geox $(date +%F %R)" + log Debug "Update geox $(date +%F %R)" return 0 else return 1 @@ -137,7 +130,7 @@ update_subs() { # If yq native doesn't exist if [ "${yq_command}" -eq 1 ]; then if [ ! -e "${box_dir}/bin/yq" ]; then - log debug "yq file not found, start to download from github" + log Debug "yq file not found, start to download from github" update_yq fi yq_command=$(command -v "${box_dir}/bin/yq" >/dev/null 2>&1; echo $?) @@ -147,7 +140,7 @@ update_subs() { enhanced=true update_file_name="${update_file_name}.subscription" else - log warn "yq not found, this will update main configuration $(if [ "${bin_name}" = "clash" ]; then echo "${clash_config}"; else echo "${sing_config}"; fi)" + log Warning "yq not found, this will update main configuration $(if [ "${bin_name}" = "clash" ]; then echo "${clash_config}"; else echo "${sing_config}"; fi)" fi fi @@ -156,35 +149,35 @@ update_subs() { # subscription clash if [ -n "${subscription_url_clash}" ]; then if [ "${update_subscription}" = "true" ]; then - log info "daily updates subs" - log debug "Downloading ${update_file_name}" + log Info "daily updates subs" + log Debug "Downloading ${update_file_name}" if update_file "${update_file_name}" "${subscription_url_clash}"; then - log info "${update_file_name} saved" + log Info "${update_file_name} saved" # If there is a yq command, extract the proxy information from the yml and output it to the clash_provide_config file if [ "${enhanced}" = "true" ]; then - if ${yq_cmd} eval '.proxies' "${update_file_name}" >/dev/null 2>&1; then + if ${yq_cmd} '.proxies' "${update_file_name}" >/dev/null 2>&1; then "${yq_cmd}" '.proxies' "${update_file_name}" > "${clash_provide_config}" "${yq_cmd}" -i '{"proxies": .}' "${clash_provide_config}" - log info "subscription success" - log info "Update subscription $(date +"%F %R")" - if [[ -f "${update_file_name}.bak" ]]; then + log Info "subscription success" + log Info "Update subscription $(date +"%F %R")" + if [ -f "${update_file_name}.bak" ]; then rm "${update_file_name}.bak" fi else - log error "${update_file_name} update subscription failed" + log Error "${update_file_name} update subscription failed" return 1 fi fi return 0 else - log error "update subscription failed" + log Error "update subscription failed" return 1 fi else return 1 fi else - log warn "${bin_name} subscription url is empty..." + log Warning "${bin_name} subscription url is empty..." return 1 fi ;; @@ -192,10 +185,10 @@ update_subs() { if [ -n "${subscription_url_sing}" ]; then # subscription sing-box if [ "${update_subscription}" = "true" ]; then - log info "daily updates subs" - log debug "Downloading ${update_file_name}" + log Info "daily updates subs" + log Debug "Downloading ${update_file_name}" if update_file "${update_file_name}" "${subscription_url_sing}"; then - log info "${update_file_name} saved" + log Info "${update_file_name} saved" if [ "${enhanced}" = "true" ]; then if "${yq_cmd}" -e . "${update_file_name}" >/dev/null 2>&1; then cp "${update_file_name}" "${sing_provide_config}" @@ -205,59 +198,140 @@ update_subs() { # script to edit sing-box subscriptions # removed the structure: inbounds/experimental/route/log and dns - "${yq_cmd}" eval 'del(.inbounds, .experimental, .route, .log, .dns)' -i --output-format=json "${sing_provide_config}" + "${yq_cmd}" 'del(.inbounds, .experimental, .route, .log, .dns)' -i --output-format=json "${sing_provide_config}" # remove outbound with type: direct/block/dns/selector/urltest - "${yq_cmd}" eval 'del(.outbounds[] | select(.type == "direct" or .type == "block" or .type == "dns" or .type == "selector" or .type == "urltest"))' -i --output-format=json "${sing_provide_config}" + "${yq_cmd}" 'del(.outbounds[] | select(.type == "direct" or .type == "block" or .type == "dns" or .type == "selector" or .type == "urltest"))' -i --output-format=json "${sing_provide_config}" - # create new outbounds with type: selector, tag: ✿✘ꕥ in ${sing_provide_config} - "${yq_cmd}" eval '.outbounds += [{"tag": "✿✘ꕥ", "type": "selector", "outbounds": [.outbounds[].tag]}]' -i --output-format=json "${sing_provide_config}" + # create new outbounds with type: selector, tag: ❀✿❀ in ${sing_provide_config} + "${yq_cmd}" '.outbounds += [{"tag": "❀✿❀", "type": "selector", "outbounds": [.outbounds[].tag]}]' -i --output-format=json "${sing_provide_config}" - # create new outbounds with type: urltest, tag: ✿✘ꕥ[urltest] in ${sing_provide_config} - "${yq_cmd}" eval '.outbounds += [{"tag": "✿✘ꕥ[urltest]", "type": "urltest", "url": "https://www.gstatic.com/generate_204", "interval": "3m", "outbounds": [.outbounds[].tag]}]' -i --output-format=json "${sing_provide_config}" + # create new outbounds with type: urltest, tag: ❀✿❀[urltest] in ${sing_provide_config} + "${yq_cmd}" '.outbounds += [{"tag": "❀✿❀[urltest]", "type": "urltest", "url": "https://www.gstatic.com/generate_204", "interval": "3m", "outbounds": [.outbounds[].tag]}]' -i --output-format=json "${sing_provide_config}" - # renew outbounds with tag: ✿✘ꕥ in main ${sing_config} dan ${sing_provide_config} - "${yq_cmd}" eval 'del(.outbounds[].outbounds[] | select(. == "✿✘ꕥ"))' -i --output-format=json "${sing_provide_config}" - "${yq_cmd}" eval 'del(.outbounds[].outbounds[] | select(. == "✿✘ꕥ"))' -i --output-format=json "${sing_config}" - "${yq_cmd}" eval '.outbounds[0].outbounds += ["✿✘ꕥ"]' -i --output-format=json "${sing_config}" + # renew outbounds with tag: ❀✿❀ in main ${sing_config} dan ${sing_provide_config} + "${yq_cmd}" 'del(.outbounds[].outbounds[] | select(. == "❀✿❀"))' -i --output-format=json "${sing_provide_config}" + "${yq_cmd}" 'del(.outbounds[].outbounds[] | select(. == "❀✿❀"))' -i --output-format=json "${sing_config}" + "${yq_cmd}" '.outbounds[0].outbounds += ["❀✿❀"]' -i --output-format=json "${sing_config}" - # renew outbounds with tag: ✿✘ꕥ[urltest] in main ${sing_config} dan ${sing_provide_config} - "${yq_cmd}" eval 'del(.outbounds[].outbounds[] | select(. == "✿✘ꕥ[urltest]"))' -i --output-format=json "${sing_provide_config}" - "${yq_cmd}" eval 'del(.outbounds[].outbounds[] | select(. == "✿✘ꕥ[urltest]"))' -i --output-format=json "${sing_config}" - "${yq_cmd}" eval '.outbounds[0].outbounds += ["✿✘ꕥ[urltest]"]' -i --output-format=json "${sing_config}" + # renew outbounds with tag: ❀✿❀[urltest] in main ${sing_config} dan ${sing_provide_config} + "${yq_cmd}" 'del(.outbounds[].outbounds[] | select(. == "❀✿❀[urltest]"))' -i --output-format=json "${sing_provide_config}" + "${yq_cmd}" 'del(.outbounds[].outbounds[] | select(. == "❀✿❀[urltest]"))' -i --output-format=json "${sing_config}" + "${yq_cmd}" '.outbounds[0].outbounds += ["❀✿❀[urltest]"]' -i --output-format=json "${sing_config}" - log info "subscription success" - log info "Update subscription $(date +"%F %R")" + log Info "subscription success" + log Info "Update subscription $(date +"%F %R")" else - log error "update subscription failed" - log error "${update_file_name} error" + log Error "update subscription failed" + log Error "${update_file_name} error" return 1 fi fi return 0 else - log error "update subscription failed" + log Error "update subscription failed" return 1 fi else return 1 fi else - log warn "${bin_name} subscription url is empty..." + log Warning "${bin_name} subscription url is empty..." return 1 fi ;; "xray" | "v2fly") - log warn "${bin_name} does not support subscriptions.." + log Warning "${bin_name} does not support subscriptions.." return 1 ;; *) - log error "<${bin_name}> unknown binary." + log Error "<${bin_name}> unknown binary." return 1 ;; esac } +update_kernel() { + # su -c /data/adb/box/scripts/box.tool upcore + mkdir -p "${bin_dir}/backup" + if [ -f "${bin_dir}/${bin_name}" ]; then + cp "${bin_dir}/${bin_name}" "${bin_dir}/backup/${bin_name}.bak" >/dev/null 2>&1 + fi + case $(uname -m) in + "aarch64") arch="arm64"; platform="android" ;; + "armv7l"|"armv8l") arch="armv7"; platform="linux" ;; + "i686") arch="386"; platform="linux" ;; + "x86_64") arch="amd64"; platform="linux" ;; + *) log Warning "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; + esac + # Do anything else below + file_kernel="${bin_name}-${arch}" + case "${bin_name}" in + "sing-box") + url_down="https://github.com/SagerNet/sing-box/releases" + if [ "${singbox_releases}" = "false" ]; then + sing_box_version_temp=$(busybox wget --no-check-certificate -qO- "${url_down}" | grep -oE '/tag/v[0-9]+\.[0-9]+-[a-z0-9]+' | head -1 | busybox awk -F'/' '{print $3}') + else + sing_box_version_temp=$(busybox wget --no-check-certificate -qO- "${url_down}" | grep -oE '/tag/v[0-9]+\.[0-9]+\.[0-9]+' | head -1 | busybox awk -F'/' '{print $3}') + fi + sing_box_version=${sing_box_version_temp#v} + download_link="${url_down}/download/${sing_box_version_temp}/sing-box-${sing_box_version}-${platform}-${arch}.tar.gz" + log Debug "download ${download_link}" + update_file "${box_dir}/${file_kernel}.tar.gz" "${download_link}" && extra_kernel + ;; + "clash") + if [ "${meta}" = "true" ]; then + # set download link and get the latest version + download_link="https://github.com/MetaCubeX/Clash.Meta/releases" + if [ "$use_ghproxy" == true ]; then + download_link="https://ghproxy.com/${download_link}" + fi + # tag=$(busybox wget --no-check-certificate -qO- ${download_link} | grep -oE 'tag\/([^"]+)' | cut -d '/' -f 2 | head -1) + tag="Prerelease-Alpha" + latest_version=$(busybox wget --no-check-certificate -qO- "${download_link}/expanded_assets/${tag}" | grep -oE "alpha-[0-9a-z]+" | head -1) + # set the filename based on platform and architecture + filename="clash.meta-${platform}-${arch}-${latest_version}" + # download and update the file + log Debug "download ${download_link}/download/${tag}/${filename}.gz" + update_file "${box_dir}/${file_kernel}.gz" "${download_link}/download/${tag}/${filename}.gz" && extra_kernel + # if meta flag is false, download clash premium/dev + else + # if dev flag is true, download latest dev version + if [ "${dev}" != "false" ]; then + log Debug "download https://release.dreamacro.workers.dev/latest/clash-linux-${arch}-latest.gz" + update_file "${box_dir}/${file_kernel}.gz" "https://release.dreamacro.workers.dev/latest/clash-linux-${arch}-latest.gz" && extra_kernel + else + # if dev flag is false, download latest premium version + filename=$(busybox wget --no-check-certificate -qO- "https://github.com/Dreamacro/clash/releases/expanded_assets/premium" | grep -oE "clash-linux-${arch}-[0-9]+.[0-9]+.[0-9]+" | head -1) + log Debug "download https://github.com/Dreamacro/clash/releases/download/premium/${filename}.gz" + update_file "${box_dir}/${file_kernel}.gz" "https://github.com/Dreamacro/clash/releases/download/premium/${filename}.gz" && extra_kernel + fi + fi + ;; + "xray"|"v2fly") + [ "${bin_name}" = "xray" ] && bin='Xray' || bin='v2ray' + api_url="https://api.github.com/repos/$(if [ "${bin_name}" = "xray" ]; then echo "XTLS/Xray-core/releases"; else echo "v2fly/v2ray-core/releases"; fi)" + # set download link and get the latest version + latest_version=$(busybox wget --no-check-certificate -qO- ${api_url} | grep "tag_name" | grep -o "v[0-9.]*" | head -1) + case $(uname -m) in + "i386") download_file="$bin-linux-32.zip" ;; + "x86_64") download_file="$bin-linux-64.zip" ;; + "armv7l"|"armv8l") download_file="$bin-linux-arm32-v7a.zip" ;; + "aarch64") download_file="$bin-android-arm64-v8a.zip" ;; + *) log Error "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; + esac + # Do anything else below + download_link="https://github.com/$(if [ "${bin_name}" = "xray" ]; then echo "XTLS/Xray-core/releases"; else echo "v2fly/v2ray-core/releases"; fi)" + log Debug "Downloading ${download_link}/download/${latest_version}/${download_file}" + update_file "${box_dir}/${file_kernel}.zip" "${download_link}/download/${latest_version}/${download_file}" && extra_kernel + ;; + *) + log Error "<${bin_name}> unknown binary." + exit 1 + ;; + esac +} + # Check and update kernel extra_kernel() { case "${bin_name}" in @@ -272,10 +346,10 @@ extra_kernel() { if [ -f "${box_pid}" ]; then restart_box else - log debug "${bin_name} does not need to be restarted." + log Debug "${bin_name} does not need to be restarted." fi else - log error "Failed to extract or move the kernel." + log Error "Failed to extract or move the kernel." fi ;; "sing-box") @@ -290,10 +364,10 @@ extra_kernel() { if [ -f "${box_pid}" ]; then restart_box else - log debug "${bin_name} does not need to be restarted." + log Debug "${bin_name} does not need to be restarted." fi else - log warn "Failed to extract ${box_dir}/${file_kernel}.tar.gz." + log Warning "Failed to extract ${box_dir}/${file_kernel}.tar.gz." fi ;; "v2fly"|"xray") @@ -312,18 +386,18 @@ extra_kernel() { if [ -f "${box_pid}" ]; then restart_box else - log debug "${bin_name} does not need to be restarted." + log Debug "${bin_name} does not need to be restarted." fi else - log error "Failed to move the kernel." + log Error "Failed to move the kernel." fi else - log warn "Failed to extract ${box_dir}/${file_kernel}.zip." + log Warning "Failed to extract ${box_dir}/${file_kernel}.zip." fi rm -rf "${bin_dir}/update" ;; *) - log error "<${bin_name}> unknown binary." + log Error "<${bin_name}> unknown binary." exit 1 ;; esac @@ -333,101 +407,20 @@ extra_kernel() { chmod 6755 ${bin_path} } -update_kernel() { - # su -c /data/adb/box/scripts/box.tool upcore - mkdir -p "${bin_dir}/backup" - if [ -f "${bin_dir}/${bin_name}" ]; then - cp "${bin_dir}/${bin_name}" "${bin_dir}/backup/${bin_name}.bak" >/dev/null 2>&1 - fi - case $(uname -m) in - "aarch64") arch="arm64"; platform="android" ;; - "armv7l"|"armv8l") arch="armv7"; platform="linux" ;; - "i686") arch="386"; platform="linux" ;; - "x86_64") arch="amd64"; platform="linux" ;; - *) log warn "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; - esac - # Do anything else below - file_kernel="${bin_name}-${arch}" - case "${bin_name}" in - "sing-box") - url_down="https://github.com/SagerNet/sing-box/releases" - if [ "${singbox_releases}" = "false" ]; then - sing_box_version_temp=$(busybox wget --no-check-certificate -qO- "${url_down}" | grep -oE '/tag/v[0-9]+\.[0-9]+-[a-z0-9]+' | head -1 | busybox awk -F'/' '{print $3}') - else - sing_box_version_temp=$(busybox wget --no-check-certificate -qO- "${url_down}" | grep -oE '/tag/v[0-9]+\.[0-9]+\.[0-9]+' | head -1 | busybox awk -F'/' '{print $3}') - fi - sing_box_version=${sing_box_version_temp#v} - download_link="${url_down}/download/${sing_box_version_temp}/sing-box-${sing_box_version}-${platform}-${arch}.tar.gz" - log debug "download ${download_link}" - update_file "${box_dir}/${file_kernel}.tar.gz" "${download_link}" && extra_kernel - ;; - "clash") - if [ "${meta}" = "true" ]; then - # set download link and get the latest version - download_link="https://github.com/MetaCubeX/Clash.Meta/releases" - if [[ "$use_ghproxy" == true ]]; then - download_link="https://ghproxy.com/${download_link}" - fi - # tag=$(busybox wget --no-check-certificate -qO- ${download_link} | grep -oE 'tag\/([^"]+)' | cut -d '/' -f 2 | head -1) - tag="Prerelease-Alpha" - latest_version=$(busybox wget --no-check-certificate -qO- "${download_link}/expanded_assets/${tag}" | grep -oE "alpha-[0-9a-z]+" | head -1) - # set the filename based on platform and architecture - filename="clash.meta-${platform}-${arch}-${latest_version}" - # download and update the file - log debug "download ${download_link}/download/${tag}/${filename}.gz" - update_file "${box_dir}/${file_kernel}.gz" "${download_link}/download/${tag}/${filename}.gz" && extra_kernel - # if meta flag is false, download clash premium/dev - else - # if dev flag is true, download latest dev version - if [ "${dev}" != "false" ]; then - log debug "download https://release.dreamacro.workers.dev/latest/clash-linux-${arch}-latest.gz" - update_file "${box_dir}/${file_kernel}.gz" "https://release.dreamacro.workers.dev/latest/clash-linux-${arch}-latest.gz" && extra_kernel - else - # if dev flag is false, download latest premium version - filename=$(busybox wget --no-check-certificate -qO- "https://github.com/Dreamacro/clash/releases/expanded_assets/premium" | grep -oE "clash-linux-${arch}-[0-9]+.[0-9]+.[0-9]+" | head -1) - log debug "download https://github.com/Dreamacro/clash/releases/download/premium/${filename}.gz" - update_file "${box_dir}/${file_kernel}.gz" "https://github.com/Dreamacro/clash/releases/download/premium/${filename}.gz" && extra_kernel - fi - fi - ;; - "xray"|"v2fly") - [ "${bin_name}" = "xray" ] && bin='Xray' || bin='v2ray' - api_url="https://api.github.com/repos/$(if [ "${bin_name}" = "xray" ]; then echo "XTLS/Xray-core/releases"; else echo "v2fly/v2ray-core/releases"; fi)" - # set download link and get the latest version - latest_version=$(busybox wget --no-check-certificate -qO- ${api_url} | grep "tag_name" | grep -o "v[0-9.]*" | head -1) - case $(uname -m) in - "i386") download_file="$bin-linux-32.zip" ;; - "x86_64") download_file="$bin-linux-64.zip" ;; - "armv7l"|"armv8l") download_file="$bin-linux-arm32-v7a.zip" ;; - "aarch64") download_file="$bin-android-arm64-v8a.zip" ;; - *) log error "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; - esac - # Do anything else below - download_link="https://github.com/$(if [ "${bin_name}" = "xray" ]; then echo "XTLS/Xray-core/releases"; else echo "v2fly/v2ray-core/releases"; fi)" - log debug "Downloading ${download_link}/download/${latest_version}/${download_file}" - update_file "${box_dir}/${file_kernel}.zip" "${download_link}/download/${latest_version}/${download_file}" && extra_kernel - ;; - *) - log error "<${bin_name}> unknown binary." - exit 1 - ;; - esac -} - # Check and update yacd update_dashboard() { # su -c /data/adb/box/scripts/box.tool upyacd if [ "${bin_name}" = "clash" -o "${bin_name}" = "sing-box" ]; then file_dashboard="${box_dir}/${bin_name}/dashboard.zip" url="https://github.com/MetaCubeX/Yacd-meta/archive/gh-pages.zip" - if [[ "$use_ghproxy" == true ]]; then + if [ "$use_ghproxy" == true ]; then url="https://ghproxy.com/${url}" fi dir_name="Yacd-meta-gh-pages" - log debug "Download ${url}" + log Debug "Download ${url}" if busybox wget --no-check-certificate "${url}" -O "${file_dashboard}" >&2; then if [ ! -d "${box_dir}/${bin_name}/dashboard" ]; then - log info "dashboard folder not exist, creating it" + log Info "dashboard folder not exist, creating it" mkdir "${box_dir}/${bin_name}/dashboard" else rm -rf "${box_dir}/${bin_name}/dashboard/"* @@ -442,52 +435,42 @@ update_dashboard() { rm -f "${file_dashboard}" rm -rf "${box_dir}/${bin_name}/dashboard/${dir_name}" else - log error "Failed to download dashboard" >&2 + log Error "Failed to download dashboard" >&2 return 1 fi return 0 else - log debug "${bin_name} does not support dashboards" + log Debug "${bin_name} does not support dashboards" return 1 fi } # Function for detecting ports used by a process port_detection() { - sleep 1.5 + sleep 1 # Use 'command' function to check availability of 'ss' if command -v ss > /dev/null ; then # Use 'awk' with a regular expression to match the process ID - ports=$(ss -antup | busybox awk -v pid="$(busybox pidof "${bin_name}")" '$7 ~ pid {print $5}' | busybox awk -F ':' '{print $2}' | sort -u) >/dev/null 2>&1 - else - # Note the warning message if 'ss' is not available - log debug "ss command not found, skipping port detection." >&2 - return - fi - # Make a note of the detected ports - now=$(date +"%I:%M %p") - if busybox pidof "${bin_name}" >/dev/null 2>&1; then - if [ -t 1 ]; then - echo -n "${orange}${now} [debug]: ${bin_name} port detected: ${normal}" - else - echo -n "${now} [debug]: ${bin_name} port detected: " | tee -a "${box_log}" >> /dev/null 2>&1 - fi - # write ports - while read -r port; do - sleep 0.5 + ports=$(ss -antup | busybox awk -v PID="$(busybox pidof "${bin_name}")" '$7 ~ PID {print $5}' | busybox awk -F ':' '{print $2}' | sort -u) >/dev/null 2>&1 + # Make a note of the detected ports + if busybox pidof "${bin_name}" >/dev/null 2>&1; then if [ -t 1 ]; then - echo -n "${red}${port} $normal" + echo -n "${orange}${now} [debug]: ${bin_name} port detected:${normal}" else - echo -n "${port} " | tee -a "${box_log}" >> /dev/null 2>&1 + echo -n "${now} [debug]: ${bin_name} port detected:" | tee -a "${box_log}" >> /dev/null 2>&1 fi - done <<< "${ports}" - # Add a newline to the output if running in terminal - if [ -t 1 ]; then - echo -e "\033[1;31m""\033[0m" + # write ports + while read -r port; do + sleep 0.5 + [ -t 1 ] && (echo -n "${red}${port}|$normal") || (echo -n "${port}|" | tee -a "${box_log}" >> /dev/null 2>&1) + done <<< "${ports}" + # Add a newline to the output if running in terminal + [ -t 1 ] && echo -e "\033[1;31m""\033[0m" || echo "" >> "${box_log}" 2>&1 else - echo "" >> "${box_log}" 2>&1 + return 1 fi else + log Debug "ss command not found, skipping port detection." >&2 return 1 fi } @@ -496,40 +479,40 @@ port_detection() { cgroup_limit() { # Check if the cgroup memory limit has been set. if [ -z "${cgroup_memory_limit}" ]; then - log warn "cgroup_memory_limit is not set" + log Warning "cgroup_memory_limit is not set" return 1 fi + # Check if the cgroup memory path is set and exists. if [ -z "${cgroup_memory_path}" ]; then local cgroup_memory_path=$(mount | grep cgroup | busybox awk '/memory/{print $3}' | head -1) if [ -z "${cgroup_memory_path}" ]; then - log warn "cgroup_memory_path is not set and could not be found" + log Warning "cgroup_memory_path is not set and could not be found" return 1 fi - elif [ ! -d "${cgroup_memory_path}" ]; then - log warn "${cgroup_memory_path} does not exist" + else + log Warning "Leave the 'cgroup_memory_path' field empty to obtain the path." return 1 fi + # Check if box_pid is set and exists. - if [ -z "${box_pid}" ]; then - log warn "box_pid is not set" - return 1 - elif [ ! -f "${box_pid}" ]; then - log warn "${box_pid} does not exist" + if [ ! -f "${box_pid}" ]; then + log Warning "${box_pid} does not exist" return 1 fi + # Create cgroup directory and move process to cgroup. - local bin_name=${bin_name} + bin_name=${bin_name} # local bin_name=$(basename "$0") mkdir -p "${cgroup_memory_path}/${bin_name}" - local pid=$(cat "${box_pid}") + local PID=$(<"${box_pid}" 2>/dev/null) - if [ ! -z "${pid}" ]; then - echo "${pid}" > "${cgroup_memory_path}/${bin_name}/cgroup.procs" \ - && log info "Moved process ${pid} to ${cgroup_memory_path}/${bin_name}/cgroup.procs" + if [ ! -z "$PID" ]; then + echo "$PID" > "${cgroup_memory_path}/${bin_name}/cgroup.procs" \ + && log Info "Moved process $PID to ${cgroup_memory_path}/${bin_name}/cgroup.procs" # Set memory limit for cgroups. echo "${cgroup_memory_limit}" > "${cgroup_memory_path}/${bin_name}/memory.limit_in_bytes" \ - && log info "Set memory limit to ${cgroup_memory_limit} for ${cgroup_memory_path}/${bin_name}/memory.limit_in_bytes" + && log Info "Set memory limit to ${cgroup_memory_limit} for ${cgroup_memory_path}/${bin_name}/memory.limit_in_bytes" else return 1 fi @@ -541,29 +524,29 @@ rconf() { # su -c /data/adb/box/scripts/box.tool rconf case "${bin_name}" in sing-box) - if ${bin_path} check -D "${box_dir}/${bin_name}" --config-directory "${box_dir}/sing-box" > "${box_run}/${bin_name}-report.log" 2>&1; then - log info "config.json passed" + if ${bin_path} check -D "${box_dir}/${bin_name}" --config-directory "${box_dir}/sing-box" > "${box_run}/${bin_name}.err.log" 2>&1; then + log Info "${sing_config} passed" reload else - log error "config.json check failed" - cat "${box_run}/${bin_name}-report.log" >&2 + log Debug "${sing_config}" + log Error "$(<"${box_run}/${bin_name}.err.log")" >&2 exit 1 fi ;; clash) - if ${bin_path} -t -d "${box_dir}/clash" -f "${clash_config}" > "${box_run}/${bin_name}-report.log" 2>&1; then - log info "config.yaml passed" + if ${bin_path} -t -d "${box_dir}/clash" -f "${clash_config}" > "${box_run}/${bin_name}.err.log" 2>&1; then + log Info "${clash_config} passed" if [ -t 1 ] && [ "${meta}" = "true" ]; then reload fi else - log error "config.yaml check failed" - cat "${box_run}/${bin_name}-report.log" >&2 + info debug "${clash_config}" + log Error "$(<"${box_run}/${bin_name}.err.log")" >&2 exit 1 fi ;; *) - log error "<${bin_name}> unknown binary." + log Error "<${bin_name}> unknown binary." exit 1 ;; esac @@ -575,7 +558,7 @@ reload() { case "${bin_name}" in sing-box) if kill -SIGHUP "$(busybox pidof sing-box)" >/dev/null 2>&1; then - log debug "Restart with -SIGHUP done" + log Debug "Restart with -SIGHUP done" return 0 else flag=true @@ -586,7 +569,7 @@ reload() { ip_port=$(busybox awk '/external-controller:/ {print $2}' "${clash_config}") >/dev/null 2>&1 secret=$(busybox awk '/secret:/ {print $2}' "${clash_config}") >/dev/null 2>&1 if busybox wget --header="Authorization: Bearer ${secret}" --post-data "" -O /dev/null "http://${ip_port}/restart" >/dev/null 2>&1; then - log debug "Restart with clash.meta api done" + log Debug "Restart with clash.meta api done" return 0 else flag=true @@ -606,7 +589,6 @@ case "$1" in ;; upyacd) if update_dashboard; then - sleep 0.75 busybox pidof "${bin_name}" >/dev/null 2>&1 && open_yacd fi ;; @@ -643,7 +625,6 @@ case "$1" in ;; geosub) update_geox - sleep 0.5 update_subs if ! reload; then if [ -f "${box_pid}" ] && [ "${bin_name}" != "clash" ] && [ "${flag}" = "true" ]; then diff --git a/box/scripts/start.sh b/box/scripts/start.sh index 566e869..c7c31f4 100755 --- a/box/scripts/start.sh +++ b/box/scripts/start.sh @@ -21,24 +21,37 @@ refresh_box() { } start_service() { - if [ ! -f "/data/adb/box/manual" ]; then if [ ! -f "${moddir}/disable" ]; then "${scripts_dir}/box.service" start >> "/dev/null" 2>&1 fi +} - if [ -f "/data/adb/box/run/box.pid" ]; then +enable_iptables() { + PIDS=("clash" "xray" "sing-box" "v2fly") + PID="" + i=0 + while [ -z "$PID" ] && [ "$i" -lt "${#PIDS[@]}" ]; do + PID=$(${busybox} pidof "${PIDS[$i]}") + i=$((i+1)) + done + + if [ -n "$PID" ]; then "${scripts_dir}/box.iptables" enable >> "/dev/null" 2>&1 fi +} - for pid in $(pidof inotifyd); do - if grep -q box.inotify /proc/${pid}/cmdline; then +start_inotifyd() { + for PID in $(${busybox} pidof inotifyd); do + if grep -q box.inotify /proc/$PID/cmdline; then kill -15 ${pid} fi done - sleep 0.3 inotifyd "${scripts_dir}/box.inotify" "${moddir}" >> "/dev/null" 2>&1 & - fi } refresh_box -start_service \ No newline at end of file +if [ ! -f "/data/adb/box/manual" ]; then + start_service + enable_iptables + start_inotifyd +fi \ No newline at end of file diff --git a/box/settings.ini b/box/settings.ini index 5d2423e..93f6bb2 100755 --- a/box/settings.ini +++ b/box/settings.ini @@ -2,6 +2,9 @@ export PATH="/data/adb/magisk:/data/adb/ksu/bin:$PATH:/system/bin" +# Take the current time +now=$(date +"%I:%M %p") + # define the settings and paths settings="/data/adb/box/settings.ini" @@ -44,7 +47,7 @@ ignore_out_list=() # Set cgroup to limit memory usage cgroup_memory="false" -cgroup_memory_limit="50M" +cgroup_memory_limit="20M" cgroup_memory_path="" # Set box directory variables @@ -101,24 +104,22 @@ white="\033[1;37" gray="\033[1;90m" log() { - # Take the current time - now=$(date +"%I:%M %p") - # Selects the text color according to the parameters - case $1 in - info) color="${blue}" ;; - error) color="${red}" ;; - warn) color="${yellow}" ;; - *) color="${green}" ;; - esac - # Add messages to time and parameters - message="${now} [$1]: $2" - if [ -t 1 ]; then - # Prints messages to the console - echo -e "${color}${message}${normal}" - else - # Print messages to a log file - echo "${message}" >> ${box_log} 2>&1 - fi + # Selects the text color according to the parameters + case $1 in + info) color="${blue}" ;; + error) color="${red}" ;; + warn) color="${yellow}" ;; + *) color="${green}" ;; + esac + # Add messages to time and parameters + message="${now} [$1]: $2" + if [ -t 1 ]; then + # Prints messages to the console + echo -e "${color}${message}${normal}" + else + # Print messages to a log file + echo "${message}" >> ${box_log} 2>&1 + fi } # open yacd on start diff --git a/box/sing-box/config.json b/box/sing-box/config.json index 32eda33..e0636ce 100755 --- a/box/sing-box/config.json +++ b/box/sing-box/config.json @@ -92,7 +92,7 @@ "clash_api": { "external_controller": "127.0.0.1:9090", "external_ui": "./dashboard", - "store_selected": false + "store_selected": true } } } \ No newline at end of file