mirror of
https://github.com/wnlen/clash-for-linux.git
synced 2026-02-04 10:11:28 +08:00
Merge branch 'master' of https://github.com/wnlen/clash-for-linux
This commit is contained in:
6
.env
6
.env
@ -31,6 +31,12 @@ export CLASH_SUBSCRIPTION=''
|
|||||||
# 留空时:脚本可自动生成随机值(若你的启动脚本支持)
|
# 留空时:脚本可自动生成随机值(若你的启动脚本支持)
|
||||||
export CLASH_SECRET=''
|
export CLASH_SECRET=''
|
||||||
|
|
||||||
|
# 是否在启动输出中显示完整 Secret(不推荐)
|
||||||
|
CLASH_SHOW_SECRET=true
|
||||||
|
|
||||||
|
# 是否显示脱敏 Secret(推荐)
|
||||||
|
CLASH_SHOW_SECRET_MASKED=true
|
||||||
|
|
||||||
# External Controller(Clash RESTful API)
|
# External Controller(Clash RESTful API)
|
||||||
# ⚠️ 安全建议:
|
# ⚠️ 安全建议:
|
||||||
# - 默认仅监听本机:127.0.0.1:9090 (推荐)
|
# - 默认仅监听本机:127.0.0.1:9090 (推荐)
|
||||||
|
|||||||
@ -1,9 +1,20 @@
|
|||||||
mixed-port: 7890
|
mixed-port: 7890
|
||||||
allow-lan: false
|
allow-lan: false
|
||||||
|
bind-address: '*'
|
||||||
mode: rule
|
mode: rule
|
||||||
log-level: info
|
log-level: info
|
||||||
|
ipv6: true
|
||||||
|
udp: true
|
||||||
|
|
||||||
|
external-controller: 127.0.0.1:9090
|
||||||
|
external-ui: /opt/clash-for-linux/dashboard/public
|
||||||
|
secret: ""
|
||||||
|
|
||||||
proxies: []
|
proxies: []
|
||||||
|
proxy-groups: []
|
||||||
|
|
||||||
rules:
|
rules:
|
||||||
- MATCH,DIRECT
|
- MATCH,DIRECT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,17 @@
|
|||||||
mixed-port: 7890
|
mixed-port: 7890
|
||||||
allow-lan: false
|
allow-lan: false
|
||||||
|
bind-address: '*'
|
||||||
mode: rule
|
mode: rule
|
||||||
log-level: info
|
log-level: info
|
||||||
|
ipv6: true
|
||||||
|
udp: true
|
||||||
|
|
||||||
|
external-controller: 127.0.0.1:9090
|
||||||
|
external-ui: /opt/clash-for-linux/dashboard/public
|
||||||
|
secret: ""
|
||||||
|
|
||||||
proxies: []
|
proxies: []
|
||||||
|
proxy-groups: []
|
||||||
|
|
||||||
rules:
|
rules:
|
||||||
- MATCH,DIRECT
|
- MATCH,DIRECT
|
||||||
|
|||||||
26
install.sh
26
install.sh
@ -239,13 +239,29 @@ api_host="${EXTERNAL_CONTROLLER%:*}"
|
|||||||
if [ -z "$api_host" ] || [ "$api_host" = "$EXTERNAL_CONTROLLER" ]; then
|
if [ -z "$api_host" ] || [ "$api_host" = "$EXTERNAL_CONTROLLER" ]; then
|
||||||
api_host="127.0.0.1"
|
api_host="127.0.0.1"
|
||||||
fi
|
fi
|
||||||
echo -e "🌐 Dashboard:http://${api_host}:${api_port}/ui"
|
|
||||||
|
|
||||||
# secret 可能在 .env 里是 CLASH_SECRET
|
# ---- Secret 展示(脱敏)----
|
||||||
if [ -n "${CLASH_SECRET:-}" ]; then
|
CONF_DIR="${CLASH_INSTALL_DIR:-/opt/clash-for-linux}/conf"
|
||||||
echo -e "🔐 Secret:${CLASH_SECRET}"
|
CONF_FILE="$CONF_DIR/config.yaml"
|
||||||
|
|
||||||
|
# 读取 secret(如果 clash 还没生成 config,就先不显示)
|
||||||
|
SECRET_VAL=""
|
||||||
|
if [ -f "$CONF_FILE" ]; then
|
||||||
|
SECRET_VAL="$(awk -F': *' '/^secret:/{print $2; exit}' "$CONF_FILE" | tr -d '"' | tr -d "'" )"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$SECRET_VAL" ]; then
|
||||||
|
# 脱敏显示:前4后4
|
||||||
|
MASKED="${SECRET_VAL:0:4}****${SECRET_VAL: -4}"
|
||||||
|
echo ""
|
||||||
|
echo -e "🌐 Dashboard:http://${api_host}:${api_port}/ui"
|
||||||
|
echo "🔐 Secret:${MASKED}"
|
||||||
|
echo " 查看完整 Secret:sudo awk -F': *' '/^secret:/{print \$2; exit}' $CONF_FILE"
|
||||||
else
|
else
|
||||||
echo -e "🔐 Secret:请查看 .env 或启动日志输出"
|
echo ""
|
||||||
|
echo -e "🌐 Dashboard:http://${api_host}:${api_port}/ui"
|
||||||
|
echo "🔐 Secret:未配置(当前为无鉴权模式,仅限本机访问),可用以下命令查看:"
|
||||||
|
echo " sudo awk -F': *' '/^secret:/{print \$2; exit}' $CONF_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
|||||||
53
start.sh
53
start.sh
@ -53,15 +53,38 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 获取 CLASH_SECRET 值:优先 .env;否则尝试读取旧 config;否则生成随机数
|
# 获取 CLASH_SECRET 值:优先 .env;其次读取旧 config;占位符视为无效;最后生成随机值
|
||||||
Secret="${CLASH_SECRET:-}"
|
Secret="${CLASH_SECRET:-}"
|
||||||
|
|
||||||
|
# 尝试从旧 config.yaml 读取(仅当 .env 未提供)
|
||||||
if [ -z "$Secret" ] && [ -f "$Conf_Dir/config.yaml" ]; then
|
if [ -z "$Secret" ] && [ -f "$Conf_Dir/config.yaml" ]; then
|
||||||
Secret="$(awk -F': ' '/^secret:/{print $2; exit}' "$Conf_Dir/config.yaml" || true)"
|
Secret="$(awk -F': *' '/^secret:/{gsub(/"/,"",$2); print $2; exit}' "$Conf_Dir/config.yaml" || true)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 若读取到的是占位符(如 ${CLASH_SECRET}),视为无效
|
||||||
|
if [[ "$Secret" =~ ^\$\{.*\}$ ]]; then
|
||||||
|
Secret=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 兜底生成随机 secret
|
||||||
if [ -z "$Secret" ]; then
|
if [ -z "$Secret" ]; then
|
||||||
Secret="$(openssl rand -hex 32)"
|
Secret="$(openssl rand -hex 32)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 强制写入 secret 到指定配置文件(存在则替换,不存在则追加)
|
||||||
|
force_write_secret() {
|
||||||
|
local file="$1"
|
||||||
|
[ -f "$file" ] || return 0
|
||||||
|
|
||||||
|
if grep -qE '^[[:space:]]*secret:' "$file"; then
|
||||||
|
# 替换整行 secret(无论原来是啥,包括 SECRET_PLACEHOLDER / "${CLASH_SECRET}")
|
||||||
|
sed -i -E "s|^[[:space:]]*secret:.*$|secret: ${Secret}|g" "$file"
|
||||||
|
else
|
||||||
|
# 没有 secret 行就追加到文件末尾
|
||||||
|
printf "\nsecret: %s\n" "$Secret" >> "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# 设置默认值
|
# 设置默认值
|
||||||
CLASH_HTTP_PORT="${CLASH_HTTP_PORT:-7890}"
|
CLASH_HTTP_PORT="${CLASH_HTTP_PORT:-7890}"
|
||||||
CLASH_SOCKS_PORT="${CLASH_SOCKS_PORT:-7891}"
|
CLASH_SOCKS_PORT="${CLASH_SOCKS_PORT:-7891}"
|
||||||
@ -155,6 +178,8 @@ ensure_fallback_config() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
# 强制写入真实 secret
|
||||||
|
force_write_secret "$Conf_Dir/config.yaml"
|
||||||
}
|
}
|
||||||
|
|
||||||
SKIP_CONFIG_REBUILD=false
|
SKIP_CONFIG_REBUILD=false
|
||||||
@ -319,11 +344,11 @@ if [ "$SKIP_CONFIG_REBUILD" != "true" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# 写入 secret
|
# 写入 secret
|
||||||
sed -r -i "/^secret: /s@(secret: ).*@\1${Secret}@g" "$Conf_Dir/config.yaml" || true
|
force_write_secret "$Conf_Dir/config.yaml"
|
||||||
else
|
else
|
||||||
# 兜底路径:尽量也写入 secret(若 config 里有 secret: 行就替换;没有就追加)
|
# 兜底路径:尽量也写入 secret(若 config 里有 secret: 行就替换;没有就追加)
|
||||||
if grep -qE '^secret:\s*' "$Conf_Dir/config.yaml" 2>/dev/null; then
|
if grep -qE '^secret:\s*' "$Conf_Dir/config.yaml" 2>/dev/null; then
|
||||||
sed -r -i "/^secret: /s@(secret: ).*@\1${Secret}@g" "$Conf_Dir/config.yaml" || true
|
force_write_secret "$Conf_Dir/config.yaml"
|
||||||
else
|
else
|
||||||
echo "secret: ${Secret}" >> "$Conf_Dir/config.yaml" || true
|
echo "secret: ${Secret}" >> "$Conf_Dir/config.yaml" || true
|
||||||
fi
|
fi
|
||||||
@ -337,6 +362,12 @@ if [ ! -s "$Conf_Dir/config.yaml" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 最终护栏:禁止未渲染的占位符进入运行态
|
||||||
|
if grep -q '\${' "$Conf_Dir/config.yaml"; then
|
||||||
|
echo "[ERROR] config.yaml contains unresolved placeholders (\${...}). Please check template rendering." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo -e '\n正在启动Clash服务...'
|
echo -e '\n正在启动Clash服务...'
|
||||||
Text5="服务启动成功!"
|
Text5="服务启动成功!"
|
||||||
Text6="服务启动失败!"
|
Text6="服务启动失败!"
|
||||||
@ -360,7 +391,19 @@ if_success "$Text5" "$Text6" "$ReturnStatus"
|
|||||||
echo ''
|
echo ''
|
||||||
if [ "$EXTERNAL_CONTROLLER_ENABLED" = "true" ]; then
|
if [ "$EXTERNAL_CONTROLLER_ENABLED" = "true" ]; then
|
||||||
echo -e "Clash Dashboard 访问地址: http://${EXTERNAL_CONTROLLER}/ui"
|
echo -e "Clash Dashboard 访问地址: http://${EXTERNAL_CONTROLLER}/ui"
|
||||||
echo -e "Secret: ${Secret}"
|
|
||||||
|
SHOW_SECRET="${CLASH_SHOW_SECRET:-false}"
|
||||||
|
SHOW_SECRET_MASKED="${CLASH_SHOW_SECRET_MASKED:-true}"
|
||||||
|
|
||||||
|
if [ "$SHOW_SECRET" = "true" ]; then
|
||||||
|
echo -e "Secret: ${Secret}"
|
||||||
|
elif [ "$SHOW_SECRET_MASKED" = "true" ]; then
|
||||||
|
# 脱敏:前4后4
|
||||||
|
masked="${Secret:0:4}****${Secret: -4}"
|
||||||
|
echo -e "Secret: ${masked} (set CLASH_SHOW_SECRET=true to show full)"
|
||||||
|
else
|
||||||
|
echo -e "Secret: 已生成(未显示)。查看:/opt/clash-for-linux/conf/config.yaml 或 .env"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "External Controller (Dashboard) 已禁用"
|
echo -e "External Controller (Dashboard) 已禁用"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user