Caddy下的Trojan和NaiveProxy配置.md

之前我一直使用的是vless和NaiveProxy 两种方式进行翻墙,这几年一直没有什么问题,但是犹豫xray升级之后,不再支持vless,这就导致了我只能使用NaiveProxy 进行翻墙,但是NaiveProxy 得手机客户端没几个好用的,很多都是需要使用插件外置的,于是就产生了升级和重新配置得想法。

首先,先说下我得环境,我得服务端用的是Caddy v2,简单方便得自动管理SSL证书,应用后端我之前比较喜欢用的是x-ui进行配置,然后再通过反代到对应docker的端口去。
于是我的选型方案就是优先能够实现这些功能,正好在GitHub找到对应的案例应用,所以就开始了升级之路。

修改dockerfile

之前我的caddy是直接使用官方推荐的方式,自己编译插件,毕竟要实现Trojan和NaiveProxy还需要两个特定的插件forwardproxy和Trojan-Go。这个导致的问题是每次编译都需要很长时间,有时候长达10分钟和处理器能力相关。如果是瓦工的机器,早就给我封锁了。

1
2
3
4
5
6
7
8
9
FROM caddy:builder-alpine AS builder

RUN xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/caddyserver/forwardproxy@caddy2

FROM caddy:alpine

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

正好GitHub它会每次拉取最新的Caddy版本并进行编译,加上实现案例必须的插件。而且我看了,对方应该设置了git action,更新的很及时,跟官方同步。于是我修改了下官方的dockerfile文件:

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
FROM alpine:latest # 使用最新版本

RUN apk add --no-cache \
ca-certificates \
libcap \
mailcap

RUN set -eux; \
mkdir -p \
/config/caddy \
/data/caddy \
/etc/caddy \
/usr/share/caddy \
; \
wget -O /etc/caddy/Caddyfile "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/config/Caddyfile"; \
wget -O /usr/share/caddy/index.html "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/welcome/index.html"

RUN set -eux; \
apkArch="$(apk --print-arch)"; \
case "$apkArch" in \
x86_64) binArch='amd64'; checksum='626682d623ca04356ab3c9a93a82386cfde6d8243b11f2d0eea9e97ba630c7ada62373401e96b72c6690c98ae8dd004d61fafe477f5249690d5cb251ebbfd2d9' ;; \
armhf) binArch='armv6'; checksum='c4647ed1b5407bd61d55f357af62d3935f2972bb5b03472a2747c4c19610376174bdb573f10b936cbc81acd8a103a0b961118d360cebe2b60693161f83e7f046' ;; \
armv7) binArch='armv7'; checksum='e6794aef179ec3319c5d692fedbb424532a47d7caf19a67ad2a4317c5f2776baaf47658f9e1f7fd37d6f3447a18285cd1d7cb91d0088f5cd01d73874a43aa9c2' ;; \
aarch64) binArch='arm64'; checksum='6d100bfd609e8cfe6a51afe1b86066ac68f53ac56670c74a7d7537d93c643aa7f0e82b9f3083218eee1d369a427bfcdafcb445c7a730f9fc0ddf546401d95484' ;; \
ppc64el|ppc64le) binArch='ppc64le'; checksum='9559d544b8f919837f66623955fd95b03511d85c56455f43d9cc6d0010c00bb1e81fc3b7b5e5a2f8d1d0f65d9571c80cb8b706ea94e2baaaeffec5ae52f68a34' ;; \
riscv64) binArch='riscv64'; checksum='9633d6f6c2bf1911d5887a5d0ea885413785e0968550875b995eecc3bb5fbd1267edec0add94a0286349273e4df0dc1f1067d5639c2393019e235536c1b7c477' ;; \
s390x) binArch='s390x'; checksum='5b29b377409abb9b8d241b95a11f1dd5d709759760b1514c9fbf616c3975048cf384441527fdc179bb8b08dc6189afe9df33499b46509e5d0e3bd6da8bb293b1' ;; \
*) echo >&2 "error: unsupported architecture ($apkArch)"; exit 1 ;;\
esac; \

wget -O /tmp/caddy.tar.gz "https://github.com/lxhao61/integrated-examples/releases/latest/download/caddy-linux-${binArch}.tar.gz"; \ ## 替换掉下载地址
tar x -z -f /tmp/caddy.tar.gz -C /usr/bin caddy; \
rm -f /tmp/caddy.tar.gz; \
setcap cap_net_bind_service=+ep /usr/bin/caddy; \
chmod +x /usr/bin/caddy; \
caddy version

ENV XDG_CONFIG_HOME /config
ENV XDG_DATA_HOME /data

LABEL org.opencontainers.image.title=Caddy
LABEL org.opencontainers.image.description="a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go"
LABEL org.opencontainers.image.url=https://caddyserver.com
LABEL org.opencontainers.image.documentation=https://caddyserver.com/docs
LABEL org.opencontainers.image.vendor="Light Code Labs"
LABEL org.opencontainers.image.licenses=Apache-2.0
LABEL org.opencontainers.image.source="https://github.com/caddyserver/caddy-docker"

EXPOSE 80
EXPOSE 443
EXPOSE 443/udp
EXPOSE 2019

WORKDIR /srv

CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile.json"] ##修改命令不再使用caddyfile,这点后文会解释。

如果你有需要直接复制粘贴即可。需要注意这个是Linux版本的,他会测试系统型号,然后下载对应的包。这个执行起来就快多了,不用再次编译。

使用json文件替换原来的Caddyfile

