Add Claude API router and AdWireGuard projects

- Implement Claude API smart router with automatic failover
- Support 4 providers: Claude Pro, DeepSeek, Kimi, Claude API
- Update models: DeepSeek to deepseek-reasoner, Kimi to kimi-k2
- Add AdWireGuard: WireGuard VPN + AdGuard DNS filtering
- Consolidate tokens into single tokens.txt file
- Add mDNS reflector to Home Assistant setup

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Will Song
2025-07-14 20:30:56 -05:00
parent 261ac9d563
commit 9728a8054f
53 changed files with 2285 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
services:
# WireGuard VPN Server
wireguard:
image: linuxserver/wireguard:latest
container_name: wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
environment:
- PUID=1000
- PGID=1000
- TZ=America/Chicago
- SERVERURL=will123song.xyz # 从caddy配置中获取的域名
- SERVERPORT=51820
- PEERS=5 # 支持5个客户端
- PEERDNS=10.99.99.1 # 使用AdGuard作为DNS
- INTERNAL_SUBNET=10.99.99.0
- ALLOWEDIPS=0.0.0.0/0
- LOG_CONFS=true
volumes:
- ./wireguard_config:/config
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp"
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
restart: unless-stopped
networks:
adwireguard_network:
ipv4_address: 10.99.99.2
# AdGuard Home DNS Server (integrated with WireGuard)
adguard:
image: adguard/adguardhome:latest
container_name: adguard_wg
restart: unless-stopped
ports:
- "3002:3000/tcp" # Web UI (different port to avoid conflict)
volumes:
- ./adguard_work:/opt/adguardhome/work
- ./adguard_conf:/opt/adguardhome/conf
networks:
adwireguard_network:
ipv4_address: 10.99.99.1
depends_on:
- wireguard
# Web管理界面代理 (可选)
nginx:
image: nginx:alpine
container_name: adwireguard_web
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./web:/usr/share/nginx/html:ro
networks:
- adwireguard_network
depends_on:
- adguard
- wireguard
volumes:
wireguard_config:
adguard_work:
adguard_conf:
networks:
adwireguard_network:
driver: bridge
ipam:
config:
- subnet: 10.99.99.0/24
gateway: 10.99.99.1

51
adwireguard/nginx.conf Normal file
View File

@@ -0,0 +1,51 @@
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# 默认站点 - AdWireGuard管理面板
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# 静态文件
location / {
try_files $uri $uri/ /index.html;
}
# AdGuard Web UI代理
location /adguard/ {
proxy_pass http://10.99.99.1:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WireGuard配置下载
location /wireguard/ {
alias /config/peer_configs/;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
}
}

View File

