diff --git a/box/scripts/box.inotify b/box/scripts/box.inotify index ee0ac4c..ce80175 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 +"%I.%M %p %z") +now=$(date +"%R") events=$1 monitor_dir=$2 @@ -16,11 +16,11 @@ monitor_file=$3 service_control() { if [ "${monitor_file}" = "disable" ]; then if [ "${events}" = "d" ]; then - "${service_path}" start > "${run_path}/service.log" 2>> "${run_path}/service.log" && \ - "${iptables_path}" enable >> "${run_path}/service.log" 2>> "${run_path}/service.log" + "${service_path}" start > "${run_path}/service.log" 2>&1 && \ + "${iptables_path}" enable >> "${run_path}/service.log" 2>&1 elif [ "${events}" = "n" ]; then - "${iptables_path}" disable >> "${run_path}/service.log" 2>> "${run_path}/service.log" && \ - "${service_path}" stop >> "${run_path}/service.log" 2>> "${run_path}/service.log" + "${iptables_path}" disable >> "${run_path}/service.log" 2>&1 && \ + "${service_path}" stop >> "${run_path}/service.log" 2>&1 fi fi } diff --git a/box/scripts/box.iptables b/box/scripts/box.iptables index f8a77d8..ce4d879 100755 --- a/box/scripts/box.iptables +++ b/box/scripts/box.iptables @@ -16,14 +16,15 @@ clash_dns_port="" tun_device="" # Looking for value from "fake-ip-range: / listen: / tun_device" block in YAML / JSON configuration file +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) +clash_dns_port=$(busybox awk -F ':' '/listen:/ { print $3;found=1; exit } END{ if(!found) print "1053" }' "${clash_config}" 2>/dev/null) + if [ "${bin_name}" = "clash" ]; then tun_device=$(busybox awk '/device: / { print $2;found=1; exit } END{ if(!found) print "utun" }' "${clash_config}" 2>/dev/null) elif [ "${bin_name}" = "sing-box" ]; then tun_device=$(find "${data_dir}/sing-box/" -type f -name "*.json" -exec busybox awk -F'"' '/interface_name/{ if ($4 != "tun0") {print $4; found=1; exit} } END{ if(!found) print "tun0" }' {} \; 2>/dev/null | head -n 1) fi -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) -clash_dns_port=$(busybox awk -F ':' '/listen:/ { print $3;found=1; exit } END{ if(!found) print "1053" }' "${clash_config}" 2>/dev/null) probe_empty () { if [ "${bin_name}" = "clash" ]; then @@ -147,7 +148,7 @@ start_redirect() { done ${iptables} -t nat -A BOX_EXTERNAL -p tcp -i lo -j REDIRECT --to-ports "${redir_port}" - + if [ "${ap_list}" != "" ]; then for ap in "${ap_list[@]}"; do ${iptables} -t nat -A BOX_EXTERNAL -p tcp -i "${ap}" -j REDIRECT --to-ports "${redir_port}" @@ -192,19 +193,25 @@ start_redirect() { log info "proxy-mode: ${proxy_mode} < [ ${packages_list[*]} ] no transparent proxy." fi elif [ "${proxy_mode}" = "whitelist" ]; then - # Route apps to Box - # loop through the UID list - while read -r appid; do - # add iptables rules for TCP traffic - ${iptables} -t nat -A BOX_LOCAL -p tcp -m owner --uid-owner "${appid}" -j REDIRECT --to-ports "${redir_port}" - done < "${uid_list[*]}" + if [ "$(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." + else + # Route apps to Box + # loop through the UID list + while read -r appid; do + # add iptables rules for TCP traffic + ${iptables} -t nat -A BOX_LOCAL -p tcp -m owner --uid-owner "${appid}" -j REDIRECT --to-ports "${redir_port}" + done < "${uid_list[*]}" - # close the file handle for the UID list - # exec <&- + # close the file handle for the UID list + # exec <&- - ${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." + ${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." + fi else log warn "proxy-mode: ${proxy_mode} < error." ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports "${redir_port}" @@ -269,8 +276,8 @@ start_tproxy() { # Bypass other if # Notice: Some interface is named with r_ / oem / nm_ / qcom_ # It might need more complicated solution. - ${iptables} -t mangle -I BOX_EXTERNAL -i rmnet_data+ -j RETURN - ${iptables} -t mangle -I BOX_EXTERNAL -i ccmni+ -j RETURN + # ${iptables} -t mangle -I BOX_EXTERNAL -i rmnet_data+ -j RETURN + # ${iptables} -t mangle -I BOX_EXTERNAL -i ccmni+ -j RETURN # Bypass intranet # Add rules for intranet subnets @@ -360,7 +367,7 @@ start_tproxy() { # ${iptables} -t mangle -A BOX_LOCAL -m owner ! --uid 0-99999999 -j DROP if [ "${proxy_mode}" = "blacklist" ]; then - if [ "$(cat ${uid_list[*]})" = "" ]; then + if [ "$(cat ${uid_list[@]})" = "" ]; then # 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}" @@ -382,24 +389,31 @@ start_tproxy() { fi elif [ "${proxy_mode}" = "whitelist" ]; then - # Route apps to Box - # loop through uid list and add iptables rule - while read -r appid; do - ${iptables} -t mangle -A BOX_LOCAL -p tcp -m owner --uid-owner "${appid}" -j MARK --set-mark "${fwmark}" - ${iptables} -t mangle -A BOX_LOCAL -p udp -m owner --uid-owner "${appid}" -j MARK --set-mark "${fwmark}" - done < "${uid_list[*]}" - - # close the file handle for the UID list - # exec <&- + if [ "$(cat "${uid_list[@]}")" = "" ]; then + # 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." + else + # Route apps to Box + # loop through uid list and add iptables rule + while read -r appid; do + ${iptables} -t mangle -A BOX_LOCAL -p tcp -m owner --uid-owner "${appid}" -j MARK --set-mark "${fwmark}" + ${iptables} -t mangle -A BOX_LOCAL -p udp -m owner --uid-owner "${appid}" -j MARK --set-mark "${fwmark}" + done < "${uid_list[*]}" - ${iptables} -t mangle -A BOX_LOCAL -p tcp -m owner --uid-owner 0 -j MARK --set-mark "${fwmark}" - ${iptables} -t mangle -A BOX_LOCAL -p udp -m owner --uid-owner 0 -j MARK --set-mark "${fwmark}" - # Route dnsmasq to Box - ${iptables} -t mangle -A BOX_LOCAL -p tcp -m owner --uid-owner 1052 -j MARK --set-mark "${fwmark}" - ${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." + # close the file handle for the UID list + # exec <&- + + ${iptables} -t mangle -A BOX_LOCAL -p tcp -m owner --uid-owner 0 -j MARK --set-mark "${fwmark}" + ${iptables} -t mangle -A BOX_LOCAL -p udp -m owner --uid-owner 0 -j MARK --set-mark "${fwmark}" + # Route dnsmasq to Box + ${iptables} -t mangle -A BOX_LOCAL -p tcp -m owner --uid-owner 1052 -j MARK --set-mark "${fwmark}" + ${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." + fi else log debug "proxy-mode: ${proxy_mode} < error" ${iptables} -t mangle -A BOX_LOCAL -p tcp -j MARK --set-mark "${fwmark}" @@ -416,7 +430,7 @@ start_tproxy() { ${iptables} -t mangle -I PREROUTING -p tcp -m socket -j DIVERT - # # Disable QUIC + # Disable QUIC if [ "${quic}" = "disable" ]; then ${iptables} -A OUTPUT -p udp --dport 443 -j REJECT ${iptables} -A OUTPUT -p udp --dport 80 -j REJECT @@ -438,14 +452,14 @@ start_tproxy() { ${iptables} -t nat -F CLASH_DNS_EXTERNAL ${iptables} -t nat -A CLASH_DNS_EXTERNAL -p udp --dport 53 -j REDIRECT --to-ports "${clash_dns_port}" ${iptables} -t nat -I PREROUTING -j CLASH_DNS_EXTERNAL - + # Create and configure CLASH_DNS_LOCAL chain ${iptables} -t nat -N CLASH_DNS_LOCAL ${iptables} -t nat -F CLASH_DNS_LOCAL ${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 @@ -457,7 +471,6 @@ start_tproxy() { fi fi } - stop_tproxy() { if [ "${iptables}" != "ip6tables -w 64" ]; then ip rule del fwmark "${fwmark}" table "${table}" pref "${pref}" @@ -656,15 +669,15 @@ if [ "${proxy_mode}" != "tun" ]; then 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; } if [ "${ipv6}" = "true" ]; then - 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 ip6tables transparent proxy rules done." || { log error "create ip6tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } + 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 ip6tables transparent proxy rules done." || { log error "create ip6tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1; } else - disable_ipv6 - log warn "disable IPv6." + disable_ipv6 + log warn "disable IPv6." fi ;; *) diff --git a/box/scripts/box.service b/box/scripts/box.service index 2f70ce4..48381d1 100755 --- a/box/scripts/box.service +++ b/box/scripts/box.service @@ -4,22 +4,20 @@ scripts=$(realpath $0) scripts_dir=$(dirname ${scripts}) source /data/adb/box/settings.ini -# Reads the enable value from the tun configuration -# singbox_tun=$(find /data/adb/box/sing-box/ -name "*.json" -exec busybox awk -F':' '/"type":[[:space:]]*"tun"/{gsub(/^[[:space:]]+|[",[:space:]]+$/,"",$2); print $2}' {} \; | tr -d '"') -clash_tun_status=$(busybox awk -F ': ' '/^tun: *$/{getline; print $2}' "${clash_config}") - delete_logs() { # Delete logs for each bin in the list - log info "deleting & backup logs for ${bin_list[*]}" - for bin in "${bin_list[@]}" ; do + log info "deleting and backing up logs for ${bin_list[*]}" + for bin in "${bin_list[@]}"; do if [ -f "${run_path}/${bin}.log" ]; then mv "${run_path}/${bin}.log" "${run_path}/${bin}-$(date +%Y-%m-%d-%H-%M-%S).log" fi done + # Delete other log files find "${run_path}" -type f \( -name "root" -o -name "*.yaml" -o -name "*.list" -o -name "*.inotify.log" -o -name "*-report.log" \) -exec rm -f {} \; || log warn "Error deleting other log files" + # Delete logs that are three days old or older - find "${run_path}" -type f -name "*.log" -mtime +2 -exec rm -f {} \; || log warn "Error deleting old log" + find "${run_path}" -type f -name "*.log" -mtime +2 -exec rm -f {} \; || log warn "Error deleting old logs" } crontab_geo() { @@ -31,14 +29,18 @@ crontab_geo() { log debug "${bin_name} subscription (${auto_update_subscription})." fi else - log info "Crontab geox & subscription is disabled." + log info "Crontab geox and subscription is disabled." fi } detected_port() { sleep 1 - [ "${port_detect}" = "true" ] && ${scripts_dir}/box.tool port || \ - log debug "${bin_name} skip port detected." && return 1 + if [ "${port_detect}" = "true" ]; then + ${scripts_dir}/box.tool port + else + log debug "${bin_name} skipped port detected." + return 1 + fi } still_alive() { @@ -60,62 +62,38 @@ still_alive() { } check_permission() { - if [ "${box_user_group}" = "root:net_admin" ]; then - if [ ! -f ${bin_path} ]; then - log error "Kernel '${bin_name}' is missing." - log error "Please download the '${bin_name}' kernel and place it in the ${bin_kernel}/ directory." - exit 1 - fi + if 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}') + box_user_id=$(id -u ${box_user}) + box_group_id=$(id -g ${box_group}) + # Check if box_user and box_group exist + [ ${box_user_id} ] && [ ${box_group_id} ] || ( log error "${box_user_group} error, use root:net_admin instead." && box_user_group="root:net_admin" ) + bin_path=$(which ${bin_name}) + # Set ownership and permission of kernel directory + chown ${box_user_group} ${bin_path} + chmod 0700 ${bin_path} + chmod 0644 "${data_dir}/${bin_name}"/* + # 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 + setcap 'cap_net_admin,cap_net_raw,cap_net_bind_service+ep' ${bin_path} || (box_user_group="root:net_admin" && log error "setcap authorization failed, you may need libcap package.") + fi + # Set ownership of data directory + chown -R ${box_user_group} ${data_dir} + log info "Using kernel directory ${bin_name} in ${bin_path}." + elif [ -f ${bin_path} ]; then # Set ownership and permission of kernel directory chown ${box_user_group} ${bin_path} - chmod 6755 ${bin_path} - chmod 644 "${data_dir}/${bin_name}"/* + chmod 0700 ${bin_path} + chmod 0644 "${data_dir}/${bin_name}"/* # Set ownership of data directory chown -R ${box_user_group} ${data_dir} - log info "use the kernel located in '${bin_path}'" + log info "Use the kernel located in '${bin_path}'." else - if 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}') - box_user_id=$(id -u ${box_user}) - box_group_id=$(id -g ${box_group}) - # Check if box_user and box_group exist - if [ ${box_user_id} ] && [ ${box_group_id} ]; then - bin_path=$(which ${bin_name}) - # Set ownership and permission of kernel directory - chown ${box_user_group} ${bin_path} - chmod 6755 ${bin_path} - chmod 644 "${data_dir}/${bin_name}"/* - # 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 command -v setcap > /dev/null; then - setcap 'cap_net_admin,cap_net_raw,cap_net_bind_service+ep' ${bin_path} || (box_user_group="root:net_admin" && log error "setcap authorization failed, you may need libcap package.") - else - box_user_group="root:net_admin" - log warn "setcap authorization failed, you may need libcap package. Using root:net_admin instead." - fi - fi - # Set ownership of data directory - chown -R ${box_user_group} ${data_dir} - log info "Using kernel directory ${bin_name} in ${bin_path}" - else - bin_path=$(which ${bin_name}) - box_user_group="root:net_admin" - log warn "${box_user_group} error. Using root:net_admin instead." - # Set ownership and permission of kernel directory - chown ${box_user_group} ${bin_path} - chmod 6755 ${bin_path} - chmod 644 "${data_dir}/${bin_name}"/* - # Set ownership of data directory - chown -R ${box_user_group} ${data_dir} - log info "use the kernel located in '${bin_path}'" - fi - else - log error "Kernel '${bin_name}' is missing." - log error "Please download the '${bin_name}' kernel, place it in the /data/adb/modules/box_for_root/system/bin/ directory and reboot." - exit 1 - fi + log error "Kernel '${bin_name}' is missing." + log error "Please download the '${bin_name}' kernel and place it in the ${bin_kernel}/ directory." + exit 1 fi } @@ -146,11 +124,14 @@ check_in_bin() { create_tun() { # Enable IP forwarding - sysctl net.ipv4.ip_forward=1 >/dev/null 2>&1 + if ! sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1; then + log warn "Cannot enable IP forwarding." + fi + # Creates a symlink for /dev/tun if it doesn't already exist if [ ! -c "/dev/net/tun" ]; then if ! mkdir -p /dev/net; then - log warn "Cannot create directory /dev/net" >&2 + log warn "Cannot create directory /dev/net." exit 1 fi if ! mknod /dev/net/tun c 10 200; then @@ -163,44 +144,64 @@ create_tun() { fi } -default_tproxy() { - # set network_mode variable value to "tproxy" - sed -i 's/\(network_mode=\)\"[^\"]*\"/\1"tproxy"/g' ${settings} -} - prepare_singbox() { - if [ "${network_mode}" = "mixed" ] || [ "${proxy_mode}" = "tun" ]; then + # Reads the enable value from the tun configuration + # singbox_tun=$(find /data/adb/box/sing-box/ -name "*.json" -exec busybox awk -F':' '/"type":[[:space:]]*"tun"/{gsub(/^[[:space:]]+|[",[:space:]]+$/,"",$2); print $2}' {} \; | tr -d '"') + + if [[ "${network_mode}" == "mixed" || "${proxy_mode}" == "tun" ]]; then sed -i 's/"auto_detect_interface": false/"auto_detect_interface": true/g' "${data_dir}/sing-box/"*.json - sed -i 's/auto_route\": false/auto_route\": true/g' "${data_dir}/sing-box/"*.json + sed -i 's/auto_route": false/auto_route": true/g' "${data_dir}/sing-box/"*.json else sed -i 's/"auto_detect_interface": true/"auto_detect_interface": false/g' "${data_dir}/sing-box/"*.json - sed -i 's/auto_route\": true/auto_route\": false/g' "${data_dir}/sing-box/"*.json + sed -i 's/auto_route": true/auto_route": false/g' "${data_dir}/sing-box/"*.json fi - sleep 0.5 } prepare_clash() { 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" /data/adb/box/settings.ini + sed -i "s/ipv6=.*/ipv6=\"${ipv6}\"/g" "${settings}" + clash_external_ui=$(busybox awk '/external-ui: /{print $1}' "${clash_config}") - [ -z "${clash_external_ui}" ] && printf "\nexternal-ui: ./dashboard/dist" >> "${clash_config}" + if [ -z "${clash_external_ui}" ]; then + echo -e "\nexternal-ui: ./dashboard/dist" >> "${clash_config}" + fi + clash_tproxy_port=$(busybox awk '/tproxy-port: /{print $1}' "${clash_config}") - [ -z "${clash_tproxy_port}" ] && printf "\ntproxy-port: ${tproxy_port}" >> "${clash_config}" + if [ -z "${clash_tproxy_port}" ]; then + echo -e "\ntproxy-port: ${tproxy_port}" >> "${clash_config}" + fi + clash_redir_port=$(busybox awk '/redir-port: /{print $1}' "${clash_config}") - [ -z "${clash_redir_port}" ] && printf "\nredir-port: ${redir_port}" >> "${clash_config}" + if [ -z "${clash_redir_port}" ]; then + echo -e "\nredir-port: ${redir_port}" >> "${clash_config}" + fi + + if [ "${network_mode}" = "mixed" ] || [ "${proxy_mode}" = "tun" ]; then + clash_tun_status=$(busybox awk -F ': ' '/^tun: *$/{getline; print $2}' "${clash_config}") + if [ -z "${clash_tun_status}" ]; then +echo -e "\n +tun: + enable: true + mtu: 9000 + device: utun + stack: system # gvisor / system + dns-hijack: + - any:53 + auto-route: true + auto-detect-interface: true +" >> "${clash_config}" + fi + sed -i "/tun:/ {n;s/enable: false/enable: true/}" "${clash_config}" + else + sed -i "/tun:/ {n;s/enable: true/enable: false/}" "${clash_config}" + fi + + # Reads the enable value from the tun configuration + clash_tun_status=$(busybox awk -F ': ' '/^tun: *$/{getline; print $2}' "${clash_config}") if [ "${clash_tun_status}" != "true" ]; then sed -i -E "s/(tproxy-port: )[0-9]+/\1${tproxy_port}/" "${clash_config}" - default_tproxy else - sed -i -E "s/(network_mode=)\"[^\"]+\"/\1\"mixed\"/" "${settings}" - fi - sleep 0.5 -} - -prepare_xvray() { - if [ ! -f "${data_dir}/${bin_name}"/*.json ]; then - log error "file ${data_dir}/${bin_name}/*.json not found" - exit 1 + [ "${proxy_mode}" != "tun" ] && sed -i 's/network_mode=.*/network_mode="mixed"/g' "${settings}" fi } @@ -212,7 +213,7 @@ run_box() { sing-box) prepare_singbox if ${bin_path} check -D "${data_dir}/${bin_name}" --config-directory "${data_dir}/sing-box" > "${run_path}/${bin_name}-report.log" 2>&1 ; then - nohup busybox setuidgid 0:3005 ${bin_path} run -D "${data_dir}/${bin_name}" --config-directory "${data_dir}/sing-box" > "${run_path}/${bin_name}.log" 2>&1 & + nohup busybox setuidgid ${box_user_group} ${bin_path} run -D "${data_dir}/${bin_name}" --config-directory "${data_dir}/sing-box" > "${run_path}/${bin_name}.log" 2>&1 & echo -n $! > "${pid_file}" else log error "Configuration failed, please check the ${run_path}/${bin_name}-report.log file." @@ -225,7 +226,7 @@ run_box() { clash) prepare_clash if ${bin_path} -t -d "${data_dir}/${bin_name}" -f "${clash_config}" > "${run_path}/${bin_name}-report.log" 2>&1; then - nohup busybox setuidgid 0:3005 ${bin_path} -d "${data_dir}/${bin_name}" -f "${clash_config}" > "${run_path}/${bin_name}.log" 2>&1 & + nohup busybox setuidgid ${box_user_group} ${bin_path} -d "${data_dir}/${bin_name}" -f "${clash_config}" > "${run_path}/${bin_name}.log" 2>&1 & echo -n $! > "${pid_file}" else log error "configuration failed, please check the ${run_path}/${bin_name}-report.log file." @@ -235,12 +236,16 @@ run_box() { fi ;; xray) - default_tproxy - prepare_xvray + # set network_mode variable value to "tproxy" + sed -i 's/\(network_mode=\)\"[^\"]*\"/\1"tproxy"/g' ${settings} + if [ ! -f "${data_dir}/${bin_name}"/*.json ]; then + log error "file ${data_dir}/${bin_name}/*.json not found" + exit 1 + fi export XRAY_LOCATION_ASSET="${data_dir}/${bin_name}" export XRAY_LOCATION_CONFDIR="${data_dir}/${bin_name}" if ${bin_path} -test > "${run_path}/${bin_name}-report.log" 2>&1; then - nohup busybox setuidgid 0:3005 ${bin_path} > "${run_path}/${bin_name}.log" 2>&1 & + nohup busybox setuidgid ${box_user_group} ${bin_path} > "${run_path}/${bin_name}.log" 2>&1 & echo -n $! > "${pid_file}" else log error "configuration failed, please check the ${run_path}/${bin_name}-report.log file." @@ -250,12 +255,16 @@ run_box() { fi ;; v2fly) - default_tproxy - prepare_xvray + # set network_mode variable value to "tproxy" + sed -i 's/\(network_mode=\)\"[^\"]*\"/\1"tproxy"/g' ${settings} + if [ ! -f "${data_dir}/${bin_name}"/*.json ]; then + log error "file ${data_dir}/${bin_name}/*.json not found" + exit 1 + fi export V2RAY_LOCATION_ASSET="${data_dir}/${bin_name}" export V2RAY_LOCATION_CONFDIR="${data_dir}/${bin_name}" if (${bin_path} test > "${run_path}/${bin_name}-report.log" 2>&1) ; then - nohup busybox setuidgid 0:3005 ${bin_path} run > "${run_path}/${bin_name}.log" 2>&1 & + nohup busybox setuidgid ${box_user_group} ${bin_path} run > "${run_path}/${bin_name}.log" 2>&1 & echo -n $! > ${pid_file} else log error "configuration failed, please check the ${run_path}/${bin_name}-report.log file." @@ -287,40 +296,50 @@ 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. + bin_usage() { # Get the process ID of the binary bin_pid=$(busybox pidof ${bin_name}) + if [ -z "${bin_pid}" ]; then - log error "${bin_name} is not running" + log error "${bin_name} is not running." return fi + # Get the memory usage of the binary - rss=$(grep VmRSS /proc/${bin_pid}/status | busybox awk '{print $2}') + rss=$(grep VmRSS /proc/${bin_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/${bin_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}') + state=$(grep State /proc/${bin_pid}/status | busybox awk '{ print $2" "$3 }') + # Get the user and group of the binary user_group=$(stat -c %U:%G /proc/${bin_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} status: ${state} (PID: ${bin_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 pcpu | busybox awk 'NR==2{print $1}' 2> /dev/null) + cpu=$(ps -p ${bin_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) if [ -n "${running_time}" ]; then - log info "${bin_name} running time: ${running_time} seconds" + log info "${bin_name} running time: ${running_time}" else log info "${bin_name} running time: not available" fi + # Save the process ID to the pid file echo -n "${bin_pid}" > "${pid_file}" } @@ -368,13 +387,14 @@ crontab_alive() { } start_box() { - # Cleared the log file and added the timestamp and delimiter + # Clear the log file and add the timestamp and delimiter echo -n "" > "${logs_file}" - # command command -v to check whether busybox is installed or not on your system. + # 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" + 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 if [ -t 1 ]; then echo -e "\033[1;31m$(date)\033[0m" echo -e "\033[1;32m--------------------------------------------\033[0m" @@ -386,7 +406,7 @@ start_box() { if bin_pid=$(busybox pidof "${bin_name}"); then log info "${bin_name} service is still running, refreshing iptables" if "${scripts_dir}/box.iptables" renew; then - log info "iptables refreshed successfully" + log info "iptables is refreshed successfully" exit 1 else log error "failed to refresh iptables" @@ -398,23 +418,21 @@ start_box() { *) log error "bin_name: '${bin_name}' not defined"; exit 1 ;; esac fi - # Checked permissions, checked for bin existence, deleted old logs, created a TUN, ran box, and waited for 1 second - # Executes the check_permission,check_in_bin & delete_logs function + # Check permissions, check for bin existence, delete old logs, create a TUN if necessary, run box, and wait for 1 second check_permission check_in_bin delete_logs - if [ "${network_mode}" = "mixed" ] || [ "${proxy_mode}" = "tun" ]; then - # Executes the create_tun function + if [[ "${network_mode}" == "mixed" || "${proxy_mode}" == "tun" ]]; then create_tun fi run_box && sleep 1 - # Executes crontab_alive if crontab_sec is not equal to "false" + # Execute crontab_alive if crontab_sec is not equal to "false" if [ "${crontab_sec}" != "false" ]; then crontab_alive else log info "crontab: disabled." fi - # Executes the cgroup limit, detected_port, still_alive, display_bin_pid function + # Execute the cgroup_limit, display_bin_pid, detected_port, still_alive functions cgroup_limit detected_port still_alive @@ -422,35 +440,43 @@ start_box() { } stop_box() { - # Use `pgrep` command to find cronjob PID + # Find cronjob PID using `pgrep` cronkill=$(pgrep -f "crond -c ${run_path}") for cron in ${cronkill[@]}; do kill -15 "${cron}" done - # Using a loop to kill each binary + # Kill each binary using a loop for bin in ${bin_list[@]}; do - # Use `busybox pkill` to kill the binary with signal 15 - busybox pkill -15 "${bin}" || killall -15 "${bin}" + # Use `busybox pkill` to kill the binary with signal 15, otherwise use `killall`. + if busybox pkill -15 "${bin}"; then + : # Do nothing if busybox pkill is successful + else + killall -15 "${bin}" || true + fi done sleep 1 # Check if the binary has stopped - if ! busybox pidof ${bin_name} >/dev/null 2>&1; then + if ! busybox pidof "${bin_name}" >/dev/null 2>&1; then # Delete the `box.pid` file if it exists - if [ -f ${run_path}/box.pid ]; then + if [ -f "${pid_file}" ]; then rm -f "${pid_file}" sleep 0.5 fi display_bin_pid || log warn "${bin_name} disconnected." else - log error "failed to stop ${bin_name}" - log warn "force stop ${bin_name}." + log error "Failed to stop ${bin_name}" + log warn "Force stop ${bin_name}." for bin in "${bin_list[@]}"; do - # Use `busybox pkill` to kill the binary with signal 9 - busybox pkill -9 "${bin}" >/dev/null 2>&1 || killall -9 "${bin}" >/dev/null 2>&1 + # Use `busybox pkill` to kill the binary with signal 9, otherwise use `killall`. + if busybox pkill -9 "${bin}"; then + : # Do nothing if busybox pkill is successful + else + killall -9 "${bin}" >/dev/null 2>&1 || true + fi done sleep 0.5 # Check whether the binary has stopped - if ! busybox pidof ${bin_name} >/dev/null 2>&1; then + if ! busybox pidof "${bin_name}" >/dev/null 2>&1; then log warn "done" fi fi @@ -476,8 +502,13 @@ case "$1" in clash) log debug "$(${bin_path} -v)";; *) log debug "$(${bin_path} version)";; esac - [ $(busybox pidof ${bin_name}) ] && \ - bin_usage || log warn "${bin_name} service is stopped" + + # Memeriksa apakah layanan sudah berjalan atau belum + if [ $(busybox pidof ${bin_name}) ]; then + bin_usage + else + log warn "${bin_name} service is stopped" + fi ;; *) echo "$0: usage: $0 {start|stop|restart|usage}" diff --git a/box/scripts/box.tool b/box/scripts/box.tool index 3b286f9..145a616 100755 --- a/box/scripts/box.tool +++ b/box/scripts/box.tool @@ -5,58 +5,54 @@ scripts_dir=$(dirname ${scripts}) source /data/adb/box/settings.ini user_agent="box_for_root" -meta=true # option to download Clash kernel clash-premium{false} or clash-meta{true} -dev=true # for clash-premium, -singbox_releases=false # option to download Singbox kernel beta or release - -# log on terminal -logs() { - now=$(date +"%I.%M %P") - if [ -t 1 ]; then - case $1 in - info) echo -n "\033[1;34m${now} [info]: $2\033[0m";; - port) echo -n "\033[1;33m$2 \033[0m";; - testing) echo -n "\033[1;34m$2\033[0m";; - success) echo -n "\033[1;32m$2 \033[0m";; - failed) echo -n "\033[1;31m$2 \033[0m";; - *) echo -n "\033[1;35m${now} [$1]: $2\033[0m";; - esac - else - case $1 in - info) echo -n "${now} [info]: $2" | tee -a ${logs_file} >> /dev/null 2>&1;; - port) echo -n "$2 " | tee -a ${logs_file} >> /dev/null 2>&1;; - testing) echo -n "$2" | tee -a ${logs_file} >> /dev/null 2>&1;; - success) echo -n "$2 " | tee -a ${logs_file} >> /dev/null 2>&1;; - failed) echo -n "$2 " | tee -a ${logs_file} >> /dev/null 2>&1;; - *) echo -n "${now} [$1]: $2" | tee -a ${logs_file} >> /dev/null 2>&1;; - esac - fi -} +# option to download Clash kernel clash-premium{false} or clash-meta{true} +meta="true" +# for clash-premium +dev=true +# option to download Singbox kernel beta or release +singbox_releases=false # Check internet connection with mlbox -testing() { - # check DNS - logs info "dns=" - for network in $(${data_dir}/bin/mlbox -timeout=5 -dns="-qtype=A -domain=asia.pool.ntp.org" | grep -v 'timeout' | grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}'); do - ntpip=${network} - break - done - [ ! -z "${ntpip}" ] && logs success "done" || logs failed "failed" - # check HTTP - if [ -n "${ntpip}" ]; then - logs testing "http=" - httpIP=$(busybox wget -qO- http://182.254.116.116/d?dn=reddit.com\&clientip=1 | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n 1) - [ -n "${httpIP}" ] && ( httpIP="${httpIP#*\|}"; logs success "done" ) || logs failed "failed" - # check HTTPS - logs testing "https=" - httpsResp=$(busybox wget -qO- --timeout=5 "https://api.infoip.io" 2>&1 | grep -Ev 'timeout|httpGetResponse' | grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}') - [ -n "${httpsResp}" ] && logs success "done" || logs failed "failed" - # check UDP - logs testing "udp=" - currentTime=$(${data_dir}/bin/mlbox -timeout=7 -ntp="${ntpip}" | grep -v 'timeout') - echo "${currentTime}" | grep -qi 'LI:' && logs success "done" || logs failed "failed" +check_connection_with_mlbox() { + now=$(date +"%R") + connect="\033[1;32mconnect\033[0m" + failed="\033[1;33mfailed\033[0m" + + # Check DNS + echo -n "\033[1;34m${now} [info]: dns=\033[0m" + ntpip=$(${data_dir}/bin/mlbox -timeout=5 -dns="-qtype=A -domain=asia.pool.ntp.org" | grep -v 'timeout' | grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}' | head -n 1) + if [ -z "${ntpip}" ]; then + echo "$failed" + else + echo "$connect" + + # Check HTTP + echo -n "\033[1;34m${now} [info]: http=\033[0m" + httpIP=$(busybox wget -qO- "http://182.254.116.116/d?dn=reddit.com&clientip=1" | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n 1 | cut -d "|" -f 2) + if [ -z "${httpIP}" ]; then + echo "$failed" + else + echo "$connect" + + # Check HTTPS + echo -n "\033[1;34m${now} [info]: https=\033[0m" + httpsResp=$(${data_dir}/bin/mlbox -timeout=5 -http="https://api.infoip.io" 2>&1 | grep -Ev 'timeout|httpGetResponse' | grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}') + if [ -z "${httpsResp}" ]; then + echo "$failed" + else + echo "$connect" + + # Check UDP + echo -n "\033[1;34m${now} [info]: udp=\033[0m" + currentTime=$(${data_dir}/bin/mlbox -timeout=7 -ntp="${ntpip}" | grep -v 'timeout') + if echo "${currentTime}" | grep -qi 'LI:'; then + echo "$connect" + else + echo "$failed" + fi + fi + fi fi - [ -t 1 ] && echo -e "\033[1;31m\033[0m" || echo "" | tee -a ${logs_file} >> /dev/null 2>&1 } # Check if a binary is running by checking the pid file @@ -149,12 +145,12 @@ update_subgeo() { ;; esac if [ "${auto_update_geox}" = "true" ] && log debug "Downloading ${geoip_url}" && update_file "${geoip_file}" "${geoip_url}" && log debug "Downloading ${geosite_url}" && update_file "${geosite_file}" "${geosite_url}"; then - log debug "Update geo $(date +"%Y-%m-%d %I.%M %p")" + log debug "Update geo $(date +"%F %R")" flag=false fi if [ "${bin_name}" = "clash" ] && [ "${auto_update_subscription}" = "true" ] && update_file "${clash_config}" "${subscription_url}"; then - flag=true log debug "Downloading ${clash_config}" + flag=true fi if [ -f "${pid_file}" ] && [ "${flag}" = "true" ]; then restart_box @@ -163,32 +159,39 @@ update_subgeo() { # Function for detecting ports used by a process port_detection() { - # Use 'command' function to check if 'ss' is available + # Gunakan fungsi 'command' untuk memeriksa ketersediaan 'ss' if command -v ss > /dev/null ; then - # Use 'awk' with a regular expression to match the process ID + # Gunakan 'awk' dengan regular expression untuk mencocokkan ID proses ports=$(ss -antup | busybox awk -v pid="$(busybox pidof "${bin_name}")" '$7 ~ pid {print $5}' | busybox awk -F ':' '{print $2}' | sort -u) else - # Log a warning message if 'ss' is not available + # Catat pesan peringatan jika 'ss' tidak tersedia log debug "ss command not found, skipping port detection." >&2 return fi - # Log the detected ports - logs debug "${bin_name} port detected: " - while read -r port ; do - sleep 0.5 - logs port "${port}" - done <<< "${ports}" - # Add a newline to the output if running in a terminal - [ -t 1 ] && echo -e "\033[1;31m""\033[0m" || echo "" >> "${logs_file}" 2>&1 -} -# kill bin -kill_alive() { - for list in "${bin_list[@]}" ; do - if busybox pidof "${list}" >/dev/null ; then - busybox pkill -15 "${list}" >/dev/null 2>&1 || killall -15 "${list}" >/dev/null 2>&1 + # Catat port yang terdeteksi + now=$(date +"%R") + if [ -t 1 ]; then + echo -n "\033[1;33m${now} [debug]: ${bin_name} port detected: \033[0m" + else + echo -n "${now} [debug]: ${bin_name} port detected: " | tee -a "${logs_file}" >> /dev/null 2>&1 + fi + + while read -r port; do + sleep 0.5 + if [ -t 1 ]; then + echo -n "\033[1;33m${port} \033[0m" + else + echo -n "${port} " | tee -a "${logs_file}" >> /dev/null 2>&1 fi - done + done <<< "${ports}" + + # Tambahkan newline pada output jika dijalankan di terminal + if [ -t 1 ]; then + echo -e "\033[1;31m""\033[0m" + else + echo "" >> "${logs_file}" 2>&1 + fi } update_kernel() { @@ -214,7 +217,6 @@ update_kernel() { 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 "${data_dir}/${file_kernel}.tar.gz" "${download_link}" - # [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 ;; clash) if [ "${meta}" = "true" ]; then @@ -225,7 +227,7 @@ update_kernel() { 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}" - [ $(uname -m) != "aarch64" ] || filename+="-cgo" + # [ $(uname -m) != "aarch64" ] || filename+="-cgo" filename+="-${latest_version}" # download and update the file log debug "download ${download_link}/download/${tag}/${filename}.gz" @@ -243,43 +245,24 @@ update_kernel() { update_file "${data_dir}/${file_kernel}.gz" "https://github.com/Dreamacro/clash/releases/download/premium/${filename}.gz" fi fi - # if the update_file command was successful, kill the alive process - # [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 ;; - xray) + 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- https://api.github.com/repos/XTLS/Xray-core/releases | grep "tag_name" | grep -o "v[0-9.]*" | head -1) + 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="Xray-linux-32.zip" ;; - "x86_64") download_file="Xray-linux-64.zip" ;; - "armv7l"|"armv8l") download_file="Xray-linux-arm32-v7a.zip" ;; - "aarch64") download_file="Xray-android-arm64-v8a.zip" ;; + "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/XTLS/Xray-core/releases" + 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 "${data_dir}/${file_kernel}.zip" "${download_link}/download/${latest_version}/${download_file}" - # if the update_file command was successful, kill the alive process - # [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 ;; - v2fly) - # set download link and get the latest version - latest_version=$(busybox wget --no-check-certificate -qO- https://api.github.com/repos/v2fly/v2ray-core/releases | grep "tag_name" | grep -o "v[0-9.]*" | head -1) - case $(uname -m) in - "i386") download_file="v2ray-linux-32.zip" ;; - "x86_64") download_file="v2ray-linux-64.zip" ;; - "armv7l"|"armv8l") download_file="v2ray-linux-arm32-v7a.zip" ;; - "aarch64") download_file="v2ray-android-arm64-v8a.zip" ;; - *) log error "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; - esac - # Do anything else below - download_link="https://github.com/v2fly/v2ray-core/releases" - log debug "Downloading ${download_link}/download/${latest_version}/${download_file}" - update_file "${data_dir}/${file_kernel}.zip" "${download_link}/download/${latest_version}/${download_file}" - # if the update_file command was successful, kill the alive process - # [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 - ;; *) log error "kernel error." exit 1 @@ -289,33 +272,50 @@ update_kernel() { case "${bin_name}" in clash) gunzip_command=$(command -v gunzip >/dev/null 2>&1 && echo "gunzip" || echo "busybox gunzip") - if ${gunzip_command} "${data_dir}/${file_kernel}.gz" >&2 && mv "${data_dir}/${file_kernel}" "${bin_kernel}/${bin_name}"; then - [ -f "${pid_file}" ] && restart_box || log debug "${bin_name} does not need to be restarted" + if ${gunzip_command} "${data_dir}/${file_kernel}.gz" >&2 && + mv "${data_dir}/${file_kernel}" "${bin_kernel}/${bin_name}"; then + if [ -f "${pid_file}" ]; then + restart_box + else + 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) tar_command=$(command -v tar >/dev/null 2>&1 && echo "tar" || echo "busybox tar") - if ${tar_command} -xf "${data_dir}/${file_kernel}.tar.gz" -C "${data_dir}/bin" >&2 && mv "${data_dir}/bin/sing-box-${sing_box_version}-${platform}-${arch}/sing-box" "${bin_kernel}/${bin_name}" && rm -r "${data_dir}/bin/sing-box-${sing_box_version}-${platform}-${arch}"; then - [ -f "${pid_file}" ] && restart_box || log debug "${bin_name} does not need to be restarted" + if ${tar_command} -xf "${data_dir}/${file_kernel}.tar.gz" -C "${data_dir}/bin" >&2 && + mv "${data_dir}/bin/sing-box-${sing_box_version}-${platform}-${arch}/sing-box" "${bin_kernel}/${bin_name}" && + rm -r "${data_dir}/bin/sing-box-${sing_box_version}-${platform}-${arch}"; then + if [ -f "${pid_file}" ]; then + restart_box + else + log debug "${bin_name} does not need to be restarted." + fi else - log warn "failed to extract ${data_dir}/${file_kernel}.tar.gz" && flag="false" + log warn "Failed to extract ${data_dir}/${file_kernel}.tar.gz." + flag="false" fi ;; v2fly|xray) [ "${bin_name}" = "xray" ] && bin='xray' || bin='v2ray' unzip_command=$(command -v unzip >/dev/null 2>&1 && echo "unzip" || echo "busybox unzip") - if ${unzip_command} -o "${data_dir}/${file_kernel}.zip" "${bin}" -d "${bin_kernel}" >&2 ; then + + if ${unzip_command} -o "${data_dir}/${file_kernel}.zip" "${bin}" -d "${bin_kernel}" >&2; then if mv "${bin_kernel}/${bin}" "${bin_kernel}/${bin_name}"; then - [ -f "${pid_file}" ] && restart_box || log debug "${bin_name} does not need to be restarted" + if [ -f "${pid_file}" ]; then + restart_box + else + 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 ${data_dir}/${file_kernel}.zip" + log warn "Failed to extract ${data_dir}/${file_kernel}.zip." fi - ;; + ;; *) log error "kernel error." exit 1 @@ -329,23 +329,26 @@ update_kernel() { # Function to limit cgroup memory cgroup_limit() { - # Check if cgroup_memory_limit is set + # Periksa apakah cgroup_memory_limit telah diatur. if [ -z "${cgroup_memory_limit}" ]; then log warn "cgroup_memory_limit is not set" return 1 fi - # Check if cgroup_memory_path is set and exists + + # Periksa apakah cgroup_memory_path diatur dan ada. 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 cannot be found" + log warn "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" return 1 fi - # Check if pid_file is set and exists + + # Periksa apakah pid_file diatur dan ada. if [ -z "${pid_file}" ]; then log warn "pid_file is not set" return 1 @@ -353,25 +356,30 @@ cgroup_limit() { log warn "${pid_file} does not exist" return 1 fi - # Create cgroup directory and move process to cgroup - local bin_name=$(basename "$0") + + # Buat direktori cgroup dan pindahkan proses ke cgroup. + local bin_name=${bin_name} + # local bin_name=$(basename "$0") mkdir -p "${cgroup_memory_path}/${bin_name}" local pid=$(cat "${pid_file}") + 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 cgroup + + # Tetapkan batas memori untuk cgroup. 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" + return 0 } update_dashboard() { - if [ "${bin_name}" = "sing-box" ] || [ "${bin_name}" = "clash" ]; then + if [[ "${bin_name}" == "sing-box" || "${bin_name}" == "clash" ]]; then file_dashboard="${data_dir}/${bin_name}/dashboard.zip" rm -rf "${data_dir}/${bin_name}/dashboard/dist" - url="https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip" - dir_name="Yacd-meta-gh-pages" - busybox wget --no-check-certificate "${url}" -O "${file_dashboard}" 2>&1 + url="https://github.com/CHIZI-0618/yacd/archive/gh-pages.zip" + dir_name="yacd-gh-pages" + busybox wget --no-check-certificate "${url}" -O "${file_dashboard}" >&2 || { log error "Failed to download ${url}"; exit 1; } unzip -o "${file_dashboard}" "${dir_name}/*" -d "${data_dir}/${bin_name}/dashboard" >&2 mv -f "${data_dir}/${bin_name}/dashboard/${dir_name}" "${data_dir}/${bin_name}/dashboard/dist" rm -f "${file_dashboard}" @@ -410,7 +418,7 @@ reload() { case "$1" in testing) - testing + check_connection_with_mlbox ;; keepdns) keep_dns diff --git a/box/scripts/start.sh b/box/scripts/start.sh index 68adcce..5f391d5 100755 --- a/box/scripts/start.sh +++ b/box/scripts/start.sh @@ -16,14 +16,20 @@ refresh_box() { start_service() { if [ ! -f "/data/adb/box/manual" ]; then - [ ! -f "${moddir}/disable" ] && "${scripts_dir}/box.service" start >> "/dev/null" 2>&1 - [ -f "/data/adb/box/run/box.pid" ] && "${scripts_dir}/box.iptables" enable >> "/dev/null" 2>&1 + if [ ! -f "${moddir}/disable" ]; then + "${scripts_dir}/box.service" start >> "/dev/null" 2>&1 + fi - for pid in $(pidof inotifyd) ; do - if grep -q box.inotify /proc/${pid}/cmdline ; then + if [ -f "/data/adb/box/run/box.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 kill ${pid} fi done + inotifyd "${scripts_dir}/box.inotify" "${moddir}" >> "/dev/null" 2>&1 & fi } diff --git a/box/settings.ini b/box/settings.ini index ea07fa8..ab8bb8d 100755 --- a/box/settings.ini +++ b/box/settings.ini @@ -13,14 +13,13 @@ port_detect="false" # enable/disable IPv6: true / false ipv6="false" # list of available kernel binaries -bin_list=("clash" "sing-box" "xray" "v2fly") +bin_list=( "clash" "sing-box" "xray" "v2fly" ) # select the client to use : clash / sing-box / xray / v2fly bin_name="clash" # This script is used to set the user and group for the BFM core files. # If you want to change the user or group, make sure the BFM core files are located in the /system/bin directory, otherwise the changes will not take effect. # If you are using Magisk, you can copy the BFM core files (sing-box, clash, etc.) to /data/adb/modules/box_for_root/system/bin/ and reboot the phone. -# box_user_group="bin:system" box_user_group="root:net_admin" # redirect: tcp only, / tproxy: for tcp+udp with tproxy, / mixed: mode with redirect[tcp] and tun[udp] @@ -37,7 +36,7 @@ ap_list=( "softap+" "wlan+" "swlan+" "ap+" "rndis+" ) ignore_out_list=() # Set update interval using cron, for more information: https://crontab.guru/ -crontab_sec='false' +crontab_sec="false" update_interval="0 12 */3 * *" # updates will run at 12 noon every three days. # Update sub&geo # Type "su -c /data/adb/box/scripts/box.tool subgeo" to update @@ -62,29 +61,34 @@ scripts_dir="${data_dir}/scripts" system_packages_file="/data/system/packages.list" uid_list=("/data/adb/box/run/appuid.list") -# config clash +# konfigurasi clash name_clash_config="config.yaml" clash_config="${data_dir}/clash/${name_clash_config}" -# Set DNS variables, doc dns https://adguard-dns.io/kb/general/dns-providers/ -intervaldns="" -# intervaldns="*/10 * * * *" # +# Mengatur variabel DNS, dokumentasi DNS ada di https://adguard-dns.io/kb/general/dns-providers/. +# Variabel intervaldns harus dalam format cron. Misalnya "*/10 * * * *" untuk menjalankannya setiap 10 menit. +# Jika tidak ada jadwal yang ingin diatur, intervaldns harus dikosongkan. +intervaldns="*/10 * * * *" static_dns1="94.140.14.14" static_dns2="2a10:50c0::ad1:ff" log() { - # Get the current time - now=$(date +"%I.%M %P") - case $1 in - info) color="\033[1;34m" ;; # print the log message in blue - error) color="\033[1;31m" ;; # print the log message in red - warn) color="\033[1;33m" ;; # print the log message in yellow - *) color="\033[1;32m" ;; # print the log message in magenta - esac - message="${now} [$1]: $2" - if [ -t 1 ]; then - echo -e "${color}${message}\033[0m" - else - echo "${message}" | tee -a ${logs_file} >> /dev/null 2>&1 - fi -} + # Mengambil waktu saat ini + now=$(date +"%R") + # Memilih warna teks sesuai parameter + case $1 in + info) color="\033[1;34m" ;; # untuk pesan info, tulisan warna biru + error) color="\033[1;31m" ;; # untuk pesan error, tulisan warna merah + warn) color="\033[1;33m" ;; # untuk pesan warn, tulisan warna kuning + *) color="\033[1;32m" ;; # untuk opsi parameter yang tidak dikenali, tulisan warna magenta + esac + # Menambah pesan ke waktu dan parameter + message="${now} [$1]: $2" + if [ -t 1 ]; then + # Mencetak pesan ke konsol + echo -e "${color}${message}\033[0m" + else + # Mencetak pesan ke file log + echo "${message}" >> ${logs_file} 2>&1 + fi +} \ No newline at end of file