之前使用的是Caddyfile文件进行配置,好处是简单,但是现在涉及一些比较精细的操作Caddyfile文件就比较难以实现,比如
206-caddy下的Trojan和NaiveProxy配置-2025-05-30-16-10-29
这种复杂的功能在握手之前就要判断出是否正确的HTTPS协议,这样可以避免一些主动探测,增强安全性。而这个功能Caddyfile就无法实现。其次是json文件Caddy v2的升级必备,你使用的Caddyfile文件其实是系统后台转换成json文件后执行的。
Caddy也提供了一个转换命令

docker exec 容器 caddy caddy adapt --config /etc/caddy/Caddyfile --adapter caddyfile

复制下来之后,格式化一下就行,会有一些小瑕疵,但是保证可以运行。
这边提供一个json文件并且解释一下对应:
PS:json文件无法注释,所以如果要用,复制后删除掉注释部分。

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
{
"admin": {
"disabled": true,
"config": {
"persist": false
}
},# 禁用后台管理,造抄就行
"logging": {
"logs": {
"default": {
"writer": {
"output": "file",
"filename": "/usr/share/caddy/log/error.log"
},
"encoder": {
"format": "console"
},
"level": "ERROR",
"exclude": [
"http.log.access.log0"
]
},
"log0": {
"writer": {
"output": "file",
"filename": "/usr/share/caddy/log/access.log"
},
"encoder": {
"format": "console"
},
"include": [
"http.log.access.log0"
]
}
}
},# 日志配置,自己决定要不要
"apps": {
"http": {
"servers": {
"srv0": { #这个名字随意命名
"listen": [
":443"
],
"listener_wrappers": [
{
"wrapper": "trojan"
}
],#根据上面流程图,监听443,和trojan协议
"routes": [ # 这个是路由,如果你有多个域名需要在这里进行匹配风流,我这边就一个,所以没有用match
{ #第一个处理NaiveProxy的代理,验证用户名密码,没问题就直接代理
"handle": [
{
"auth_credentials": [
"#用户名:密码然后使用其字符串使用后面 base64 编码2次命令生成:echo -n "user:pass" | base64 | tr -d '\n' | base64#"
],
"handler": "forward_proxy",
"hide_ip": true,
"hide_via": true,
"probe_resistance": {}
}
]
},
{ #第二个处理是直接强制HTTPS,然后再反向代理到docker的端口去
"handle": [
{
"handler": "headers",
"response": {
"set": {
"Strict-Transport-Security": [
"max-age=31536000; includeSubDomains; preload"
]
}
}
},
{
"handler": "reverse_proxy",
"upstreams": [
{
"dial": "172.18.0.3:4567"
}
]
}
]
}
],
"tls_connection_policies": [#配置对应域名的协议,造抄就行
{
"match": {
"sni": [
"xxx.xxxr.com"
]
},
"cipher_suites": [
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
],
"alpn": [
"h3",
"h2",
"http/1.1"
]
}
],
"logs": {
"default_logger_name": "log0"
},
"protocols": [
"h1",
"h2",
"h3"
]
}
}
},
"trojan": {
"proxy": {
"proxy": "no_proxy"
},
"upstream": {
"upstream": "caddy"
},
"users": [
"diy6443" #trojan的密码,后续客户端要用
]
},
"tls": { #下面这块是TLS证书申请的,这边提供把域名写上之后,系统自动会申请,这边用了Cloudflare的DNS解析,可以换成自己的还有他们官方的
"certificates": {
"automate": [
"xxxxx.xxxx.com"
]
},
"automation": {
"policies": [
{
"subjects": [
"manhua.minsummer.com"
],
"issuers": [
{
"challenges": {
"dns": {
"provider": {
"api_token": "xxxx",
"name": "cloudflare"
}
}
},
"email": "Email邮箱",
"module": "acme"
},
{
"ca": "https://acme.zerossl.com/v2/DV90",
"challenges": {
"dns": {
"provider": {
"api_token": "xxxx",
"name": "cloudflare"
}
}
},
"email": "Email邮箱",
"module": "acme"
}
]
}
]
}
}
}
}

从json文件可以看出,它可以实现十分细致的协议判断。这边由于我只有一个网站,所以比较简便,如果多个网站共存,需要在routes里面增加match匹配让它根据进来的不同域名分别方向代理到不同的docker端口去。

客户端配置及优化

NaiveProxy

NaiveProxy官方有几种调优方式这块可以看对应的服务器优化,这里主要说的是使用Quic协议进行访问。具体可以查看两者区别:

quic://user:[email protected]

简单说这个协议握手次数更短,建议使用,另外还有一些参数,可以自行进行调整。NaiveProxy的配置文件是JSON格式的

1
2
3
4
{
"listen": "socks://127.0.0.1:1080",
"proxy": "https://user:[email protected]"
}

写好之后,在V2rayNG里面调用即可
206-caddy下的Trojan和NaiveProxy配置-2025-05-30-16-51-41

Trojan

这个就要简单了,直接新增配置即可。
206-caddy下的Trojan和NaiveProxy配置-2025-05-30-16-53-53

总结

至此,所有的配置结束。总结下就是在研究的过程中,发现现在内核都在不断更新,无论是协议还是客户端。这次也算是完成了自己一直想要做的一件事吧。每次手机上网翻墙都不是很方便。
而且这么更新之后,后续对服务器的占用会更少,只需要一个Trojan和NaiveProxy即可满足大部分需求,至于安全性,一个是因为DMIT支持免费换IP,还有就是NaiveProxy这么多年用下来没有任何问题。