Caddy分流sni的reality代理方案


前言

本文采用集成L4插件的Caddy负责入站分流、sing-box容器作为vless+vision+reality协议组合的xray代理节点,旨在充分发挥Caddy自动签发证书的便利性与sing-box的代理协议配置多样性,为同时具有可靠代理和建站需求的服主提供更统一且灵活的部署思路。

准备

复现本文的操作实践依赖以下前提条件:

  • 用户已自行购买IP无污染VPS和域名mydomain.com
  • 为充分利用域名,使用子域blog.mydomain.com建设网站以伪造服务器用途
  • 如无特殊说明,本系列反代服务均采用低权限运行监听高位端口,由iptables转发标准https请求(即4438443)

预期达成的效果或功能:

  • 除SSH之外服务器整体对外仅开放标准https端口(443)呈现网站内容,可套CDN防护避免暴露真实IP地址
  • xray代理流量伪装成指向其他境外站点流量,保障流量意图隐匿且线路不经过CDN劣化
  • 代理服务端sing-box以podman容器(类docker)方式部署(可采用无根模式),支持无人值守自动更新
  • 关站或域名到期不影响代理

Caddy安装及配置

定制化部署Caddy

由于sni回落依赖高级功能,您不能直接使用熟悉的包管理器安装Caddy而是需要编译一个集成了插件的定制版本。对新手而言直接从Caddy官网云编译下载成品是最便捷的选择。本文场景下除了layer4支持以外还挑选了cloudflareDNS插件用于请求泛域名证书,我们假定您在建站阶段已经用电子邮件[email protected]科赋锐网站注册过并托管您的域名,在账号管理页面可获取MY_API_TOKEN用于完善tls配置。最后将下载到对应操作系统的执行文件重命名为无后缀的caddy并传至/usr/local/bin路径,按需配置执行权限并将服务加入进程守护:

1
2
sudo chmod +x /usr/local/bin/caddy
sudo curl -o /etc/systemd/system/caddy.service https://raw.githubusercontent.com/caddyserver/dist/refs/heads/master/init/caddy.service && sudo systemctl daemon-reload

编写Caddy配置文件

/etc/caddy/Caddyfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
https_port 8443
admin off
acme_dns cloudflare MY_API_TOKEN
email my@email.com
log {
output file /log/path/sys.log
level error
}
layer4 {
:8443 {
@reality tls sni itunes.apple.com
route @reality {
proxy {
upstream 127.0.0.1:7893
}
}
route { # Fallback to reverse proxy
proxy {
proxy_protocol v2
upstream 127.0.0.1:8443
}
}
}
}
}
*.mydomain.com {
encode gzip zstd
log {
output file /log/path/access.log
}
@blog host blog.mydomain.com
handle @blog {
reverse_proxy 127.0.0.1:8080 # website
}
handle {
abort # Fallback for otherwise unhandled domains
}
}

需要注意的是,sing-box v1.6.0+移除了对Proxy_Protocol的支持,因此xray代理流量的l4路由不配置此参数。最后不要忘记创建配置文件中提到的系统日志/log/path/sys.log和访问日志/log/path/access.log

性能调优

开启BBR拥塞缓解算法

1
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_congestion_control

防火墙适配

此处提供一个具备基础防护功能的iptables配置,它保留了22端口的ssh通信,同时接收443端口流量并转发至服务器内部Caddy监听的8443端口:

/etc/iptables.rules
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Generated by iptables-save v1.8.7 on Thu Jun 16 22:39:34 2022
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -m tcp --dport 8443 -j MARK --set-xmark 0x1/0xffffffff
-A PREROUTING -p udp -m udp --dport 8443 -j MARK --set-xmark 0x1/0xffffffff
COMMIT
# Completed on Thu Jun 16 22:39:34 2022
# Generated by iptables-save v1.8.7 on Thu Jun 16 22:39:34 2022
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m mark --mark 0x1 -j DROP
-A INPUT -p tcp -m multiport --dports 22,8443 -j ACCEPT
-A INPUT -p udp -m multiport --dports 8443 -j ACCEPT
# Completed on Thu Jun 16 22:39:34 2022
# Generated by iptables-save v1.8.7 on Thu Jun 16 22:39:34 2022
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8443
-A PREROUTING -p udp -m udp --dport 443 -j REDIRECT --to-ports 8443
COMMIT
# Completed on Thu Jun 16 22:39:34 2022

为防止提权漏洞被利用,我们强烈建议您不要赋予Caddy根权限就只是为了简单接管443端口。想要应用此防火墙配置,请使用iptables-restore /path/to/iptables.rules命令。

sing-box安装及配置

以容器(podman)方式部署

podman是一种兼容docker镜像的容器管理工具,较新的科学上网工具通常不会提供各发行版的软件源,但基本都维护更新docker镜像。podman本身亦具备一键更新命令podman auto-update且支持自动化定期执行,适合无人值守环境。
要通过podman部署容器,首先需要安装它。在debian-based发行版中的安装命令是sudo apt install podman,之后使用高度类似docker create的语法部署容器:

