目录

「Proxy」从无敌到破防

VPS

IP History

  1. 176.122.181.40 (搬瓦工,跪于:2018.0311)
  2. 176.122.182.5 (寿终)
  3. 45.32.227.71 (寿终)
  4. 207.246.71.248 (寿终)
  5. 108.61.171.5 (寿终)
  6. 80.240.29.153 (更换)
  7. 45.63.55.222 (暂停使用Vultr)
  8. 35.194.164.32 (启用Google,谷歌云有额外防火墙需要配置)
  9. 35.221.203.243 (GCP,寿终)
  10. 107.148.241.109 (TripodCloud,寿终)
  11. 89.208.243.18 (BandwagonHost)
  12. 107.148.218.205 (TripodCloud,联通丢包更换)
  13. 107.148.241.190 (TripodCloud,寿终)
  14. 107.148.241.136 (TripodCloud,寿终)
  15. 107.148.246.9 (TripodCloud)
  16. 45.62.116.203 (BandwagonHost)

修改密码

passwd

修改SSH端口 [32722]

Debian 10/11/12

## 添加 sshd 新端口支持
vim /etc/ssh/sshd_config
# 取消默认端口22前注释
Port 22
# 新增一行
Port 32722
# 取消允许远程登录前注释
PermitRootLogin yes
# 允许使用用户名和密码登录
PasswordAuthtntication yes
# 保存并退出
service ssh restart

性能测试

CPU、内存、硬盘检测
# 查看CPU信息
cat /proc/cpuinfo
# 查看内存信息
cat /proc/meminfo
# 查看硬盘信息
df -lh
硬盘IO性能测试
dd if=/dev/zero of=test bs=64k count=4k oflag=dsync
dd if=/dev/zero of=test bs=8k count=256k conv=fdatasync
WGET下载测试
wget http://cachefly.cachefly.net/100mb.test
PING及TOP测试

防火墙

UFW
sudo apt update && sudo apt install ufw -y

# default
sudo ufw default deny incoming
sudo ufw default allow outgoing

# ssh
sudo ufw allow 32722/tcp

# reality
sudo ufw allow 443/tcp

# web & vless+xhttp+cdn
sudo ufw allow 80/tcp
sudo ufw allow 8443/tcp
# sudo ufw delete allow 8443/tcp

# Hysteria 2
sudo ufw allow 32055/udp  # listening
sudo ufw allow 42055:45055/udp  # jumping

# enable
sudo ufw enable

# reload
sudo ufw reload

端口转发

ufw

Debian 13

# IPv4
sudo nano /etc/ufw/before.rules

# 在最顶端插入
# ----------- 自定义 UDP 端口转发开始 -----------
*nat
:PREROUTING ACCEPT [0:0]
-A PREROUTING -p udp --dport 42055:45055 -j REDIRECT --to-ports 32055
COMMIT
# ----------- 自定义 UDP 端口转发结束 -----------

IPv6
sudo nano /etc/ufw/before6.rules

# 同样在最顶端插入
# ----------- 自定义 UDP 端口转发开始 -----------
*nat
:PREROUTING ACCEPT [0:0]
-A PREROUTING -p udp --dport 42055:45055 -j REDIRECT --to-ports 32055
COMMIT
# ----------- 自定义 UDP 端口转发结束 -----------

# 查看配置结果
sudo nft list table ip nat
sudo nft list table ip6 nat
# sudo nft list ruleset -4 | grep -A 3 -B 3 "32055"
# sudo nft list ruleset -6 | grep -A 3 -B 3 "32055"
iptables

< Debian 13

# hysteria 转发
sudo iptables -t nat -A PREROUTING -p udp --dport 42055:45055 -j REDIRECT --to-ports 32055
sudo ip6tables -t nat -A PREROUTING -p udp --dport 42055:45055 -j REDIRECT --to-ports 32055
# # 取消 hysteria 转发
# sudo iptables -t nat -D PREROUTING -p udp --dport 42055:45055 -j REDIRECT --to-ports 32055
# sudo ip6tables -t nat -D PREROUTING -p udp --dport 42055:45055 -j REDIRECT --to-ports 32055

# 规则持久化
sudo apt-get update && sudo apt-get install -y iptables-persistent

