mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-10-26 18:12:51 +08:00
579 lines
14 KiB
Bash
Executable File
579 lines
14 KiB
Bash
Executable File
#!/bin/sh
|
|
# Copyright (C) 2022-2025 xiaorouji
|
|
# Copyright (C) 2026 Openwrt-Passwall Organization
|
|
|
|
CONFIG=passwall
|
|
APP_PATH=/usr/share/${CONFIG}
|
|
TMP_PATH=/tmp/etc/${CONFIG}
|
|
TMP_PATH2=${TMP_PATH}_tmp
|
|
LOCK_PATH=/var/lock
|
|
LOG_FILE=/tmp/log/${CONFIG}.log
|
|
TMP_ACL_PATH=${TMP_PATH}/acl
|
|
TMP_BIN_PATH=${TMP_PATH}/bin
|
|
TMP_IFACE_PATH=${TMP_PATH}/iface
|
|
TMP_ROUTE_PATH=${TMP_PATH}/route
|
|
TMP_SCRIPT_FUNC_PATH=${TMP_PATH}/script_func
|
|
RULES_PATH=/usr/share/${CONFIG}/rules
|
|
USER_RULES_PATH=/etc/${CONFIG}/rules
|
|
|
|
IPv6_REGEX="([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|"
|
|
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,7}:|"
|
|
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|"
|
|
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|"
|
|
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|"
|
|
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|"
|
|
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|"
|
|
IPv6_REGEX="${IPv6_REGEX}[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|"
|
|
IPv6_REGEX="${IPv6_REGEX}:((:[0-9a-fA-F]{1,4}){1,7}|:)|"
|
|
IPv6_REGEX="${IPv6_REGEX}fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|"
|
|
IPv6_REGEX="${IPv6_REGEX}::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|"
|
|
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
|
|
IPv4_REGEX="((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
|
|
|
|
. /lib/functions/network.sh
|
|
|
|
echolog() {
|
|
local d="$(date "+%Y-%m-%d %H:%M:%S")"
|
|
echo -e "$d: $*" >>$LOG_FILE
|
|
}
|
|
|
|
clean_log() {
|
|
logsnum=$(cat $LOG_FILE 2>/dev/null | wc -l)
|
|
[ "$logsnum" -gt 1000 ] && {
|
|
echo "" > $LOG_FILE
|
|
echolog "日志文件过长,清空处理!"
|
|
}
|
|
}
|
|
|
|
config_get_type() {
|
|
local ret=$(uci -q get "${CONFIG}.${1}" 2>/dev/null)
|
|
printf '%s' "${ret:=$2}"
|
|
}
|
|
|
|
config_n_get() {
|
|
local ret=$(uci -q get "${CONFIG}.${1}.${2}" 2>/dev/null)
|
|
printf '%s' "${ret:=$3}"
|
|
}
|
|
|
|
config_t_get() {
|
|
local index=${4:-0}
|
|
local ret=$(uci -q get "${CONFIG}.@${1}[${index}].${2}" 2>/dev/null)
|
|
printf '%s' "${ret:=${3}}"
|
|
}
|
|
|
|
eval_set_val() {
|
|
for i in $@; do
|
|
for j in $i; do
|
|
eval $j
|
|
done
|
|
done
|
|
}
|
|
|
|
eval_unset_val() {
|
|
for i in $@; do
|
|
for j in $i; do
|
|
eval unset $j
|
|
done
|
|
done
|
|
}
|
|
|
|
lua_api() {
|
|
local func=${1}
|
|
[ -z "${func}" ] && {
|
|
echo "nil"
|
|
return
|
|
}
|
|
echo $(lua -e "local api = require 'luci.passwall.api' print(api.${func})")
|
|
}
|
|
|
|
eval_cache_var() {
|
|
[ -s "$TMP_PATH/var" ] && . "$TMP_PATH/var"
|
|
}
|
|
|
|
del_cache_var() {
|
|
local key="${1}"
|
|
[ -n "${key}" ] && [ -f "${TMP_PATH}/var" ] && {
|
|
sed -i "/^${key}=/d" "$TMP_PATH/var" >/dev/null 2>&1
|
|
}
|
|
}
|
|
|
|
set_cache_var() {
|
|
local key="${1}"
|
|
shift 1
|
|
[ -n "${key}" ] && {
|
|
del_cache_var ${key}
|
|
local val="$@"
|
|
[ -n "${val}" ] && {
|
|
[ ! -d $TMP_PATH ] && mkdir -p $TMP_PATH
|
|
printf '%s=%s\n' "$key" "$(shell_quote "$val")" >> "$TMP_PATH/var"
|
|
eval "$key=\$val"
|
|
}
|
|
}
|
|
}
|
|
|
|
get_cache_var() {
|
|
[ -n "$1" ] && [ -s "$TMP_PATH/var" ] && (
|
|
. "$TMP_PATH/var"
|
|
eval "printf '%s' \"\${$1-}\""
|
|
)
|
|
}
|
|
|
|
first_type() {
|
|
[ "${1#/}" != "$1" ] && [ -x "$1" ] && echo "$1" && return
|
|
for p in "/bin/$1" "/usr/bin/$1" "${TMP_BIN_PATH:-/tmp}/$1"; do
|
|
[ -x "$p" ] && echo "$p" && return
|
|
done
|
|
command -v "$1" 2>/dev/null || command -v "$2" 2>/dev/null
|
|
}
|
|
|
|
get_enabled_anonymous_secs() {
|
|
uci -q show "${CONFIG}" | grep "${1}\[.*\.enabled='1'" | cut -d '.' -sf2
|
|
}
|
|
|
|
get_geoip() {
|
|
local geo_output_path="$TMP_PATH2/geo_output"
|
|
mkdir -p ${geo_output_path}
|
|
local geoip_code="$1"
|
|
local geoip_type_flag=""
|
|
local output_path="${geo_output_path}/geoip-${geoip_code}-$2"
|
|
[ ! -s "${output_path}" ] && {
|
|
local geoip_path="$(config_n_get @global_rules[0] v2ray_location_asset)"
|
|
geoip_path="${geoip_path%*/}/geoip.dat"
|
|
local bin="$(first_type $(config_n_get @global_app[0] geoview_file) geoview)"
|
|
[ -n "$bin" ] && [ -s "$geoip_path" ] || { echo ""; return; }
|
|
case "$2" in
|
|
"ipv4") geoip_type_flag="-ipv6=false" ;;
|
|
"ipv6") geoip_type_flag="-ipv4=false" ;;
|
|
esac
|
|
"$bin" -input "$geoip_path" -list "$geoip_code" $geoip_type_flag -lowmem=true -output ${output_path}
|
|
}
|
|
[ -s "${output_path}" ] && cat "${output_path}"
|
|
}
|
|
|
|
get_host_ip() {
|
|
local host=$2
|
|
local count=$3
|
|
[ -z "$count" ] && count=3
|
|
local isip=""
|
|
local ip=""
|
|
if [ "$1" = "ipv6" ]; then
|
|
host=${host#[}
|
|
host=${host%]}
|
|
isip=$(printf '%s' "$host" | grep -E "^($IPv6_REGEX)$")
|
|
[ -n "$isip" ] && ip=$isip
|
|
else
|
|
isip=$(printf '%s' "$host" | grep -E "^($IPv4_REGEX)$")
|
|
[ -n "$isip" ] && ip=$isip
|
|
fi
|
|
[ -z "$isip" ] && {
|
|
local t=4
|
|
[ "$1" = "ipv6" ] && t=6
|
|
local vpsrip=$(resolveip -$t -t "$count" "$host" | awk 'NR==1{print}')
|
|
ip=$vpsrip
|
|
}
|
|
[ -n "$ip" ] && echo "$ip"
|
|
}
|
|
|
|
get_node_host_ip() {
|
|
local ip
|
|
local address=$(config_n_get $1 address)
|
|
[ -n "$address" ] && {
|
|
local use_ipv6=$(config_n_get $1 use_ipv6)
|
|
local network_type="ipv4"
|
|
[ "$use_ipv6" = "1" ] && network_type="ipv6"
|
|
ip=$(get_host_ip $network_type $address)
|
|
}
|
|
echo $ip
|
|
}
|
|
|
|
get_ip_port_from() {
|
|
local __host=${1}; shift 1
|
|
local __ipv=${1}; shift 1
|
|
local __portv=${1}; shift 1
|
|
local __ucipriority=${1}; shift 1
|
|
|
|
local val1="$__host" val2
|
|
case "$__host" in
|
|
*\#*) val1=${__host%#*}; val2=${__host##*#} ;;
|
|
\[*\]:*) val1=${__host%\]:*}; val2=${__host##*:} ;;
|
|
*:*:*) ;;
|
|
*:*) val1=${__host%:*}; val2=${__host##*:} ;;
|
|
esac
|
|
if [ -n "${__ucipriority}" ]; then
|
|
val2=$(config_n_get "$__host" port "$val2")
|
|
val1=$(config_n_get "$__host" address "$val1")
|
|
fi
|
|
val1=${val1#[}
|
|
val1=${val1%]}
|
|
eval "${__ipv}=\$val1; ${__portv}=\$val2"
|
|
}
|
|
|
|
parse_doh() {
|
|
local __doh=$1 __url_var=$2 __host_var=$3 __port_var=$4 __bootstrap_var=$5
|
|
__doh=$(printf '%s' "$__doh" | tr -d ' \t\n')
|
|
local __url=${__doh%%,*}
|
|
local __bootstrap=${__doh#*,}
|
|
[ "$__bootstrap" = "$__doh" ] && __bootstrap=""
|
|
local __host_port=$(lua_api "get_domain_from_url(\"${__url}\")")
|
|
local __host __port
|
|
if echo "${__host_port}" | grep -q '^\[.*\]:[0-9]\+$'; then
|
|
__host=${__host_port%%]:*}]
|
|
__port=${__host_port##*:}
|
|
elif echo "${__host_port}" | grep -q ':[0-9]\+$'; then
|
|
__host=${__host_port%:*}
|
|
__port=${__host_port##*:}
|
|
else
|
|
__host=${__host_port}
|
|
__port=443
|
|
fi
|
|
__host=${__host#[}
|
|
__host=${__host%]}
|
|
if [ "$(lua_api "is_ip(\"${__host}\")")" = "true" ]; then
|
|
__bootstrap=${__host}
|
|
fi
|
|
__bootstrap=${__bootstrap#[}
|
|
__bootstrap=${__bootstrap%]}
|
|
eval "${__url_var}='${__url}' ${__host_var}='${__host}' ${__port_var}='${__port}' ${__bootstrap_var}='${__bootstrap}'"
|
|
}
|
|
|
|
host_from_url(){
|
|
local f="${1}"
|
|
f=${f#*://}
|
|
f=${f%%[/?#]*}
|
|
f=${f##*@}
|
|
case "$f" in
|
|
\[*\]*) f=${f#\[}; f=${f%%\]*} ;;
|
|
*) f=${f%%:*} ;;
|
|
esac
|
|
printf '%s' "$f"
|
|
}
|
|
|
|
hosts_foreach() {
|
|
local __hosts
|
|
eval "__hosts=\$${1}"; shift 1
|
|
local __func=${1}; shift 1
|
|
local __default_port=${1}; shift 1
|
|
local __ret=1
|
|
|
|
[ -z "${__hosts}" ] && return 0
|
|
local __ip __port
|
|
for __host in $(echo $__hosts | sed 's/[ ,]/\n/g'); do
|
|
get_ip_port_from "$__host" "__ip" "__port"
|
|
eval "$__func \"${__host}\" \"\${__ip}\" \"\${__port:-${__default_port}}\" \"$@\""
|
|
__ret=$?
|
|
[ ${__ret} -ge ${ERROR_NO_CATCH:-1} ] && return ${__ret}
|
|
done
|
|
return 0
|
|
}
|
|
|
|
check_host() {
|
|
local f=${1}
|
|
a=$(echo $f | grep "\/")
|
|
[ -n "$a" ] && return 1
|
|
# 判断是否包含汉字~
|
|
local tmp=$(echo -n $f | awk '{print gensub(/[!-~]/,"","g",$0)}')
|
|
[ -n "$tmp" ] && return 1
|
|
return 0
|
|
}
|
|
|
|
normalize_dns() {
|
|
local s="$1"
|
|
local addr port="${2-}"
|
|
case "$s" in
|
|
\[*\]:*)
|
|
# [ip6]:port
|
|
addr="${s%\]:*}"
|
|
addr="${addr#\[}"
|
|
port="${s##*:}"
|
|
;;
|
|
*\#*)
|
|
# ip4#port or ip6#port
|
|
addr="${s%\#*}"
|
|
port="${s##*\#}"
|
|
;;
|
|
*.*:*)
|
|
# ip4:port
|
|
addr="${s%:*}"
|
|
port="${s##*:}"
|
|
;;
|
|
\[*\])
|
|
# [ip6]
|
|
addr="${s#\[}"
|
|
addr="${addr%\]}"
|
|
;;
|
|
*)
|
|
addr="$s"
|
|
;;
|
|
esac
|
|
[ -n "$port" ] && echo "${addr}#${port}" || echo "$addr"
|
|
}
|
|
|
|
format_dns() {
|
|
local dns="${1%%#*}"
|
|
local port="${1#*#}"
|
|
[ "$port" = "$1" ] && port="${2-53}"
|
|
case "$dns" in
|
|
*:*) echo "[$dns]:$port" ;;
|
|
*) echo "$dns:$port" ;;
|
|
esac
|
|
}
|
|
|
|
check_port_exists() {
|
|
local port=$1
|
|
local protocol=$2
|
|
[ -n "$protocol" ] || protocol="tcp,udp"
|
|
local result=
|
|
if [ "$protocol" = "tcp" ]; then
|
|
result=$(netstat -tln | grep -c ":$port ")
|
|
elif [ "$protocol" = "udp" ]; then
|
|
result=$(netstat -uln | grep -c ":$port ")
|
|
elif [ "$protocol" = "tcp,udp" ]; then
|
|
result=$(netstat -tuln | grep -c ":$port ")
|
|
fi
|
|
echo "${result}"
|
|
}
|
|
|
|
get_new_port() {
|
|
local default_start_port=2001
|
|
local min_port=1025
|
|
local max_port=49151
|
|
local port="$1" # Required parameter; please pass "auto" if you want it to be automatic.
|
|
local protocol=$(echo "$2" | tr 'A-Z' 'a-z')
|
|
local is_auto
|
|
if [ "$port" = "auto" ]; then
|
|
is_auto=1
|
|
local last_get_new_port_auto=$(get_cache_var "last_get_new_port_auto")
|
|
if [ -n "$last_get_new_port_auto" ]; then
|
|
port=$(expr "$last_get_new_port_auto" + 1)
|
|
else
|
|
port=$default_start_port
|
|
fi
|
|
fi
|
|
([ "$port" -lt "$min_port" ] || [ "$port" -gt "$max_port" ]) && port=$default_start_port
|
|
local start_port=$port
|
|
while :; do
|
|
local result=$(check_port_exists "$port" "$protocol")
|
|
if [ "$is_auto" = "1" ] && [ -n "$(get_cache_var "get_port_${port}")" ]; then
|
|
# The port has already been allocated, continue to the next port.
|
|
result=1
|
|
fi
|
|
[ "$result" = "0" ] && break
|
|
if [ "$port" -lt "$max_port" ]; then
|
|
# If the port is smaller than the maximum port, increment by 1 and continue.
|
|
port=$(expr "$port" + 1)
|
|
else
|
|
port=$min_port
|
|
fi
|
|
[ "$port" -eq "$start_port" ] && return 1
|
|
done
|
|
if [ "$is_auto" = "1" ]; then
|
|
# Set cache to prevent the port from being allocated again.
|
|
set_cache_var "get_port_${port}" "1"
|
|
set_cache_var "last_get_new_port_auto" "$port"
|
|
fi
|
|
echo "$port"
|
|
}
|
|
|
|
check_ver() {
|
|
local version1="$1"
|
|
local version2="$2"
|
|
local i v1 v1_1 v1_2 v1_3 v2 v2_1 v2_2 v2_3
|
|
local old_ifs="$IFS"
|
|
IFS='.'
|
|
set -- $version1; v1_1=${1:-0}; v1_2=${2:-0}; v1_3=${3:-0}
|
|
set -- $version2; v2_1=${1:-0}; v2_2=${2:-0}; v2_3=${3:-0}
|
|
IFS="$old_ifs"
|
|
for i in 1 2 3; do
|
|
eval v1=\$v1_$i
|
|
eval v2=\$v2_$i
|
|
if [ "$v1" -gt "$v2" ]; then
|
|
# $1 大于 $2
|
|
echo 0
|
|
return
|
|
elif [ "$v1" -lt "$v2" ]; then
|
|
# $1 小于 $2
|
|
echo 1
|
|
return
|
|
fi
|
|
done
|
|
# $1 等于 $2
|
|
echo 255
|
|
}
|
|
|
|
has_1_65535() {
|
|
local val="$1"
|
|
val=${val//:/-}
|
|
case ",$val," in
|
|
*,1-65535,*) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
add_ip2route() {
|
|
local ip=$(get_host_ip "ipv4" $1)
|
|
[ -z "$ip" ] && {
|
|
echolog " - 无法解析[${1}],路由表添加失败!"
|
|
return 1
|
|
}
|
|
local remarks="${1}"
|
|
[ "$remarks" != "$ip" ] && remarks="${1}(${ip})"
|
|
|
|
local gateway device
|
|
network_get_gateway gateway "$2"
|
|
network_get_device device "$2"
|
|
[ -z "${device}" ] && device=$(ubus call "network.interface.$2" status 2>/dev/null | jsonfilter -e '@.device' 2>/dev/null)
|
|
[ -z "${device}" ] && [ -d "/sys/class/net/$2" ] && device="$2"
|
|
[ -z "${device}" ] && device="$2"
|
|
|
|
if [ -n "${gateway}" ]; then
|
|
if route add -host "$ip" gw "$gateway" dev "$device" >/dev/null 2>&1; then
|
|
printf '%s\n' "$ip" >> "$TMP_ROUTE_PATH/$device"
|
|
echolog " - [${remarks}]添加到接口[${device}]路由表成功!"
|
|
else
|
|
echolog " - [${remarks}]添加到接口[${device}]路由表失败!"
|
|
return 1
|
|
fi
|
|
else
|
|
echolog " - [${remarks}]添加到接口[${device}]路由表失败!原因是找不到[${device}]网关。"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
delete_ip2route() {
|
|
[ -d "${TMP_ROUTE_PATH}" ] && {
|
|
local interface
|
|
for interface in $(ls ${TMP_ROUTE_PATH}); do
|
|
for ip in $(cat ${TMP_ROUTE_PATH}/${interface}); do
|
|
route del -host ${ip} dev ${interface} >/dev/null 2>&1
|
|
done
|
|
done
|
|
}
|
|
}
|
|
|
|
shell_quote() {
|
|
printf "'"
|
|
printf '%s' "$1" | sed "s/'/'\\\\''/g"
|
|
printf "'"
|
|
}
|
|
|
|
get_process_start_time() {
|
|
sed 's/.*) //' "/proc/$1/stat" 2>/dev/null | awk '{print $20}'
|
|
}
|
|
|
|
ln_run() {
|
|
local file_func=${1}
|
|
local ln_name=${2}
|
|
local output=${3}
|
|
|
|
shift 3;
|
|
case "$ln_name" in
|
|
dnsmasq*) set -- -k "$@" ;;
|
|
haproxy) set -- -db "$@" ;;
|
|
esac
|
|
if [ "${file_func%%/*}" != "${file_func}" ]; then
|
|
[ ! -L "${file_func}" ] && {
|
|
ln -s "${file_func}" "${TMP_BIN_PATH}/${ln_name}" >/dev/null 2>&1
|
|
file_func="${TMP_BIN_PATH}/${ln_name}"
|
|
}
|
|
[ -x "${file_func}" ] || echolog " - $(readlink ${file_func}) 没有执行权限,无法启动:${file_func} $*"
|
|
fi
|
|
#echo "${file_func} $*" >&2
|
|
[ -n "${file_func}" ] || {
|
|
echolog " - 找不到 ${ln_name},无法启动..."
|
|
return 1
|
|
}
|
|
|
|
"$file_func" "$@" >"$output" 2>&1 &
|
|
local pid=$!
|
|
|
|
[ "$NO_REC_PROCESS" = "1" ] && return
|
|
local process_file=$(mktemp "$TMP_SCRIPT_FUNC_PATH/XXXXXX")
|
|
local arg
|
|
{
|
|
printf '%s\n' "$pid" "$(get_process_start_time "$pid")"
|
|
printf '%s' "$(shell_quote "$file_func")"
|
|
for arg in "$@"; do
|
|
printf ' %s' "$(shell_quote "$arg")"
|
|
done
|
|
printf ' >%s 2>&1\n' "$(shell_quote "$output")"
|
|
} > "$process_file"
|
|
}
|
|
|
|
kill_all() {
|
|
kill -9 $(pidof "$@") >/dev/null 2>&1
|
|
}
|
|
|
|
get_subscribe_host(){
|
|
local line
|
|
uci show "${CONFIG}" | grep "=subscribe_list" | while read -r line; do
|
|
local section="$(echo "$line" | cut -d '.' -sf 2 | cut -d '=' -sf 1)"
|
|
local url="$(config_n_get $section url)"
|
|
[ -n "$url" ] || continue
|
|
url="$(host_from_url "$url")"
|
|
echo "$url"
|
|
done
|
|
}
|
|
|
|
gen_lanlist() {
|
|
cat $USER_RULES_PATH/lanlist_ipv4 | tr -s '\n' | grep -v "^#"
|
|
}
|
|
|
|
gen_lanlist_6() {
|
|
cat $USER_RULES_PATH/lanlist_ipv6 | tr -s '\n' | grep -v "^#"
|
|
}
|
|
|
|
get_wan_ips() {
|
|
local family="$1"
|
|
local NET_ADDR
|
|
local iface addr addrs
|
|
local INTERFACES=$(ubus call network.interface dump | jsonfilter -e \
|
|
'@.interface[!(@.interface ~ /lan/) && @.route[0]].interface')
|
|
for iface in $INTERFACES; do
|
|
if [ "$family" = "ip6" ]; then
|
|
network_get_ipaddrs6 addrs "$iface"
|
|
else
|
|
network_get_ipaddrs addrs "$iface"
|
|
fi
|
|
for addr in $addrs; do
|
|
case "$addr" in
|
|
""|0.0.0.0|::|fe80:*) continue ;;
|
|
esac
|
|
case " $NET_ADDR " in
|
|
*" $addr "*) ;;
|
|
*) NET_ADDR="${NET_ADDR:+$NET_ADDR }$addr" ;;
|
|
esac
|
|
done
|
|
done
|
|
echo "$NET_ADDR"
|
|
}
|
|
|
|
get_local_ips() {
|
|
local family="$1"
|
|
local ALL_IPS WAN_IPS ip NET_ADDR
|
|
if [ "$family" = "ip6" ]; then
|
|
ALL_IPS=$(ip -o -6 addr show scope global | awk '{print $4}' | cut -d/ -f1)
|
|
WAN_IPS=$(get_wan_ips ip6)
|
|
else
|
|
ALL_IPS=$(ip -o -4 addr show scope global | awk '{print $4}' | cut -d/ -f1)
|
|
WAN_IPS=$(get_wan_ips ip4)
|
|
fi
|
|
# 补充回环(scope global 不包含)
|
|
[ "$family" = "ip6" ] && ALL_IPS="$ALL_IPS ::1"
|
|
[ "$family" != "ip6" ] && ALL_IPS="$ALL_IPS 127.0.0.1"
|
|
for ip in $ALL_IPS; do
|
|
case "$ip" in
|
|
""|0.0.0.0|::) continue ;;
|
|
esac
|
|
case " $WAN_IPS " in
|
|
*" $ip "*) continue ;;
|
|
esac
|
|
case " $NET_ADDR " in
|
|
*" $ip "*) ;;
|
|
*) NET_ADDR="${NET_ADDR:+$NET_ADDR }$ip" ;;
|
|
esac
|
|
done
|
|
for ip in $NET_ADDR; do
|
|
echo "$ip"
|
|
done
|
|
}
|