This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
# Gitea Actions CI 模板(统一极简合规门禁)
|
||||||
|
# 复制为 <repo>/.gitea/workflows/ci.yml 后即可用;无需调整。
|
||||||
|
# 说明:runner 容器无外网且无 pip(Gitea 实例限制),CI 只做本地可完成的合规检查;
|
||||||
|
# 依赖安装与测试一律在本地运行(开发机上完成)。
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ci-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Gitea 合规校验
|
||||||
|
run: |
|
||||||
|
if git ls-tree -r HEAD | awk '$1==160000' | grep -q .; then echo "HEAD 含 gitlink"; exit 1; fi
|
||||||
|
if git ls-files .DS_Store | grep -q .; then echo "跟踪 .DS_Store"; exit 1; fi
|
||||||
|
if git grep -n -I -E 'sk-[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|xox[baprs]-[A-Za-z0-9-]{10,}' HEAD | grep -q .; then echo "检出疑似凭证"; exit 1; fi
|
||||||
|
echo "Gitea 合规校验通过"
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Secrets
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
secrets/
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# vpn-rules
|
||||||
|
|
||||||
|
「哪些连接必须**直连、绝不进代理**」的规则真源(single source of truth),供电脑端
|
||||||
|
Clash Verge 和华硕路由器上的 mihomo(Magic Catling2)等消费端同步引用,一处维护、处处生效。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
vpn-rules/
|
||||||
|
├── direct.yaml # 规则真源(mihomo rule-provider 格式)
|
||||||
|
└── scripts/
|
||||||
|
└── gen_clash_verge_script.py # 真源 → Clash Verge Script.js 生成器
|
||||||
|
```
|
||||||
|
|
||||||
|
## 为什么需要它
|
||||||
|
|
||||||
|
- 香港代理节点有流量配额(如 BygCloud 100GiB 用满),国内站点/内网流量被隧道进代理会白白烧配额。
|
||||||
|
- 必须直连的对象:FRP 控制面(mTLS)、B 站全系、DeepSeek/MiniMax 等国内 LLM API、
|
||||||
|
内网/私有 IP 段、国区 iCloud、UGREEN 绿联 NAS 云。
|
||||||
|
- **踩坑**:Clash Verge 全局 `Merge.yaml` 的 `prepend-rules` 会被内核忽略(不生效),
|
||||||
|
全局直连规则的唯一正确机制是 `profiles/Script.js`(`main(config)` 把规则 prepend 进 `config.rules`)。
|
||||||
|
|
||||||
|
## 消费端接入
|
||||||
|
|
||||||
|
### Clash Verge(macOS)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 生成并写入 Clash Verge 数据目录的 Script.js
|
||||||
|
python3 scripts/gen_clash_verge_script.py
|
||||||
|
# 然后在 Clash Verge 界面点「重启内核」生效
|
||||||
|
```
|
||||||
|
|
||||||
|
对当前及以后新增/切换的所有订阅生效;订阅更新不会覆盖它。
|
||||||
|
|
||||||
|
### 路由器 mihomo(Magic Catling2 / OpenWrt)
|
||||||
|
|
||||||
|
rule-provider 引用(policy 在外层指定),定期自动拉取真源:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
rule-providers:
|
||||||
|
vpn-direct:
|
||||||
|
type: http
|
||||||
|
behavior: classical
|
||||||
|
url: https://gitea.puyuanfh.cn/ageorge156/vpn-rules/raw/branch/main/direct.yaml
|
||||||
|
interval: 86400
|
||||||
|
path: ./ruleset/vpn-direct.yaml
|
||||||
|
|
||||||
|
rules:
|
||||||
|
- RULE-SET,vpn-direct,DIRECT
|
||||||
|
```
|
||||||
|
|
||||||
|
> 路由器内网自建 Gitea(192.168.50.2:3000)也可直连:`http://192.168.50.2:3000/ageorge156/vpn-rules/raw/branch/main/direct.yaml`。
|
||||||
|
|
||||||
|
## 维护流程
|
||||||
|
|
||||||
|
1. 改 `direct.yaml`(rule-provider 条目,**不含**策略字段)。
|
||||||
|
2. `git commit` + push 到本仓库 `main`。
|
||||||
|
3. Clash Verge 端重跑 `python3 scripts/gen_clash_verge_script.py` + 重启内核;
|
||||||
|
路由器端等 rule-provider 到期自动拉新或手动 reload。
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
# 全局直连(DIRECT)规则真源 — mihomo rule-provider 格式
|
||||||
|
#
|
||||||
|
# 用法:本文件是「哪些连接必须直连、绝不进代理」的唯一真源。
|
||||||
|
# 消费端(Clash Verge / 路由器 mihomo)用 rule-provider 引用它,或由
|
||||||
|
# scripts/gen_clash_verge_script.py 生成为 Clash Verge 的 Script.js。
|
||||||
|
#
|
||||||
|
# rule-provider 引用示例(policy 在外层规则里指定):
|
||||||
|
# rule-providers:
|
||||||
|
# vpn-direct:
|
||||||
|
# type: http
|
||||||
|
# behavior: classical
|
||||||
|
# url: https://gitea.puyuanfh.cn/ageorge156/vpn-rules/raw/branch/main/direct.yaml
|
||||||
|
# interval: 86400
|
||||||
|
# path: ./ruleset/vpn-direct.yaml
|
||||||
|
# rules:
|
||||||
|
# - RULE-SET,vpn-direct,DIRECT
|
||||||
|
#
|
||||||
|
# 修改后:直接 commit 到本仓库 main;Clash Verge 端重跑
|
||||||
|
# python3 scripts/gen_clash_verge_script.py (默认写入 Clash Verge 数据目录并提示重启内核)
|
||||||
|
# 路由器端则等 rule-provider 的 interval 到期或手动 reload。
|
||||||
|
|
||||||
|
payload:
|
||||||
|
# FRP 控制面(mTLS)保持直连
|
||||||
|
- DOMAIN,frp.puyuanfh.cn
|
||||||
|
- IP-CIDR,8.133.177.3/32,no-resolve
|
||||||
|
|
||||||
|
# 国内视频(B 站全系)直连
|
||||||
|
- DOMAIN-SUFFIX,bilibili.com
|
||||||
|
- DOMAIN-SUFFIX,bilibili.cn
|
||||||
|
- DOMAIN-SUFFIX,bilivideo.com
|
||||||
|
- DOMAIN-SUFFIX,bili2233.cn
|
||||||
|
- DOMAIN-SUFFIX,hdslb.com
|
||||||
|
|
||||||
|
# 国内 IP 兜底:任何其它国内站点不再被隧道到 HK 代理
|
||||||
|
- GEOIP,CN,no-resolve
|
||||||
|
|
||||||
|
# 国内 LLM API 直连(DeepSeek / MiniMax 含海螺 AI)
|
||||||
|
- DOMAIN-SUFFIX,deepseek.com
|
||||||
|
- DOMAIN-SUFFIX,minimaxi.com
|
||||||
|
- DOMAIN-SUFFIX,minimax.chat
|
||||||
|
- DOMAIN-SUFFIX,hailuoai.com
|
||||||
|
- DOMAIN,minimax-public-cdn.oss-cn-wulanchabu.aliyuncs.com
|
||||||
|
|
||||||
|
# 内网 / 私有段绝不上代理
|
||||||
|
- IP-CIDR,127.0.0.0/8,no-resolve
|
||||||
|
- IP-CIDR,10.0.0.0/8,no-resolve
|
||||||
|
- IP-CIDR,172.16.0.0/12,no-resolve
|
||||||
|
- IP-CIDR,192.168.0.0/16,no-resolve
|
||||||
|
- IP-CIDR,100.64.0.0/10,no-resolve
|
||||||
|
- DOMAIN-SUFFIX,.local
|
||||||
|
|
||||||
|
# 国区 iCloud 保持国内
|
||||||
|
- DOMAIN-SUFFIX,icloud.com.cn
|
||||||
|
|
||||||
|
# UGREEN 绿联 NAS / SyncSpace 云保持国内
|
||||||
|
- DOMAIN-SUFFIX,ug.link
|
||||||
|
- DOMAIN-SUFFIX,ugreen.com
|
||||||
|
- DOMAIN-SUFFIX,ugnas.cloud
|
||||||
|
- DOMAIN-SUFFIX,ugos.cn
|
||||||
|
- DOMAIN-KEYWORD,ugreen
|
||||||
|
- DOMAIN-KEYWORD,ugnas
|
||||||
|
- DOMAIN-KEYWORD,ugreengroup
|
||||||
|
- IP-CIDR,110.42.0.0/16,no-resolve
|
||||||
|
- IP-CIDR,43.248.128.0/17,no-resolve
|
||||||
|
- IP-CIDR,111.170.0.0/16,no-resolve
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""把 direct.yaml(真源)生成为 Clash Verge 的全局增强脚本 Script.js。
|
||||||
|
|
||||||
|
用法:
|
||||||
|
python3 scripts/gen_clash_verge_script.py [--out 目标路径]
|
||||||
|
|
||||||
|
默认输出到 Clash Verge 数据目录 profiles/Script.js(全局直连规则的唯一正确机制,
|
||||||
|
见 clash-verge-config 记忆)。生成后需在 Clash Verge 界面点「重启内核」生效。
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
DEFAULT_OUT = Path.home() / "Library/Application Support/io.github.clash-verge-rev.clash-verge-rev/profiles/Script.js"
|
||||||
|
|
||||||
|
|
||||||
|
def load_payload(path: Path) -> list[str]:
|
||||||
|
payload: list[str] = []
|
||||||
|
with path.open(encoding="utf-8") as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("- "):
|
||||||
|
payload.append(line[2:].strip())
|
||||||
|
if not payload:
|
||||||
|
raise SystemExit(f"❌ direct.yaml 里没有 payload 条目: {path}")
|
||||||
|
return payload
|
||||||
|
|
||||||
|
|
||||||
|
def to_rule(entry: str) -> str:
|
||||||
|
"""rule-provider 条目(无策略)→ 完整规则(补 DIRECT)。"""
|
||||||
|
if entry.endswith(",no-resolve"):
|
||||||
|
return f"{entry[:-len(',no-resolve')]},DIRECT,no-resolve"
|
||||||
|
return f"{entry},DIRECT"
|
||||||
|
|
||||||
|
|
||||||
|
def render_script(payload: list[str]) -> str:
|
||||||
|
rules = [f" {to_rule(e)!r}," for e in payload]
|
||||||
|
lines = "\n".join(rules)
|
||||||
|
return f"""// 由 vpn-rules/direct.yaml 生成 — 勿手改,改真源后重跑 gen_clash_verge_script.py。
|
||||||
|
// 全局直连规则:FRP 控制面、B站、国内 LLM、内网段、国区 iCloud、UGREEN 一律 DIRECT。
|
||||||
|
const prependRules = [
|
||||||
|
{lines}
|
||||||
|
];
|
||||||
|
|
||||||
|
function main(config, profileName) {{
|
||||||
|
const existingRules = Array.isArray(config.rules) ? config.rules : [];
|
||||||
|
const existingRuleSet = new Set(existingRules);
|
||||||
|
|
||||||
|
config.rules = [
|
||||||
|
...prependRules.filter((rule) => !existingRuleSet.has(rule)),
|
||||||
|
...existingRules,
|
||||||
|
];
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
ap = argparse.ArgumentParser(description="direct.yaml → Clash Verge Script.js")
|
||||||
|
ap.add_argument("--out", default=str(DEFAULT_OUT), help="输出路径")
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
payload = load_payload(REPO_ROOT / "direct.yaml")
|
||||||
|
script = render_script(payload)
|
||||||
|
out = Path(args.out)
|
||||||
|
out.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
out.write_text(script, encoding="utf-8")
|
||||||
|
print(f"✅ 已生成 {out}({len(payload)} 条规则)")
|
||||||
|
print(" 请在 Clash Verge 界面点「重启内核」生效。")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user