Files

244 lines
6.8 KiB
Bash
Executable File

#!/bin/sh /etc/rc.common
. /usr/lib/hijpass/app-logger.sh
USE_PROCD=1
START=99
STOP=15
NAME=hijpass
LIB_PATH="/usr/lib/$NAME"
NFT_SCRIPT="$LIB_PATH/nft.sh"
ROUTE_SCRIPT="$LIB_PATH/route.sh"
RULE_UPDATE_SCRIPT="$LIB_PATH/rules.sh"
CHINANDS_NG_SCRIPT="$LIB_PATH/chinadns-ng.sh"
GEOVIEW_SCRIPT="$LIB_PATH/geoview.sh"
CONF_PATH="/etc/$NAME"
SHUNT_CONF="$CONF_PATH/shunt.json"
# Global
ENABLED=$(uci -q get hijpass.@hijpass[0].enabled || :)
DELAY_TIME=$(uci -q get hijpass.@hijpass[0].delay_time || :)
CLIENT_DIR=$(uci -q get hijpass.@hijpass[0].client_dir || :)
# RuleDTO
CRON_CONF=$(uci -q get hijpass.@rule[0].update_schedule || :)
# Log
REDIRECT_LOG=
# DNS
DNS_SERVICE=$(uci -q get hijpass.@dns[0].dns_service || :)
DNS_HOOK=$(uci -q get hijpass.@hijpass[0].dns_hook || :)
CHINADNS_NG_CONF="$CONF_PATH/chinadns-ng.conf"
start_service() {
[ "$ENABLED" != "1" ] && return
# 启动进程
config_load $NAME
log_info "===================== Starting service ======================="
log_info "Running proxy nodes..."
config_foreach run_regular_proxy proxy_node
sleep 2
log_info "Running load balancing proxy nodes..."
config_foreach run_load_balance_proxy proxy_node
sleep 1
log_info "Running shunt..."
config_foreach run_shunt shunt
sleep 1
# 配置防火墙
log_info "Configuring firewall rules..."
reset_fw_tproxy
# 启动定时任务
log_info "Resetting geo cron jobs..."
reset_geo_cron
# 启动DNS劫持
log_info "DNS hijacking..."
start_dns_service
log_info "================ Service started successfully ================"
}
stop_service() {
log_info "===================== Stopping service ======================="
reset_geo_cron
remove_fw_tproxy
stop_dns_service
log_info "================ Service stopped successfully ================"
}
service_triggers() {
procd_add_reload_trigger "$NAME"
procd_add_interface_trigger "interface.*.up" "*" /etc/init.d/$NAME restart
}
reload_service() {
/etc/init.d/$NAME restart
}
boot() {
[ "$DELAY_TIME" -gt 0 ] && sleep "$DELAY_TIME"
restart
}
run_regular_proxy() {
local type
config_get type "$1" type
[ "$type" = "load_balance" ] && return
run_proxy "$1"
}
run_load_balance_proxy() {
local type
config_get type "$1" type
[ "$type" != "load_balance" ] && return
run_proxy "$1"
}
run_proxy() {
local command log_path name enabled nest_proxy core
local enable_std_log="1"
config_get enabled "$1" enabled
[ "$enabled" != "1" ] && return
config_get command "$1" command
config_get log_path "$1" log_path
config_get name "$1" name
config_get nest_proxy "$1" nest_proxy
config_get core "$1" core
local conf_path="$CLIENT_DIR/$name-$1.json"
case "$core" in
xray) command="xray -c $conf_path" ;;
sing-box) command="sing-box -c $conf_path run" ;;
custom) command=$(echo "$command" | sed "s|{conf_path}|$conf_path|g") ;;
*) log_warn "Node '$name' has unknown core='$core', skipping"; return ;;
esac
if [ -n "$log_path" ]; then
: > "$log_path"
command="$command >> $log_path 2>&1"
enable_std_log="0"
REDIRECT_LOG="1"
else
command="$command > /dev/null 2>&1"
fi
open_instance "$1" "$name" "$command" "$enable_std_log" "$nest_proxy"
}
run_shunt() {
local type log_path enabled ruleset_convert
config_get enabled "$1" enabled
[ "$enabled" = "0" ] && log_info "Shunt disabled, skipping" && return
config_get type "$1" type
[ -z "$type" ] && log_error "Shunt type not set" && return
config_get log_path "$1" log_path
config_get ruleset_convert "$1" ruleset_convert
local shunt_command="$type -c $SHUNT_CONF"
[ "$type" = "sing-box" ] && shunt_command="$type run -c $SHUNT_CONF"
[ "$type" = "sing-box" ] && [ "$ruleset_convert" = "1" ] && $GEOVIEW_SCRIPT -t
local enable_std_log="0"
if [ -n "$log_path" ]; then
: > "$log_path"
shunt_command="$shunt_command >> $log_path 2>&1"
REDIRECT_LOG="1"
else
shunt_command="$shunt_command > /dev/null 2>&1"
fi
open_instance "$1" "shunt" "$shunt_command" "$enable_std_log"
}
open_instance() {
log_debug "id: $1, name: $2, cmd: $3"
local instance_name="$1-$2"
local cmd="$3"
local enable_std_log="$4"
local nest_proxy="$5"
procd_open_instance "$instance_name"
procd_set_param command /bin/sh -c "$cmd"
if [ "$2" = "shunt" ]; then
procd_set_param limits core="unlimited"
procd_set_param limits nofile="1000000 1000000"
procd_set_param env "XRAY_LOCATION_ASSET=/usr/share/v2ray"
fi
config_list_foreach "$1" procd_env procd_set_env "$instance_name"
if [ "$enable_std_log" = "1" ]; then
procd_set_param stdout 1
procd_set_param stderr 1
fi
procd_set_param pidfile "/var/run/$instance_name.pid"
if [ "$nest_proxy" = "1" ]; then
procd_set_param user "root"
else
procd_set_param user "hijpass"
fi
procd_set_param respawn 10 5 2
procd_close_instance
}
procd_set_env() {
[ -z "$1" ] && return
log_debug "Setting $2 env: $1"
procd_set_param env "$1"
}
reset_fw_tproxy() {
if ! $NFT_SCRIPT reset > /dev/null 2>&1; then
stop
exit 1
fi
$ROUTE_SCRIPT reset_hijpass_route
}
remove_fw_tproxy() {
$ROUTE_SCRIPT remove_hijpass_route
$NFT_SCRIPT remove > /dev/null 2>&1
}
start_dns_service() {
if [ "$DNS_SERVICE" = "chinadns-ng" ]; then
log_info "Starting chinadns-ng service"
$CHINANDS_NG_SCRIPT
local cid
cid="$(uci show hijpass.@dns[0] | grep 'dns$' | awk -F '[.=]' '{print $2}')"
open_instance "$cid" "chinadns-ng" "$DNS_SERVICE -C $CHINADNS_NG_CONF"
fi
if [ -n "$DNS_HOOK" ]; then
[ ! -f "$DNS_HOOK" ] && log_warn "Custom DNS hook script $DNS_HOOK not found" && return 1
log_info "Executing custom DNS hook script (start)"
$DNS_HOOK start || log_error "Custom DNS hook script execute failed"
fi
}
stop_dns_service() {
if [ "$DNS_SERVICE" = "chinadns-ng" ]; then
rm -f "$CHINADNS_NG_CONF" && log_info "Deleted chinadns-ng conf"
fi
if [ -n "$DNS_HOOK" ]; then
[ ! -f "$DNS_HOOK" ] && log_warn "Custom DNS hook script $DNS_HOOK not found" && return 1
log_info "Executing custom DNS hook script (stop)"
$DNS_HOOK stop || log_warn "Custom DNS hook script execute failed"
fi
}
reset_geo_cron() {
sed -i '/hijpass\/rules\.sh/d' /etc/crontabs/root 2>/dev/null
sed -i '/hijpass\/clean-service-log\.sh hijpass/d' /etc/crontabs/root 2>/dev/null
if [ "$REDIRECT_LOG" = "1" ]; then
echo "*/10 * * * * /usr/lib/hijpass/clean-service-log.sh hijpass" >> /etc/crontabs/root
log_info "Added log split service cron job: */10 * * * * /usr/lib/hijpass/clean-service-log.sh hijpass"
fi
if [ -z "$CRON_CONF" ] || [ "$ENABLED" != "1" ]; then
/etc/init.d/cron restart > /dev/null 2>&1
return 0
fi
echo "$CRON_CONF $RULE_UPDATE_SCRIPT update" >> /etc/crontabs/root
log_info "Added rule update cron job: $CRON_CONF $RULE_UPDATE_SCRIPT update"
/etc/init.d/cron restart > /dev/null 2>&1
}