Add Clash subscription with User-Agent routing
- clash.yaml template (proxy-providers -> x-ui base64 sub URL) in assets/clash/ - install_clash_sub() downloads and substitutes domain/sub_path at install time - nginx: map $http_user_agent $is_clash_client detects Clash/Mihomo/Stash/Surfboard - sub_path locations rewrite to internal /__clash_sub on UA match - /__clash_sub serves /var/www/subpage/clash.yaml as text/yaml - Regular clients still proxy to x-ui sub port unchanged - Uninstall cleans /var/www/subpage/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
c548d9934a
commit
138e41574c
@@ -0,0 +1,92 @@
|
|||||||
|
mixed-port: 7890
|
||||||
|
allow-lan: false
|
||||||
|
log-level: info
|
||||||
|
ipv6: false
|
||||||
|
|
||||||
|
mode: rule
|
||||||
|
dns:
|
||||||
|
enable: true
|
||||||
|
use-hosts: true
|
||||||
|
ipv6: false
|
||||||
|
enhanced-mode: redir-host
|
||||||
|
listen: 127.0.0.1:6868
|
||||||
|
default-nameserver:
|
||||||
|
- 1.1.1.1
|
||||||
|
- 8.8.8.8
|
||||||
|
- 1.0.0.1
|
||||||
|
nameserver:
|
||||||
|
- https://1.1.1.1/dns-query#PROXY
|
||||||
|
- https://8.8.8.8/dns-query#PROXY
|
||||||
|
- https://1.0.0.1/dns-query#PROXY
|
||||||
|
- 8.8.8.8
|
||||||
|
- 1.1.1.1
|
||||||
|
|
||||||
|
profile:
|
||||||
|
store-selected: true
|
||||||
|
|
||||||
|
proxy-groups:
|
||||||
|
- name: PROXY
|
||||||
|
proxies:
|
||||||
|
- auto
|
||||||
|
use:
|
||||||
|
- sub
|
||||||
|
type: select
|
||||||
|
|
||||||
|
- name: auto
|
||||||
|
use:
|
||||||
|
- sub
|
||||||
|
type: url-test
|
||||||
|
url: http://cp.cloudflare.com
|
||||||
|
interval: 300
|
||||||
|
tolerance: 150
|
||||||
|
lazy: true
|
||||||
|
|
||||||
|
proxy-providers:
|
||||||
|
sub:
|
||||||
|
type: http
|
||||||
|
url: https://${DOMAIN}/${SUB_PATH}/
|
||||||
|
path: ./proxy_providers/base64.yml
|
||||||
|
interval: 3600
|
||||||
|
health-check:
|
||||||
|
enable: true
|
||||||
|
url: https://www.gstatic.com/generate_204
|
||||||
|
interval: 300
|
||||||
|
timeout: 5000
|
||||||
|
lazy: true
|
||||||
|
expected-status: 204
|
||||||
|
|
||||||
|
rule-providers:
|
||||||
|
ru-bundle:
|
||||||
|
type: http
|
||||||
|
behavior: domain
|
||||||
|
format: mrs
|
||||||
|
url: https://github.com/legiz-ru/mihomo-rule-sets/raw/main/ru-bundle/rule.mrs
|
||||||
|
path: ./ru-bundle/rule.mrs
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
rules:
|
||||||
|
- PROCESS-NAME,Discord.exe,PROXY
|
||||||
|
- PROCESS-NAME,com.supercell.clashofclans,PROXY
|
||||||
|
- PROCESS-NAME,com.supercell.brawlstars,PROXY
|
||||||
|
- RULE-SET,ru-bundle,PROXY
|
||||||
|
- MATCH,DIRECT
|
||||||
|
|
||||||
|
sniffer:
|
||||||
|
enable: true
|
||||||
|
force-dns-mapping: true
|
||||||
|
parse-pure-ip: true
|
||||||
|
sniff:
|
||||||
|
HTTP:
|
||||||
|
ports: [80, 8080-8880]
|
||||||
|
override-destination: true
|
||||||
|
TLS:
|
||||||
|
ports: [443, 8443]
|
||||||
|
|
||||||
|
tun:
|
||||||
|
enable: true
|
||||||
|
stack: system
|
||||||
|
dns-hijack:
|
||||||
|
- any:53
|
||||||
|
auto-redir: true
|
||||||
|
auto-route: true
|
||||||
|
auto-detect-interface: true
|
||||||
+37
-2
@@ -141,7 +141,7 @@ uninstall_xui() {
|
|||||||
$Pak -y purge nginx nginx-common nginx-core nginx-full python3-certbot-nginx
|
$Pak -y purge nginx nginx-common nginx-core nginx-full python3-certbot-nginx
|
||||||
$Pak -y autoremove
|
$Pak -y autoremove
|
||||||
$Pak -y autoclean
|
$Pak -y autoclean
|
||||||
rm -rf /var/www/html/ /var/www/diagnostics/ /etc/nginx/ /usr/share/nginx/
|
rm -rf /var/www/html/ /var/www/diagnostics/ /var/www/subpage/ /etc/nginx/ /usr/share/nginx/
|
||||||
systemctl stop mtr-backend 2>/dev/null || true
|
systemctl stop mtr-backend 2>/dev/null || true
|
||||||
systemctl disable mtr-backend 2>/dev/null || true
|
systemctl disable mtr-backend 2>/dev/null || true
|
||||||
rm -f /etc/systemd/system/mtr-backend.service
|
rm -f /etc/systemd/system/mtr-backend.service
|
||||||
@@ -307,9 +307,10 @@ EOF
|
|||||||
|
|
||||||
# Shared proxy locations for xray inbounds (included by both vhosts)
|
# Shared proxy locations for xray inbounds (included by both vhosts)
|
||||||
cat > /etc/nginx/snippets/includes.conf <<EOF
|
cat > /etc/nginx/snippets/includes.conf <<EOF
|
||||||
#Subscription (plain/encode)
|
#Subscription (plain/encode) — Clash/Mihomo clients get static clash.yaml by UA
|
||||||
location /${sub_path} {
|
location /${sub_path} {
|
||||||
if (\$hack = 1) { return 404; }
|
if (\$hack = 1) { return 404; }
|
||||||
|
if (\$is_clash_client = 1) { rewrite ^ /__clash_sub last; }
|
||||||
proxy_redirect off;
|
proxy_redirect off;
|
||||||
proxy_set_header Host \$host;
|
proxy_set_header Host \$host;
|
||||||
proxy_set_header X-Real-IP \$remote_addr;
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
@@ -318,6 +319,7 @@ EOF
|
|||||||
}
|
}
|
||||||
location /${sub_path}/ {
|
location /${sub_path}/ {
|
||||||
if (\$hack = 1) { return 404; }
|
if (\$hack = 1) { return 404; }
|
||||||
|
if (\$is_clash_client = 1) { rewrite ^ /__clash_sub last; }
|
||||||
proxy_redirect off;
|
proxy_redirect off;
|
||||||
proxy_set_header Host \$host;
|
proxy_set_header Host \$host;
|
||||||
proxy_set_header X-Real-IP \$remote_addr;
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
@@ -401,6 +403,12 @@ limit_req_zone \$binary_remote_addr zone=diag_api:10m rate=6r/m;
|
|||||||
limit_req_zone \$binary_remote_addr zone=diag_page:10m rate=30r/m;
|
limit_req_zone \$binary_remote_addr zone=diag_page:10m rate=30r/m;
|
||||||
limit_conn_zone \$binary_remote_addr zone=per_ip:10m;
|
limit_conn_zone \$binary_remote_addr zone=per_ip:10m;
|
||||||
|
|
||||||
|
# Detect Clash/Mihomo subscription clients by User-Agent
|
||||||
|
map \$http_user_agent \$is_clash_client {
|
||||||
|
~*(clash|clashx|clashn|mihomo|stash|surfboard) 1;
|
||||||
|
default 0;
|
||||||
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
server_tokens off;
|
server_tokens off;
|
||||||
server_name ${domain};
|
server_name ${domain};
|
||||||
@@ -493,6 +501,16 @@ server {
|
|||||||
add_header Content-Disposition "attachment" always;
|
add_header Content-Disposition "attachment" always;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Clash subscription — internal static file served by UA routing ──────────
|
||||||
|
location = /__clash_sub {
|
||||||
|
internal;
|
||||||
|
default_type text/plain;
|
||||||
|
alias /var/www/subpage/clash.yaml;
|
||||||
|
add_header Content-Type "text/yaml; charset=utf-8" always;
|
||||||
|
add_header Content-Disposition "attachment; filename=clash.yaml" always;
|
||||||
|
add_header Cache-Control "no-store" always;
|
||||||
|
}
|
||||||
|
|
||||||
include /etc/nginx/snippets/includes.conf;
|
include /etc/nginx/snippets/includes.conf;
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@@ -854,6 +872,20 @@ EOF
|
|||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
# INSTALL FAKE SITE
|
# INSTALL FAKE SITE
|
||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
install_clash_sub() {
|
||||||
|
local clash_dir="/var/www/subpage"
|
||||||
|
mkdir -p "${clash_dir}"
|
||||||
|
if curl -fsSL "${GITHUB_RAW}/assets/clash/clash.yaml" -o "${clash_dir}/clash.yaml"; then
|
||||||
|
sed -i "s|\${DOMAIN}|${domain}|g" "${clash_dir}/clash.yaml"
|
||||||
|
sed -i "s|\${SUB_PATH}|${sub_path}|g" "${clash_dir}/clash.yaml"
|
||||||
|
chown -R www-data:www-data "${clash_dir}" 2>/dev/null || true
|
||||||
|
chmod 644 "${clash_dir}/clash.yaml"
|
||||||
|
msg_ok "Clash subscription config installed."
|
||||||
|
else
|
||||||
|
msg_err "Failed to download clash.yaml from GitHub."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
install_fake_site() {
|
install_fake_site() {
|
||||||
local idx=$(( (RANDOM % FAKE_SITE_COUNT) + 1 ))
|
local idx=$(( (RANDOM % FAKE_SITE_COUNT) + 1 ))
|
||||||
local site_id
|
local site_id
|
||||||
@@ -1011,6 +1043,8 @@ show_results() {
|
|||||||
echo -e "Username: ${config_username}\n"
|
echo -e "Username: ${config_username}\n"
|
||||||
echo -e "Password: ${config_password}\n"
|
echo -e "Password: ${config_password}\n"
|
||||||
msg_inf "────────────────────────────────────────────────────────────────────────────────"
|
msg_inf "────────────────────────────────────────────────────────────────────────────────"
|
||||||
|
msg_inf "Clash Sub (auto by UA): https://${domain}/${sub_path}/\n"
|
||||||
|
msg_inf "────────────────────────────────────────────────────────────────────────────────"
|
||||||
msg_inf "Network Diagnostics: https://${domain}${diag_path}\n"
|
msg_inf "Network Diagnostics: https://${domain}${diag_path}\n"
|
||||||
msg_inf "────────────────────────────────────────────────────────────────────────────────"
|
msg_inf "────────────────────────────────────────────────────────────────────────────────"
|
||||||
msg_inf "Please save this screen!"
|
msg_inf "Please save this screen!"
|
||||||
@@ -1038,6 +1072,7 @@ main() {
|
|||||||
|
|
||||||
configure_nginx
|
configure_nginx
|
||||||
configure_xui_db
|
configure_xui_db
|
||||||
|
install_clash_sub
|
||||||
install_fake_site
|
install_fake_site
|
||||||
install_diagnostics
|
install_diagnostics
|
||||||
tune_system
|
tune_system
|
||||||
|
|||||||
Reference in New Issue
Block a user