diff --git a/.github/workflows/del.yml b/.github/workflows/del.yml old mode 100644 new mode 100755 diff --git a/README.md b/README.md index 7aa6aa0..3fe3718 100755 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # Box for Magisk -[README ID](index_id.md) || [README EN](index_en.md) +[README ID](index_id.md) || [README EN](index_en.md) || [README CN](index_cn.md) [![ANDROID](https://img.shields.io/badge/Android-3DDC84?style=for-the-badge&logo=android&logoColor=white)]() +[![RELEASES](https://img.shields.io/github/downloads/taamarin/box_for_magisk/total.svg?style=for-the-badge)](https://github.com/taamarin/box_for_magisk/releases) A fork of [CHIZI-0618/box4magisk](https://github.com/CHIZI-0618/box4magisk) diff --git a/binary/arm.tar.bz2 b/binary/arm.tar.bz2 index 3fe8538..9328720 100755 Binary files a/binary/arm.tar.bz2 and b/binary/arm.tar.bz2 differ diff --git a/binary/arm64.tar.bz2 b/binary/arm64.tar.bz2 index 6381f91..09b4c44 100755 Binary files a/binary/arm64.tar.bz2 and b/binary/arm64.tar.bz2 differ diff --git a/box_service.sh b/box_service.sh index 43aa3b8..83cc0cf 100755 --- a/box_service.sh +++ b/box_service.sh @@ -1,10 +1,14 @@ #!/system/bin/sh ( -until [ $(getprop init.svc.bootanim) = "stopped" ] ; do - sleep 3 -done + until [ $(getprop init.svc.bootanim) = "stopped" ]; do + sleep 3 + done -chmod 755 /data/adb/box/scripts/start.sh -/data/adb/box/scripts/start.sh + if [ -f "/data/adb/box/scripts/start.sh" ]; then + chmod 755 /data/adb/box/scripts/* + /data/adb/box/scripts/start.sh + else + echo "File '/data/adb/box/scripts/start.sh' not found" + fi )& \ No newline at end of file diff --git a/build.sh b/build.sh index 330d35d..62321fa 100755 --- a/build.sh +++ b/build.sh @@ -1,3 +1,3 @@ #!/bin/sh -zip -r -o -X -ll box_for_magisk-$(cat module.prop | grep 'version=' | awk -F '=' '{print $2}').zip ./ -x '.git/*' -x 'index_id.md' -x 'CHANGELOG.md' -x 'update.json' -x 'build.sh' -x '.github/*' \ No newline at end of file +zip -r -o -X -ll box_for_magisk-$(cat module.prop | grep 'version=' | awk -F '=' '{print $2}').zip ./ -x '.git/*' -x 'index_id.md' -x 'index_en.md' -x 'CHANGELOG.md' -x 'update.json' -x 'build.sh' -x '.github/*' \ No newline at end of file diff --git a/customize.sh b/customize.sh index 93fc64b..3764306 100755 --- a/customize.sh +++ b/customize.sh @@ -27,21 +27,25 @@ else ui_print "- Device sdk: $API" fi -# check architecture -if [ "$ARCH" != "arm" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "x64" ]; then - abort "! Unsupported platform: $ARCH" -else - ui_print "- Device platform: $ARCH" -fi +ui_print "- check architecture" +case $ARCH in + arm|arm64|x86|x64) + ui_print "- Device platform: $ARCH" + ;; + *) + abort "! Unsupported platform: $ARCH" + ;; +esac ui_print "- Installing Box for Magisk" if [ -d "/data/adb/box" ] ; then ui_print "- Backup box" - mkdir -p /data/adb/box/${latest} - mv /data/adb/box/* /data/adb/box/${latest}/ + mkdir -p "/data/adb/box/${latest}" + mv /data/adb/box/* "/data/adb/box/${latest}/" fi +ui_print "- Set architecture ${ARCH}" case "${ARCH}" in arm) architecture="armv7" @@ -55,71 +59,133 @@ case "${ARCH}" in x64) architecture="amd64" ;; + *) + abort "Error: Unsupported architecture ${ARCH}" + ;; esac -ui_print "- Mkdir BFM folder" -mkdir -p ${MODPATH}/system/bin -mkdir -p ${MODPATH}/system/etc/security/cacerts -mkdir -p /data/adb/box -mkdir -p /data/adb/box/bin -mkdir -p /data/adb/box/dashboard -mkdir -p /data/adb/box/run -mkdir -p /data/adb/box/scripts -mkdir -p /data/adb/box/xray -mkdir -p /data/adb/box/v2fly -mkdir -p /data/adb/box/sing-box -mkdir -p /data/adb/box/clash +ui_print "- Create directories" +mkdir -p "${MODPATH}/system/bin" +mkdir -p "${MODPATH}/system/etc/security/cacerts" +mkdir -p "/data/adb/box" +mkdir -p "/data/adb/box/bin" +mkdir -p "/data/adb/box/run" +mkdir -p "/data/adb/box/scripts" +mkdir -p "/data/adb/box/xray" +mkdir -p "/data/adb/box/v2fly" +mkdir -p "/data/adb/box/sing-box" +mkdir -p "/data/adb/box/clash" +mkdir -p "/data/adb/box/dashboard" +mkdir -p "/data/adb/box/clash/dashboard" +mkdir -p "/data/adb/box/sing-box/dashboard" -ui_print "- Extracting BFM files" -unzip -o "${ZIPFILE}" -x 'META-INF/*' -d ${MODPATH} >&2 -unzip -j -o "${ZIPFILE}" 'uninstall.sh' -d ${MODPATH} >&2 +ui_print "- Extract the ZIP file and skip the META-INF folder into the ${MODPATH} folder" +unzip -o "${ZIPFILE}" -x 'META-INF/*' -d "${MODPATH}" >&2 + +ui_print "- Extract the files uninstall.sh and box_service.sh into the ${MODPATH} folder and /data/adb/service.d" +unzip -j -o "${ZIPFILE}" 'uninstall.sh' -d "${MODPATH}" >&2 unzip -j -o "${ZIPFILE}" 'box_service.sh' -d /data/adb/service.d >&2 -tar -xjf ${MODPATH}/binary/${ARCH}.tar.bz2 -C ${MODPATH}/system/bin >&2 -ui_print "- Create resolv.conf" -if [ ! -f "/system/etc/resolv.conf" ] ; then - touch ${MODPATH}/system/etc/resolv.conf - echo nameserver 8.8.8.8 > ${MODPATH}/system/etc/resolv.conf - echo nameserver 9.9.9.9 >> ${MODPATH}/system/etc/resolv.conf - echo nameserver 1.1.1.1 >> ${MODPATH}/system/etc/resolv.conf - echo nameserver 149.112.112.112 >> ${MODPATH}/system/etc/resolv.conf -fi +ui_print "- Extract the files from the binary archive and copy them to the /system/bin and /data/adb/box/bin" +tar -xjf "${MODPATH}/binary/${ARCH}.tar.bz2" -C "${MODPATH}/system/bin" >&2 +tar -xjf "${MODPATH}/binary/${ARCH}.tar.bz2" "mlbox" -C /data/adb/box/bin >&2 + +ui_print "- Extract the dashboard.zip file to the folder /data/adb/box/clash/dashboard and /data/adb/box/sing-box/dashboard" +unzip -o "${MODPATH}/dashboard.zip" -d /data/adb/box/dashboard/ >&2 +unzip -o "${MODPATH}/dashboard.zip" -d /data/adb/box/clash/dashboard/ >&2 +unzip -o "${MODPATH}/dashboard.zip" -d /data/adb/box/sing-box/dashboard/ >&2 + +ui_print "" +ui_print "--------------------------------------------------------" +ui_print "- Are you going to create a resolve.conf file?" +ui_print "- Press Vol Up: to create the resolve.conf file." +ui_print "- Press Vol Down: to ignore the resolve.conf file." +while true ; do + getevent -lc 1 2>&1 | grep KEY_VOLUME > $TMPDIR/events + sleep 1 + if $(cat $TMPDIR/events | grep -q KEY_VOLUMEUP) ; then + ui_print "- Create a resolve.conf file if it doesn't already exist and add server nameservers." + if [ ! -f "/data/adb/modules/box_for_magisk/system/etc/resolv.conf" ]; then + cat > "${MODPATH}/system/etc/resolv.conf" <&1 | grep KEY_VOLUME > $TMPDIR/events + sleep 1 + if $(cat $TMPDIR/events | grep -q KEY_VOLUMEUP) ; then + ui_print "- it will take a while...." + if [ ! -f /data/adb/box/run/box.pid ]; then + /data/adb/box/scripts/box.tool all && echo "- downloads are complete." + else + ui_print " - BFM service is still running, Cannot update geo and kernel, as it will cause conflicts" + ui_print " - Download manually after reboot is complete" + fi + break + elif $(cat $TMPDIR/events | grep -q KEY_VOLUMEDOWN) ; then + ui_print "- ignore download GEOX and KERNEL" + break + fi +done + ui_print "- Installation is complete, reboot your device" +ui_print "" ui_print " --- Notes --- " ui_print "[+] report issues to @taamarin on Telegram" ui_print "[+] Join @taamarin on telegram to get more updates" \ No newline at end of file diff --git a/dashboard.zip b/dashboard.zip new file mode 100644 index 0000000..ac32a75 Binary files /dev/null and b/dashboard.zip differ diff --git a/index_en.md b/index_en.md new file mode 100644 index 0000000..214b638 --- /dev/null +++ b/index_en.md @@ -0,0 +1,124 @@ +## WARNING +This project is not responsible for: damaged devices, damaged SD cards, or burnt SoCs. + +**Make sure your configuration file does not cause traffic loopback, otherwise it may cause your phone to restart endlessly.** + +If you really don't know how to configure this module, you may need an application like ClashForAndroid, v2rayNG, Surfboard, SagerNet, AnXray, etc. + +## Installation +- Download the module zip package from RELEASE and install it via MAGISK. Then reboot. +- Make sure you are connected to the internet, and execute the following command to download binaries etc: +```shell + su -c /data/adb/box/scripts/box.tool upyacd +``` +```shell + su -c /data/adb/box/scripts/box.tool subgeo +``` +```shell + su -c /data/adb/box/scripts/box.tool upcore +``` + +- Support for the next online module update in Magisk Manager (updating the module will take effect without rebooting). + +### Notes +This module includes: + - [clash](https://github.com/Dreamacro/clash)、 + - [clash.meta](https://github.com/MetaCubeX/Clash.Meta)、[sing-box](https://github.com/SagerNet/sing-box)、 + - [v2ray-core](https://github.com/v2fly/v2ray-core)、 + - [Xray-core](https://github.com/XTLS/Xray-core). + - [sing-box](). + +After installing the module, download the appropriate core file for your device's architecture and place it in the /data/adb/box/bin/ directory, or execute: + +```shell +su -c /data/adb/box/scripts/box.tool upcore +``` + +## konfigurasi +- bin_name: + - clash + - xray + - v2ray + - sing-box + +- Each core works in the directory `/data/adb/box/bin/${bin_name}`, and the core name is determined by `bin_name` in the file `BFM`. +- Each core configuration file needs to be customized by the user, and the scripts will check the validity of the configuration, and the check result will be saved in the file `/data/adb/box/run/runs.log.` +- Tip: `clash` and `sing-box` come with ready-to-work default configurations with the transparent proxy script. For further configuration, see the official documentation. Address: [dokumen clash](https://github.com/Dreamacro/clash/wiki/configuration), [dokumen sing-box](https://sing-box.sagernet.org/configuration/outbound/) + + +## Instructions +### Conventional method (standard & recommended method) +#### Start and stop management services +**Layanan inti berikut secara kolektif disebut sebagai `BFM`** +- The following core services are collectively referred to as `BFM` +- You can enable or disable the module through the Magisk Manager application **in real time** to start or stop the `BFM` service, **without restarting the device**. Starting the service may take a few seconds, and stopping the service can take effect immediately. + +#### Select applications (APPs) that require proxy +- `BFM` defaults to proxying all applications (APPs) for all Android users. +- If you want `BFM` to proxy all applications (APP), except for certain ones, please open the file `/data/adb/box/settings.ini` and change the value of `proxy_mode` to `blacklist` (default), add packages to `packages_list`, for example: `packages_list=("com.termux" "org.telegram.messenger")` +- Use `whitelist` if you only want to proxy certain applications (APP). +- When the value of `proxy_mode` is `core/tun`, transparent proxy will not work, only the corresponding kernel will start, which can be used to support TUN, currently only `clash` and `sing-box` are available. + +### Advanced usage +#### Changing proxy mode +- `BFM` uses `TPROXY` to transparently proxy TCP + UDP (default). If it detects that the device does not support TPROXY, open `/data/adb/box/settings.ini` and change `network_mode="redirect"` to use `redirect` for TCP proxy only. +- Open the file `/data/adb/box/settings.ini`, change the value of network_mode to redirect, tproxy, or mixed. +- redirect: `redirec TCP only.` +- tproxy: `tproxy TCP + UDP.` +- mixed: `redirec TCP + tun UDP.` + +#### Bypass transparent proxy when connecting to Wi-Fi or hotspot +- `BFM` transparently proxies localhost and hotspot (including USB tethering) by default. +- Open the file `/data/adb/box/settings.ini`, modify `ignore_out_list` and add `wlan+`, then transparent proxy will bypass wlan, and hotspot won't connect to the proxy. +- Open the file `/data/adb/box/settings.ini`, modify `ap_list` and add `wlan+`. `BFM` will proxy the hotspot (for MediaTek devices, it may be ap+ / wlan+). +- Use the ifconfig command in the terminal to find out the name of the AP. + +#### Enter manual mode +- If you want to fully control `BFM` by running commands, just create a new file `/data/adb/box/manual`. In this case, the `BFM` service will not start automatically when your device is turned on, and you also cannot set the start or stop of the service through the Magisk Manager app. + +#### Starting and stopping the management service +The `BFM` service script is /data/adb/box/scripts/box.service + +- Start `BFM`: +```shell + su -c /data/adb/box/scripts/box.service start +``` +- Stop `BFM`: +```shell + su -c /data/adb/box/scripts/box.service stop +``` + +- The terminal will print logs and output them to a log file simultaneously. + +#### Manage whether transparent proxy is enabled +- The transparent proxy script is `/data/adb/box/scripts/box.tproxy` + +- Enable transparent proxy: +```shell + su -c /data/adb/box/scripts/box.tproxy enable +``` + +- Disable transparent proxy: +```shell + su -c /data/adb/box/scripts/box.tproxy disable +``` + +## Other instructions +- When modifying any of the core configuration files, please ensure that the tproxy related configurations are consistent with the definitions in the `/data/adb/box/settings.ini` file. +- If the machine has a **public IP address**, add the IP to the intranet in the `/data/adb/box/settings.ini` file to prevent traffic loops. +- Logs for the `BFM` service can be found in the `/data/adb/box/run` directory. + + +## Uninstall +- Removing the installation of this module from Magisk Manager will remove `/data/adb/service.d/box_service.sh` and keep the `BFM` data directory at /data/adb/box. +- You can use the following commands to remove the `BFM` data: + +```shell + su -c rm -rf /data/adb/box +``` +```shell + su -c rm -rf /data/adb/service.d/box_service.sh +``` + +## CHANGELOG +[CHANGELOG](CHANGELOG.md) diff --git a/index_id.md b/index_id.md old mode 100644 new mode 100755 diff --git a/module.prop b/module.prop index a43cbec..e11a409 100755 --- a/module.prop +++ b/module.prop @@ -1,6 +1,6 @@ id=box_for_magisk name=Box for Magisk -version=v0.2.1 +version=v0.4 versionCode=20230220 author=t@amarin description=use sing-box, clash, v2ray, and xray for tunnel proxy on android device diff --git a/scripts/bin/mlbox b/scripts/bin/mlbox deleted file mode 100755 index c3e492a..0000000 Binary files a/scripts/bin/mlbox and /dev/null differ diff --git a/scripts/clash/assets/llycoris.txt b/scripts/clash/assets/llycoris.txt deleted file mode 100755 index f2c30c7..0000000 --- a/scripts/clash/assets/llycoris.txt +++ /dev/null @@ -1 +0,0 @@ -proxies: \ No newline at end of file diff --git a/scripts/clash/config.yaml b/scripts/clash/config.yaml index 730189a..1d57827 100755 --- a/scripts/clash/config.yaml +++ b/scripts/clash/config.yaml @@ -1,17 +1,193 @@ +redir-port: 9797 +tproxy-port: 9898 +mode: rule +allow-lan: true +unified-delay: true +bind-address: '*' +# info / warning / error / debug / silent +log-level: silent +ipv6: false +geodata-mode: true +geodata-loader: memconservative +external-controller: 0.0.0.0:9090 +# external-controller-tls: 0.0.0.0:9091 # RESTful API HTTPS device +# secret: "123456" +external-ui: ./dashboard/dist +# tcp-concurrent: false +# inbound-tfo: false +# global-client-fingerprint: chrome +# interface-name: "rmnet_data+" +# routing-mark: 233 +geox-url: + mmdb: "https://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb" + geoip: "https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat" + geosite: "https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat" +find-process-mode: strict # always, strict, off + +profile: + store-selected: true + store-fake-ip: false + +# experimental: + # sniff-tls-sni: false + # udp-fallback-match: false + +# sniffer: + # enable: false + # ## 对 redir-host 类型识别的流量进行强制嗅探 + # ## 如:Tun、Redir 和 TProxy 并 DNS 为 redir-host 皆属于 + # force-dns-mapping: true + # parse-pure-ip: true + # override-destination: true + # sniff: + # TLS: + # # ports:[443, 8443] + # HTTP: + # ports: [80, 8080-8880] + # override-destination: true + # force-domain: + # - +.v2ex.com + # # skip-domain: + # # - +.google.com + # sniffing: + # - tls + # - http + # port-whitelist: + # - "80" + # - "443" + +# tun: + # enable: true + # # biarkan default utun + # device: utun + # mtu: 9000 + # # gvisor / lwip / system + # stack: system + # dns-hijack: + # - any:53 + # # bagi yg awam, kalau TUN on wajib true, only armv8/64 + # auto-route: true + # auto-detect-interface: true + # # end + # inet4-address: 172.19.0.1/30 + # inet6-address: [fdfe:dcba:9876::1/126] + # strict_route: false + # # include_android_user: + # # - 0 + # # - 10 + # # include_package: + # # - com.android.chrome + # # exclude_package: + # # - com.android.captiveportallogin + +dns: + enable: true + ipv6: false + prefer-h3: true + default-nameserver: + # cloudflare + - '1.1.1.1#BFM' + # google + - '8.8.8.8' + listen: 0.0.0.0:1053 + use-hosts: true + # redir-host / fake-ip + enhanced-mode: fake-ip + fake-ip-range: 28.0.0.1/8 + fake-ip-filter: + - '+.lan' + nameserver: + # cloudflare + - '1.1.1.1' + - 'tls://1.0.0.1:853#BFM' + # google + - '8.8.8.8#BFM' + - 'tls://8.8.4.4:853' + # proxy-server-nameserver: + # - '1.1.1.1' + # nameserver-policy: { "geosite:youtube": [1.1.1.1, 8.8.8.8] } + + # fallback: + # - 'https://8.8.8.8/dns-query' + # - 'tcp://8.8.4.4' + # - 'quic://dns.adguard.com:784' + # fallback-filter: + # geoip: false + # geoip-code: 'ID' + # geosite: + # # - gfw + # ipcidr: + # # - 240.0.0.0/4 + # domain: + # - '+.google.com' + # - '+.facebook.com' + # - '+.youtube.com' + # - '+.github.com' + +hosts: + # block update system android + 'ota.googlezip.net': 127.0.0.1 + 'ota-cache1.googlezip.net': 127.0.0.1 + 'ota-cache2.googlezip.net': 127.0.0.1 + proxies: proxy-groups: - - name: "llycoris" - type: select - use: [ - 🌸 - ] + - { name: 'BFM', type: select, use: ["@BFM"] } + - { name: 'block', type: select, proxies: ["REJECT", "BFM"] } proxy-providers: - 🌸: + '@BFM': type: file - path: ./assets/llycoris.txt + path: ./provide/domestic.yml + # filter: 'xxx' # Mendukung ekspresi reguler untuk memfilter berdasarkan nama node + # exclude-filter: 'ctb' # Mendukung ekspresi reguler untuk dikecualikan berdasarkan nama node + # exclude-type: 'ss|http' # Tidak mendukung ekspresi reguler, dipisahkan dengan '|', dikecualikan menurut jenis node health-check: enable: true - url: http://cp.cloudflare.com/generate_204 + url: http://www.gstatic.com/generate_204 interval: 1200 rules: - - MATCH,llycoris \ No newline at end of file + ## block ads + - DOMAIN-SUFFIX,googlesyndication.com,BFM + + ## block iklan + # - AND,((GEOSITE,category-ads-all),(NOT,((DOMAIN-SUFFIX,googlesyndication.com)))),REJECT + - GEOSITE,category-ads-all,block + + ## rules telegram + # - GEOIP,telegram,BFM + + ## direct FCM + # - AND,((NETWORK,TCP),(DST-PORT,5228-5230),(OR,((DOMAIN-KEYWORD,google)))),DIRECT + + ## direct ntp + # - AND,((NETWORK,UDP),(DST-PORT,123)),DIRECT + # - DST-PORT,123/136/137-139,DIRECT,udp + + ## block udp/quic YouTube + - AND,((NETWORK,udp),(OR,((DST-PORT,443),(GEOSITE,youtube)))),block + # - AND,((NETWORK,udp),(GEOSITE,youtube)),REJECT + + ## rules inner, recommended untuk non kuota reguler + # - AND,((PROCESS-NAME,clash),(NOT,((IN-TYPE,inner)))),REJECT + - IN-TYPE,inner,BFM + ## final + - MATCH,BFM + +## rules clash premium +# rule-providers: + # block: + # type: http + # behavior: domain + # url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt" + # path: ./ruleset/block.yaml + # interval: 86400 +# script: + # shortcuts: + # # quic: network == 'udp' and dst_port == 443 + # youshit: network == 'udp' and ('youtube' in host or 'googlevideo' in host) +# rules: + # - DOMAIN-SUFFIX,googlesyndication.com,BFM + # - RULE-SET,block,block + # # - SCRIPT,quic,block + # - SCRIPT,youshit,block + # - MATCH,BFM \ No newline at end of file diff --git a/scripts/clash/provide/domestic.yml b/scripts/clash/provide/domestic.yml new file mode 100755 index 0000000..9919f0a --- /dev/null +++ b/scripts/clash/provide/domestic.yml @@ -0,0 +1,2 @@ +proxies: +## tambah akun mu \ No newline at end of file diff --git a/scripts/settings.ini b/scripts/settings.ini index b1f81b3..71cc6e9 100755 --- a/scripts/settings.ini +++ b/scripts/settings.ini @@ -1,116 +1,108 @@ #!/system/bin/sh -export PATH=$(magisk --path)/.magisk/busybox:$PATH:/system/bin -settings="/data/adb/box/settings.ini" +export PATH="$(magisk --path)/.magisk/busybox:$PATH:/system/bin" -# path busybox +# define the settings and paths +settings="/data/adb/box/settings.ini" busybox_path="/data/adb/magisk/busybox" -# true: enable / false: disable Ipv6 -ipv6="false" -# true: for download Kernel meta, / false: Kernel premium -# su -c /data/adb/box/scripts/box.tool upcore -meta="true" -# for download clash premium / dev -dev="true" -# port detect +# enable/disable port detection: true / false port_detect="true" -# If you want to change the user or group, you must make the BFM core 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_magisk/system/bin/ and reboot the phone +# enable/disable IPv6: true / false +ipv6="true" + +# list of available kernel binaries +bin_list=("clash" "sing-box" "xray" "v2fly") + +# select the client to use : clash / sing-box / xray / v2fly +bin_name="clash" + +# set the port numbers for tproxy and redir +tproxy_port='9898' +redir_port='9797' + +# 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_magisk/system/bin/ and reboot the phone. # box_user_group="bin:system" box_user_group="root:net_admin" -# bin kernel -c="clash" -s="sing-box" -x="xray" -v="v2fly" -bin_list=("${c}" "${x}" "${s}" "${v}") -# select client -bin_name=$c - -# make sure the port is in sync with the config -tproxy_port="9898" -redir_port="9797" - -# redirect: tcp / tproxy: udp + tcp / mixed: tcp + tun +# redirect: tcp only, / tproxy: for tcp+udp with tproxy, / mixed: mode with redirect[tcp] and tun[udp] +# Network mode: tproxy for transparent proxying network_mode="tproxy" -# blacklist / whitelist / core (only tun) -proxy_mode="blacklist" -# Package Name -# ex: package_lis=(org.telegram.messenger xyz.nextalone.nagram com.whatsapp) -packages_list=() -# ap_list=("softap+" "wlan+" "swlan+" "ap+" "rndis+") -# for AP info type "ifconfig" in terminal -ap_list=("softap+" "wlan+" "swlan+" "ap+" "rndis+") -# for AP bypass +# Proxy mode: blacklist / whitelist / tun (only tun auto-route) +proxy_mode="blacklist" + +# List of package names to be proxied +packages_list=( com.v2ray.ang ) + +# Display AP info by typing "ifconfig" in terminal +ap_list=( "softap+" "wlan+" "swlan+" "ap+" "rndis+" ) + +# Ignore AP in the out list ignore_out_list=() -# set interval update, info: https://crontab.guru/ -crontab_sec="false" -# "0 00 * * *" / every 12 p.m -update_interval="0 00 * * *" -# update sub&geo -# type su -c /data/adb/box/scripts/box.tool subgeo -auto_updategeox="true" -# only clash subscription url -auto_updatesubcript="false" -subcript_url="http://127.0.0.1:9090/ui/akun.yaml" +# Set update interval using cron, for more information: https://crontab.guru/ +crontab_sec='true' +update_interval="0 00 * * *" # update every day at 12 a.m -# cgroup to limit memory usage -cgroup_memory="false" -# leave blank, for default value -cgroup_memory_path="" +# Update sub&geo +# Type "su -c /data/adb/box/scripts/box.tool subgeo" to update +auto_update_geox="true" + +# Only update clash subscription URL +auto_update_subscription="false" +subscription_url="" + +# Set cgroup to limit memory usage +cgroup_memory="true" cgroup_memory_limit="50M" +cgroup_memory_path="" -# box directory +# Set box directory variables data_dir="/data/adb/box" -# run directory run_path="${data_dir}/run" -# log file logs_file="${run_path}/runs.log" -# pid file pid_file="${run_path}/box.pid" -# bin directory bin_kernel="${data_dir}/bin" -# bin pat bin_path="${bin_kernel}/${bin_name}" -# scripts directory scripts_dir="${data_dir}/scripts" -# list uuid system_packages_file="/data/system/packages.list" -uid_list="${run_path}/appuid.list" -#config clash +uid_list=("/data/adb/box/run/appuid.list") + +# config clash name_clash_config="config.yaml" clash_config="${data_dir}/clash/${name_clash_config}" +# Membaca nilai enable dari konfigurasi tun +clash_tun_status=$(awk -F ': ' '/^tun: *$/{getline; print $2}' "${clash_config}") -# biarkan default utun -tun_device="utun" -cek_tun_device=$(grep "device:" /data/adb/box/template.yml | awk -F ': ' '{print $2}') -# clash dns.fake-ip-range -clash_fake_ip_range="43.0.0.1/8" -ceks_fake_ip_range=$(grep "fake-ip-range:" ${data_dir}/template.yml | awk -F ': ' '{print $2}') -# clash dns.listen -clash_dns_port="1053" -ceks_dns_port=$(grep "listen:" ${data_dir}/template.yml | awk -F ':' '{print $3}') -# tun stack lwip(use cgo kernel) / system / gvisor -clash_stack=$(grep "stack:" ${data_dir}/template.yml | awk -F ': ' '{print $2}') -# tun status false / true -clash_tun_status=$(awk -F ': ' '/^tun: *$/{getline; print $2}' ${data_dir}/template.yml) - -# Dns Static -static_dns1="8.8.4.4" -static_dns2="2001:4860:4860::8844" +# Set DNS variables, doc dns https://adguard-dns.io/kb/general/dns-providers/ +intervaldns="" +# intervaldns="*/10 * * * *" # +static_dns1="94.140.14.14" +static_dns2="2a10:50c0::ad1:ff" log() { - export TZ=Asia/Jakarta - now=$(date +"%I.%M %p %z") + # Set the timezone to Asia/Jakarta + export TZ=Asia/Jakarta + # Get the current time + now=$(date +"%I.%M %p %Z") case $1 in - info)[ -t 1 ] && echo -e "\033[1;34m${now} [info]: $2\033[0m" || echo "${now} [info]: $2" | tee -a ${logs_file} >> /dev/null 2>&1;; - error)[ -t 1 ] && echo -e "\033[1;31m${now} [error]: $2\033[0m" || echo "${now} [error]: $2" | tee -a ${logs_file} >> /dev/null 2>&1;; - warn)[ -t 1 ] && echo -e "\033[1;33m${now} [warn]: $2\033[0m" || echo "${now} [warn]: $2" | tee -a ${logs_file} >> /dev/null 2>&1;; - *)[ -t 1 ] && echo -e "\033[1;35m${now} [$1]: $2\033[0m" || echo "${now} [$1]: $2" | tee -a ${logs_file} >> /dev/null 2>&1;; + # print the log message in blue + info) color="\033[1;34m" ;; + # print the log message in red + error) color="\033[1;31m" ;; + # print the log message in yellow + warn) color="\033[1;33m" ;; + # print the log message in magenta + *) color="\033[1;35m" ;; esac -} \ No newline at end of file + 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 +} diff --git a/scripts/sing-box/config.json b/scripts/sing-box/config.json old mode 100644 new mode 100755 index cb432e4..370eb1d --- a/scripts/sing-box/config.json +++ b/scripts/sing-box/config.json @@ -6,42 +6,14 @@ "timestamp": false }, "dns": { - "final": "cloudflare", - "strategy": "prefer_ipv4", - "disable_cache": false, - "disable_expire": false, "servers": [ { "tag": "cloudflare", - "address": "1.1.1.1", - "detour": "sing-box" - }, - { - "tag": "googledns", - "address": "8.8.8.8", - "detour": "sing-box" - }, - { - "tag": "block", - "address": "rcode://success" + "address": "tls://1.1.1.1" } ], - "rules": [ - { - "domain_suffix": [ - "googlesyndication.com" - ], - "server": "cloudflare", - "disable_cache": false - }, - { - "geosite": [ - "category-ads-all" - ], - "server": "block", - "disable_cache": false - } - ] + "rules": [], + "strategy": "ipv4_only" }, "inbounds": [ { @@ -49,15 +21,10 @@ "tag": "tproxy-in", "listen": "::", "listen_port": 9898, - "network": [ - "udp", - "tcp" - ], - "tcp_fast_open": true, "sniff": true, "sniff_override_destination": true, "sniff_timeout": "300ms", - "domain_strategy": "prefer_ipv4", + "domain_strategy": "ipv4_only", "udp_timeout": 300 } ], @@ -75,51 +42,70 @@ "tag": "dns-out" }, { - "tag": "sing-box", + "tag": "BFM", + "type": "selector", + "outbounds": [ + "akun-a" + ] + }, + { + "tag": "blacklist", "type": "selector", "outbounds": [ "direct", - "sub-box" - ] + "block" + ], + "default": "block" }, { - "tag": "opok tsel", + "tag": "akun-a", "type": "vmess", - "server": "159.223.38.70", - "server_port": 80, - "uuid": "8a03dce3-3c8f-4785-be8d-bc8a832d0884", + "server": "server.com", + "server_port": 12345, + "uuid": "aaa-aaa-aaa", "security": "auto", "alter_id": 0, + "network": [ + "tcp", + "udp" + ], + "packet_encoding": "xudp", "transport": { "type": "ws", - "path": "/worryfree", + "path": "/path", "headers": { - "Host": "dynamic-sg1b.obfs.xyz" + "Host": "host.com" } } - }, - { - "tag": "sub-box", - "type": "selector", - "outbounds": [ - "opok tsel" - ] } ], "route": { - "final": "sing-box", - "geoip": { - "download_url": "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db", - "download_detour": "direct" - }, - "geosite": { - "download_url": "https://github.com/CHIZI-0618/v2ray-rules-dat/raw/release/geosite.db", - "download_detour": "direct" - }, + "final": "BFM", "rules": [ { "protocol": "dns", "outbound": "dns-out" + }, + { + "domain_suffix": [ + "googlesyndication.com" + ], + "outbound": "BFM" + }, + { + "protocol": [ + "quic" + ], + "port": [ + 443 + ], + "network": "udp", + "geosite": "youtube", + "outbound": "blacklist" + }, + { + "geosite": "category-ads-all", + "outbound": "blacklist" } ], "find_process": false, @@ -128,7 +114,7 @@ "experimental": { "clash_api": { "external_controller": "0.0.0.0:9090", - "external_ui": "../dashboard/dist", + "external_ui": "./dashboard/dist", "store_selected": false } } diff --git a/scripts/src/box.inotify b/scripts/src/box.inotify index ce87b32..2a5e19e 100755 --- a/scripts/src/box.inotify +++ b/scripts/src/box.inotify @@ -1,33 +1,33 @@ #!/system/bin/sh -scripts=$(realpath $0) -scripts_dir=$(dirname ${scripts}) +scripts=$(realpath "$0") +scripts_dir=$(dirname "${scripts}") 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") +now=$(date +"%I.%M %p %z") events=$1 monitor_dir=$2 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 - 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 + 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" + 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" fi fi } -[ -d ${run_path} ] || (mkdir -p ${run_path}) -if [ -f "${data_box}/settings.ini" ] ; then +mkdir -p "${run_path}" +if [ -f "${data_box}/settings.ini" ]; then service_control else - echo "${now} [ERROR] settings.ini file not found" > ${run_path}/error.inotify.log + echo "${now} [ERROR] settings.ini file not found" > "${run_path}/error.inotify.log" fi \ No newline at end of file diff --git a/scripts/src/box.iptables b/scripts/src/box.iptables index d114376..edf3970 100755 --- a/scripts/src/box.iptables +++ b/scripts/src/box.iptables @@ -4,18 +4,40 @@ scripts=$(realpath $0) scripts_dir=$(dirname ${scripts}) source /data/adb/box/settings.ini -table="223" -fwmark="222" -pref="100" +# set -euo pipefail + +# Variabel yang digunakan +table='223' +fwmark='222' +pref='100' +# Inisialisasi variabel +clash_fake_ip_range="" +clash_dns_port="" +# sesuai dengan nama tun di konfigurasi anda, Clash.Premium default "utun" +tun_device="utun" + +# Mencari nilai dari blok "fake-ip-range: / listen: / device:" dalam file konfigurasi YAML +# clash_fake_ip_range=$(awk '/fake-ip-range: / { print $2; exit }' "${clash_config}" || echo "198.18.0.1/16") +clash_fake_ip_range=$(awk '/fake-ip-range: /{print $2;found=1;exit} END{if(!found) print "198.18.0.1/16"}' "${clash_config}") +# tun_device=$(awk '/device: / { print $2; exit }' "${clash_config}")) +clash_enhanced_mode=$(awk '/enhanced-mode: / { print $2; exit }' "${clash_config}") +clash_dns_port=$(awk -F ':' '/listen:/ { print $3; exit }' "${clash_config}") + +probe_empty () { +if [ "${bin_name}" = "clash" ]; then + if [ "${clash_enhanced_mode}" = "fake-ip" ] ; then + if [ -z "${clash_fake_ip_range}" ] && [ -z "${clash_dns_port}" ]; then + log info "Tidak dapat menemukan nilai dari blok 'listen/fake-ip-range' dalam file konfigurasi YAML." + exit 1 + else + # Menampilkan hasil + log debug "Ip dari clash_fake_ip_range: ${clash_fake_ip_range}" + log debug "port dari clash_dns_port: ${clash_dns_port}" + fi + fi +fi +} -# ipts_version=$(iptables -V | grep -o "v1\.[0-9]") -# if [ "${ipts_version}" = "v1.4" ] ; then - # ipts="iptables" - # ip6ts="ip6tables" -# else - # ipts="iptables -w 100" - # ip6ts="ip6tables -w 100" -# fi probe_user_group() { if bin_pid=$(pidof ${bin_name}) ; then @@ -23,158 +45,207 @@ probe_user_group() { box_group=$(stat -c %G /proc/${bin_pid}) return 0 else - box_user=$(echo ${box_user_group} | awk -F ':' '{print $1}') - box_group=$(echo ${box_user_group} | awk -F ':' '{print $2}') + IFS=':' read -r box_user box_group <<< "${box_user_group}" return 1 fi } disable_ipv6() { - echo 0 > /proc/sys/net/ipv6/conf/all/accept_ra - echo 0 > /proc/sys/net/ipv6/conf/wlan0/accept_ra - echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6 - echo 1 > /proc/sys/net/ipv6/conf/default/disable_ipv6 - echo 1 > /proc/sys/net/ipv6/conf/wlan0/disable_ipv6 + sysctl -w net.ipv6.conf.all.accept_ra=0 + sysctl -w net.ipv6.conf.wlan0.accept_ra=0 + sysctl -w net.ipv6.conf.all.disable_ipv6=1 + sysctl -w net.ipv6.conf.default.disable_ipv6=1 + sysctl -w net.ipv6.conf.wlan0.disable_ipv6=1 } + ipv6_enable() { - echo 1 > /proc/sys/net/ipv6/conf/all/accept_ra - echo 1 > /proc/sys/net/ipv6/conf/wlan0/accept_ra - echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6 - echo 0 > /proc/sys/net/ipv6/conf/default/disable_ipv6 - echo 0 > /proc/sys/net/ipv6/conf/wlan0/disable_ipv6 + sysctl -w net.ipv6.conf.all.accept_ra=1 + sysctl -w net.ipv6.conf.wlan0.accept_ra=1 + sysctl -w net.ipv6.conf.all.disable_ipv6=0 + sysctl -w net.ipv6.conf.default.disable_ipv6=0 + sysctl -w net.ipv6.conf.wlan0.disable_ipv6=0 } -intranet=(0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16 192.0.0.0/24 192.0.2.0/24 192.88.99.0/24 192.168.0.0/16 198.51.100.0/24 203.0.113.0/24 224.0.0.0/4 240.0.0.0/4 255.255.255.255/32) -intranet6=(::/128 ::1/128 ::ffff:0:0/96 100::/64 64:ff9b::/96 2001::/32 2001:10::/28 2001:20::/28 2001:db8::/32 2002::/16 fe80::/10 ff00::/8) +intranet=( + 0.0.0.0/8 + 10.0.0.0/8 + 100.64.0.0/10 + 127.0.0.0/8 + 169.254.0.0/16 + 192.0.0.0/24 + 192.0.2.0/24 + 192.88.99.0/24 + 192.168.0.0/16 + 198.51.100.0/24 + 203.0.113.0/24 + 224.0.0.0/4 + 240.0.0.0/4 + 255.255.255.255/32 +) +intranet6=( + ::/128 + ::1/128 + ::ffff:0:0/96 + 100::/64 + 64:ff9b::/96 + 2001::/32 + 2001:10::/28 + 2001:20::/28 + 2001:db8::/32 + 2002::/16 + fe80::/10 + ff00::/8 +) -network_port () { - if [ "${network_mode}" = "tproxy" ] ; then - $(/system/bin/netstat -tnulp | grep -q "${tproxy_port}") || \ - log error "tproxy_port out of sync with config" +network_port() { + if [ "${network_mode}" = "tproxy" ] && [ "${proxy_mode}" != "tun" ]; then + /system/bin/netstat -tnulp | grep -q "${tproxy_port}" && \ + log info "tproxy_port: ${tproxy_port} is in sync with config" || \ + log error "tproxy_port: ${tproxy_port} out of sync with config" fi - if [ "${network_mode}" = "mixed" ] || [ "${proxy_mode}" = "core" ] ; then - $(/system/bin/ifconfig | grep -q ${tun_device}) || \ - log error "tun_device: ${tun_device} not found" + + if [ "${network_mode}" = "mixed" ] || [ "${proxy_mode}" = "tun" ]; then + /system/bin/ifconfig | grep -q "${tun_device}" && \ + log info "using tun_device: '${tun_device}' " || \ + log error "tun_device: '${tun_device}' not found" fi } find_packages_uid() { echo -n "" > ${uid_list} - for package in ${packages_list[*]} ; do - awk '$1~/'^"${package}"$'/{print $2}' ${system_packages_file} >> ${uid_list} + for package in "${packages_list[@]}"; do + awk -v p="${package}" '$1~p{print $2}' "${system_packages_file}" >> "${uid_list}" done } forward() { - ${iptables} $1 FORWARD -o ${tun_device} -j ACCEPT - ${iptables} $1 FORWARD -i ${tun_device} -j ACCEPT + ${iptables} $1 FORWARD -o "${tun_device}" -j ACCEPT + ${iptables} $1 FORWARD -i "${tun_device}" -j ACCEPT } start_redirect() { - if [ "${iptables}" != "ip6tables -w 100" ] ; then + if [ "${iptables}" != "ip6tables -w 100" ]; then ${iptables} -t nat -N BOX_EXTERNAL ${iptables} -t nat -F BOX_EXTERNAL ${iptables} -t nat -N BOX_LOCAL ${iptables} -t nat -F BOX_LOCAL fi - if [ "${iptables}" != "ip6tables -w 100" ] ; then - if [ "${bin_name}" = "clash" ] ; then - ${iptables} -t nat -A BOX_EXTERNAL -p udp --dport 53 -j REDIRECT --to-ports ${clash_dns_port} - ${iptables} -t nat -A BOX_LOCAL -p udp --dport 53 -j REDIRECT --to-ports ${clash_dns_port} - ${iptables} -t nat -A BOX_EXTERNAL -d ${clash_fake_ip_range} -p icmp -j DNAT --to-destination 127.0.0.1 - ${iptables} -t nat -A BOX_LOCAL -d ${clash_fake_ip_range} -p icmp -j DNAT --to-destination 127.0.0.1 + if [ "${iptables}" != "ip6tables -w 100" ]; then + if [ "${bin_name}" = "clash" ]; then + ${iptables} -t nat -A BOX_EXTERNAL -p udp --dport 53 -j REDIRECT --to-ports "${clash_dns_port}" + ${iptables} -t nat -A BOX_LOCAL -p udp --dport 53 -j REDIRECT --to-ports "${clash_dns_port}" + if [ "${clash_enhanced_mode}" = "fake-ip" ] ; then + ${iptables} -t nat -A BOX_EXTERNAL -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + ${iptables} -t nat -A BOX_LOCAL -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + fi # else # Other types of inbound should be added here to receive DNS traffic instead of sniffing - # ${iptables} -t nat -A BOX_EXTERNAL -p udp --dport 53 -j REDIRECT --to-ports ${redir_port} - # ${iptables} -t nat -A BOX_LOCAL -p udp --dport 53 -j REDIRECT --to-ports ${redir_port} + # ${iptables} -t nat -A BOX_EXTERNAL -p udp --dport 53 -j REDIRECT --to-ports "${redir_port}" + # ${iptables} -t nat -A BOX_LOCAL -p udp --dport 53 -j REDIRECT --to-ports "${redir_port}" fi - - for subnet in ${intranet[*]} ; do - ${iptables} -t nat -A BOX_EXTERNAL -d ${subnet} -j RETURN - ${iptables} -t nat -A BOX_LOCAL -d ${subnet} -j RETURN + +# Allow access to intranet subnets + for subnet in "${intranet[@]}"; do + ${iptables} -t nat -A BOX_EXTERNAL -d "${subnet}" -m comment --comment "Allow access to intranet subnet ${subnet}" -j RETURN + ${iptables} -t nat -A BOX_LOCAL -d "${subnet}" -m comment --comment "Allow access to intranet subnet ${subnet}" -j RETURN done + + ${iptables} -t nat -A BOX_EXTERNAL -p tcp -i lo -j REDIRECT --to-ports "${redir_port}" - ${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} + 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}" done log info "${ap_list[*]} transparent proxy." fi ${iptables} -t nat -I PREROUTING -j BOX_EXTERNAL - ${iptables} -t nat -I BOX_LOCAL -m owner --uid-owner ${box_user} --gid-owner ${box_group} -j RETURN + ${iptables} -t nat -I BOX_LOCAL -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -j RETURN - if [ "${ignore_out_list}" != "" ] ; then - for ignore in ${ignore_out_list[*]} ; do - ${iptables} -t nat -I BOX_LOCAL -o ${ignore} -j RETURN + if [ "${ignore_out_list}" != "" ]; then + for ignore in "${ignore_out_list[@]}"; do + ${iptables} -t nat -I BOX_LOCAL -o "${ignore}" -j RETURN done log info "${ignore_out_list[*]} ignore transparent proxy." fi fi - if [ "${iptables}" != "ip6tables -w 100" ] ; then - if [ "${proxy_mode}" = "blacklist" ] ; then - if [ "$(cat ${uid_list[*]})" = "" ] ; then + # check if iptables is not ip6tables + if [ "${iptables}" != "ip6tables -w 100" ]; then + # check proxy mode + if [ "${proxy_mode}" = "blacklist" ]; then + # check if uid list is empty + 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." + ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports "${redir_port}" + log info "Transparent proxy for all apps." else # Bypass apps - for appid in $(cat ${uid_list[*]}) ; do - ${iptables} -t nat -I BOX_LOCAL -m owner --uid-owner ${appid} -j RETURN - done + # loop through the UID list + while read -r appid; do + # add iptables rules for returning packets + ${iptables} -t nat -I BOX_LOCAL -m owner --uid-owner "${appid}" -j RETURN + done < "${uid_list[*]}" + + # close the file handle for the UID list + # exec <&- + # Allow !app - ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports ${redir_port} - log info "proxy mode: ${proxy_mode}, ${packages_list[*]} no transparent proxy." + ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports "${redir_port}" + log info "Proxy mode: ${proxy_mode}, ${packages_list[*]} no transparent proxy." fi - elif [ "${proxy_mode}" = "whitelist" ] ; then + elif [ "${proxy_mode}" = "whitelist" ]; then # Route apps to Box - for appid in $(cat ${uid_list[*]}) ; do - ${iptables} -t nat -A BOX_LOCAL -p tcp -m owner --uid-owner ${appid} -j REDIRECT --to-ports ${redir_port} - done - ${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." + # 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 <&- + + ${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." else - log warn "proxy mode: ${proxy_mode}, error." - ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports ${redir_port} - log info "transparent proxy for all apps." + log warn "Proxy mode: ${proxy_mode}, error." + ${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports "${redir_port}" + log info "Transparent proxy for all apps." fi fi - if [ "${iptables}" != "ip6tables -w 100" ] ; then + if [ "${iptables}" != "ip6tables -w 100" ]; then ${iptables} -t nat -I OUTPUT -j BOX_LOCAL fi - if [ "${iptables}" != "ip6tables -w 100" ] ; then - ${iptables} -A OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner ${box_user} --gid-owner ${box_group} -m tcp --dport ${redir_port} -j REJECT + if [ "${iptables}" != "ip6tables -w 100" ]; then + ${iptables} -A OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -m tcp --dport "${redir_port}" -j REJECT else - ${iptables} -A OUTPUT -d ::1 -p tcp -m owner --uid-owner ${box_user} --gid-owner ${box_group} -m tcp --dport ${redir_port} -j REJECT + ${iptables} -A OUTPUT -d ::1 -p tcp -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -m tcp --dport "${redir_port}" -j REJECT fi } stop_redirect() { - if [ "${iptables}" != "ip6tables -w 100" ] ; then + if [ "${iptables}" != "ip6tables -w 100" ]; then ${iptables} -t nat -D PREROUTING -j BOX_EXTERNAL ${iptables} -t nat -D OUTPUT -j BOX_LOCAL fi - if [ "${iptables}" != "ip6tables -w 100" ] ; then - ${iptables} -D OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner ${box_user} --gid-owner ${box_group} -m tcp --dport ${redir_port} -j REJECT - ${iptables} -D OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner 0 --gid-owner 3005 -m tcp --dport ${redir_port} -j REJECT + if [ "${iptables}" != "ip6tables -w 100" ]; then + ${iptables} -D OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -m tcp --dport "${redir_port}" -j REJECT + ${iptables} -D OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner 0:3005 -m tcp --dport "${redir_port}" -j REJECT else - ${iptables} -D OUTPUT -d ::1 -p tcp -m owner --uid-owner ${box_user} --gid-owner ${box_group} -m tcp --dport ${redir_port} -j REJECT - ${iptables} -D OUTPUT -d ::1 -p tcp -m owner --uid-owner 0 --gid-owner 3005 -m tcp --dport ${redir_port} -j REJECT + ${iptables} -D OUTPUT -d ::1 -p tcp -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -m tcp --dport "${redir_port}" -j REJECT + ${iptables} -D OUTPUT -d ::1 -p tcp -m owner --uid-owner 0:3005 -m tcp --dport "${redir_port}" -j REJECT fi - if [ "${iptables}" != "ip6tables -w 100" ] ; then - ${iptables} -t nat -D BOX_EXTERNAL -d ${clash_fake_ip_range} -p icmp -j DNAT --to-destination 127.0.0.1 - ${iptables} -t nat -D BOX_LOCAL -d ${clash_fake_ip_range} -p icmp -j DNAT --to-destination 127.0.0.1 - + if [ "${iptables}" != "ip6tables -w 100" ]; then + ${iptables} -t nat -D BOX_EXTERNAL -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + ${iptables} -t nat -D BOX_LOCAL -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + ${iptables} -t nat -F BOX_EXTERNAL ${iptables} -t nat -X BOX_EXTERNAL ${iptables} -t nat -F BOX_LOCAL @@ -183,15 +254,18 @@ stop_redirect() { } start_tproxy() { - if [ "${iptables}" != "ip6tables -w 100" ] ; then - ip rule add fwmark ${fwmark} table ${table} pref ${pref} - ip route add local default dev lo table ${table} + if [ "${iptables}" != "ip6tables -w 100" ]; then + ip rule add fwmark "${fwmark}" table "${table}" pref "${pref}" + ip route add local default dev lo table "${table}" else - ip -6 rule add fwmark ${fwmark} table ${table} pref ${pref} - ip -6 route add local default dev lo table ${table} + ip -6 rule add fwmark "${fwmark}" table "${table}" pref "${pref}" + ip -6 route add local default dev lo table "${table}" fi - ${iptables} -t mangle -N BOX_EXTERNAL + # Create the BOX_EXTERNAL chain if it doesn't exist + ${iptables} -t mangle -N BOX_EXTERNAL 2>/dev/null + # Set the default policy of the chain to RETURN + # ${iptables} -t mangle -P BOX_EXTERNAL RETURN ${iptables} -t mangle -F BOX_EXTERNAL # Bypass box itself @@ -204,40 +278,43 @@ start_tproxy() { ${iptables} -t mangle -I BOX_EXTERNAL -i ccmni+ -j RETURN # Bypass intranet - if [ "${bin_name}" = "clash" ] ; then - if [ "${iptables}" != "ip6tables -w 100" ] ; then - for subnet in ${intranet[*]} ; do - ${iptables} -t mangle -A BOX_EXTERNAL -d ${subnet} -j RETURN - done - else - for subnet6 in ${intranet6[*]} ; do - ${iptables} -t mangle -A BOX_EXTERNAL -d ${subnet6} -j RETURN - done - fi + # Add rules for intranet subnets + if [ "${iptables}" != "ip6tables -w 100" ]; then + for subnet in "${intranet[@]}"; do + if [ "${bin_name}" = "clash" ]; then + ${iptables} -t mangle -A BOX_EXTERNAL -d "${subnet}" -j RETURN + else + ${iptables} -t mangle -A BOX_EXTERNAL -d "${subnet}" -p udp ! --dport 53 -j RETURN + ${iptables} -t mangle -A BOX_EXTERNAL -d "${subnet}" ! -p udp -j RETURN + fi + done else - if [ "${iptables}" != "ip6tables -w 100" ] ; then - for subnet in ${intranet[*]} ; do - ${iptables} -t mangle -A BOX_EXTERNAL -d ${subnet} -p udp ! --dport 53 -j RETURN - ${iptables} -t mangle -A BOX_EXTERNAL -d ${subnet} ! -p udp -j RETURN - done - else - for subnet6 in ${intranet6[*]} ; do - ${iptables} -t mangle -A BOX_EXTERNAL -d ${subnet6} -p udp ! --dport 53 -j RETURN - ${iptables} -t mangle -A BOX_EXTERNAL -d ${subnet6} ! -p udp -j RETURN - done - fi + # Add rules for intranet6 subnets + for subnet6 in "${intranet6[@]}"; do + if [ "${bin_name}" = "clash" ]; then + ${iptables} -t mangle -A BOX_EXTERNAL -d "${subnet6}" -j RETURN + else + ${iptables} -t mangle -A BOX_EXTERNAL -d "${subnet6}" -p udp ! --dport 53 -j RETURN + ${iptables} -t mangle -A BOX_EXTERNAL -d "${subnet6}" ! -p udp -j RETURN + fi + done fi + # Append the BOX_EXTERNAL chain to the PREROUTING chain + ${iptables} -t mangle -A PREROUTING -j BOX_EXTERNAL - ${iptables} -t mangle -A BOX_EXTERNAL -p tcp -i lo -j TPROXY --on-port ${tproxy_port} --tproxy-mark ${fwmark} - ${iptables} -t mangle -A BOX_EXTERNAL -p udp -i lo -j TPROXY --on-port ${tproxy_port} --tproxy-mark ${fwmark} + ${iptables} -t mangle -A BOX_EXTERNAL -p tcp -i lo -j TPROXY --on-port "${tproxy_port}" --tproxy-mark "${fwmark}" + ${iptables} -t mangle -A BOX_EXTERNAL -p udp -i lo -j TPROXY --on-port "${tproxy_port}" --tproxy-mark "${fwmark}" # Allow ap interface # Notice: Old android device may only have one wlan interface. # Some new android device have multiple wlan interface like wlan0(for internet), wlan1(for AP). - if [ "${ap_list}" != "" ] ; then - for ap in ${ap_list[*]} ; do - ${iptables} -t mangle -A BOX_EXTERNAL -p tcp -i ${ap} -j TPROXY --on-port ${tproxy_port} --tproxy-mark ${fwmark} - ${iptables} -t mangle -A BOX_EXTERNAL -p udp -i ${ap} -j TPROXY --on-port ${tproxy_port} --tproxy-mark ${fwmark} + # loop through the access point list + if [ "${ap_list}" != "" ]; then + for ap in ${ap_list[@]} ; do + # add iptables rules for TCP traffic + ${iptables} -t mangle -A BOX_EXTERNAL -p tcp -i "${ap}" -j TPROXY --on-port "${tproxy_port}" --tproxy-mark "${fwmark}" + # add iptables rules for UDP traffic + ${iptables} -t mangle -A BOX_EXTERNAL -p udp -i "${ap}" -j TPROXY --on-port "${tproxy_port}" --tproxy-mark "${fwmark}" done [ "${iptables}" != "ip6tables -w 100" ] && log info "${ap_list[*]} transparent proxy." fi @@ -247,83 +324,91 @@ start_tproxy() { ${iptables} -t mangle -F BOX_LOCAL # Bypass ignored interfaces - if [ "${ignore_out_list}" != "" ] ; then - for ignore in ${ignore_out_list[*]} ; do - ${iptables} -t mangle -I BOX_LOCAL -o ${ignore} -j RETURN + if [ "${ignore_out_list}" != "" ]; then + for ignore in ${ignore_out_list[@]} ; do + ${iptables} -t mangle -I BOX_LOCAL -o "${ignore}" -j RETURN done [ "${iptables}" != "ip6tables -w 100" ] && log info "${ignore_out_list[*]} ignore transparent proxy." fi - # Bypass intranet - if [ "${bin_name}" = "clash" ] ; then - if [ "${iptables}" != "ip6tables -w 100" ] ; then - ${iptables} -t mangle -A BOX_LOCAL -p udp --dport 53 -j RETURN - for subnet in ${intranet[*]} ; do - ${iptables} -t mangle -A BOX_LOCAL -d ${subnet} -j RETURN + # Bypass intranet Clash + if [ "${bin_name}" = "clash" ]; then + ${iptables} -t mangle -A BOX_LOCAL -p udp --dport 53 -j RETURN + if [ "${iptables}" != "ip6tables -w 100" ]; then + for subnet in "${intranet[@]}"; do + ${iptables} -t mangle -A BOX_LOCAL -d "${subnet}" -j RETURN done else - ${iptables} -t mangle -A BOX_LOCAL -p udp --dport 53 -j RETURN - for subnet6 in ${intranet6[*]} ; do - ${iptables} -t mangle -A BOX_LOCAL -d ${subnet6} -j RETURN + for subnet6 in "${intranet6[@]}"; do + ${iptables} -t mangle -A BOX_LOCAL -d "${subnet6}" -j RETURN done fi else - if [ "${iptables}" != "ip6tables -w 100" ] ; then - for subnet in ${intranet[*]} ; do - ${iptables} -t mangle -A BOX_LOCAL -d ${subnet} -p udp ! --dport 53 -j RETURN - ${iptables} -t mangle -A BOX_LOCAL -d ${subnet} ! -p udp -j RETURN + if [ "${iptables}" != "ip6tables -w 100" ]; then + for subnet in "${intranet[@]}"; do + ${iptables} -t mangle -A BOX_LOCAL -d "${subnet}" -p udp ! --dport 53 -j RETURN + ${iptables} -t mangle -A BOX_LOCAL -d "${subnet}" ! -p udp -j RETURN done else - for subnet6 in ${intranet6[*]} ; do - ${iptables} -t mangle -A BOX_LOCAL -d ${subnet6} -p udp ! --dport 53 -j RETURN - ${iptables} -t mangle -A BOX_LOCAL -d ${subnet6} ! -p udp -j RETURN + for subnet6 in "${intranet6[@]}"; do + ${iptables} -t mangle -A BOX_LOCAL -d "${subnet6}" -p udp ! --dport 53 -j RETURN + ${iptables} -t mangle -A BOX_LOCAL -d "${subnet6}" ! -p udp -j RETURN done fi fi # Bypass box itself - ${iptables} -t mangle -I BOX_LOCAL -m owner --uid-owner ${box_user} --gid-owner ${box_group} -j RETURN + ${iptables} -t mangle -I BOX_LOCAL -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -j RETURN # ${iptables} -t mangle -I BOX_LOCAL -m mark --mark ${routing_mark} -j RETURN # Disable kernel # ${iptables} -t mangle -A BOX_LOCAL -m owner ! --uid 0-99999999 -j DROP - if [ "${proxy_mode}" = "blacklist" ] ; then - if [ "$(cat ${uid_list[*]})" = "" ] ; then + if [ "${proxy_mode}" = "blacklist" ]; 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} + ${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 100" ] && log info "transparent proxy for all apps." else # Bypass apps - for appid in $(cat ${uid_list[*]}) ; do - ${iptables} -t mangle -I BOX_LOCAL -m owner --uid-owner ${appid} -j RETURN - done + + while read -r appid; do + ${iptables} -t mangle -I BOX_LOCAL -m owner --uid-owner "${appid}" -j RETURN + done < "${uid_list[*]}" + + # close the file handle for the UID list + # exec <&- + # Allow !app - ${iptables} -t mangle -A BOX_LOCAL -p tcp -j MARK --set-mark ${fwmark} - ${iptables} -t mangle -A BOX_LOCAL -p udp -j MARK --set-mark ${fwmark} + ${iptables} -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 100" ] && log info "proxy mode: ${proxy_mode}, ${packages_list[*]} no transparent proxy." fi - elif [ "${proxy_mode}" = "whitelist" ] ; then + elif [ "${proxy_mode}" = "whitelist" ]; then # Route apps to Box - for appid in $(cat ${uid_list[*]}) ; 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 + # 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 <&- - ${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} + ${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} + ${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} + [ "${bin_name}" != "clash" ] && ${iptables} -t mangle -A BOX_LOCAL -p udp --dport 53 -j MARK --set-mark "${fwmark}" [ "${iptables}" != "ip6tables -w 100" ] && log info "proxy mode: ${proxy_mode}, ${packages_list[*]} transparent proxy." else log debug "proxy mode: ${proxy_mode}, error" - ${iptables} -t mangle -A BOX_LOCAL -p tcp -j MARK --set-mark ${fwmark} - ${iptables} -t mangle -A BOX_LOCAL -p udp -j MARK --set-mark ${fwmark} + ${iptables} -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 100" ] && log info "transparent proxy for all apps." fi @@ -331,57 +416,69 @@ start_tproxy() { ${iptables} -t mangle -N DIVERT ${iptables} -t mangle -F DIVERT - ${iptables} -t mangle -A DIVERT -j MARK --set-mark ${fwmark} + ${iptables} -t mangle -A DIVERT -j MARK --set-mark "${fwmark}" ${iptables} -t mangle -A DIVERT -j ACCEPT ${iptables} -t mangle -I PREROUTING -p tcp -m socket -j DIVERT # This rule blocks local access to tproxy-port to prevent traffic loopback. - if [ "${iptables}" != "ip6tables -w 100" ] ; then - ${iptables} -A OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner ${box_user} --gid-owner ${box_group} -m tcp --dport ${tproxy_port} -j REJECT + if [ "${iptables}" != "ip6tables -w 100" ]; then + ${iptables} -A OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -m tcp --dport "${tproxy_port}" -j REJECT else - ${iptables} -A OUTPUT -d ::1 -p tcp -m owner --uid-owner ${box_user} --gid-owner ${box_group} -m tcp --dport ${tproxy_port} -j REJECT + ${iptables} -A OUTPUT -d ::1 -p tcp -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -m tcp --dport "${tproxy_port}" -j REJECT fi - if [ "${iptables}" != "ip6tables -w 100" ] ; then - if [ "${bin_name}" = "clash" ] ; then + if [ "${iptables}" != "ip6tables -w 100" ]; then + if [ "${bin_name}" = "clash" ]; then + # Create and configure CLASH_DNS_EXTERNAL chain ${iptables} -t nat -N CLASH_DNS_EXTERNAL ${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 -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 -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 (proxies such as clash do not support forwarding ICMP), - # just that it returns a result, "--to-destination" can be set to a reachable address. - ${iptables} -t nat -I OUTPUT -d ${clash_fake_ip_range} -p icmp -j DNAT --to-destination 127.0.0.1 - ${iptables} -t nat -I PREROUTING -d ${clash_fake_ip_range} -p icmp -j DNAT --to-destination 127.0.0.1 + # Fix ICMP (ping) + # This does not guarantee that the ping result is valid + # Just that it returns a result + # "--to-destination" can be set to a reachable address. + if [ "${clash_enhanced_mode}" = "fake-ip" ] ; then + ${iptables} -t nat -I OUTPUT -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + ${iptables} -t nat -I PREROUTING -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + fi fi fi } stop_tproxy() { - if [ "${iptables}" != "ip6tables -w 100" ] ; then - ip rule del fwmark ${fwmark} table ${table} pref ${pref} - ip route del local default dev lo table ${table} - ip route flush table ${table} + if [ "${iptables}" != "ip6tables -w 100" ]; then + ip rule del fwmark "${fwmark}" table "${table}" pref "${pref}" + ip route del local default dev lo table "${table}" + ip route flush table "${table}" else - ip -6 rule del fwmark ${fwmark} table ${table} pref ${pref} - ip -6 route del local default dev lo table ${table} - ip -6 route flush table ${table} + ip -6 rule del fwmark "${fwmark}" table "${table}" pref "${pref}" + ip -6 route del local default dev lo table "${table}" + ip -6 route flush table "${table}" fi + ip rule delete not fwmark 2022 table main + ip rule delete iif lo lookup 2022 + ip rule delete iif utun lookup main suppress_prefixlength 0 + ip rule delete iif lo from 28.0.0.0/30 lookup 2022 + ${iptables} -t mangle -D PREROUTING -j BOX_EXTERNAL ${iptables} -t mangle -D PREROUTING -p tcp -m socket -j DIVERT ${iptables} -t mangle -D OUTPUT -j BOX_LOCAL + ${iptables} -t mangle -D BOX_EXTERNAL -i rmnet_data+ -j RETURN + ${iptables} -t mangle -D BOX_EXTERNAL -i ccmni+ -j RETURN + ${iptables} -t mangle -F BOX_EXTERNAL ${iptables} -t mangle -X BOX_EXTERNAL @@ -391,15 +488,15 @@ stop_tproxy() { ${iptables} -t mangle -F DIVERT ${iptables} -t mangle -X DIVERT - if [ "${iptables}" != "ip6tables -w 100" ] ; then - ${iptables} -D OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner ${box_user} --gid-owner ${box_group} -m tcp --dport ${tproxy_port} -j REJECT - ${iptables} -D OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner 0 --gid-owner 3005 -m tcp --dport ${tproxy_port} -j REJECT + if [ "${iptables}" != "ip6tables -w 100" ]; then + ${iptables} -D OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -m tcp --dport "${tproxy_port}" -j REJECT + ${iptables} -D OUTPUT -d 127.0.0.1 -p tcp -m owner --uid-owner 0 --gid-owner 3005 -m tcp --dport "${tproxy_port}" -j REJECT else - ${iptables} -D OUTPUT -d ::1 -p tcp -m owner --uid-owner ${box_user} --gid-owner ${box_group} -m tcp --dport ${tproxy_port} -j REJECT - ${iptables} -D OUTPUT -d ::1 -p tcp -m owner --uid-owner 0 --gid-owner 3005 -m tcp --dport ${tproxy_port} -j REJECT + ${iptables} -D OUTPUT -d ::1 -p tcp -m owner --uid-owner "${box_user}" --gid-owner "${box_group}" -m tcp --dport "${tproxy_port}" -j REJECT + ${iptables} -D OUTPUT -d ::1 -p tcp -m owner --uid-owner 0 --gid-owner 3005 -m tcp --dport "${tproxy_port}" -j REJECT fi - if [ "${iptables}" != "ip6tables -w 100" ] ; then + if [ "${iptables}" != "ip6tables -w 100" ]; then ${iptables} -t nat -D PREROUTING -j CLASH_DNS_EXTERNAL ${iptables} -t nat -D OUTPUT -j CLASH_DNS_LOCAL @@ -409,38 +506,48 @@ stop_tproxy() { ${iptables} -t nat -F CLASH_DNS_LOCAL ${iptables} -t nat -X CLASH_DNS_LOCAL - - ${iptables} -t nat -D OUTPUT -d ${clash_fake_ip_range} -p icmp -j DNAT --to-destination 127.0.0.1 - ${iptables} -t nat -D PREROUTING -d ${clash_fake_ip_range} -p icmp -j DNAT --to-destination 127.0.0.1 + + + ${iptables} -t nat -D OUTPUT -p icmp -d "${clash_fake_ip_range}" -j DNAT --to-destination 127.0.0.1 + ${iptables} -t nat -D PREROUTING -p icmp -d "${clash_fake_ip_range}" -j DNAT --to-destination 127.0.0.1 + # ${iptables} -t nat -D OUTPUT -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 + # ${iptables} -t nat -D PREROUTING -d "${clash_fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1 fi } -if [ "${proxy_mode}" != "core" ] ; then +if [ "${proxy_mode}" != "tun" ]; then case "$1" in enable) + probe_empty network_port - probe_user_group || log Error "failed to check Box user group, please make sure ${bin_name} core is started." - iptables="iptables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="iptables -w 100" && stop_redirect >> /dev/null 2>&1 - iptables="iptables -w 100" && forward -D >> /dev/null 2>&1 + probe_user_group || log error "failed to check Box user group, please make sure ${bin_name} kernel is started." + #ipv4 + iptables="iptables -w 100" && { + stop_tproxy + stop_redirect + forward -D + } >> /dev/null 2>&1 #ipv6 - iptables="ip6tables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="ip6tables -w 100" && stop_redirect >> /dev/null 2>&1 - iptables="ip6tables -w 100" && forward -D >> /dev/null 2>&1 + iptables="ip6tables -w 100" && { + stop_tproxy + stop_redirect + forward -D + } >> /dev/null 2>&1 + # find uuid apps/game find_packages_uid case "${network_mode}" in tproxy) log info "use tproxy: tcp + udp." log info "creating iptables transparent proxy rules." iptables="iptables -w 100" - intranet[${#intranet[@]}]=$(ip address | grep -w inet | grep -v 127 | awk '{print $2}') - start_tproxy && log info "create iptables transparent proxy rules done." || (log error "create ip6tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1) - if [ "${ipv6}" = "true" ] ; then + intranet+=($(ip address | awk '/inet / && !/127\.0\.0\.1/ {print $2}')) + start_tproxy && log info "create iptables transparent proxy rules done." || { log error "create iptables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } + if [ "${ipv6}" = "true" ]; then log debug "use IPv6." ipv6_enable iptables="ip6tables -w 100" - intranet6[${#intranet6[@]}]=$(ip address | grep -w inet6 | grep -v ::1 | grep -v fe80 | awk '{print $2}') - start_tproxy && log info "create ip6tables transparent proxy rules done." || (log error "create ip6tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1) + intranet6+=($(ip address | awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) + start_tproxy && log info "create ip6tables transparent proxy rules done." || { log error "create ip6tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } else disable_ipv6 log warn "disable IPv6." @@ -450,36 +557,36 @@ if [ "${proxy_mode}" != "core" ] ; then log info "use redirect: tcp only" log info "creating iptables transparent proxy rules." iptables="iptables -w 100" - intranet[${#intranet[@]}]=$(ip address | grep -w inet | grep -v 127 | awk '{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 + intranet+=($(ip address | 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 100" - intranet6[${#intranet6[@]}]=$(ip address | grep -w inet6 | grep -v ::1 | grep -v fe80 | awk '{print $2}') - start_redirect && log info "create ip6tables transparent proxy rules done." || (log error "create ip6tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1) + intranet6+=($(ip address | awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) + 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." fi ;; mixed) - log info "use mixed: tcp + tun, stack: ${clash_stack}." + log info "use mixed: tcp + tun" log info "creating iptables transparent proxy rules." iptables="iptables -w 100" forward -I || forward -D >> /dev/null 2>&1 - intranet[${#intranet[@]}]=$(ip address | grep -w inet | grep -v 127 | awk '{print $2}') + intranet+=($(ip address | 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 100" - intranet6[${#intranet6[@]}]=$(ip address | grep -w inet6 | grep -v ::1 | grep -v fe80 | awk '{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) + if [ "${ipv6}" = "true" ]; then + log debug "use IPv6." + ipv6_enable + iptables="ip6tables -w 100" + intranet6+=($(ip address | 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 ;; *) @@ -491,16 +598,12 @@ if [ "${proxy_mode}" != "core" ] ; then ${scripts_dir}/box.tool testing ;; renew) + probe_empty network_port - probe_user_group || log Error "failed to check Box user group, please make sure ${bin_name} core is started." + probe_user_group || log error "failed to check Box user group, please make sure ${bin_name} kernel is started." log warn "cleaning up iptables transparent proxy rules." - iptables="iptables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="iptables -w 100" && stop_redirect >> /dev/null 2>&1 - iptables="iptables -w 100" && forward -D >> /dev/null 2>&1 - #ipv6 - iptables="ip6tables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="ip6tables -w 100" && stop_redirect >> /dev/null 2>&1 - iptables="ip6tables -w 100" && forward -D >> /dev/null 2>&1 + iptables="iptables -w 100" && { stop_tproxy; stop_redirect; forward -D; } >> /dev/null 2>&1 + iptables="ip6tables -w 100" && { stop_tproxy; stop_redirect; forward -D; } >> /dev/null 2>&1 log warn "clean up iptables transparent proxy rules done." find_packages_uid case "${network_mode}" in @@ -508,14 +611,14 @@ if [ "${proxy_mode}" != "core" ] ; then log info "use tproxy: tcp + udp." log info "creating iptables transparent proxy rules." iptables="iptables -w 100" - intranet[${#intranet[@]}]=$(ip address | grep -w inet | grep -v 127 | awk '{print $2}') - start_tproxy && log info "create iptables transparent proxy rules done." || (log error "create ip6tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1) - if [ "${ipv6}" = "true" ] ; then + intranet+=($(ip address | awk '/inet / && !/127\.0\.0\.1/ {print $2}')) + start_tproxy && log info "create iptables transparent proxy rules done." || { log error "create iptables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } + if [ "${ipv6}" = "true" ]; then log debug "use IPv6." ipv6_enable iptables="ip6tables -w 100" - intranet6[${#intranet6[@]}]=$(ip address | grep -w inet6 | grep -v ::1 | grep -v fe80 | awk '{print $2}') - start_tproxy && log info "create ip6tables transparent proxy rules done." || (log error "create ip6tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1) + intranet6+=($(ip address | awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) + start_tproxy && log info "create ip6tables transparent proxy rules done." || { log error "create ip6tables transparent proxy rules failed." && stop_tproxy >> /dev/null 2>&1; } else disable_ipv6 log warn "disable IPv6." @@ -525,36 +628,36 @@ if [ "${proxy_mode}" != "core" ] ; then log info "use redirect: tcp only" log info "creating iptables transparent proxy rules." iptables="iptables -w 100" - intranet[${#intranet[@]}]=$(ip address | grep -w inet | grep -v 127 | awk '{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 + intranet+=($(ip address | 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 100" - intranet6[${#intranet6[@]}]=$(ip address | grep -w inet6 | grep -v ::1 | grep -v fe80 | awk '{print $2}') - start_redirect && log info "create ip6tables transparent proxy rules done." || (log error "create ip6tables transparent proxy rule failed." && stop_redirect >> /dev/null 2>&1) + intranet6+=($(ip address | awk '/inet6/ && !/::1/ && !/fe80/ {print $2}')) + 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." fi ;; mixed) - log info "use mixed: tcp + tun, stack: ${clash_stack}." + log info "use mixed: tcp + tun" log info "creating iptables transparent proxy rules." iptables="iptables -w 100" forward -I || forward -D >> /dev/null 2>&1 - intranet[${#intranet[@]}]=$(ip address | grep -w inet | grep -v 127 | awk '{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 100" - intranet6[${#intranet6[@]}]=$(ip address | grep -w inet6 | grep -v ::1 | grep -v fe80 | awk '{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) + intranet+=($(ip address | 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 100" + intranet6+=($(ip address | 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 ;; *) @@ -568,13 +671,18 @@ if [ "${proxy_mode}" != "core" ] ; then disable) probe_user_group log warn "cleaning up iptables transparent proxy rules." - iptables="iptables -w 100" && stop_tproxy - iptables="iptables -w 100" && stop_redirect - iptables="iptables -w 100" && forward -D + #ipv4 + iptables="iptables -w 100" && { + stop_tproxy + stop_redirect + forward -D + } #ipv6 - iptables="ip6tables -w 100" && stop_tproxy - iptables="ip6tables -w 100" && stop_redirect - iptables="ip6tables -w 100" && forward -D + iptables="ip6tables -w 100" && { + stop_tproxy + stop_redirect + forward -D + } ipv6_enable log warn "clean up iptables transparent proxy rules done." ;; @@ -586,22 +694,27 @@ else case "$1" in enable) network_port - probe_user_group || log Error "failed to check Box user group, please make sure ${bin_name} core is started." + probe_user_group || log error "failed to check Box user group, please make sure ${bin_name} kernel is started." log info "proxy_mode: ${proxy_mode}, disable transparent proxy." - iptables="iptables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="iptables -w 100" && stop_redirect >> /dev/null 2>&1 - iptables="iptables -w 100" && forward -D >> /dev/null 2>&1 + #ipv4 + iptables="iptables -w 100" && { + stop_tproxy + stop_redirect + forward -D + } >> /dev/null 2>&1 #ipv6 - iptables="ip6tables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="ip6tables -w 100" && stop_redirect >> /dev/null 2>&1 - iptables="ip6tables -w 100" && forward -D >> /dev/null 2>&1 + iptables="ip6tables -w 100" && { + stop_tproxy + stop_redirect + forward -D + } >> /dev/null 2>&1 iptables="iptables -w 100" - forward -I && log info "use tun: tcp + udp, stack: ${clash_stack}" || (log info "use tun: tcp + udp failed." && forward -D >> /dev/null 2>&1) - if [ "${ipv6}" = "true" ] ; then + forward -I && log info "use tun: tcp + udp" || { log info "use tun: tcp + udp failed." && forward -D >> /dev/null 2>&1; } + if [ "${ipv6}" = "true" ]; then log debug "use IPv6." ipv6_enable iptables="ip6tables -w 100" - forward -I && log info "use tun ipv6: tcp + udp, stack: ${clash_stack}" || (log info "use tun ipv6: tcp + udp failed." && forward -D >> /dev/null 2>&1) + forward -I && log info "use tun ipv6: tcp + udp" || { log info "use tun ipv6: tcp + udp failed." && forward -D >> /dev/null 2>&1; } else disable_ipv6 log warn "disable IPv6." @@ -612,23 +725,28 @@ else ;; renew) network_port - probe_user_group || log Error "failed to check Box user group, please make sure ${bin_name} core is started." + probe_user_group || log error "failed to check Box user group, please make sure ${bin_name} kernel is started." log warn "cleaning up tun rules." - iptables="iptables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="iptables -w 100" && stop_redirect >> /dev/null 2>&1 - iptables="iptables -w 100" && forward -D >> /dev/null 2>&1 + #ipv4 + iptables="iptables -w 100" && { + stop_tproxy + stop_redirect + forward -D + } >> /dev/null 2>&1 #ipv6 - iptables="ip6tables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="ip6tables -w 100" && stop_redirect >> /dev/null 2>&1 - iptables="ip6tables -w 100" && forward -D >> /dev/null 2>&1 + iptables="ip6tables -w 100" && { + stop_tproxy + stop_redirect + forward -D + } >> /dev/null 2>&1 log warn "clean up tun rules done." iptables="iptables -w 100" - forward -I && log info "use tun: tcp + udp, stack: ${clash_stack}" || log info "use tun: tcp + udp failed." - if [ "${ipv6}" = "true" ] ; then + forward -I && log info "use tun: tcp + udp" || log info "use tun: tcp + udp failed." + if [ "${ipv6}" = "true" ]; then log debug "use IPv6." ipv6_enable iptables="ip6tables -w 100" - forward -I && log info "use tun ipv6: tcp + udp, stack: ${clash_stack}" || (log info "use tun ipv6: tcp + udp failed." && forward -D >> /dev/null 2>&1) + forward -I && log info "use tun ipv6: tcp + udp" || { log info "use tun ipv6: tcp + udp failed." && forward -D >> /dev/null 2>&1; } else disable_ipv6 log warn "disable IPv6." @@ -638,14 +756,19 @@ else log info "${bin_name} connected." ;; disable) - probe_user_group || log Error "failed to check Box user group, please make sure ${bin_name} core is started." + probe_user_group || log error "failed to check Box user group, please make sure ${bin_name} kernel is started." log warn "cleaning up tun rules." - iptables="iptables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="iptables -w 100" && stop_redirect >> /dev/null 2>&1 + #ipv4 + iptables="iptables -w 100" && { + stop_tproxy + stop_redirect + } >> /dev/null 2>&1 iptables="iptables -w 100" && forward -D #ipv6 - iptables="ip6tables -w 100" && stop_tproxy >> /dev/null 2>&1 - iptables="ip6tables -w 100" && stop_redirect >> /dev/null 2>&1 + iptables="ip6tables -w 100" && { + stop_tproxy + stop_redirect + } >> /dev/null 2>&1 iptables="ip6tables -w 100" && forward -D ipv6_enable log warn "clean up tun rules done." @@ -654,4 +777,4 @@ else echo "$0: usage: $0 {enable|disable|renew}" ;; esac -fi +fi \ No newline at end of file diff --git a/scripts/src/box.service b/scripts/src/box.service index a1f465f..74483d7 100755 --- a/scripts/src/box.service +++ b/scripts/src/box.service @@ -5,217 +5,237 @@ scripts_dir=$(dirname ${scripts}) source /data/adb/box/settings.ini delete_logs() { - for list in ${bin_list[*]} ; do - rm -rf "${run_path}/${list}.log" + # Delete logs for each bin in the list + log info "Deleting & Backup logs for ${bin_list[*]}" + for bin in "${bin_list[@]}" ; do + mv "${run_path}/${bin}.log" "${run_path}/${bin}-$(date +%Y-%m-%d-%H-%M-%S).logs" + rm -f "${run_path}/${bin}.log" || log warn "Error deleting ${bin}.log" done - find ${run_path} -type f -name "root" | xargs rm -f - find ${run_path} -type f -name "*.yaml" | xargs rm -f - find ${run_path} -type f -name "*.list" | xargs rm -f - find ${run_path} -type f -name "*.inotify.log" | xargs rm -f - - # Delete the log three days ago - # find ${run_path} -mtime +3 -type f -name "*.log" | xargs rm -f + + # 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 "*.logs" -mtime +2 -exec rm -f {} \; || log warn "Error deleting old logs" } crontab_geo() { - if [ "${auto_updategeox}" != "false" ] || [ "${auto_updatesubcript}" != "false" ] ; then - echo "${update_interval} ${scripts_dir}/box.tool subgeo" >> ${run_path}/root - log debug "interval crontab geo and subscription (${update_interval})." - log debug "${bin_name} geox (${auto_updategeox})." - [ "${bin_name}" = "clash" ] && log debug "${bin_name} subscription (${auto_updatesubcript})." + if [ "${auto_update_geox}" != "false" ] || [ "${auto_update_subscription}" != "false" ]; then + echo "${update_interval} ${scripts_dir}/box.tool subgeo" >> "${run_path}/root" + log debug "Interval crontab geo and subscription (${update_interval})." + log debug "${bin_name} geox (${auto_update_geox})." + if [ "${bin_name}" = "clash" ]; then + log debug "${bin_name} subscription (${auto_update_subscription})." + fi else - log info "crontab geox & subscription is disable." + log info "Crontab geox & subscription is disabled." fi } detected_port() { - sleep 1 - [ "${port_detect}" = "true" ] && (${scripts_dir}/box.tool port) || (log warn "${bin_name} skip port detected." && return 1) -} - -temporary_config_file() { - if [ -f "${data_dir}/template.yml" ] ; then - if [ -f "${clash_config}" ] ; then - cp -f ${data_dir}/template.yml ${data_dir}/run/config.yaml.temp \ - && echo "\n" >> ${data_dir}/run/config.yaml.temp - # sed -n -E '/^proxies:$/,$p' ${clash_config} >> ${data_dir}/run/config.yaml.temp - awk '/proxies:/,EOF { print $0 }' ${clash_config} >> ${data_dir}/run/config.yaml.temp - sleep .3 - sed -i '/^[ ]*$/d' ${data_dir}/run/config.yaml.temp - else - log error "${clash_config} file is missing." - exit 1 - fi - else - log error "${data_dir}/template.yml file is missing." - exit 1 - fi - - if ! (mv ${data_dir}/run/config.yaml.temp ${data_dir}/run/config.yaml) ; then - log error "merge config failed!!!." - exit 1 - fi + [ "${port_detect}" = "true" ] && ${scripts_dir}/box.tool port || log warn "${bin_name} skip port detected." && return 1 } still_alive() { - if ! (pidof ${bin_name} > /dev/null 2>&1) ; then - log error "${bin_name} service is not running." - log error "please, check ${bin_name}.log" - kill -9 $(pidof ${bin_name}) || killall -9 ${bin_name} - rm -rf ${pid_file} + if ! pid=$(pidof ${bin_name} 2>/dev/null); then + log error "${bin_name} service is not running." + log error "Please check ${bin_name}.log for more information." exit 1 fi -} - -sinkron_port() { - if [ "${bin_name}" = "clash" ] ; then - if [ "${ceks_dns_port}" != "${clash_dns_port}" ] ; then - log info "sinkron dns listen" - sed -i "s/clash_dns_port=.*/clash_dns_port=\""${ceks_dns_port}"\"/" ${settings} - fi - if [ "${ceks_fake_ip_range}" != "${clash_fake_ip_range}" ] ; then - log error "fake-ip-range is out of sync, fix: open template.yml, match IP fake-ip-range: ${ceks_fake_ip_range} with clash_fake_ip_range: in settings.ini" - exit 1 - fi + + if ! kill -0 $pid 2>/dev/null; then + log error "${bin_name} service is not running." + log error "Killing stale pid ${pid}." + kill -9 $pid || killall -9 ${bin_name} + rm -f ${pid_file} + exit 1 fi } 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 and place it in the ${bin_path} directory." + if [ "${box_user_group}" = "root:net_admin" ]; then + if [ ! -f ${bin_path} ]; then + log error "Kernel ${bin_name} is missing." + log error "Please download and place it in the ${bin_path} directory." exit 1 fi - box_user_group="root:net_admin" + # 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 "using kernel directory ${bin_name} in ${bin_path}" + log info "Using kernel directory ${bin_name} in ${bin_path}" else if which ${bin_name} | grep -q "/system/bin/" ; then box_user=$(echo ${box_user_group} | awk -F ':' '{print $1}') box_group=$(echo ${box_user_group} | awk -F ':' '{print $2}') box_user_id=$(id -u ${box_user}) box_group_id=$(id -g ${box_group}) - [ ${box_user_id} ] && [ ${box_group_id} ] || \ - (box_user_group="root:net_admin" && log warn "${box_user_group} error, use root:net_admin instead.") - bin_path=$(which ${bin_name}) - chown ${box_user_group} ${bin_path} - chmod 6755 ${bin_path} - if [ "${box_user_id}" != "0" ] || [ "${box_group_id}" != "3005" ] ; then - # setcap has been deprecated as it does not support binary outside of the /system/bin 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.") + # 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 "Using kernel directory ${bin_name} in ${bin_path}" fi - log info "using kernel directory ${bin_name} in ${bin_path}" - chown -R ${box_user_group} ${data_dir} else - log error "kernel ${bin_name} is missing" - log error "please download kernel" - log error "replace it in the /data/adb/modules/box_for_magisk/system/bin/${bin_name} directory. and reboot " + log error "Kernel ${bin_name} is missing." + log error "Please download kernel, replace it in the /data/adb/modules/box_for_magisk/system/bin/${bin_name} directory, and reboot." exit 1 fi fi } check_in_bin() { + if ! command -v "${bin_path}" >/dev/null 2>&1; then + log error "Error: '${bin_path}' not found or not executable." + exit 1 + fi + + if [ ! -f "${bin_path}" ] || [ ! -x "${bin_path}" ]; then + log error "Error: '${bin_path}' is not a valid file or cannot be executed." + exit 1 + fi + case "${bin_name}" in clash) - test_version=$(${bin_path} -v | grep -v 'clash') - echo "${test_version}" | grep -qi 'clash' && \ - log info "$(${bin_path} -v)" || log error "kernel ${bin_name} corrupted." - ;; - sing-box) - test_version=$(${bin_path} version | grep "${bin_name}") - echo "${test_version}" | grep -qi "${bin_name}" && \ - log info "$(${bin_path} version)" || log error "kernel ${bin_name} corrupted." - ;; + if ! "${bin_path}" -v >/dev/null 2>&1; then + log error "Error: '${bin_name}' version information not available." + exit 1 + fi + log info "$(${bin_path} -v)";; *) - test_version=$(${bin_path} version | grep -v "${bin_name}") - echo "${test_version}" | grep -qi "${bin_name}" && \ - log info "$(${bin_path} version)" || log error "kernel ${bin_name} corrupted." - ;; + if ! "${bin_path}" version >/dev/null 2>&1; then + echo "Error: '${bin_name}' version information not available." + exit 1 + fi + log info "$(${bin_path} version)";; esac } create_tun() { - echo 1 > /proc/sys/net/ipv4/ip_forward - [ ! -e "/dev/net/tun" ] && \ - mkdir -p /dev/net && ln -s /dev/tun /dev/net/tun - # mkdir -p /dev/net - # [ ! -L /dev/net/tun ] && ln -sf /dev/tun /dev/net/tun + # Mengaktifkan IP forwarding + sysctl net.ipv4.ip_forward=1 >/dev/null 2>&1 + # Membuat symlink untuk /dev/tun jika belum ada + if [ ! -c "/dev/net/tun" ]; then + if ! mkdir -p /dev/net; then + log warn "Cannot create directory /dev/net" >&2 + exit 1 + fi + + if ! mknod /dev/net/tun c 10 200; then + log warn "Cannot create /dev/net/tun. Possible reasons:" + log warn "This script is not executed as root user." + log warn "Your system does not support the TUN/TAP driver." + log warn "Your system kernel version is not compatible with the TUN/TAP driver." + exit 1 + fi + fi +} + +default_tp() { + awk -v new_val="tproxy" '/network_mode/ {$0 = "network_mode=\"" new_val "\""} 1' ${settings} > ${data_dir}/tmp && mv ${data_dir}/tmp ${settings} } run_box() { log info "client list: ${bin_list[*]}" log info "select: ${bin_name}" log info "starting ${bin_name} service." - sinkron_port - ulimit -SHn 1000000 case "${bin_name}" in sing-box) - [ "${proxy_mode}" = "core" ] && \ - log info "don't forget to set 'auto detect interface': true" - # && (sed -i 's/"auto_detect_interface":.*/"auto_detect_interface": true/' ${data_dir}/sing-box/config.json) || (sed -i 's/"auto_detect_interface":.*/"auto_detect_interface": false/' ${data_dir}/sing-box/config.json) - sed -i 's/network_mode=.*/network_mode="tproxy"/' ${settings} - if (${bin_path} check -D ${data_dir}/${bin_name} > "${run_path}/${bin_name}-report.log" 2>&1) ; then - nohup setuidgid 0:3005 ${bin_path} run -D ${data_dir}/${bin_name} > "${run_path}/${bin_name}.log" 2>&1 & - echo -n $! > ${pid_file} + # if [ "${network_mode}" = "mixed" ] || [ "${proxy_mode}" = "tun" ]; then + # awk '{gsub(/"auto_detect_interface": false/,"\"auto_detect_interface\": true")}1' "${data_dir}/sing-box/config.json" > "${data_dir}/temp" && mv "${data_dir}/temp" "${data_dir}/sing-box/config.json" + # sleep 0.75 + # awk '{gsub(/auto_route\": false/, "auto_route\": true"); print}' "${data_dir}/sing-box/config.json" > "${data_dir}/temp" && mv "${data_dir}/temp" "${data_dir}/sing-box/config.json" + # else + # awk '{gsub(/auto_route\": true/, "auto_route\": false"); print}' "${data_dir}/sing-box/config.json" > "${data_dir}/temp" && mv "${data_dir}/temp" "${data_dir}/sing-box/config.json" + # sleep 0.75 + # awk '{gsub(/"auto_detect_interface": true/,"\"auto_detect_interface\": false")}1' "${data_dir}/sing-box/config.json" > "${data_dir}/temp" && mv "${data_dir}/temp" "${data_dir}/sing-box/config.json" + # fi + # sleep 1 + if ${bin_path} check -D "${data_dir}/${bin_name}" > "${run_path}/${bin_name}-report.log" 2>&1 ; then + ulimit -SHn 65535 + nohup setuidgid 0:3005 ${bin_path} run -D "${data_dir}/${bin_name}" > "${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." + log error "Configuration failed, please check the ${run_path}/${bin_name}-report.log file." >&2 exit 1 fi ;; + clash) - if [ "${clash_tun_status}" = "true" ] ; then - sed -i 's/tproxy-port:.*/tproxy-port: 0/' ${data_dir}/template.yml - sed -i 's/network_mode=.*/network_mode="mixed"/' ${settings} - sed -i 's/auto-route:.*/auto-route: true/' ${data_dir}/template.yml - sed -i 's/auto-detect-interface:.*/auto-detect-interface: true/' ${data_dir}/template.yml + if [ "${clash_tun_status}" != "true" ]; then + awk -v tproxy_port="${tproxy_port}" '/tproxy-port:/ {$2=tproxy_port} {print}' ${clash_config} > ${data_dir}/tmp && mv ${data_dir}/tmp ${clash_config} + default_tp else - sed -i "s/tproxy-port:.*/tproxy-port: ${tproxy_port}/" ${data_dir}/template.yml - # jika ingin mengunakan redirect, hapus line di bawah - sed -i 's/network_mode=.*/network_mode="tproxy"/' ${settings} - # end - sed -i 's/auto-route:.*/auto-route: false/' ${data_dir}/template.yml - sed -i 's/auto-detect-interface:.*/auto-detect-interface: false/' ${data_dir}/template.yml + awk -v new_val="mixed" '/network_mode/ {$0 = "network_mode=\"" new_val "\""} 1' ${settings} > ${data_dir}/tmp && mv ${data_dir}/tmp ${settings} fi - temporary_config_file - if (${bin_path} -t -d ${data_dir}/${bin_name} -f ${data_dir}/run/config.yaml > "${run_path}/${bin_name}-report.log") ; then - nohup setuidgid 0:3005 ${bin_path} -d ${data_dir}/${bin_name} -f ${data_dir}/run/config.yaml > "${run_path}/${bin_name}.log" 2>&1 & - echo -n $! > ${pid_file} + if ${bin_path} -t -d "${data_dir}/${bin_name}" -f "${clash_config}" > "${run_path}/${bin_name}-report.log" 2>&1; then + ulimit -SHn 65535 + nohup setuidgid 0:3005 ${bin_path} -d "${data_dir}/${bin_name}" -f "${clash_config}" > "${run_path}/${bin_name}.log" 2>&1 & + echo -n $! > "${pid_file}" else - mv ${data_dir}/run/config.yaml ${clash_config} log error "configuration failed, please check the ${run_path}/${bin_name}-report.log file." exit 1 fi ;; + xray) - sed -i 's/network_mode=.*/network_mode="tproxy"/' ${settings} - if [ ! -f ${data_dir}/${bin_name}/*.json ] ; then - log error "file ${data_dir}/xray/*.json no found" + default_tp + 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 + 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 + ulimit -SHn 65535 nohup setuidgid 0:3005 ${bin_path} > "${run_path}/${bin_name}.log" 2>&1 & - echo -n $! > ${pid_file} + echo -n $! > "${pid_file}" else - log error "configuration failed, please check the ${run_path}/${bin_name}-report.log file." + log error "configuration failed, please check the ${run_path}/${bin_name}-report.log file." exit 1 fi ;; + v2fly) - sed -i 's/network_mode=.*/network_mode="tproxy"/' ${settings} - if [ ! -f ${data_dir}/${bin_name}/*.json ] ; then - log error "file ${data_dir}/v2fly/*.json no found" + default_tp + if [ ! -f "${data_dir}/${bin_name}"/*.json ]; then + log error "file ${data_dir}/v2ray/*.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 + ulimit -SHn 65535 nohup setuidgid 0:3005 ${bin_path} run > "${run_path}/${bin_name}.log" 2>&1 & echo -n $! > ${pid_file} else @@ -232,83 +252,221 @@ run_box() { } cgroup_limit() { - [ "${cgroup_memory}" = "true" ] && (${scripts_dir}/box.tool cgroup && log info "cgroup limit: ${cgroup_memory_limit}.") || log info "${bin_name} cgroup: disable" +if [ "${cgroup_memory}" = "true" ]; then + if ${scripts_dir}/box.tool cgroup; then + log info "cgroup limit: ${cgroup_memory_limit}." + else + log error "Failed to enable cgroup for ${bin_name}." + fi +else + log info "${bin_name} cgroup: disabled." +fi } +# Function to display the usage of a binary bin_usage() { - rss=$(grep VmRSS /proc/$(pidof ${bin_name})/status | awk -F':' '{print $2}' | awk '{print $1}') - [ ${rss} -ge 1024 ] && bin_rss="$(expr ${rss} / 1024)Mb" || bin_rss="${rss}Kb" - swap=$(grep VmSwap /proc/$(pidof ${bin_name})/status | awk -F':' '{print $2}' | awk '{print $1}') - [ ${swap} -ge 1024 ] && bin_swap="$(expr ${swap} / 1024)Mb" || bin_swap="${swap}Kb" - state=$(grep State /proc/$(pidof ${bin_name})/status | awk -F':' '{print $2}' | awk '{print $2}') + # Get the process ID of the binary + bin_pid=$(pidof ${bin_name}) - if bin_pid=$(pidof ${bin_name}) ; then - log info "${bin_name} has started with the $(stat -c %U:%G /proc/${bin_pid}) user group." - log info "${bin_name} status: ${state}, PID: (${bin_pid})" - log info "${bin_name} memory usage: ${bin_rss}, swap: ${bin_swap}" - log info "${bin_name} cpu usage: $((/system/bin/ps -p $(pidof ${bin_name}) -o pcpu | grep -v %CPU | awk '{print $1}') 2> /dev/null)%" - log info "${bin_name} running time: $(/system/bin/ps -p $(pidof ${bin_name}) -o comm,etime | grep ${bin_name} | awk '{print $2}')" - echo -n ${bin_pid} > ${pid_file} + if [ -z "${bin_pid}" ]; then + log error "${bin_name} is not running" + return fi + + # Get the memory usage of the binary + rss=$(grep VmRSS /proc/${bin_pid}/status | awk '{print $2}') + [ "${rss}" -ge 1024 ] && bin_rss="$(expr ${rss} / 1024) MB" || bin_rss="${rss} KB" + swap=$(grep VmSwap /proc/${bin_pid}/status | 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 | awk '{print $2}') + + # 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} memory usage: ${bin_rss}, swap: ${bin_swap}" + + # Get the CPU usage of the binary + cpu=$(/system/bin/ps -p ${bin_pid} -o pcpu | awk 'NR==2{print $1}' 2> /dev/null) + if [ -n "${cpu}" ]; then + log info "${bin_name} cpu usage: ${cpu}%" + else + log info "${bin_name} cpu usage: not available" + fi + + # Get the running time of the binary + running_time=$(/system/bin/ps -p ${bin_pid} -o etime | awk 'NR==2{print $1}' 2> /dev/null) + if [ -n "${running_time}" ]; then + log info "${bin_name} running time: ${running_time} seconds" + else + log info "${bin_name} running time: not available" + fi + + # Save the process ID to the pid file + echo -n ${bin_pid} > ${pid_file} } display_bin_pid() { - if bin_pid=$(pidof ${bin_name}) ; then + # Mengecek apakah bin_name sudah didefinisikan + if [ -z "${bin_name}" ]; then + log error "bin_name: ${bin_name} not defined" + return 1 + fi + + # Mencari PID dari bin_name + bin_pid=$(pidof "${bin_name}") + + # Mengecek apakah bin_name sedang berjalan + if [ -n "${bin_pid}" ]; then + # Jika iya, mencetak pesan dan memanggil fungsi bin_usage + log info "${bin_name} service is running. (PID: ${bin_pid})." bin_usage - log info "${bin_name} service is running. (PID: $(pidof ${bin_name}))." else - log warn "${bin_name} service is stopped." && return 1 + # Jika tidak, mencetak pesan dan mengembalikan status 1 + log warn "${bin_name} service is stopped." + return 1 fi } crontab_alive() { - nohup crond -c ${run_path} > /dev/null 2>&1 & - crontab -c ${run_path} -r - touch ${run_path}/root - chmod 0600 ${run_path}/root - [ "${static_dns1}" != "" ] && \ - echo "*/1 * * * * ${scripts_dir}/box.tool keepdns" >> ${run_path}/root && log info "dns remains open." - [ "${bin_name}" = "clash" ] && \ - log info "configuration ${clash_config}." + # Memulai crond dengan opsi "-c" dan menyimpannya di background + nohup crond -c "${run_path}" > /dev/null 2>&1 & + # Menghapus crontab sebelumnya dan membuat crontab baru + crontab -c "${run_path}" -r + touch "${run_path}/root" + chmod 0600 "${run_path}/root" + + # Menambahkan cron job untuk memanggil box.tool keepdns setiap menit + if [ "${intervaldns}" != "" ]; then + echo "${intervaldns} ${scripts_dir}/box.tool keepdns" >> "${run_path}/root" + log info "DNS remains open." + fi + + # Menampilkan pesan konfigurasi jika bin_name adalah "clash" + if [ "${bin_name}" = "clash" ]; then + log info "Configuration ${clash_config}." + fi + + # Menjalankan fungsi crontab_geo untuk menambahkan cron job berdasarkan lokasi geografis crontab_geo } -start_box() { - echo -n "" > ${logs_file} - [ -t 1 ] && echo "\033[1;31m$(date)\033[0m" || echo "$(date)" | tee -a ${logs_file} >> /dev/null 2>&1 - line="--------------------------------------------" - [ -t 1 ] && echo "\033[1;32m$line\033[0m" || echo "$line" | tee -a ${logs_file} >> /dev/null 2>&1 - - if bin_pid=$(pidof ${bin_name}) ; then - log info "${bin_name} service is still running, refresh iptables" - ${scripts_dir}/box.iptables renew - exit 1 +data_wifi() { + network_interface=$(ip route show | sed -n '1p' | awk '{print $3}') + # network_interface=$(ip route show | sed -n '2p' | awk '{print $3}') + data_info=$(ifconfig "${network_interface}" | grep "RX bytes") + # Retrieving data usage from data information + data_usage=$(echo "$data_info" | awk '/RX bytes/ {print $2}' | cut -d: -f2) + # Convert bytes to MB/KB + if (( $(echo "${data_usage} > 1024 * 1024 * 1024" | bc -l) )); then + # Convert to GB + data_usage_gb=$(echo "scale=2; ${data_usage} / 1024 / 1024 / 1024" | bc) + log debug "Data usage: ${data_usage_gb} GB" + elif (( $(echo "${data_usage} > 1024 * 1024" | bc -l) )); then + data_usage_mb=$(echo "scale=2; ${data_usage} / 1024 / 1024" | bc) + log debug "Data usage: ${data_usage_mb} MB" + else + data_usage_mb=$(echo "scale=2; ${data_usage} / 1024" | bc) + log debug "Data usage: ${data_usage_mb} KB" fi + + # Run dumpsys command to get wifi usage + # Retrieving wifi information using ifconfig + network_ap=$(ip route show | sed -n '3p' | awk '{print $3}') + wifi_info=$(ifconfig "${network_ap}" | grep "RX bytes") + # Retrieve data usage from wifi information + wifi_usage=$(echo "$wifi_info" | awk '/RX bytes/ {print $2}' | cut -d: -f2) + # Konversi byte menjadi MB / KB + if (( $(echo "${wifi_usage} > 1024 * 1024 * 1024" | bc -l) )); then + # Convert to GB + wifi_usage_gb=$(echo "scale=2; ${wifi_usage} / 1024 / 1024 / 1024" | bc) + log debug "WiFi usage: ${wifi_usage_gb} GB" + elif (( $(echo "${wifi_usage} > 1024 * 1024" | bc -l) )); then + wifi_usage_mb=$(echo "scale=2; ${wifi_usage} / 1024 / 1024" | bc) + log debug "WiFi usage: ${wifi_usage_mb} MB" + else + wifi_usage_mb=$(echo "scale=2; ${wifi_usage} / 1024" | bc) + log debug "WiFi usage: ${wifi_usage_mb} KB" + fi +} + +start_box() { + # Mengosongkan file log dan menambahkan timestamp dan garis pembatas + echo -n "" > "${logs_file}" + # Then use the chmod command to set file permissions to 755 + if [ -t 1 ]; then + echo -e "\033[1;31m$(date)\033[0m" + echo -e "\033[1;32m--------------------------------------------\033[0m" + else + echo "$(date)" | tee -a "${logs_file}" > /dev/null 2>&1 + echo "--------------------------------------------" | tee -a "${logs_file}" > /dev/null 2>&1 + fi + + # Memperbarui iptables jika bin_name masih berjalan + if bin_pid=$(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" + exit 1 + else + log error "failed to refresh iptables" + exit 1 + fi + else + log info "Good day" + fi + + # Memeriksa izin, memeriksa keberadaan bin, menghapus log lama, membuat TUN, menjalankan box, dan menunggu selama 1 detik check_permission check_in_bin delete_logs - create_tun + if [ "${network_mode}" = "mixed" ] || [ "${proxy_mode}" = "tun" ]; then + create_tun + fi run_box && sleep 1 - [ "${crontab_sec}" != "false" ] && \ - crontab_alive || log info "crontab: disable." + # Menjalankan crontab_alive jika crontab_sec tidak sama dengan "false" + if [ "${crontab_sec}" != "false" ]; then + crontab_alive + else + log info "crontab: disabled." + fi + + # Menjalankan cgroup_limit, menunggu selama 1 detik, mendeteksi port yang digunakan, menunggu selama 1 detik, dan menampilkan PID bin cgroup_limit - detected_port || sleep 1 + sleep 1 + detected_port + sleep 1 still_alive display_bin_pid + data_wifi } stop_box() { - cronkill=$(/system/bin/ps -ef | grep root | grep "crond -c /data/adb/box/" | awk '{ print $2 }' | sort -u) - for cron in ${cronkill[*]} ; do - kill -9 ${cron} + # Menggunakan perintah `pgrep` untuk mencari PID cronjob + cronkill=$(pgrep -f "crond -c ${run_path}") + for cron in ${cronkill[@]}; do + kill -15 ${cron} done - for list in ${bin_list[*]} ; do - kill -9 $(pidof ${list}) || killall -9 ${list} + + # Menggunakan loop untuk membunuh setiap binary + for bin in ${bin_list[@]}; do + # Menggunakan `pkill` untuk membunuh binary + kill -9 "$(pidof ${bin})" || killall -9 "${bin}" done + sleep 0.5 - if ! [ $(pidof ${bin_name}) ] ; then - find ${run_path} -type f -name "box.pid" | xargs rm -f - sleep 0.5 + + # Mengecek apakah binary sudah terhenti + if ! pidof ${bin_name} >/dev/null 2>&1; then + # Menghapus file `box.pid` jika ada + if [ -f ${run_path}/box.pid ]; then + rm ${run_path}/box.pid + sleep 0.5 + fi display_bin_pid || log warn "${bin_name} disconnected." else log error "failed to stop ${bin_name}" @@ -324,29 +482,22 @@ case "$1" in stop_box ;; restart) - stop_box && sleep 1 - start_box && (${scripts_dir}/box.iptables renew) + stop_box + sleep 1 + start_box + ${scripts_dir}/box.iptables renew ;; usage) + data_wifi case "${bin_name}" in - clash)echo -e "$(${bin_path} -v)";; - *)echo -e "$(${bin_path} version)";; + clash) log debug "$(${bin_path} -v)";; + *) log debug "$(${bin_path} version)";; esac [ $(pidof ${bin_name}) ] && \ bin_usage || log warn "${bin_name} service is stopped" ;; - reload) - if [ "${bin_name}" = "clash" ] ; then - temporary_config_file - log info "Open yacd-meta/configs" - log info "klik reload configs" - else - log info "only for Clash" - fi - (${bin_path} -t -d ${data_dir}/clash -f ${data_dir}/run/config.yaml > "${run_path}/${bin_name}-report.log") && \ - log info "config.yaml passed" || log info "config.yaml ceks failed" - ;; *) - echo "$0: usage: $0 {start|testing|stop|restart|usage|reload}" + echo "$0: usage: $0 {start|stop|restart|usage}" ;; esac + \ No newline at end of file diff --git a/scripts/src/box.tool b/scripts/src/box.tool index 117407f..84c9eae 100755 --- a/scripts/src/box.tool +++ b/scripts/src/box.tool @@ -6,233 +6,283 @@ source /data/adb/box/settings.ini user_agent="${bin_name}" +# membuat log pada terminal logs() { export TZ=Asia/Jakarta - now=$(date +"%I.%M %p %z") - case $1 in - info)[ -t 1 ] && echo -n "\033[1;34m${now} [info]: $2\033[0m" || echo -n "${now} [info]: $2" | tee -a ${logs_file} >> /dev/null 2>&1;; - port)[ -t 1 ] && echo -n "\033[1;33m$2 \033[0m" || echo -n "$2 " | tee -a ${logs_file} >> /dev/null 2>&1;; - - testing)[ -t 1 ] && echo -n "\033[1;34m$2\033[0m" || echo -n "$2" | tee -a ${logs_file} >> /dev/null 2>&1;; - succes)[ -t 1 ] && echo -n "\033[1;32m$2 \033[0m" || echo -n "$2 " | tee -a ${logs_file} >> /dev/null 2>&1;; - failed)[ -t 1 ] && echo -n "\033[1;31m$2 \033[0m" || echo -n "$2 " | tee -a ${logs_file} >> /dev/null 2>&1;; - - *)[ -t 1 ] && echo -n "\033[1;35m${now} [$1]: $2\033[0m" || echo -n "${now} [$1]: $2" | tee -a ${logs_file} >> /dev/null 2>&1;; - esac + now=$(date +"%I.%M %p %Z") + 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 } -testing () { +# Memeriksa koneksi internet dengan mlbox +testing() { 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 - local ntpip=${network} - break + 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 - if [ -n "${ntpip}" ] ; then - logs succes "done" + if [ -n "${ntpip}" ]; then + logs success "done" - logs testing "http=" - httpIP=$(${data_dir}/bin/mlbox -timeout=5 -http="http://182.254.116.116/d?dn=reddit.com&clientip=1" 2>&1 | grep -Ev 'timeout|httpGetResponse' | grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}') - if [ -n "${httpIP}" ] ; then - httpIP="${httpIP#*\|}" - logs succes "done" - else - logs failed "failed" - fi - - logs testing "https=" - 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}') - [ -n "${httpsResp}" ] && logs succes "done" || logs failed "failed" - - logs testing "udp=" - currentTime=$(${data_dir}/bin/mlbox -timeout=7 -ntp="${ntpip}" | grep -v 'timeout') - echo "${currentTime}" | grep -qi 'LI:' && \ - logs succes "done" || logs failed "failed" + logs testing "http=" + httpIP=$(${data_dir}/bin/mlbox -timeout=5 -http="http://182.254.116.116/d?dn=reddit.com&clientip=1" 2>&1 | grep -Ev 'timeout|httpGetResponse' | grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}') + if [ -n "${httpIP}" ]; then + httpIP="${httpIP#*\|}" + logs success "done" + else + logs failed "failed" + fi + logs testing "https=" + 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}') + [ -n "${httpsResp}" ] && logs success "done" || logs failed "failed" + + 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" else - logs failed "failed" - fi + logs failed "failed" + fi - [ -t 1 ] && echo "\033[1;31m""\033[0m" || echo "" | tee -a ${logs_file} >> /dev/null 2>&1 + [ -t 1 ] && echo -e "\033[1;31m\033[0m" || echo "" | tee -a ${logs_file} >> /dev/null 2>&1 } +# Memeriksa koneksi internet dengan mlbox network_check() { - if [ -f ${data_dir}/bin/mlbox ] ; then - logs info "check internet connection... " - 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 [ -n "${httpsResp}" ] ; then - logs succes "done" - else - logs failed "failed" - flags=false - fi + if [ -f "${data_dir}/bin/mlbox" ]; then + logs info "Checking internet connection... " + 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 [ -n "${httpsResp}" ]; then + logs success "done" + else + logs failed "failed" + flags=false + fi + fi + if [ -t 1 ]; then + echo "\033[1;31m""\033[0m" + else + echo "" | tee -a ${logs_file} >> /dev/null 2>&1 fi - [ -t 1 ] && echo "\033[1;31m""\033[0m" || echo "" | tee -a ${logs_file} >> /dev/null 2>&1 [ "${flags}" != "false" ] || exit 1 } +# Memeriksa apakah suatu binary berjalan dengan mengecek file pid dan cmdline probe_bin_alive() { - [ -f ${pid_file} ] && cmd_file="/proc/$(pidof ${bin_name})/cmdline" || return 1 - [ -f ${cmd_file} ] && grep -q ${bin_name} ${cmd_file} && return 0 || return 1 -} - -restart_box() { - ${scripts_dir}/box.service stop - sleep 0.5 - ${scripts_dir}/box.service start - if probe_bin_alive ; then - ${scripts_dir}/box.iptables renew - log debug "$(date) ${bin_name} restart" + if [ -f "${pid_file}" ]; then + cmd_file="/proc/$(pidof "${bin_name}")/cmdline" + if [ -f "${cmd_file}" ] && grep -q "${bin_name}" "${cmd_file}"; then + return 0 # binary is alive + else + return 1 # binary is not alive + fi else - log error "${bin_name} failed to restart." + return 1 # pid file not found, binary is not alive fi } +# Restart binary, setelah dihentikan dan dijalankan kembali +restart_box() { + ${scripts_dir}/box.service restart + sleep 0.5 + if probe_bin_alive ; then + # ${scripts_dir}/box.iptables renew + log debug "$(date) ${bin_name} restarted successfully." + else + log error "Failed to restart ${bin_name}." + fi +} + +# Set DNS secara manual, mengubah net.ipv4.ip_forward dan net.ipv6.conf.all.forwarding menjadi 1 keep_dns() { local_dns1=$(getprop net.dns1) local_dns2=$(getprop net.dns2) - if [ "${local_dns1}" != "${static_dns1}" ] ; then - # for count in $(seq 1 $(getprop | grep dns | wc -l)); do - setprop net.dns1 ${static_dns1} - setprop net.dns2 ${static_dns2} - # done + if [ "${local_dns1}" != "${static_dns1}" ] || [ "${local_dns2}" != "${static_dns2}" ]; then + setprop net.dns1 "${static_dns1}" + setprop net.dns2 "${static_dns2}" + fi + if [ "$(sysctl net.ipv4.ip_forward)" != "1" ]; then + sysctl -w net.ipv4.ip_forward=1 > /dev/null + fi + if [ "$(sysctl net.ipv6.conf.all.forwarding)" != "1" ]; then + sysctl -w net.ipv6.conf.all.forwarding=1 > /dev/null fi - [ "$(sysctl net.ipv4.ip_forward)" != "1" ] && sysctl -w net.ipv4.ip_forward=1 - [ "$(sysctl net.ipv6.conf.all.forwarding)" != "1" ] && sysctl -w net.ipv6.conf.all.forwarding=1 - unset local_dns1 unset local_dns2 } +# Memperbarui file dari URL update_file() { - file="$1" - file_bak="${file}.bak" - update_url="$2" - [ -f ${file} ] \ - && mv -f ${file} ${file_bak} - request="wget" - request+=" --no-check-certificate" - request+=" --user-agent ${user_agent}" - request+=" -O ${file}" - request+=" ${update_url}" - echo ${request} - ${request} 2>&1 - sleep 0.5 - if [ -f "${file}" ] ; then - return 0 - else - [ -f "${file_bak}" ] && mv ${file_bak} ${file} + local file="$1" + local update_url="$2" + local file_bak="${file}.bak" + + if [ -f "${file}" ]; then + mv "${file}" "${file_bak}" || return 1 fi + + local request="wget" + local request+=" --no-check-certificate" + local request+=" --user-agent ${user_agent}" + local request+=" -O ${file}" + local request+=" ${update_url}" + + echo ${request} + ${request} >&2 || { + if [ -f "${file_bak}" ]; then + mv "${file_bak}" "${file}" || true + fi + return 1 + } + + return 0 } +# Memeriksa dan memperbarui geoip dan geosite update_subgeo() { log info "daily updates" network_check + case "${bin_name}" in clash) - if [ "${meta}" = "false" ] ; then - geoip_file="${data_dir}/clash/Country.mmdb" - geoip_url="https://github.com/Loyalsoldier/geoip/raw/release/Country-only-cn-private.mmdb" - else - geoip_file="${data_dir}/clash/GeoIP.dat" - geoip_url="https://github.com/v2fly/geoip/raw/release/geoip-only-cn-private.dat" - fi + geoip_file="${data_dir}/clash/$(if [ "${meta}" = "false" ]; then echo "Country.mmdb"; else echo "GeoIP.dat"; fi)" + geoip_url="https://github.com/$(if [ "${meta}" = "false" ]; then echo "Loyalsoldier/geoip/raw/release/Country-only-cn-private.mmdb"; else echo "v2fly/geoip/raw/release/geoip-only-cn-private.dat"; fi)" + geosite_file="${data_dir}/clash/GeoSite.dat" geosite_url="https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" - ;; + ;; sing-box) geoip_file="${data_dir}/sing-box/geoip.db" geoip_url="https://github.com/SagerNet/sing-geoip/releases/download/20221012/geoip-cn.db" geosite_file="${data_dir}/sing-box/geosite.db" geosite_url="https://github.com/CHIZI-0618/v2ray-rules-dat/raw/release/geosite.db" - ;; + ;; *) geoip_file="${data_dir}/${bin_name}/geoip.dat" geoip_url="https://github.com/v2fly/geoip/raw/release/geoip-only-cn-private.dat" geosite_file="${data_dir}/${bin_name}/geosite.dat" geosite_url="https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" - ;; + ;; esac - if [ "${auto_updategeox}" = "true" ] ; then - if log debug "download ${geoip_url}" && update_file ${geoip_file} ${geoip_url} && log debug "download ${geosite_url}" && update_file ${geosite_file} ${geosite_url} ; then - log debug "Update geo $(date +"%Y-%m-%d %I.%M %p")" - flag=false - fi + 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")" + flag=false fi - if [ "${bin_name}" = "clash" ] ; then - if [ "${auto_updatesubcript}" = "true" ] ; then - log debug "download ${clash_config}" - if update_file ${clash_config} ${subcript_url} ; then - flag=true - fi - fi + + if [ "${bin_name}" = "clash" ] && [ "${auto_update_subscription}" = "true" ] && update_file "${clash_config}" "${subscription_url}"; then + flag=true + log debug "Downloading ${clash_config}" fi - if [ -f "${pid_file}" ] && [ "${flag}" = "true" ] ; then + + if [ -f "${pid_file}" ] && [ "${flag}" = "true" ]; then restart_box fi } +# Function for detecting ports used by a process port_detection() { - match_count=0 - if (ss -h > /dev/null 2>&1) ; then - port=$(ss -antup | grep "${bin_name}" | awk '$7~/'pid=$(pidof ${bin_name})*'/{print $5}' | awk -F ':' '{print $2}' | sort -u) + # Use 'command' function to check if 'ss' is available + if command -v ss > /dev/null ; then + # Use 'awk' with a regular expression to match the process ID + ports=$(ss -antup | awk -v pid="$(pidof "${bin_name}")" '$7 ~ pid {print $5}' | awk -F ':' '{print $2}' | sort -u) else - log warn "skip port detected" - exit 0 + # Log a warning message if 'ss' is not available + log debug "Warning: 'ss' command not found, skipping port detection." >&2 + return fi - logs debug "${bin_name} port detected: " - for sub_port in ${port[*]} ; do - sleep 0.5 - logs port "${sub_port}" - done - [ -t 1 ] && echo "\033[1;31m""\033[0m" || echo "" | tee -a ${logs_file} >> /dev/null 2>&1 + # 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 + if [ -t 1 ]; then + echo -e "\033[1;31m""\033[0m" + else + echo "" >> "${logs_file}" 2>&1 + fi } +# kill bin kill_alive() { - for list in ${bin_list[*]} ; do - kill -9 $(pidof ${list}) || killall -9 ${list} + for list in "${bin_list[@]}" ; do + if pgrep "$list" >/dev/null ; then + kill -9 $(pgrep "$list") >/dev/null 2>&1 || killall -9 "$list" >/dev/null 2>&1 + fi done } update_kernel() { + # su -c /data/adb/box/scripts/box.tool upcore network_check - if [ $(uname -m) = "aarch64" ] ; then - arch="arm64" - platform="android" - else - arch="armv7" - platform="linux" - fi - local file_kernel="${bin_name}-${arch}" + case $(uname -m) in + "aarch64") arch="arm64"; platform="android" ;; + "armv7l") arch="armv7"; platform="linux" ;; + "i686") arch="386"; platform="linux" ;; + "x86_64") arch="amd64"; platform="linux" ;; + *) log warn "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; + esac +# Lakukan hal lainnya di bawah ini + file_kernel="${bin_name}-${arch}" case "${bin_name}" in sing-box) - local sing_box_version_temp=$(wget --no-check-certificate -qO- "https://api.github.com/repos/SagerNet/sing-box/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') - local sing_box_version=${sing_box_version_temp:1} - download_link="https://github.com/SagerNet/sing-box/releases/download/${sing_box_version_temp}/sing-box-${sing_box_version}-${platform}-${arch}.tar.gz" + url_api="https://api.github.com/repos/SagerNet/sing-box/releases/latest" + url_down="https://github.com/SagerNet/sing-box/releases" + sing_box_version_temp=$(wget --no-check-certificate -qO- "${url_api}" | grep '"tag_name":' | cut -d'"' -f4) + sing_box_version=${sing_box_version_temp#v} + download_link="${url_down}/download/${sing_box_version_temp}/sing-box-${sing_box_version}-${platform}-${arch}.tar.gz" log debug "download ${download_link}" update_file "${data_dir}/${file_kernel}.tar.gz" "${download_link}" - [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 + # [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 ;; clash) - if [ "${meta}" = "true" ] ; then - tag="Prerelease-Alpha" - tag_name="alpha-[0-9,a-z]+" + # set meta and dev flags + meta=true + dev=true + # if meta flag is true, download clash.meta + if [ "${meta}" = "true" ]; then + # set download link and get the latest version download_link="https://github.com/taamarin/Clash.Meta/releases" - local latest_version=$(wget --no-check-certificate -qO- "${download_link}/expanded_assets/${tag}" | grep -oE "${tag_name}" | head -1) - filename="clash.meta" - filename+="-${platform}" - filename+="-${arch}" - filename+="-cgo" + tag=$(wget --no-check-certificate -qO- ${download_link} | grep -oE 'tag\/([^"]+)' | cut -d '/' -f 2 | head -1) + latest_version=$(wget --no-check-certificate -qO- "${download_link}/expanded_assets/${tag}" | grep -oE "alpha-[0-9,a-z]+" | head -1) + # set the filename based on platform and architecture + filename="clash.meta-${platform}-${arch}" + [ $(uname -m) != "aarch64" ] || filename+="-cgo" filename+="-${latest_version}" + # download and update the file log debug "download ${download_link}/download/${tag}/${filename}.gz" update_file "${data_dir}/${file_kernel}.gz" "${download_link}/download/${tag}/${filename}.gz" + # if meta flag is false, download clash premium/dev else - if [ "${dev}" != "false" ] ; then + # if dev flag is true, download latest dev version + if [ "${dev}" != "false" ]; then download_link="https://release.dreamacro.workers.dev/latest" log debug "download ${download_link}/clash-linux-${arch}-latest.gz" update_file "${data_dir}/${file_kernel}.gz" "${download_link}/clash-linux-${arch}-latest.gz" + # if dev flag is false, download latest premium version else download_link="https://github.com/Dreamacro/clash/releases" filename=$(wget --no-check-certificate -qO- "${download_link}/expanded_assets/premium" | grep -oE "clash-linux-${arch}-[0-9]+.[0-9]+.[0-9]+" | head -1) @@ -240,31 +290,42 @@ update_kernel() { update_file "${data_dir}/${file_kernel}.gz" "${download_link}/download/premium/${filename}.gz" fi fi - [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 + # if the update_file command was successful, kill the alive process + # [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 ;; xray) + # set download link and get the latest version + latest_version=$(wget --no-check-certificate -qO- https://api.github.com/repos/XTLS/Xray-core/releases | 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") download_file="Xray-linux-arm32-v7a.zip" ;; + "aarch64") download_file="Xray-android-arm64-v8a.zip" ;; + *) log error "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; + esac + # Lakukan hal lainnya di bawah ini download_link="https://github.com/XTLS/Xray-core/releases" - github_api="https://api.github.com/repos/XTLS/Xray-core/releases" - local latest_version=$(wget --no-check-certificate -qO- ${github_api} | grep "tag_name" | grep -o "v[0-9.]*" | head -1) - - [ $(uname -m) != "aarch64" ] \ - && download_file="Xray-linux-arm32-v7a.zip" || download_file="Xray-android-arm64-v8a.zip" - - log debug "download ${download_link}/download/${latest_version}/${download_file}" + log debug "Downloading ${download_link}/download/${latest_version}/${download_file}" update_file "${data_dir}/${file_kernel}.zip" "${download_link}/download/${latest_version}/${download_file}" - [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 + # 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=$(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") 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 + # Lakukan hal lainnya di bawah ini download_link="https://github.com/v2fly/v2ray-core/releases" - github_api="https://api.github.com/repos/v2fly/v2ray-core/releases" - local latest_version=$(wget --no-check-certificate -qO- ${github_api} | grep "tag_name" | grep -o "v[0-9.]*" | head -1) - - [ $(uname -m) != "aarch64" ] \ - && download_file="v2ray-linux-arm32-v7a.zip" || download_file="v2ray-android-arm64-v8a.zip" - - log debug "download ${download_link}/download/${latest_version}/${download_file}" + log debug "Downloading ${download_link}/download/${latest_version}/${download_file}" update_file "${data_dir}/${file_kernel}.zip" "${download_link}/download/${latest_version}/${download_file}" - [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 + # if the update_file command was successful, kill the alive process + # [ "$?" = "0" ] && kill_alive > /dev/null 2>&1 ;; *) log error "kernel error." && exit 1 @@ -273,132 +334,210 @@ update_kernel() { case "${bin_name}" in clash) - [ -f /system/bin/gunzip ] \ - && local extra="/system/bin/gunzip" || local extra="${busybox_path} gunzip" - if (${extra} "${data_dir}/${file_kernel}.gz" >&2) ; then - mv -f "${data_dir}/${file_kernel}" "${bin_kernel}/${bin_name}" \ - && flag="true" || log error "failed to move the kernel" - [ -f "${pid_file}" ] && [ "${flag}" = "true" ] \ - && restart_box || log debug "${bin_name} does not restart" + gunzip_command=$(command -v gunzip >/dev/null 2>&1 && echo "gunzip" || echo "${busybox_path} 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" else - log warn "failed extra file ${data_dir}/${file_kernel}.gz" + log error "Failed to extract or move the kernel" fi ;; sing-box) - [ -f /system/bin/tar ] \ - && local extra="/system/bin/tar" || local extra="${busybox_path} tar" - if (${extra} -xf "${data_dir}/${file_kernel}.tar.gz" -C ${data_dir}/bin >&2) ; then - 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}" \ - && flag="true" || log error "failed to move the kernel" - [ -f "${pid_file}" ] && [ "${flag}" = "true" ] \ - && restart_box || log debug "${bin_name} does not restart" + tar_command=$(command -v tar >/dev/null 2>&1 && echo "tar" || echo "${busybox_path} 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" else - log warn "failed extra file ${data_dir}/${file_kernel}.gz" + log warn "failed to extract ${data_dir}/${file_kernel}.tar.gz" && flag="false" fi ;; v2fly) - [ -f /system/bin/unzip ] \ - && local extra="/system/bin/unzip" || local extra="${busybox_path} unzip" - if (${extra} -o "${data_dir}/${file_kernel}.zip" "v2ray" -d ${bin_kernel} >&2) ; then - mv "${bin_kernel}/v2ray" "${bin_kernel}/v2fly" \ - && flag="true" || log error "failed to move the kernel" - [ -f "${pid_file}" ] && [ "${flag}" = "true" ] \ - && restart_box || log debug "${bin_name} does not restart" + unzip_command=$(command -v unzip >/dev/null 2>&1 && echo "unzip" || echo "${busybox_path} unzip") + if ${unzip_command} -o "${data_dir}/${file_kernel}.zip" "v2ray" -d "${bin_kernel}" >&2; then + if mv "${bin_kernel}/v2ray" "${bin_kernel}/v2fly"; then + [ -f "${pid_file}" ] && restart_box || log debug "${bin_name} does not need to be restarted" + else + log error "failed to move the kernel" + fi else - log warn "failed extra file ${data_dir}/${file_kernel}.gz" + log warn "failed to extract ${data_dir}/${file_kernel}.zip" fi ;; - xray) - [ -f /system/bin/unzip ] \ - && local extra="/system/bin/unzip" || local extra="${busybox_path} unzip" - if (${extra} -o "${data_dir}/${file_kernel}.zip" "xray" -d ${bin_kernel} >&2) ; then - mv "${bin_kernel}/xray" "${bin_kernel}/xray" \ - && flag="true" || log error "failed to move the kernel" - [ -f "${pid_file}" ] && [ "${flag}" = "true" ] \ - && restart_box || log debug "${bin_name} does not restart" + xray) + unzip_command=$(command -v unzip >/dev/null 2>&1 && echo "unzip" || echo "${busybox_path} unzip") + if ${unzip_command} -o "${data_dir}/${file_kernel}.zip" "xray" -d "${bin_kernel}" >&2; then + if mv "${bin_kernel}/xray" "${bin_kernel}/xray"; then + [ -f "${pid_file}" ] && restart_box || log debug "${bin_name} does not need to be restarted" + else + log error "failed to move the kernel" + fi else - log warn "failed extra file ${data_dir}/${file_kernel}.gz" + log warn "failed to extract ${data_dir}/${file_kernel}.zip" fi ;; *) log error "kernel error." && exit 1 ;; esac + + find "${data_dir}" -type f -name "${file_kernel}.*" -delete + chown ${box_user_group} ${bin_path} + chmod 6755 ${bin_path} } +# Function to limit cgroup memory cgroup_limit() { - [ "${cgroup_memory_limit}" = "" ] && return - [ "${cgroup_memory_path}" = "" ] \ - && cgroup_memory_path=$(mount | grep cgroup | awk '/memory/{print $3}' | head -1) + # Check if cgroup_memory_limit is set + 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 + if [ -z "${cgroup_memory_path}" ]; then + local cgroup_memory_path=$(mount | grep cgroup | awk '/memory/{print $3}' | head -1) + if [ -z "${cgroup_memory_path}" ]; then + log warn "cgroup_memory_path is not set and cannot 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 + if [ -z "${pid_file}" ]; then + log warn "pid_file is not set" + return 1 + elif [ ! -f "${pid_file}" ]; then + log warn "${pid_file} does not exist" + return 1 + fi + + # Create cgroup directory and move process to cgroup + local bin_name=$(basename "$0") mkdir -p "${cgroup_memory_path}/${bin_name}" - echo $(cat ${pid_file}) > "${cgroup_memory_path}/${bin_name}/cgroup.procs" \ - && log info "${cgroup_memory_path}/${bin_name}/cgroup.procs" + 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 echo "${cgroup_memory_limit}" > "${cgroup_memory_path}/${bin_name}/memory.limit_in_bytes" \ - && log info "${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() { network_check - file_dasboard="${data_dir}/dashboard.zip" - rm -rf ${data_dir}/dashboard/dist - #url="https://github.com/haishanh/yacd/archive/refs/heads/gh-pages.zip" - url="https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip" - dir_name="Yacd-meta-gh-pages" - wget --no-check-certificate "${url}" -O ${file_dasboard} 2>&1 - unzip -o "${file_dasboard}" "${dir_name}/*" -d "${data_dir}/dashboard" >&2 - mv -f ${data_dir}/dashboard/"${dir_name}" "${data_dir}/dashboard/dist" - rm -rf ${file_dasboard} + 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" + wget --no-check-certificate "${url}" -O "${file_dashboard}" 2>&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}" + else + log debug "${bin_name} does not support dashboards" + fi } run_base64() { - if [ "$(cat ${data_dir}/sing-box/acc.txt 2>&1)" != "" ] ; then - log info "$(cat ${data_dir}/sing-box/acc.txt 2>&1)" - base64 ${data_dir}/sing-box/acc.txt > ${data_dir}/dashboard/dist/proxy.txt - log info "ceks ${data_dir}/dashboard/dist/proxy.txt" - log info "done" + acc_file="${data_dir}/sing-box/acc.txt" + proxy_file="${data_dir}/dashboard/dist/proxy.txt" + + if [ -s "$acc_file" ]; then + log info "$(cat "$acc_file" 2>&1)" + base64 "${acc_file}" > "${proxy_file}" + log info "Generated ${proxy_file}" + log info "Done" else - log warn "${data_dir}/sing-box/acc.txt is empty" + log warn "${acc_file} is empty or does not exist" exit 1 fi } -cp_bin () { - ( cp /data/adb/box/bin/* /data/adb/modules/box_for_magisk/system/bin ) && log debug "file copy done" +# copy bin ke system/bin +cp_bin() { + if cp /data/adb/box/bin/* /data/adb/modules/box_for_magisk/system/bin/; then + log debug "File copy completed successfully." + else + log debug "File copy failed." >&2 + exit 1 + fi +} + +reload() { + case "${bin_name}" in + sing-box) + if ${bin_path} check -D "${data_dir}/${bin_name}" > "${run_path}/${bin_name}-report.log" 2>&1; then + log info "config.json passed" + log info "Open yacd-meta/configs and click 'Reload Configs'" + else + log error "config.json check failed" + cat "${run_path}/${bin_name}-report.log" >&2 + exit 1 + fi + ;; + clash) + if ${bin_path} -t -d "${data_dir}/clash" -f "${clash_config}" > "${run_path}/${bin_name}-report.log" 2>&1; then + log info "config.yaml passed" + log info "Open yacd-meta/configs and click 'Reload Configs'" + else + log error "config.yaml check failed" + cat "${run_path}/${bin_name}-report.log" >&2 + exit 1 + fi + ;; + *) + log error "Unknown binary: ${bin_name}" + exit 1 + ;; + esac } case "$1" in - subgeo) - update_subgeo - find ${data_dir}/${bin_name} -type f -name "*.db.bak" | xargs rm -f - find ${data_dir}/${bin_name} -type f -name "*.dat.bak" | xargs rm -f - ;; testing) testing ;; - port) - port_detection - ;; - cgroup) - cgroup_limit - ;; - upcore) - update_kernel - ;; - upyacd) - update_dashboard - ;; - rbase64) - run_base64 - ;; keepdns) keep_dns ;; connect) network_check ;; + rbase64) + run_base64 + ;; + upyacd) + update_dashboard + ;; + upcore) + update_kernel + ;; + cgroup) + cgroup_limit + ;; + port) + port_detection + ;; + subgeo) + update_subgeo + find "${data_dir}/${bin_name}" -type f -name "*.db.bak" -delete + find "${data_dir}/${bin_name}" -type f -name "*.dat.bak" -delete + ;; + reload) + reload + ;; + all) + for list in "${bin_list[@]}" ; do + bin_name="${list}" + update_kernel + update_subgeo + done + ;; *) - echo "$0: usage: $0 {connect|rbase64|upyacd|upcore|cgroup|port|subgeo}" + echo "$0: usage: $0 {reload|testing|keepdns|connect|rbase64|upyacd|upcore|cgroup|port|subgeo|all}" + exit 1 ;; esac \ No newline at end of file diff --git a/scripts/src/start.sh b/scripts/src/start.sh index 5254bbf..87c7c09 100755 --- a/scripts/src/start.sh +++ b/scripts/src/start.sh @@ -1,26 +1,28 @@ #!/system/bin/sh moddir="/data/adb/modules/box_for_magisk" -if [ -n "$(magisk -v | grep lite)" ] ; then - moddir=/data/adb/lite_modules/box_for_magisk +if [ -n "$(magisk -v | grep lite)" ]; then + moddir="/data/adb/lite_modules/box_for_magisk" fi scripts_dir="/data/adb/box/scripts" refresh_box() { - if [ -f /data/adb/box/run/box.pid ] ; then - ${scripts_dir}/box.service stop >> /dev/null 2>&1 - ${scripts_dir}/box.iptables disable >> /dev/null 2>&1 + if [ -f "/data/adb/box/run/box.pid" ]; then + "${scripts_dir}/box.service" stop >> "/dev/null" 2>&1 + "${scripts_dir}/box.iptables" disable >> "/dev/null" 2>&1 fi } 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 - inotifyd ${scripts_dir}/box.inotify ${moddir} >> /dev/null 2>&1 & + if [ ! -f "/data/adb/box/manual" ]; then + if [ ! -f "${moddir}/disable" ]; then + "${scripts_dir}/box.service" start >> "/dev/null" 2>&1 + fi + if [ -f "/data/adb/box/run/box.pid" ]; then + "${scripts_dir}/box.iptables" enable >> "/dev/null" 2>&1 + fi + inotifyd "${scripts_dir}/box.inotify" "${moddir}" >> "/dev/null" 2>&1 & # echo -n $! > /data/adb/box/run/inotifyd.pid fi } diff --git a/scripts/template.yml b/scripts/template.yml deleted file mode 100644 index 9259f21..0000000 --- a/scripts/template.yml +++ /dev/null @@ -1,145 +0,0 @@ -# port: 9494 -# socks-port: 9595 -# mixed-port: 9696 -redir-port: 9797 -tproxy-port: 9898 -mode: rule -allow-lan: true -unified-delay: true -bind-address: '*' -# info / warning / error / debug / silent -log-level: warning -ipv6: false -geodata-mode: true -geodata-loader: memconservative -external-controller: 0.0.0.0:9090 -external-controller-tls: 0.0.0.0:9091 # RESTful API HTTPS device -# secret: "123456" -external-ui: ../dashboard/dist -tcp-concurrent: false -inbound-tfo: true -# global-client-fingerprint: chrome -# interface-name: "" -# routing-mark: 233 -geox-url: - mmdb: "https://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb" - geoip: "https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat" - geosite: "https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat" -# - always, Diaktifkan untuk memaksa semua proses agar cocok -# - strict, Secara default, ini dinilai dari √clash apakah diaktifkan atau tidak -# - off, tidak cocok dengan prosesnya, disarankan untuk menggunakan mode ini di router -find-process-mode: strict # always, strict, off - -profile: - store-selected: true - store-fake-ip: false - -# experimental: - # sniff-tls-sni: false - # udp-fallback-match: false - # # fingerprint: "" - -sniffer: - enable: false - ## 对 redir-host 类型识别的流量进行强制嗅探 - ## 如:Tun、Redir 和 TProxy 并 DNS 为 redir-host 皆属于 - force-dns-mapping: true - parse-pure-ip: true - override-destination: true - sniff: - TLS: - # ports:[443, 8443] - HTTP: - ports: [80, 8080-8880] - override-destination: true - force-domain: - - +.v2ex.com - # skip-domain: - # - +.google.com - sniffing: - - tls - - http - port-whitelist: - - "80" - - "443" - -tun: - enable: false - # biarkan default utun - device: utun - mtu: 9000 - # gvisor / lwip / system - stack: system - dns-hijack: - - any:53 - auto-route: false - auto-detect-interface: false - inet4-address: 172.19.0.1/30 - inet6-address: [fdfe:dcba:9876::1/126] - strict_route: false - # inet4_route_address: - # - 0.0.0.0/1 - # - 128.0.0.0/1 - # inet6_route_address: - # - "::/1" - # - "8000::/1" - # include_android_user: - # - 0 - # - 10 - # include_package: - # - com.android.chrome - # exclude_package: - # - com.android.captiveportallogin - -dns: - enable: true - ipv6: false - prefer-h3: true - default-nameserver: - - '1.1.1.1' - - '8.8.8.8' - listen: 0.0.0.0:1053 - use-hosts: true - # redir-host / fake-ip - enhanced-mode: fake-ip - fake-ip-range: 43.0.0.1/8 - fake-ip-filter: - - '+.lan' - - '+.stun.*.*' - - '+.stun.*.*.*' - - '+.stun.*.*.*.*' - - '+.stun.*.*.*.*.*' - nameserver: - - '1.1.1.1' - - 'tls://1.0.0.1:853' - - '8.8.8.8' - - 'tls://8.8.4.4:853' - # - 'tls://1.1.1.1:853' # DNS over TLS - # - 'tls://1dot1dot1dot1.cloudflare-dns.com:853' - # - https://doh.pub/dns-query # DNS over HTTPS - # - https://dns.alidns.com/dns-query#h3=true - # - https://mozilla.cloudflare-dns.com/dns-query#clash&h3=true - # proxy-server-nameserver: - # - '1.1.1.1' - # # nameserver-policy: - # # '+.googlesyndication.com': 1.1.1.1 - # fallback: - # - 'https://8.8.8.8/dns-query' - # - 'tcp://8.8.4.4' - # # - 'quic://dns.adguard.com:784' # DNS over QUIC - # fallback-filter: - # geoip: false - # geoip-code: 'ID' - # geosite: - # # - gfw - # ipcidr: - # # - 240.0.0.0/4 - # domain: - # - '+.google.com' - # - '+.facebook.com' - # - '+.youtube.com' - # - '+.github.com' -hosts: - 'ota.googlezip.net': 127.0.0.1 - 'ota-cache1.googlezip.net': 127.0.0.1 - 'ota-cache2.googlezip.net': 127.0.0.1 \ No newline at end of file diff --git a/scripts/v2fly/config.json b/scripts/v2fly/config.json index da42c1b..73612fe 100755 --- a/scripts/v2fly/config.json +++ b/scripts/v2fly/config.json @@ -35,14 +35,12 @@ "settings": { "vnext": [ { - "address": "104.21.235.171", + "address": "server.com", "port": 80, "users": [ { "alterId": 0, - "encryption": "", - "flow": "", - "id": "uuid", + "id": "aaa-aaa-aaa", "level": 8, "security": "auto" } @@ -52,12 +50,16 @@ }, "streamSettings": { "network": "ws", - "security": "", + "security": "none", + "tlsSettings": { + "allowInsecure": false, + "serverName": "sni.com" + }, "wsSettings": { "headers": { - "Host": "x-ui-llyc.hidedns.me" + "Host": "host.com" }, - "path": "/pulsa" + "path": "/sheynsw" } }, "tcpSettings": null, @@ -89,7 +91,7 @@ "tag": "dns-out", "protocol": "dns", "settings": { - "address": "1.1.1.1" + "address": "8.8.8.8" } } ], @@ -100,7 +102,7 @@ "domain:ota-cache2.googlezip.net": "127.0.0.1" }, "servers": [ - "8.8.8.8" + "1.1.1.1" ], "tag": "dns", "queryStrategy": "UseIP" @@ -117,21 +119,6 @@ ], "outboundTag": "dns-out" }, - { - "ip": [ - "1.1.1.1" - ], - "outboundTag": "proxy", - "port": "53", - "type": "field" - }, - { - "type": "field", - "outboundTag": "direct", - "protocol": [ - "bittorrent" - ] - }, { "domain": [ "regexp:\\.googlesyndication.com$" diff --git a/scripts/xray/config.json b/scripts/xray/config.json index da42c1b..9a7bdf5 100755 --- a/scripts/xray/config.json +++ b/scripts/xray/config.json @@ -29,51 +29,11 @@ } ], "outbounds": [ - { - "tag": "proxy", - "protocol": "vmess", - "settings": { - "vnext": [ - { - "address": "104.21.235.171", - "port": 80, - "users": [ - { - "alterId": 0, - "encryption": "", - "flow": "", - "id": "uuid", - "level": 8, - "security": "auto" - } - ] - } - ] - }, - "streamSettings": { - "network": "ws", - "security": "", - "wsSettings": { - "headers": { - "Host": "x-ui-llyc.hidedns.me" - }, - "path": "/pulsa" - } - }, - "tcpSettings": null, - "sockopt": { - "domainStrategy": "UseIP" - }, - "mux": { - "concurrency": 8, - "enabled": false - } - }, { "tag": "direct", "protocol": "freedom", "settings": { - "domainStrategy": "UseIP" + "domainStrategy": "UseIPv4" } }, { @@ -89,7 +49,50 @@ "tag": "dns-out", "protocol": "dns", "settings": { - "address": "1.1.1.1" + "address": "8.8.8.8" + } + }, + { + "tag": "proxy", + "protocol": "vless", + "settings": { + "vnext": [ + { + "address": "128.199.233.181", + "port": 443, + "users": [ + { + "encryption": "none", + "flow": "xtls-rprx-vision", + "id": "8aeaf535-f729-4330-9474-669726f8c9d7", + "level": 8, + "security": "auto" + } + ] + } + ] + }, + "streamSettings": { + "network": "tcp", + "security": "tls", + "tcpSettings": { + "header": { + "type": "none" + } + }, + "tlsSettings": { + "allowInsecure": true, + "fingerprint": "", + "serverName": "www.google.com" + } + }, + "mux": { + "concurrency": 8, + "enabled": false + }, + "tcpSettings": null, + "sockopt": { + "domainStrategy": "UseIPv4" } } ], @@ -103,7 +106,7 @@ "8.8.8.8" ], "tag": "dns", - "queryStrategy": "UseIP" + "queryStrategy": "UseIPv4" }, "routing": { "domainStrategy": "IPIfNonMatch", @@ -117,21 +120,6 @@ ], "outboundTag": "dns-out" }, - { - "ip": [ - "1.1.1.1" - ], - "outboundTag": "proxy", - "port": "53", - "type": "field" - }, - { - "type": "field", - "outboundTag": "direct", - "protocol": [ - "bittorrent" - ] - }, { "domain": [ "regexp:\\.googlesyndication.com$"