mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-15 04:53:00 +08:00
544 lines
18 KiB
Bash
544 lines
18 KiB
Bash
#!/bin/sh /etc/rc.common
|
|
|
|
USE_PROCD=1
|
|
START=99
|
|
STOP=90 # 确保在防火墙重载前停止
|
|
|
|
NAME="${NAME:-UAmask}"
|
|
PROG="${PROG:-/usr/bin/$NAME}"
|
|
PID_FILE="/var/run/$NAME.pid"
|
|
CORE_CONFIG_DIR="${CORE_CONFIG_DIR:-/var/run/$NAME}"
|
|
CORE_CONFIG_PATH="$CORE_CONFIG_DIR/config.json"
|
|
JSHN_LIB="${JSHN_LIB:-/usr/share/libubox/jshn.sh}"
|
|
|
|
# --- NFT (fw4) 变量 ---
|
|
FW_CONFIG_NAME="UAmask" # 防火墙 UCI 规则的名称
|
|
NFT_PATH="/tmp/UAmask_rules.nft" # .nft 文件的路径 (使用 /tmp/)
|
|
|
|
# --- IPT (fw3) 变量 ---
|
|
IPT="iptables"
|
|
CHAIN_PREROUTING="UAmask_prerouting"
|
|
CHAIN_OUTPUT="UAmask_output"
|
|
|
|
IPSET_NAME="UAmask_bypass_set"
|
|
|
|
# --- 防火墙检测 ---
|
|
FW_TYPE=""
|
|
|
|
detect_firewall() {
|
|
if command -v fw4 >/dev/null 2>&1; then
|
|
FW_TYPE="nft"
|
|
else
|
|
FW_TYPE="ipt"
|
|
fi
|
|
}
|
|
|
|
# 脚本加载时执行防火墙检测
|
|
detect_firewall
|
|
|
|
# NFTABLES (fw4) 函数
|
|
|
|
# 仅清理规则和 uci,不重载 (NFT helper)
|
|
unset_firewall_rules_nft() {
|
|
rm -f "${NFT_PATH}" # 清理生成的规则文件
|
|
uci -q delete firewall.${FW_CONFIG_NAME}
|
|
uci commit firewall
|
|
}
|
|
|
|
# 清理防火墙规则并重载 (NFT)
|
|
unset_firewall_nft() {
|
|
logger -t "$NAME" "Removing firewall rules (nft)..."
|
|
unset_firewall_rules_nft
|
|
nft delete chain inet fw4 UAmask_prerouting_before 2>/dev/null || true
|
|
nft delete chain inet fw4 UAmask_output_after 2>/dev/null || true
|
|
nft delete set inet fw4 ${IPSET_NAME} 2>/dev/null || true
|
|
fw4 reload >/dev/null 2>&1
|
|
logger -t "$NAME" "Firewall rules removed (nft)."
|
|
}
|
|
|
|
# 自动管理防火墙规则 (NFT)
|
|
set_firewall_nft() {
|
|
# 1. 确保旧规则被彻底清除
|
|
unset_firewall_rules_nft
|
|
|
|
# 2. 从 UCI 读取配置
|
|
config_load "$NAME"
|
|
local port
|
|
local iface_list
|
|
local bypass_gid
|
|
local bypass_ports_list
|
|
local bypass_ips_list
|
|
local force_replace
|
|
local proxy_host
|
|
local enable_firewall_set
|
|
|
|
config_get port "main" "port" "12032"
|
|
config_get iface_list "main" "iface" "br-lan"
|
|
config_get bypass_gid "main" "bypass_gid" "65533"
|
|
config_get bypass_ports_list "main" "bypass_ports" ""
|
|
config_get bypass_ips_list "main" "bypass_ips" ""
|
|
config_get_bool proxy_host "main" "proxy_host" ""
|
|
config_get_bool enable_firewall_set "main" "enable_firewall_set" "0"
|
|
|
|
# 3. 格式化接口
|
|
local nft_ifaces
|
|
set -- $iface_list
|
|
if [ "$#" -eq 1 ]; then
|
|
nft_ifaces="\"$1\"" # 单个接口
|
|
else
|
|
nft_ifaces="{ $(echo "$iface_list" | sed -e 's/ /", "/g' -e 's/^/"/' -e 's/$/"/') }" # 多个接口
|
|
fi
|
|
|
|
# 4. 格式化豁免 IPs
|
|
local nft_ips_rule
|
|
if [ -n "$bypass_ips_list" ]; then
|
|
local nft_ips
|
|
nft_ips="{ $(echo "$bypass_ips_list" | sed -e 's/ /, /g') }"
|
|
nft_ips_rule="ip daddr != $nft_ips \\"
|
|
else
|
|
nft_ips_rule="# No bypass IPs configured"
|
|
fi
|
|
|
|
# 5. 格式化豁免 Ports
|
|
local nft_ports_rule
|
|
if [ -n "$bypass_ports_list" ]; then
|
|
local nft_ports
|
|
nft_ports="{ $(echo "$bypass_ports_list" | sed -e 's/ /, /g') }"
|
|
nft_ports_rule="tcp dport != $nft_ports \\"
|
|
else
|
|
nft_ports_rule="# No bypass ports configured"
|
|
fi
|
|
|
|
> "${NFT_PATH}"
|
|
if [ "$enable_firewall_set" = "1" ] && ! command -v nft >/dev/null 2>&1; then
|
|
logger -t "$NAME" "Error: 'nft' command (nftables) is not installed. Domain bypass disabled."
|
|
enable_firewall_set="0"
|
|
fi
|
|
|
|
if [ "$enable_firewall_set" = "1" ]; then
|
|
logger -t "$NAME" "Ensuring nftables set '${IPSET_NAME}' exists..."
|
|
nft add set inet fw4 ${IPSET_NAME} "{ type ipv4_addr . inet_service ; timeout 10m ;}"
|
|
if [ $? -ne 0 ]; then
|
|
logger -t "$NAME" "Error: Failed to create nftables set '${IPSET_NAME}'. Domain bypass disabled."
|
|
enable_firewall_set="0"
|
|
fi
|
|
fi
|
|
|
|
# 6. 动态写入 .nft 文件
|
|
cat > "${NFT_PATH}" << EOF
|
|
chain UAmask_prerouting_before {
|
|
type nat hook prerouting priority dstnat - 1;
|
|
|
|
$( [ "$enable_firewall_set" = "1" ] && echo "iifname $nft_ifaces ip protocol tcp ip daddr . tcp dport @$IPSET_NAME return" )
|
|
|
|
iifname $nft_ifaces ip protocol tcp \\
|
|
$nft_ips_rule
|
|
$nft_ports_rule
|
|
redirect to :$port
|
|
}
|
|
|
|
EOF
|
|
|
|
if [ "$proxy_host" = "1" ]; then
|
|
cat >> "${NFT_PATH}" << EOF
|
|
|
|
chain UAmask_output_after {
|
|
type nat hook output priority -100;
|
|
|
|
$( [ "$enable_firewall_set" = "1" ] && echo "ip protocol tcp ip daddr . tcp dport @$IPSET_NAME return" )
|
|
|
|
ip protocol tcp \\
|
|
# 豁免局域网、环回、保留地址等
|
|
$nft_ips_rule
|
|
# 豁免端口
|
|
$nft_ports_rule
|
|
# 豁免 UAmask 自己的流量
|
|
# 同时豁免 OpenClash 的流量 (GID 65534),防止循环
|
|
meta skgid != { $bypass_gid, 65534 } \\
|
|
redirect to :$port
|
|
}
|
|
|
|
EOF
|
|
logger -t "$NAME" "proxy_host is enabled. Added UAmask_output_after chain."
|
|
else
|
|
logger -t "$NAME" "proxy_host is disabled. Skipping UAmask_output_after chain."
|
|
fi
|
|
logger -t "$NAME" "Generated nftables rules at ${NFT_PATH}"
|
|
# 7. 注册防火墙规则
|
|
uci set firewall.${FW_CONFIG_NAME}="include"
|
|
uci set firewall.${FW_CONFIG_NAME}.type="nftables"
|
|
uci set firewall.${FW_CONFIG_NAME}.path="${NFT_PATH}"
|
|
uci set firewall.${FW_CONFIG_NAME}.enabled="1"
|
|
uci commit firewall
|
|
nft delete chain inet fw4 UAmask_prerouting_before 2>/dev/null || true
|
|
nft delete chain inet fw4 UAmask_output_after 2>/dev/null || true
|
|
fw4 reload >/dev/null 2>&1
|
|
logger -t "$NAME" "Firewall rules applied (nft)."
|
|
}
|
|
|
|
# IPTABLES (fw3) 函数
|
|
|
|
# 清理防火墙规则并重载 (IPT)
|
|
unset_firewall_ipt() {
|
|
logger -t "$NAME" "Removing firewall rules (iptables)..."
|
|
|
|
# 循环尝试删除跳转规则,直到成功或失败
|
|
while $IPT -t nat -D PREROUTING -j $CHAIN_PREROUTING 2>/dev/null; do :; done
|
|
while $IPT -t nat -D OUTPUT -j $CHAIN_OUTPUT 2>/dev/null; do :; done
|
|
|
|
|
|
$IPT -t nat -F $CHAIN_PREROUTING 2>/dev/null || true
|
|
$IPT -t nat -X $CHAIN_PREROUTING 2>/dev/null || true
|
|
|
|
$IPT -t nat -F $CHAIN_OUTPUT 2>/dev/null || true
|
|
$IPT -t nat -X $CHAIN_OUTPUT 2>/dev/null || true
|
|
|
|
ipset destroy "$IPSET_NAME" 2>/dev/null || true
|
|
|
|
/etc/init.d/firewall reload >/dev/null 2>&1
|
|
logger -t "$NAME" "Firewall rules removed (iptables)."
|
|
}
|
|
|
|
# 自动管理防火墙规则 (IPT)
|
|
set_firewall_ipt() {
|
|
# 1. 确保旧规则被彻底清除
|
|
unset_firewall_ipt
|
|
|
|
# 2. 从 UCI 读取配置 (此部分不变)
|
|
config_load "$NAME"
|
|
local port
|
|
local iface_list
|
|
local bypass_gid
|
|
local bypass_ports_list
|
|
local bypass_ips_list
|
|
local proxy_host
|
|
local enable_firewall_set
|
|
|
|
config_get port "main" "port" "12032"
|
|
config_get iface_list "main" "iface" "br-lan"
|
|
config_get bypass_gid "main" "bypass_gid" "65533"
|
|
config_get bypass_ports_list "main" "bypass_ports" ""
|
|
config_get bypass_ips_list "main" "bypass_ips" ""
|
|
config_get_bool proxy_host "main" "proxy_host" ""
|
|
|
|
config_get_bool enable_firewall_set "main" "enable_firewall_set" "0"
|
|
if [ "$enable_firewall_set" = "1" ]; then
|
|
if ! command -v ipset >/dev/null 2>&1; then
|
|
logger -t "$NAME" "Error: 'ipset' package is not installed. Domain bypass disabled."
|
|
enable_firewall_set="0"
|
|
else
|
|
logger -t "$NAME" "Creating ipset '$IPSET_NAME' for domain bypass..."
|
|
ipset create "$IPSET_NAME" hash:ip,port timeout 600 -exist
|
|
fi
|
|
fi
|
|
# --- IPTABLES 规则设置 ---
|
|
|
|
# 3. 创建自定义链
|
|
$IPT -t nat -N $CHAIN_PREROUTING
|
|
$IPT -t nat -N $CHAIN_OUTPUT
|
|
|
|
if [ "$enable_firewall_set" = "1" ]; then
|
|
$IPT -t nat -A $CHAIN_PREROUTING -m set --match-set "$IPSET_NAME" dst,dst -j RETURN
|
|
fi
|
|
|
|
# 4. 填充 PREROUTING 链
|
|
for iface in $iface_list; do
|
|
for ip in $bypass_ips_list; do
|
|
$IPT -t nat -A $CHAIN_PREROUTING -i "$iface" -p tcp -d "$ip" -j RETURN
|
|
done
|
|
if [ -n "$bypass_ports_list" ]; then
|
|
local ipt_ports=$(echo "$bypass_ports_list" | sed 's/ /,/g')
|
|
$IPT -t nat -A $CHAIN_PREROUTING -i "$iface" -p tcp -m multiport --dports "$ipt_ports" -j RETURN
|
|
fi
|
|
# 将剩余的 TCP 流量重定向到代理端口
|
|
$IPT -t nat -A $CHAIN_PREROUTING -i "$iface" -p tcp -j REDIRECT --to-port "$port"
|
|
done
|
|
|
|
# 5. OUTPUT 链处理本机流量
|
|
if [ "$proxy_host" = "1" ]; then
|
|
# 域名绕过规则
|
|
if [ "$enable_firewall_set" = "1" ]; then
|
|
$IPT -t nat -A $CHAIN_OUTPUT -m set --match-set "$IPSET_NAME" dst -j RETURN
|
|
fi
|
|
# 豁免 UAmask 自己的流量 (通过 GID)
|
|
$IPT -t nat -A $CHAIN_OUTPUT -p tcp -m owner --gid-owner "$bypass_gid" -j RETURN
|
|
# 同时豁免 OpenClash 的流量 (GID 65534),防止循环
|
|
$IPT -t nat -A $CHAIN_OUTPUT -p tcp -m owner --gid-owner "65534" -j RETURN
|
|
|
|
# 豁免指定的目标 IP
|
|
for ip in $bypass_ips_list; do
|
|
$IPT -t nat -A $CHAIN_OUTPUT -p tcp -d "$ip" -j RETURN
|
|
done
|
|
|
|
# 豁免指定的端口
|
|
if [ -n "$bypass_ports_list" ]; then
|
|
local ipt_ports=$(echo "$bypass_ports_list" | sed 's/ /,/g')
|
|
$IPT -t nat -A $CHAIN_OUTPUT -p tcp -m multiport --dports "$ipt_ports" -j RETURN
|
|
fi
|
|
|
|
# 将剩余的 TCP 流量重定向到代理端口
|
|
$IPT -t nat -A $CHAIN_OUTPUT -p tcp -j REDIRECT --to-port "$port"
|
|
|
|
# 将自定义 OUTPUT 链挂载到内置的 OUTPUT 链
|
|
$IPT -t nat -I OUTPUT 1 -j $CHAIN_OUTPUT
|
|
logger -t "$NAME" "proxy_host is enabled. Added iptables rules for OUTPUT chain."
|
|
else
|
|
logger -t "$NAME" "proxy_host is disabled. Skipping OUTPUT chain rules."
|
|
fi
|
|
|
|
# 6. 将自定义 PREROUTING 链挂载到内置的 PREROUTING 链
|
|
$IPT -t nat -I PREROUTING 1 -j $CHAIN_PREROUTING
|
|
|
|
logger -t "$NAME" "Firewall rules (iptables) applied."
|
|
}
|
|
|
|
|
|
# 通用封装函数
|
|
|
|
set_firewall() {
|
|
if [ "$FW_TYPE" = "nft" ]; then
|
|
set_firewall_nft
|
|
else
|
|
set_firewall_ipt
|
|
fi
|
|
}
|
|
|
|
unset_firewall() {
|
|
if [ "$FW_TYPE" = "nft" ]; then
|
|
unset_firewall_nft
|
|
else
|
|
unset_firewall_ipt
|
|
fi
|
|
}
|
|
|
|
# 通用服务函数 (启动、停止、组设置)
|
|
|
|
# 检查并创建专用组
|
|
setup_group() {
|
|
config_load "$NAME"
|
|
local bypass_gid
|
|
config_get bypass_gid "main" "bypass_gid" "65533"
|
|
|
|
if ! grep -q ":$bypass_gid:" /etc/group; then
|
|
echo "UAmask:x:$bypass_gid:" >> /etc/group
|
|
fi
|
|
}
|
|
|
|
|
|
trim_config_value() {
|
|
local value="$1"
|
|
value="${value#"${value%%[![:space:]]*}"}"
|
|
value="${value%"${value##*[![:space:]]}"}"
|
|
printf '%s' "$value"
|
|
}
|
|
|
|
json_add_csv_array() {
|
|
local name="$1"
|
|
local remaining="$2"
|
|
local item
|
|
|
|
json_add_array "$name"
|
|
while [ -n "$remaining" ]; do
|
|
case "$remaining" in
|
|
*,*)
|
|
item="${remaining%%,*}"
|
|
remaining="${remaining#*,}"
|
|
;;
|
|
*)
|
|
item="$remaining"
|
|
remaining=""
|
|
;;
|
|
esac
|
|
item="$(trim_config_value "$item")"
|
|
[ -n "$item" ] && json_add_string "" "$item"
|
|
done
|
|
json_close_array
|
|
}
|
|
|
|
generate_core_config() {
|
|
local tmp_config="$CORE_CONFIG_PATH.tmp.$$"
|
|
local validation_output
|
|
local port ua log_level log_file whitelist
|
|
local match_mode keywords ua_regex replace_method partial_replace
|
|
local enable_firewall_set firewall_ua_whitelist firewall_ua_bypass firewall_drop_on_match
|
|
local firewall_advanced_settings firewall_nonhttp_threshold firewall_timeout firewall_decision_delay
|
|
local operating_profile cache_size buffer_size pool_size gogc_value
|
|
|
|
if [ ! -r "$JSHN_LIB" ]; then
|
|
logger -t "$NAME" "Cannot generate core config: jshn.sh is unavailable."
|
|
return 1
|
|
fi
|
|
. "$JSHN_LIB"
|
|
|
|
config_get port "main" "port" "12032"
|
|
config_get ua "main" "ua" "FFF"
|
|
config_get log_level "main" "log_level" "info"
|
|
config_get log_file "main" "log_file" "/tmp/UAmask/UAmask.log"
|
|
config_get whitelist "main" "whitelist" ""
|
|
|
|
config_get match_mode "main" "match_mode" "keywords"
|
|
config_get keywords "main" "keywords" "iPhone,iPad,Android,Macintosh,Windows"
|
|
config_get ua_regex "main" "ua_regex" "(iPhone|iPad|Android|Macintosh|Windows|Linux)"
|
|
config_get replace_method "main" "replace_method" "full"
|
|
partial_replace=0
|
|
[ "$replace_method" = "partial" ] && partial_replace=1
|
|
|
|
config_get_bool enable_firewall_set "main" "enable_firewall_set" "0"
|
|
config_get firewall_ua_whitelist "main" "Firewall_ua_whitelist" ""
|
|
config_get_bool firewall_ua_bypass "main" "Firewall_ua_bypass" "0"
|
|
config_get_bool firewall_drop_on_match "main" "Firewall_drop_on_match" "0"
|
|
config_get_bool firewall_advanced_settings "main" "firewall_advanced_settings" "0"
|
|
config_get firewall_nonhttp_threshold "main" "firewall_nonhttp_threshold" "5"
|
|
config_get firewall_timeout "main" "firewall_timeout" "28800"
|
|
config_get firewall_decision_delay "main" "firewall_decision_delay" "60"
|
|
|
|
if [ "$enable_firewall_set" != "1" ]; then
|
|
firewall_ua_whitelist=""
|
|
firewall_ua_bypass=0
|
|
firewall_drop_on_match=0
|
|
fi
|
|
if [ "$firewall_advanced_settings" != "1" ]; then
|
|
firewall_nonhttp_threshold=5
|
|
firewall_timeout=28800
|
|
firewall_decision_delay=60
|
|
else
|
|
# Preserve the safety floors used by the legacy flag-based launcher.
|
|
[ "$firewall_nonhttp_threshold" -ge 1 ] 2>/dev/null || firewall_nonhttp_threshold=5
|
|
[ "$firewall_timeout" -ge 60 ] 2>/dev/null || firewall_timeout=28800
|
|
[ "$firewall_decision_delay" -ge 10 ] 2>/dev/null || firewall_decision_delay=60
|
|
fi
|
|
|
|
config_get operating_profile "main" "operating_profile" "Medium"
|
|
config_get cache_size "main" "cache_size" "2000"
|
|
config_get buffer_size "main" "buffer_size" "8192"
|
|
config_get pool_size "main" "pool_size" "0"
|
|
config_get gogc_value "main" "gogc_value" "100"
|
|
|
|
umask 077
|
|
mkdir -p "$CORE_CONFIG_DIR" || return 1
|
|
mkdir -p "$(dirname "$log_file")" || return 1
|
|
|
|
json_init
|
|
json_add_int "schema_version" 1
|
|
|
|
json_add_object "listen"
|
|
json_add_int "port" "$port"
|
|
json_add_string "dial_timeout" "30s"
|
|
json_add_string "client_keep_alive" "3m"
|
|
json_add_string "upstream_keep_alive" "3m"
|
|
json_close_object
|
|
|
|
json_add_object "rewrite"
|
|
json_add_string "user_agent" "$ua"
|
|
json_add_string "mode" "$match_mode"
|
|
json_add_csv_array "keywords" "$keywords"
|
|
json_add_csv_array "whitelist" "$whitelist"
|
|
json_add_string "pattern" "$ua_regex"
|
|
json_add_boolean "partial_replace" "$partial_replace"
|
|
json_close_object
|
|
|
|
json_add_object "firewall"
|
|
json_add_string "backend" "$FW_TYPE"
|
|
json_add_string "set_name" "$IPSET_NAME"
|
|
json_add_csv_array "ua_whitelist" "$firewall_ua_whitelist"
|
|
json_add_boolean "drop_on_match" "$firewall_drop_on_match"
|
|
json_add_string "whitelist_timeout" "24h"
|
|
json_add_object "non_http"
|
|
json_add_boolean "enabled" "$firewall_ua_bypass"
|
|
json_add_int "threshold" "$firewall_nonhttp_threshold"
|
|
json_add_string "decision_delay" "${firewall_decision_delay}s"
|
|
json_add_string "http_cooldown" "1h"
|
|
json_add_string "timeout" "${firewall_timeout}s"
|
|
json_add_string "cleanup_interval" "10m"
|
|
json_close_object
|
|
json_close_object
|
|
|
|
json_add_object "observe"
|
|
json_add_string "log_level" "$log_level"
|
|
json_add_string "log_file" "$log_file"
|
|
json_add_string "stats_file" "/tmp/UAmask.stats"
|
|
json_add_string "stats_interval" "5s"
|
|
json_close_object
|
|
|
|
json_add_object "performance"
|
|
json_add_string "profile" "$operating_profile"
|
|
json_add_int "cache_size" "$cache_size"
|
|
json_add_int "buffer_size" "$buffer_size"
|
|
json_add_int "pool_size" "$pool_size"
|
|
json_add_int "gc_percent" "$gogc_value"
|
|
json_close_object
|
|
|
|
if ! json_dump > "$tmp_config"; then
|
|
logger -t "$NAME" "Failed to serialize core configuration."
|
|
rm -f "$tmp_config"
|
|
return 1
|
|
fi
|
|
|
|
validation_output="$("$PROG" -check-config -config "$tmp_config" 2>&1)"
|
|
if [ $? -ne 0 ]; then
|
|
logger -t "$NAME" "Core configuration validation failed: $validation_output"
|
|
rm -f "$tmp_config"
|
|
return 1
|
|
fi
|
|
|
|
if ! chmod 600 "$tmp_config"; then
|
|
logger -t "$NAME" "Failed to secure generated core configuration."
|
|
rm -f "$tmp_config"
|
|
return 1
|
|
fi
|
|
if ! mv -f "$tmp_config" "$CORE_CONFIG_PATH"; then
|
|
logger -t "$NAME" "Failed to install core configuration."
|
|
rm -f "$tmp_config"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
start_service() {
|
|
logger -t "$NAME" "Starting $NAME with firewall $FW_TYPE..."
|
|
config_load "$NAME"
|
|
|
|
local enabled proxy_host
|
|
config_get_bool enabled "enabled" "enabled" "0"
|
|
[ "$enabled" -eq 1 ] || return 1
|
|
config_get_bool proxy_host "main" "proxy_host" "0"
|
|
|
|
if [ "$proxy_host" = "1" ]; then
|
|
setup_group
|
|
fi
|
|
if ! generate_core_config; then
|
|
logger -t "$NAME" "Refusing to start with invalid core configuration."
|
|
return 1
|
|
fi
|
|
|
|
procd_open_instance "$NAME"
|
|
procd_set_param command "$PROG" -config "$CORE_CONFIG_PATH"
|
|
procd_set_param file "$CORE_CONFIG_PATH"
|
|
procd_set_param limits nofile="65536 65536"
|
|
|
|
if [ "$proxy_host" = "1" ]; then
|
|
procd_set_param group "UAmask"
|
|
logger -t "$NAME" "Running as group 'UAmask' for host proxying."
|
|
else
|
|
logger -t "$NAME" "Running as default user (proxy_host is disabled)."
|
|
fi
|
|
|
|
procd_set_param respawn
|
|
procd_set_param stdout 1
|
|
procd_set_param stderr 1
|
|
procd_close_instance
|
|
|
|
set_firewall
|
|
}
|
|
|
|
stop_service() {
|
|
logger -t "$NAME" "Stopping $NAME..."
|
|
# 停止服务时自动清理防火墙
|
|
unset_firewall
|
|
# procd 会自动使用 pidfile 停止 start-stop-daemon
|
|
}
|
|
|
|
service_triggers() {
|
|
procd_add_reload_trigger "$NAME"
|
|
}
|