@@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AdWireGuard 管理中心</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; }
.container { background: white; border-radius: 20px; box-shadow: 0 20px 40px rgba(0,0,0,0.1); padding: 40px; max-width: 800px; width: 90%; }
.header { text-align: center; margin-bottom: 40px; }
.header h1 { color: #333; font-size: 2.5em; margin-bottom: 10px; }
.header p { color: #666; font-size: 1.1em; }
.services { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px; }
.service-card { background: #f8f9fa; border-radius: 15px; padding: 25px; text-align: center; transition: transform 0.3s ease, box-shadow 0.3s ease; border: 2px solid transparent; }
.service-card:hover { transform: translateY(-5px); box-shadow: 0 10px 30px rgba(0,0,0,0.15); border-color: #667eea; }
.service-card h3 { color: #333; margin-bottom: 15px; font-size: 1.3em; }
.service-card p { color: #666; margin-bottom: 20px; line-height: 1.6; }
.btn { display: inline-block; background: linear-gradient(135deg, #667eea, #764ba2); color: white; text-decoration: none; padding: 12px 25px; border-radius: 25px; font-weight: 500; transition: all 0.3s ease; }
.btn:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4); }
.status { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-top: 30px; }
.status-item { background: #f0f0f0; padding: 15px; border-radius: 10px; text-align: center; }
.status-item .label { font-size: 0.9em; color: #666; margin-bottom: 5px; }
.status-item .value { font-size: 1.2em; font-weight: bold; color: #333; }
.footer { text-align: center; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; color: #666; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🛡️ AdWireGuard</h1>
<p>VPN + DNS 广告过滤 统一管理中心</p>
</div>
<div class="services">
<div class="service-card">
<h3>🌐 AdGuard Home</h3>
<p>DNS广告过滤和家庭网络保护。配置黑名单、白名单查看DNS查询统计。</p>
<a href="/adguard/" class="btn">进入 AdGuard</a>
</div>
<div class="service-card">
<h3>🔒 WireGuard VPN</h3>
<p>安全的VPN隧道支持多设备连接。下载配置文件即可快速连接。</p>
<a href="/wireguard/" class="btn">下载配置</a>
</div>
</div>
<div class="status">
<div class="status-item">
<div class="label">VPN状态</div>
<div class="value" id="vpn-status">🟢 运行中</div>
</div>
<div class="status-item">
<div class="label">DNS过滤</div>
<div class="value" id="dns-status">🟢 活跃</div>
</div>
<div class="status-item">
<div class="label">支持设备</div>
<div class="value">5 台</div>
</div>
<div class="status-item">
<div class="label">服务器</div>
<div class="value">will123song.xyz</div>
</div>
</div>
<div class="footer">
<p>🚀 AdWireGuard 管理中心 | 基于 WireGuard + AdGuard Home</p>
<p style="margin-top: 10px; font-size: 0.9em;">
<strong>快速访问:</strong>
<a href="http://localhost:3001" target="_blank" style="color: #667eea; text-decoration: none;">AdGuard直连</a> |
<a href="http://localhost:8080" target="_blank" style="color: #667eea; text-decoration: none;">管理面板</a>
</p>
</div>
</div>
<script>
// 简单的状态检测
function checkStatus() {
// 这里可以添加实际的状态检测逻辑
console.log('Status check: AdWireGuard running');
}
// 页面加载完成后检测状态
document.addEventListener('DOMContentLoaded', checkStatus);
// 每30秒检测一次状态
setInterval(checkStatus, 30000);
</script>
</body>
</html>

View File

@@ -0,0 +1,7 @@
ORIG_SERVERURL="will123song.xyz"
ORIG_SERVERPORT="51820"
ORIG_PEERDNS="10.99.99.1"
ORIG_PEERS="5"
ORIG_INTERFACE="10.99.99"
ORIG_ALLOWEDIPS="0.0.0.0/0"
ORIG_PERSISTENTKEEPALIVE_PEERS=""

View File

@@ -0,0 +1,6 @@
. {
loop
errors
health
forward . /etc/resolv.conf
}

View File

@@ -0,0 +1,11 @@
[Interface]
Address = 10.99.99.2
PrivateKey = eMKDKj+T/bqWPrvhRqPx8en6Vq1BUwDuT/Hhss871HQ=
ListenPort = 51820
DNS = 10.99.99.1
[Peer]
PublicKey = WBqIC7XpVtjreZt5GF/BLo7DpXqZrbu9gv74pons2gA=
PresharedKey = mP7oNgTh4FAzKRj+Ib53SC7uMO7fhxtEdTPwOuZCwD8=
Endpoint = will123song.xyz:51820
AllowedIPs = 0.0.0.0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
mP7oNgTh4FAzKRj+Ib53SC7uMO7fhxtEdTPwOuZCwD8=

View File

@@ -0,0 +1 @@
eMKDKj+T/bqWPrvhRqPx8en6Vq1BUwDuT/Hhss871HQ=

View File

@@ -0,0 +1 @@
fdn1mU/iG6avnWBzy0dKmAxgIFLGWO77KS8nIE15fnE=

View File

@@ -0,0 +1,11 @@
[Interface]
Address = 10.99.99.3
PrivateKey = 0LFpFeHETDTVbU8vy3uq2SGNWrBH5gJYU5LKhkHWCUc=
ListenPort = 51820
DNS = 10.99.99.1
[Peer]
PublicKey = WBqIC7XpVtjreZt5GF/BLo7DpXqZrbu9gv74pons2gA=
PresharedKey = Wbwh8gE6k63LOjuXAy1sFN6VqoGcgEvq62WONHutD6I=
Endpoint = will123song.xyz:51820
AllowedIPs = 0.0.0.0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
Wbwh8gE6k63LOjuXAy1sFN6VqoGcgEvq62WONHutD6I=

View File

@@ -0,0 +1 @@
0LFpFeHETDTVbU8vy3uq2SGNWrBH5gJYU5LKhkHWCUc=

View File

@@ -0,0 +1 @@
gtav3MLgVRukd/HJ0FFOFRJ7bhx/cU3WwfTQGu79GBY=

View File

@@ -0,0 +1,11 @@
[Interface]
Address = 10.99.99.4
PrivateKey = KElddZxSWLQXsr8vgWU7CxqFnHuf3s5lS0bj9hqoT3o=
ListenPort = 51820
DNS = 10.99.99.1
[Peer]
PublicKey = WBqIC7XpVtjreZt5GF/BLo7DpXqZrbu9gv74pons2gA=
PresharedKey = NJotC0A6bO2o8mkpSWvZ1OSdi90jKkVFMSYMakzM+F0=
Endpoint = will123song.xyz:51820
AllowedIPs = 0.0.0.0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
NJotC0A6bO2o8mkpSWvZ1OSdi90jKkVFMSYMakzM+F0=

View File

@@ -0,0 +1 @@
KElddZxSWLQXsr8vgWU7CxqFnHuf3s5lS0bj9hqoT3o=

View File

@@ -0,0 +1 @@
9g0Q3umKlWhiL3dTmIiMSHXeCc9YXtg5vBTcOar7Bh8=

View File

@@ -0,0 +1,11 @@
[Interface]
Address = 10.99.99.5
PrivateKey = WA2IbKsg2rtbYCwJlZjox6nj3beGJEGu2p4qHFWHImQ=
ListenPort = 51820
DNS = 10.99.99.1
[Peer]
PublicKey = WBqIC7XpVtjreZt5GF/BLo7DpXqZrbu9gv74pons2gA=
PresharedKey = RtXAOz29/zNgr6xcdeyRE3wzzu94QuwYc7AiWBh2Wqw=
Endpoint = will123song.xyz:51820
AllowedIPs = 0.0.0.0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
RtXAOz29/zNgr6xcdeyRE3wzzu94QuwYc7AiWBh2Wqw=

View File

@@ -0,0 +1 @@
WA2IbKsg2rtbYCwJlZjox6nj3beGJEGu2p4qHFWHImQ=

View File

@@ -0,0 +1 @@
eZEv8DzOwraaUyoeU31fDUQrKzHaPC8EGEWp6JH9xiI=

View File

@@ -0,0 +1,11 @@
[Interface]
Address = 10.99.99.6
PrivateKey = eBoR6Lm6Llz8IefrHu94C9Qvc5rfUKxPaVPLmPZgiVc=
ListenPort = 51820
DNS = 10.99.99.1
[Peer]
PublicKey = WBqIC7XpVtjreZt5GF/BLo7DpXqZrbu9gv74pons2gA=
PresharedKey = irzJtDsZhpL7+y9gyUFb7JVNfWQMTwiK3HVEQR7RBYk=
Endpoint = will123song.xyz:51820
AllowedIPs = 0.0.0.0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
irzJtDsZhpL7+y9gyUFb7JVNfWQMTwiK3HVEQR7RBYk=

View File

@@ -0,0 +1 @@
eBoR6Lm6Llz8IefrHu94C9Qvc5rfUKxPaVPLmPZgiVc=

View File

@@ -0,0 +1 @@
S2rwMN2aOoC1vsyyMjA3STT3AsYFHAOuglxMn03Ut0U=

View File

@@ -0,0 +1 @@
YNXol4rvLMXngA0pkxXUkkxANO+GMYArW7usbbpkvV4=

View File

@@ -0,0 +1 @@
WBqIC7XpVtjreZt5GF/BLo7DpXqZrbu9gv74pons2gA=

View File

@@ -0,0 +1,11 @@
[Interface]
Address = ${CLIENT_IP}
PrivateKey = $(cat /config/${PEER_ID}/privatekey-${PEER_ID})
ListenPort = 51820
DNS = ${PEERDNS}
[Peer]
PublicKey = $(cat /config/server/publickey-server)
PresharedKey = $(cat /config/${PEER_ID}/presharedkey-${PEER_ID})
Endpoint = ${SERVERURL}:${SERVERPORT}
AllowedIPs = ${ALLOWEDIPS}

View File

@@ -0,0 +1,6 @@
[Interface]
Address = ${INTERFACE}.1
ListenPort = 51820
PrivateKey = $(cat /config/server/privatekey-server)
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE

View File

@@ -0,0 +1,37 @@
[Interface]
Address = 10.99.99.1
ListenPort = 51820
PrivateKey = YNXol4rvLMXngA0pkxXUkkxANO+GMYArW7usbbpkvV4=
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE
[Peer]
# peer1
PublicKey = fdn1mU/iG6avnWBzy0dKmAxgIFLGWO77KS8nIE15fnE=
PresharedKey = mP7oNgTh4FAzKRj+Ib53SC7uMO7fhxtEdTPwOuZCwD8=
AllowedIPs = 10.99.99.2/32
[Peer]
# peer2
PublicKey = gtav3MLgVRukd/HJ0FFOFRJ7bhx/cU3WwfTQGu79GBY=
PresharedKey = Wbwh8gE6k63LOjuXAy1sFN6VqoGcgEvq62WONHutD6I=
AllowedIPs = 10.99.99.3/32
[Peer]
# peer3
PublicKey = 9g0Q3umKlWhiL3dTmIiMSHXeCc9YXtg5vBTcOar7Bh8=
PresharedKey = NJotC0A6bO2o8mkpSWvZ1OSdi90jKkVFMSYMakzM+F0=
AllowedIPs = 10.99.99.4/32
[Peer]
# peer4
PublicKey = eZEv8DzOwraaUyoeU31fDUQrKzHaPC8EGEWp6JH9xiI=
PresharedKey = RtXAOz29/zNgr6xcdeyRE3wzzu94QuwYc7AiWBh2Wqw=
AllowedIPs = 10.99.99.5/32
[Peer]
# peer5
PublicKey = S2rwMN2aOoC1vsyyMjA3STT3AsYFHAOuglxMn03Ut0U=
PresharedKey = irzJtDsZhpL7+y9gyUFb7JVNfWQMTwiK3HVEQR7RBYk=
AllowedIPs = 10.99.99.6/32