科学上网

3X-UI (docker) based Hysteria2, Reality and CDN backup

参考官方文档

本方案完全基于 Docker 部署,面板网页访问经 443 端口被 3X-UI 的 Xray core 监听,回落至监听在 8080 的 Nginx 服务,经 URL 匹配反代回 3X-UI 的面板监听端口。

pathframeworknodesusers
cloudflare~/server/3x-ui/certbot/cloudflare.ini…--
cloudflare cert~/server/3x-ui/cert…--
compose config~/server/3x-ui/docker-compose.ymlv.v.-
nginx~/server/3x-ui/nginx/nginx.confv.v.-
initial package/root/yirami/3xui/*v.v.
x.
v. / deployed
deployed
搭建

构建服务所需目录

mkdir -p ~/server/3x-ui && cd ~/server/3x-ui
mkdir -p certbot/certs
mkdir -p cert db
mkdir -p nginx
框架配置

创建或恢复 token 配置用于 Cloudflare 域名鉴权

cat > ~/server/3x-ui/certbot/cloudflare.ini << EOF
dns_cloudflare_api_token = xxxxxxxxxxxxxxxxxxxxxxx
EOF

chmod 600 ~/server/3x-ui/certbot/cloudflare.ini  # 仅所有者有读写权限

创建或恢复源服务器长期证书

创建或恢复 Nginx 配置

cat << 'EOF' > ~/server/3x-ui/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    sendfile on;
    tcp_nopush on;
    keepalive_timeout 65;

    # 根据客户端请求头里的 Upgrade 状态,动态决定 Connection 头是保持 upgrade 还是 close
    # 解决 HTTP/2 降级反代时,传统“写死 Connection upgrade”导致非 WS 页面报协议追尾错误的问题
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        listen 80;
        server_name yirami.xyz *.yirami.xyz;
        return 301 https://$host$request_uri;
    }

    server {
        listen 8443 ssl;
        http2 on;
        server_name cf-v.yirami.xyz;

        ssl_certificate /root/cert/yirami_xyz.cloudflare.15y.pem;
        ssl_certificate_key /root/cert/yirami_xyz.cloudflare.15y.key;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;

        # 识别 CDN 流量,提取访问者的真实公网 IP
        # 使 Nginx 访问日志、3x-ui 防爆破(Fail2ban)里获取到真实 IP
        set_real_ip_from 0.0.0.0/0;
        real_ip_header X-Forwarded-For;

        location / {
            root /home/wwwroot/yirami.xyz;
            index index.html index.htm index.php;
        }

        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
            root /home/wwwroot/yirami.xyz;
            expires 30d;
        }

        location ~ .*\.(js|css)?$ {
            root /home/wwwroot/yirami.xyz;
            expires 12h;
        }

        location ^~ /api/say_hello_to_user/ {
            proxy_pass http://127.0.0.1:28992;
            proxy_redirect off;
            proxy_http_version 1.1;
            proxy_buffering off;  # 关闭缓存,防止 xhttp 流量在这里发生积压与延迟

            # 头部透传
            proxy_set_header Host $host;

            # Nginx 逐个检查请求头,如果存在 CF 头就传 CF 头,否则传经由 real_ip 模块解析后的 $remote_addr
            proxy_set_header X-Real-IP $http_cf_connecting_ip;
            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 https;

            # 保持流式长连接升级支持
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

            # 恶意断连防御:将超时彻底拉长到 5 分钟,防止长视频播放或挂机时被 Nginx 掐断
            proxy_read_timeout 300s;
            proxy_send_timeout 300s;
        }

        location ^~ /api/say_ok_to_other/ {
            proxy_pass http://127.0.0.1:28993;
            proxy_redirect off;
            proxy_http_version 1.1;
            proxy_buffering off;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $http_cf_connecting_ip;
            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 https;

            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

            proxy_read_timeout 300s;
            proxy_send_timeout 300s;
        }

        # 防御嗅探规则
        location ~ /\. {
            deny all;
        }

        access_log off;
    }

    server {
        listen 8443 ssl;
        http2 on;
        server_name yirami.xyz v.yirami.xyz loc.dallasus.yirami.xyz;

        ssl_certificate /etc/letsencrypt/live/yirami.xyz/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/yirami.xyz/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;

        # 识别 CDN 流量,提取访问者的真实公网 IP
        # 使 Nginx 访问日志、3x-ui 防爆破(Fail2ban)里获取到真实 IP
        set_real_ip_from 0.0.0.0/0;
        real_ip_header X-Forwarded-For;

        location / {
            root /home/wwwroot/yirami.xyz;
            index index.html index.htm index.php;
        }

        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
            root /home/wwwroot/yirami.xyz;
            expires 30d;
        }

        location ~ .*\.(js|css)?$ {
            root /home/wwwroot/yirami.xyz;
            expires 12h;
        }

        location ^~ /api/say_hello_to_user/ {
            proxy_pass http://127.0.0.1:28992;
            proxy_redirect off;
            proxy_http_version 1.1;
            proxy_buffering off;  # 关闭缓存,防止 xhttp 流量在这里发生积压与延迟

            # 头部透传
            proxy_set_header Host $host;

            # Nginx 逐个检查请求头,如果存在 CF 头就传 CF 头,否则传经由 real_ip 模块解析后的 $remote_addr
            proxy_set_header X-Real-IP $http_cf_connecting_ip;
            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 https;

            # 保持流式长连接升级支持
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

            # 恶意断连防御:将超时彻底拉长到 5 分钟,防止长视频播放或挂机时被 Nginx 掐断
            proxy_read_timeout 300s;
            proxy_send_timeout 300s;
        }

        location ^~ /api/say_ok_to_other/ {
            proxy_pass http://127.0.0.1:28993;
            proxy_redirect off;
            proxy_http_version 1.1;
            proxy_buffering off;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $http_cf_connecting_ip;
            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 https;

            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

            proxy_read_timeout 300s;
            proxy_send_timeout 300s;
        }

        location ^~ /go_anywhere_hahaha/ {
            proxy_pass http://127.0.0.1:32053;
            proxy_redirect off;
            proxy_http_version 1.1;

            # 标准头部转发
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $http_cf_connecting_ip;
            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 https;

            # 支持面板动态数据、WebSocket 实时长连接日志的反代
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

            # 支持大文件下载/备份续传
            proxy_set_header Range $http_range;
            proxy_set_header If-Range $http_if_range;

            # 防止 Nginx 缓存动态监控数据,确保面板流量图表能够及时更新
            proxy_buffering off;

            # 后端反代超时保护,防止执行大任务或查看长日志时中途断连
            proxy_connect_timeout 60s;
            proxy_send_timeout 60s;
            proxy_read_timeout 60s;
        }

        location ^~ /fetch_sub_as_you_wish/ {
            proxy_pass http://127.0.0.1:32096;
            proxy_redirect off;
            proxy_http_version 1.1;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $http_cf_connecting_ip;
            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 https;

            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

            # 支持大文件/分片(订阅分发有时需要)
            proxy_set_header Range $http_range;
            proxy_set_header If-Range $http_if_range;

            proxy_buffering off;
        }

        # 防御嗅探规则
        location ~ /\. {
            deny all;
        }

        access_log off;
    }
}
EOF

恢复主站

cd ~/server/3x-ui/nginx
git clone git@github.com:yirami/yirami.xyz.git

创建或恢复 docker compose 配置

cat <<EOF > ~/server/3x-ui/docker-compose.yml
services:
  certbot:
    image: certbot/dns-cloudflare:v5.7.0
    container_name: certbot_app
    restart: unless-stopped
    network_mode: host
    volumes:
      - $PWD/certbot/certs:/etc/letsencrypt
      - $PWD/certbot/cloudflare.ini:/etc/cloudflare.ini:ro
      - /usr/bin/docker:/usr/local/bin/docker:ro
      - /var/run/docker.sock:/var/run/docker.sock  # 赋予控制 Docker 权限,用于重载 Nginx
    deploy:
      resources:
        limits:
          cpus: '0.10'
          memory: 128M
        reservations:
          memory: 32M
    entrypoint: >
      /bin/sh -c "
      trap exit TERM; 
      while :; do 
        certbot renew --deploy-hook 'docker exec nginx_app nginx -s reload';
        sleep 12h & wait $$!;
      done"
    healthcheck:
      test: ["CMD-SHELL", "cat /proc/1/stat | grep -q 'sh' || exit 1"]
      interval: 1m
      timeout: 5s
      retries: 3
      start_period: 10s

  nginx:
    image: nginx:1.31.3-alpine3.24
    container_name: nginx_app
    restart: unless-stopped
    network_mode: host
    volumes:
      - $PWD/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - $PWD/cert/:/root/cert/:ro
      - $PWD/certbot/certs:/etc/letsencrypt:ro
      - $PWD/nginx/yirami.xyz:/home/wwwroot/yirami.xyz:ro
    environment:
      TZ: "Asia/Shanghai"
    deploy:
      resources:
        limits:
          cpus: '0.30'
          memory: 128M
        reservations:
          memory: 64M
    healthcheck:
      test: ["CMD-SHELL", "wget --no-check-certificate --spider --quiet https://127.0.0.1:8443/ || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s

  3x-ui:
    image: ghcr.io/mhsanaei/3x-ui:v3.6.0
    container_name: 3xui_app
    restart: unless-stopped
    network_mode: host
    # 给予系统网络管理权限以支持 Fail2ban 防爆破功能
    cap_add:
      - NET_ADMIN
      - NET_RAW
    volumes:
      - $PWD/db/:/etc/x-ui/
      - $PWD/cert/:/root/cert/:ro
      - $PWD/certbot/certs:/etc/letsencrypt:ro
    environment:
      TZ: "Asia/Shanghai"
      XRAY_VMESS_AEAD_FORCED: "false"
      XUI_ENABLE_FAIL2BAN: "true"
      XUI_INIT_WEB_BASE_PATH: "/go_anywhere_hahaha/"
    tty: true
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
        reservations:
          memory: 128M
    healthcheck:
      test: >
        /bin/sh -c "
        wget --spider --quiet http://127.0.0.1:32053/go_anywhere_hahaha/ || 
        wget --spider --quiet http://127.0.0.1:2053/go_anywhere_hahaha/ || 
        exit 1
        "
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 15s
EOF

单独启动 certbot 容器,依赖其证书的服务暂不启动(如 Nginx )

cd ~/server/3x-ui
docker compose up -d certbot  # 单独启动,证书未就绪不要启动 Nginx

首次需手动触发一次证书申请

docker compose run --rm --entrypoint "certbot" certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/cloudflare.ini \
  --dns-cloudflare-propagation-seconds 60 \
  -d yirami.xyz \
  -d v.yirami.xyz \
  -d loc.dallasus.yirami.xyz \
  # -d x.yirami.xyz \
  # -d loc.laus.yirami.xyz \
  --email service@yirami.xyz \
  --agree-tos \
  --no-eff-email

继续拉起 3x-ui 容器,以初始化安全配置

cd ~/server/3x-ui
docker compose up -d 3x-ui

将服务器端面板的默认端口 2053 通过 ssh 加密隧道映射到本地,以安全的初始化 3x-ui 容器

ssh -N -L 2053:127.0.0.1:2053 -p 32722 i@loc.dallasus.yirami.xyz

在本地浏览器,访问面板(如果网页打开缓慢可能需要临时开启全局代理),并以 admin/admin 登录,初始化如下配置(并重启面板):

  • 面板监听地址:127.0.0.1
  • 面板监听端口:32053
  • 面板 URL 路径:/go_anywhere_hahaha/
  • 订阅监听地址:127.0.0.1
  • 订阅监听端口:32096
  • 订阅 URL 路径:/fetch_sub_as_you_wish/
  • 用户名/密码

此时访问用户名和密码已经加强,当拉起 Nginx 容器后,其会在监听的 8443 端口上将流量卸载 TLS 后反代回面板或订阅监听端口。此处自定义面板和订阅监听端口并非出于安全考虑(它们没有暴露到外部),而是消除面板内使用 2053 端口的不安全(众所周知)警告。

cd ~/server/3x-ui
docker compose up -d nginx

但通过 8443 端口访问麻烦且不够优雅,可以借助 Cloudflare 的免费 Origin Rules 实现端口转发。转发配置完成后,可以通过 https 加密访问面板以及访问订阅

至此,代理服务的框架配置完成,备份当前配置。

sudo tar -czvf 3x-ui.framework.tgz cert/ certbot/ db/ docker-compose.yml nginx/nginx.conf

常用管理命令

# start service
docker compose up -d

# update image
docker compose down
docker compose pull
docker compose up -d

# delete
docker compose down
docker system prune -a
# rm ~/server/3x-ui -rf
节点配置

若从上一步备份恢复,需额外恢复主站

配置 Reality

若需在 mihomo 或 sing-box 内核上连接该 Reality 节点,在配置时需在入站配置中安全选项中填写最小客户端版本为(至少)1.8.2 ,详情可参考 Xray Issue 或 mihomo Issue。

配置 Hysteria
配置 Nginx 反向代理转发 xhttp 流量

采用 vless + xhttp + cdn (取代 vmess + ws + cdn )作为保底方案。使用 Nginx 反代捕获路径并转发到指定内部端口

至此,入站节点添加完成,备份当前配置。

sudo tar -czvf 3x-ui.nodes.tgz cert/ certbot/ db/ docker-compose.yml nginx/nginx.conf
故障排查
1. 走 CloudFront(AWS) 线路的 CDN 节点失效

测试发现指向 aws-x.yirami.xyz 的 CDN 保障性节点失效了,检查 AWS 端的证书续约正常且近期未修改相关回源配置。排查中发现访问 x.yirami.xyz 上的代理管理面板提示 526 证书错误。

登入服务器,执行

docker compose exec -it certbot certbot certificates

确认 Certbot 证书申请状态

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: yirami.xyz
    Serial Number: 5be1284a043a1bc7da01aaca7344070afe0
    Key Type: ECDSA
    Identifiers: yirami.xyz loc.laus.yirami.xyz x.yirami.xyz
    Expiry Date: 2026-11-12 00:22:07+00:00 (VALID: 59 days)
    Certificate Path: /etc/letsencrypt/live/yirami.xyz/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/yirami.xyz/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

可以看到证书尚在有效期。再执行

# 443 端口分配给了 Reality 节点,因此 Nginx 监听 8443 端口
openssl s_client -connect 127.0.0.1:8443 -servername x.yirami.xyz

检查 Nginx 监听端口上的证书状态

Connecting to 127.0.0.1
CONNECTED(00000003)
depth=3 C=US, O=Internet Security Research Group, CN=ISRG Root X2
verify return:1
depth=2 C=US, O=ISRG, CN=Root YE
verify return:1
depth=1 C=US, O=Let's Encrypt, CN=YE2
verify return:1
depth=0 CN=yirami.xyz
verify error:num=10:certificate has expired
notAfter=Sep 12 11:17:55 2026 GMT
verify return:1
depth=0 CN=yirami.xyz
notAfter=Sep 12 11:17:55 2026 GMT
verify return:1
---
Certificate chain
 0 s:CN=yirami.xyz
   i:C=US, O=Let's Encrypt, CN=YE2
   a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA384
   v:NotBefore: Jun 14 11:17:56 2026 GMT; NotAfter: Sep 12 11:17:55 2026 GMT
 1 s:C=US, O=Let's Encrypt, CN=YE2
   i:C=US, O=ISRG, CN=Root YE
   a:PKEY: EC, (secp384r1); sigalg: ecdsa-with-SHA384
   v:NotBefore: Sep  3 00:00:00 2025 GMT; NotAfter: Sep  2 23:59:59 2028 GMT
 2 s:C=US, O=ISRG, CN=Root YE
   i:C=US, O=Internet Security Research Group, CN=ISRG Root X2
   a:PKEY: EC, (secp384r1); sigalg: ecdsa-with-SHA384
   v:NotBefore: May 13 00:00:00 2026 GMT; NotAfter: Sep  2 23:59:59 2032 GMT
 3 s:C=US, O=Internet Security Research Group, CN=ISRG Root X2
   i:C=US, O=Internet Security Research Group, CN=ISRG Root X1
   a:PKEY: EC, (secp384r1); sigalg: sha256WithRSAEncryption
   v:NotBefore: May 13 00:00:00 2026 GMT; NotAfter: Sep  2 23:59:59 2032 GMT
---

发现刚好过期一天,显然 Certbot 容器续约的证书没有正确同步给 Nginx 容器。因此可执行

docker compose exec nginx nginx -s reload

让 Nginx 重新加载配置,在执行

openssl s_client -connect 127.0.0.1:8443 -servername x.yirami.xyz

确认新证书已经正确加载。但这不是长久之计,造成目前问题的根因是 Certbot 和 Nginx 两个容器化部署的应用间的通知机制失效了。之前在 Certbot 的配置中已经添加过类似的配置

...
    volumes:
      - /usr/bin/docker:/usr/local/bin/docker:ro
      - /var/run/docker.sock:/var/run/docker.sock  # 赋予控制 Docker 权限,用于重载 Nginx
...
    entrypoint: >
      /bin/sh -c "
      trap exit TERM; 
      while :; do 
        certbot renew --deploy-hook 'docker exec nginx_app nginx -s reload';
        sleep 12h & wait $$!;
      done"

但很显然,它没生效。在强行更新证书进行测试时出错了

root@snappy-flag-2:~/server/3x-ui# docker compose exec certbot certbot renew --force-renewal
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/yirami.xyz.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Renewing an existing certificate for yirami.xyz and 2 more
Waiting 60 seconds for DNS changes to propagate
Hook 'deploy-hook' reported error code 127
Hook 'deploy-hook' ran with error output:
 /bin/sh: docker: not found

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all renewals succeeded: 
  /etc/letsencrypt/live/yirami.xyz/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

实际进 Certbot 容器测试发现 docker 命令无法使用

docker compose exec -it certbot sh

/usr/local/bin/docker --version
# sh: /usr/local/bin/docker: not found

这应该是宿主机上的二进制文件与 Alpine 容器环境不兼容,因此原方案不可行,采用最简单的修复方案——周期性重载 Nginx 配置。首先删除掉 Certbot 中的无效配置,并在 Nginx 的配置中添加自动重载的入口

...
    entrypoint: >
      /bin/sh -c "
      while true; do
        sleep 7d;
        nginx -s reload;
      done &
      /docker-entrypoint.sh 'nginx' '-g' 'daemon off;'
      "
...

然后使用如下命令

docker compose exec nginx ps aux

确认有如下一条 sleep 7d 的 sh 进程

PID   USER     TIME  COMMAND
    1 root      0:00 nginx: master process nginx -g daemon off;
    7 root      0:00 /bin/sh -c  while true; do   sleep 7d;   nginx -s reload; done & /docker-entrypoint.sh 'nginx' '-g' 'daemon off;' 
   10 root      0:00 sleep 7d
   32 nginx     0:00 nginx: worker process
   41 root      0:00 ps aux

Cloudflare Pages based edgetunnel

本方案通过 Github Actions 的方式基于 Cloudflare Pages 部署 edgetunnel ,部署方法参考项目文档。

搭建
  1. 打开项目地址,点赞并 Fork 到自己的 Github 帐号
  2. 进入 Cloudflare 控制台,依次进入 Build -> Compute -> Workers & Pages -> Create Application
  3. 此时默认进入了创建 Worker 的选项,在下方有 “Looking to deploy Pages? Get started” 字样,点击 Get started
  4. 选择 “Import an existing Git repository” 后的 Get started 并点击 Connect Github
  5. 如果 Github 帐号已登录,会进入 Install & Authorize 页面,这里选择 Only select repositories 并选择 edgetunnel 仓库
  6. 刷新页面,直到出现 Begin setup 按钮并点击
  7. 一定要修改 Project name 避免出现敏感词
  8. 按需设置 custom domain
  9. 生成 UUID (可借助在线工具,如 UUID Generator),并复制以备后用
  10. 进入刚创建的 Pages 项目并依次点击 Settings -> Variables and Secrets -> Add ,然后填入 Text 类型的变量,其名称为 ADMIN ,内容为后台登录时需要用的管理员密码(建议设置复杂密码并使用密码管理器管理)
  11. 从 Cloudflare 主页依次进入 Build -> Storage & databases -> Workers KV -> Create Instance 创建一个用于持久存储的数据库供 Pages 项目中的程序使用
  12. 再在 Pages 项目中依次点击 Settings -> Bindings -> Add -> KV namespace,设置变量名为 KV 并选择刚刚建立的 KV 进行绑定
  13. 再回到 Deployments 选项卡下点击当前部署后的 ... 并再点击 Retry deployment
  14. 稍等片刻,打开 https://[your/projects/domain/or/custom/domain]/admin 即可访问管理面板,注意 URL 要加 /admin 后缀
配置
开启 Telegram Bot 通知

参考开发者博客

  1. 打开 Telegram 客户端,并找到 BotFather 与之对话创建 Bot ,并记下 Bot Token 备用
  2. 查看密码管理器中该 Telegram 帐号的 Chat ID 备用
  3. 在 edgetunnel 管理页面的消息通知设置中Telegram Bot 通知打开参数配置,并填入前述 Bot Token 和 Chat ID
  4. 点击可用性验证,稍等片刻如果显示有效,并且 Telegram Bot 也发来配置成功的消息,即可保存配置
  5. 最后勾选启用以开启通知功能
开启 Workers/Pages 可用请求数统计

参考开发者博客

  1. 在 Cloudflare 主页,依次进入 Build -> Compute -> Workers & Pages ,复制右下角的 Account ID 备用
  2. 在 Cloudflare 主页,依次进入 Manage account -> Account API tokens -> Create Token ,并选择 Read analytics and logs 作为创建模板,在 Zone Resources 中选定指定的域名并依次点击 Continue to summary -> Create Token 创建令牌
  3. 回到 edgetunnel 管理页面的消息通知设置中Cloudflare Workers/Pages 可用请求数统计打开参数配置,并填入前述 Account ID 和 API Token
  4. 点击可用性验证,稍等片刻如果显示验证成功,即可保存配置

BBR

Debian 10/11/12 PASSED
系统默认开启

# 开启
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
# 保存
sysctl -p
# 查看系统开关
sysctl net.ipv4.tcp_available_congestion_control
# 确认BBR开启
lsmod | grep bbr

客户端

Mihomo + MetaCube(XD)

  • docker-compose.yml

    version: '3.8'
    services:
      mihomo-server:
        image: ghcr.io/metacubex/metacubexd-server:v1.267.0
        container_name: mihomo-server
        restart: unless-stopped
        networks:
          - traefik_proxy
        ports:
          - "10808:7890"  # mixed proxy port
          - "19180:8080"  # dashboard UI + /api/control agent API
          # - '9090:9090' # mihomo Clash API + WebSocket (UI endpoint target)
        environment:
          - TZ=Asia/Shanghai
          - DEFAULT_BACKEND_URL=${MIHOMO_API_URL}
          - CONTROL_TOKEN=${MIHOMO_CTRL_TOKEN}
          - CLASH_SECRET=${MIHOMO_API_SECRET}
        volumes:
          - /path/to/your/mihomo/metacubexd-data:/data
        labels:
          - "traefik.enable=true"
          # UI
          - "traefik.http.routers.mihomo-ui.rule=Host(`your.mihomo.ui.domain`)"
          ...
          - "traefik.http.routers.mihomo-ui.service=mihomo-ui-service"
          - "traefik.http.services.mihomo-ui-service.loadbalancer.server.port=8080"
          # API
          - "traefik.http.routers.mihomo-api.rule=Host(`your.mihomo.api.domain`)"
          ...
          - "traefik.http.routers.mihomo-api.service=mihomo-api-service"
          - "traefik.http.services.mihomo-api-service.loadbalancer.server.port=9090"
        deploy:
          ...
        healthcheck:
          test: ["CMD", "wget", "-qO-", "http://localhost:8080/api/control/health"]
          ...
  • config.yaml

    mixed-port: ?           # 混合代理端口
    allow-lan: true         # 允许内网其他服务连接
    bind-address: '*'       # 监听所有网卡接口
    mode: rule              # 智能分流规则模式
    
    # 外部控制(供健康检查及前端面板连接)
    external-controller: 0.0.0.0:9090 
    secret: "?"
    
    # 纯端口代理,不需要开启 TUN
    tun:
      enable: false

配套工具

Proxifier PE | Windows

Proxychains | Linux

  1. 安装
sudo apt install -y proxychains
  1. 配置
sudo vim /etc/proxychains.conf