1
2
sudo podman create -it --name singbox --restart=unless-stopped --label io.containers.autoupdate=image --network=host --volume /etc/singbox:/etc/sing-box:z --volume /path/to/caddy/certificates/:/etc/ssl/private:z ghcr.io/sagernet/sing-box:latest -D /var/lib/sing-box -C /etc/sing-box/ run
sudo podman generate systemd --new --name singbox > /etc/systemd/system/container-singbox.service && sudo systemctl daemon-reload

可以注意到我们在sing-box容器的推荐参数之外还添加了容器对宿主服务器证书路径/path/to/caddy/certificates的访问。这是因为sing-box在实现部分代理协议时可以重复利用Caddy签发的证书,尽管对于reality来说并不是必须的。

服务端配置

以下配置将实现在7893端口上监听xray的代理请求,协议组合为时下抗检测能力较强的vless+vision+reality,降低流量特征并伪造访问意图指向了合规境外站点itunes.apple.com;具备简单的全局路由防呆(不响应目标地址为本地IP、大陆站点请求及一切bt下载)。
要使用该模板,您需要补全MY_UUID。此外服务端与客户端使用的密匙对MY_PUBLIC_KEYMY_PRIVATE_KEY,需要使用xray程序文件执行命令xray x25519 [-i "(base64.RawURLEncoding)" --std-encoding ]生成,这对于使用sing-box作为后端的我们是一个额外的小麻烦。

/etc/singbox/config.json (v1.11.x)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
{
"log": {
"disabled": false,
"level": "error",
"output": "/your/log/path/box.log",
"timestamp": true
},
"inbounds": [{
"tag": "real-in",
"type": "vless",
"listen": "::",
"listen_port": 7893,
"users": [{
"uuid": "MY_UUID",
"flow": "xtls-rprx-vision"
}],
"tls": {
"enabled": true,
"server_name": "itunes.apple.com",
"reality": {
"enabled": true,
"handshake": {
"server": "itunes.apple.com",
"server_port": 443
},
"private_key": "MY_PRIVATE_KEY",
"short_id": [""]
}
}
}],
"outbounds": [
{
"tag": "direct",
"type": "direct"
},
{
"tag": "block",
"type": "block"
}
],
"route": {
"rules": [
{
"inbound": ["real-in"],
"action": "sniff"
},
{
"type": "logical",
"mode": "or",
"rules": [
{"ip_is_private": true},
{"protocol": ["bittorrent"]},
{"rule_set": ["geoip-cn","geosite-cn"]}
],
"action": "reject",
"method": "drop"
}
],
"final": "direct",
"rule_set": [
{
"type": "remote",
"tag": "geoip-cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geoip/cn.srs",
"download_detour": "direct"
},
{
"type": "remote",
"tag": "geosite-cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/cn.srs",
"download_detour": "direct"
}
]
}
}

若您使用不同的版本,请结合官方文档酌情修改。与Caddy相似的,sing-box也需要预先创建日志文件/your/log/path/box.log以避免初启动报错。

客户端配置

因不同平台客户端配置方式各异,此处仅展示节点分享链。您需要补全与config.json文件中相同的MY_UUID、服务器的实际IPMY_SERVER_IP、与服务端 MY_PRIVATE_KEY成对的公钥MY_PUBLIC_KEY

1
vless://MY_UUID@MY_SERVER_IP:443?allowInsecure=false&flow=xtls-rprx-vision&fp=chrome&headerType=none&pbk=MY_PUBLIC_KEY&security=reality&sni=itunes.apple.com&type=tcp

此格式可通过剪贴板导入v2rayNGv2rayA等常见客户端。

完成!

校核配置文件无误后,启动Caddy与sing-box服务:

1
2
sudo systemctl enable --now caddy.service
sudo systemctl enable --now container-singbox.service

方案缺陷(?)

dest质量

在实践中您也许会注意到,由于伪装站服务器落地位置差异等因素,itunes.apple.com不一定是最合适的伪装对象,甚至有可能让自己的服务器成为其CDN反代加速节点。请参考官方建议及一些用户的心得技巧评估您的伪装站点。

保持学习

sing-box是一款锐意开发的通用代理平台,每次迭代引入新的功能特性都伴随着不同程度的调整淘汰,您需要持续跟进了解以避免配置文件过时而失效(当然抛开这一点,反网路審查本身就需要这么做),或者关闭podman自动更新。

Caddy更新缺乏便利性手段

使用定制版Caddy意味着无法享受来自维护者推送的更新,作为Web服务的第一道安全关卡,这样会错过重要的安全补丁。您不得不频繁的去官网生成下载新的执行文件。优雅专业的解决方法是架设自动化服务,同步拉取最新的代码按照自己的功能插件定制偏好定期编译。