- adjust: blacklist / whitelist
- adjust: scripts for CLASH TUN
- fix: "network_mode" ( redirect: tcp only, / tproxy: for tcp+udp with tproxy, / mixed: mode with redirect[tcp] + tun[udp] )

Changes to be committed:
       modified:   box/scripts/box.inotify
       modified:   box/scripts/box.iptables
       modified:   box/scripts/box.service
       modified:   box/scripts/box.tool
       modified:   box/scripts/start.sh
       modified:   box/settings.ini
This commit is contained in:
sheynsw
2023-04-11 03:00:35 +07:00
parent fa7cd57c86
commit c3d67d39ec
6 changed files with 388 additions and 326 deletions

View File

@@ -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
}

View File

@@ -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
;;
*)

View File

@@ -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}<unknown>' 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}"

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}