翻车的home server经验分享-反向代理 [traefik]
创作立场声明:仅个人折腾
接着上篇,反向代理选的是traefik,为啥不选nginx,因为我没找到新手教程。还有,用traefik有个好处,比如traefik的ip和端口是192.168.0.3:80,直接访问这个是会出现404的。只有用域名才能正常访问。
欢迎各位直接去看traefik官网说明,谁能一次性看明白我就拜谁为师。总之先去看看,看完后就能明白我学得是多么辛苦了。甚至不用看我写的,快点去看官网。![翻车的home server经验分享-反向代理 [traefik]](https://res.smzdm.com/images/emotions/34.png)
介绍
首先介绍下啥是反向代理,事实上我也不清楚,我就知道它们是怎么干活的,举个不恰当的例子:反向代理就像小餐馆的服务员,服务就像厨房。你向服务员点菜,他们把菜端上来,你是不能进厨房的,虽然没进到厨房但是你吃到了要吃的菜。所以把反向代理当成中间人就行了。在http服务是这样的,假设你有3个服务,然后你反向代理的ip是192.168.0.3,反向代理的端口是80,然后在没有证书的情况下。
懂了吧,你以为你访问域名时访问的是服务的真实ip,其实你访问的是反向代理的ip。所以反向代理所在的机器需要消耗cpu性能进行解码。
接下来就是安装和使用traefik了,对于搭建traefik来说,用docker-compose更方便一点。对了,用的是traefik 2.x版本,1.x的我不会用,好像过不久就会出3.x了,会不会给我gui呢,不懂。总之先从简单的http反代开始吧。虽然是这么说,但是traefik得读取静态配置才能用的下去,然后静态配置有3种方式,1是用文件,就是等下要用的,2是命令行,我经常把它和下一种方式混淆,3是环境变量,用过docker的都懂吧。
安装
在安装traefik前先装portainer,方便管理容器。
先创建custom network。默认的是bridge模式。网关默认的是.1。
docker network create --subnet=172.20.0.0/16 traefik_proxy
然后用docker cli装portainer。6053537的portainer是中文的,比较好用。
docker run -dit --restart=always--name="portainer" -p 9001:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /home/用户名/docker/portainer/data/:/data --net traefik_proxy --ip 172.20.0.2 6053537/portainer-ce
然后开始安装traefik,先建好文件夹,再建一个叫traefik.yml的文件,填入以下内容,并不需要更改。
global:
checkNewVersion: true
sendAnonymousUsage: false
log:
level: DEBUG
filePath: /etc/traefik/logs/traefik.log
accessLog:
filePath: /etc/traefik/logs/access.log
api:
dashboard: true
debug: true
insecure: true
serversTransport:
insecureSkipVerify: true
entryPoints:
web:
address: :80
providers:
docker:
exposedByDefault: false
network: traefik_proxy
watch: true
file:
directory: /etc/traefik/config
watch: true
然后就是docker-compose了,记得在portainer的堆叠里创建。
version: '3'
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
traefik_proxy:
ipv4_address: 172.20.0.3
ports:
- 80:80
- 8080:8080
environment:
- TZ=Asia/Shanghai
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /home/用户名/docker/traefik/traefik.yml:/traefik.yml:ro
- /home/用户名/docker/traefik/logs:/etc/traefik/logs
- /home/用户名/docker/traefik/config:/etc/traefik/config
networks:
traefik_proxy:
external: true
好了,现在就能用http://ip:8080访问traefik dashboard了。然后开始第一次的反向代理。
使用
HTTP
假设要绑定这个域名:traefik.子域名.duckdns.org,在/traefik/config里创建rp-traefik.yml,然后输入:
http:
routers:
traefik:
entryPoints:
- web
rule: "Host(`traefik.子域名.duckdns.org`)"
middlewares:
service: api@internal
然后要在phole local dns里把域名和dns绑定好,保存后就能访问http://traefik.子域名.duckdns.org:80了。在traefik dashboard也能看到详细。恭喜你,你学会最简单的反代了。
Traefik的3个核心是entrypoint和router和service,entrypoint在traefik.yml出现了,router在rp-traefik.yml出现了,推理下就能举一反三了,接下来就是service了。因为traefik自己反代自己,所以知道service是谁,现在反代下其它容器,给你们看看service怎么写。假设host的ip是192.168.0.20。我注册了个临时子域名lastview.duckdns.org,拿nginx来当示范吧。
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
restart: unless-stopped
networks:
traefik_proxy:
ipv4_address: 172.20.0.4
ports:
- 180:80
networks:
traefik_proxy:
external: true
在/traefik/config里创建rp-nginx.yml,然后输入(service选一种就行了):
http:
routers:
portainer:
entryPoints:
- web
rule: "Host(`lastview.duckdns.org`)"
service: nginx
services:
nginx:
loadBalancer:
servers:
- url: "http://172.20.0.4:80"
- url: "http://192.168.0.20:180"
- url: "http://nginx:80"
你们能明白ip和端口为什么那么写吧。因为在同一个custom network,所以用名字用行。Servers的3种里面选1种用就好。
所以traefik的service也能这样写,不过不推荐就是了:
services:
traefik:
loadBalancer:
servers:
- url: "http://172.20.0.3:8080"
- url: "http://192.168.0.20:8080"
- url: "http://traefik:8080"
Http的反代就是这么简单,连middlewares都不需要。
HTTPS
现在开始https,需要做点小更改,但是要一个个举出来太累了,直接把全部放出来好了。只要改邮箱就能用了。对了,修改traefik.yml完后,需要重启traefik才能生效。
global:
checkNewVersion: true
sendAnonymousUsage: false
log:
level: DEBUG
filePath: /etc/traefik/logs/traefik.log
accessLog:
filePath: /etc/traefik/logs/access.log
api:
dashboard: true
debug: true
insecure: true
serversTransport:
insecureSkipVerify: true
entryPoints:
web:
address: :80
websecure:
address: :443
certificatesResolvers:
staging:
acme:
email: 注册letsencrypt用的email
storage: /etc/traefik/certs/acme.json
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: duckdns
production:
acme:
email: 注册letsencrypt用的email
storage: /etc/traefik/certs/acme.json
caServer: "https://acme-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: duckdns
tls:
options:
default:
minVersion: VersionTLS12
curvePreferences:
- secp521r1
- secp384r1
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
mintls13:
minVersion: VersionTLS13
providers:
docker:
exposedByDefault: false
network: traefik_proxy
watch: true
file:
directory: /etc/traefik/config
watch: true
然后是traefik的docker-compose:
version: '3'
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- traefik_proxy:
ipv4_address: 172.20.0.3
ports:
- 80:80
- 443:443
environment:
- DUCKDNS_TOKEN=自己的TOKEN
- TZ=Asia/Shanghai
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /home/用户名/docker/traefik/traefik.yml:/traefik.yml:ro
- /home/用户名/docker/traefik/certs:/etc/traefik/certs
- /home/用户名/docker/traefik/logs:/etc/traefik/logs
- /home/用户名/docker/traefik/config:/etc/traefik/config
networks:
traefik_proxy:
external: true
好了,开始https反代,接着拿nginx当示范。如果不搞http,直接搞https的话,会出现这情况,访问lastview.duckdns.org,浏览器识别成http://lastview.duckdns.org,然后出现404,但是直接访问https://lastview.duckdns.org又正常。rp-nginx.yml:
http:
routers:
nginx-http:
entryPoints:
- web
rule: "Host(`lastview.duckdns.org`)"
middlewares:
- https-redirectscheme
service: nginx
nginx-https:
entryPoints:
- websecure
rule: "Host(`lastview.duckdns.org`)"
middlewares:
- default-headers
tls:
certResolver: staging #production
domains:
- main: "lastview.duckdns.org"
sans:
- "*.lastview.duckdns.org"
service: nginx
services:
nginx:
loadBalancer:
servers:
- url: http://nginx:80
middlewares:
https-redirectscheme:
redirectScheme:
scheme: https
permanent: true
default-headers:
headers:
frameDeny: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 15552000
customFrameOptionsValue: SAMEORIGIN
customRequestHeaders:
X-Forwarded-Proto: https
先用staging挑战证书,成功的话访问https就会出现熟悉的自签证书的味道。
看看证书先。
现在把acme.json清空了,然后把浏览器的cookie清了,换production挑战。有可能需要重启traefik 。
看,成了。CA证书。
然后泛域名的证书也一起注册了,剩下的容器直接用现成证书就可以了,现在拿portainer演示。rp-portainer.yml:
http:
routers:
portainer-http:
entryPoints:
- web
rule: "Host(`portainer.lastview.duckdns.org`)"
middlewares:
- https-redirectscheme
service: portainer
portainer-https:
entryPoints:
- websecure
rule: "Host(`portainer.lastview.duckdns.org`)"
middlewares:
- default-headers
tls: {}
service: portainer
services:
portainer:
loadBalancer:
servers:
- url: "http://portainer:9000"
吐槽
嘛,反代就这样结束了,接下来解释下哪里翻车了,我也不知道怎么一下子说出来,所以请听我的废话。
静态配置
现在把traefik.yml一段段拆出来解释。
global:
checkNewVersion: true
sendAnonymousUsage: false
Global嘛,有和没有都行,checkNewVersion是检查更新的,sendAnonymousUsage是traefik搜集匿名消息的。
log:
level: DEBUG
filePath: /etc/traefik/logs/traefik.log
accessLog:
filePath: /etc/traefik/logs/access.log
log嘛,就是日志。Fail2ban需要用到access.log。traefik.log是用来debug的。logLevel有DEBUG,PANIC,FATAL,ERROR,WARN,INFO。默认好像是ERROR。
api:
dashboard: true
debug: true
insecure: true
Dashboard是api的一种,所以需要开dashboard必须要开api,具体的api在traefik官网里看吧。Insecure设置为true就能用ip:端口访问dashboard了。虽然dashboard没啥鸟用。重点是所有api都会暴露traefik的重要设置,开api前三思而后行。至于api怎么看,请去官网看。
serversTransport:
insecureSkipVerify: true
如果有容器有https证书,又想反代,必须设置为true。这个好像是动态配置来着。
entryPoints:
web:
address: :80
websecure:
address: :443
入口就是访问反向代理的端口,可以随便设。现场搞个新的示范,名字叫public,端口是666的:
public:
address: :666
嘛,你懂的,80和443不能用,换个端口就行了。
certificatesResolvers:
staging:
acme:
email: 注册letsencrypt用的email
storage: /etc/traefik/certs/acme.json
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: duckdns
production:
acme:
email: 注册letsencrypt用的email
storage: /etc/traefik/certs/acme.json
caServer: "https://acme-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: duckdns
这里就是获得letsencrypt证书的地方,把email换成自己的就能用了。如果跳过staging,直接挑战production,失败次数太多是会被ban的哦。因为Let's Encrypt挑战次数有限,先用staging挑战,失败了也不会被ban,成功后再换production挑战。有时候会出现怎么也挑战不成功的情况,解决的方法就是重启机器。还有acme.json不要自己创建,要不然会出现权限问题,它需要用的权限是0600。
tls:
options:
default:
minVersion: VersionTLS12
curvePreferences:
- secp521r1
- secp384r1
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
mintls13:
minVersion: VersionTLS13
翻车的时候到了,我完全看不懂这是什么,也不知道这是不是给人看的。你懂的吧,把别人的代码直接copy过来就和闭眼过独木桥一样。
providers:
docker:
exposedByDefault: false
network: traefik_proxy
watch: true
file:
directory: /etc/traefik/config
watch: true
Provider就是提供动态配置的地方。在docker可以用cli和label。然后用file,就是我前面展示的方法。把exposedByDefault设置为false就能避免traefik自动反代容器的情况了。这个traefik_proxy是自建的,名字随便取,这样可以避免单容器多网络状态下traefik识别不了网络。把watch设置为true,那么修改完后,traefik就能自动更新,不需要重启traefik了。还有就像前面的rp-traefik.yml和rp-nginx.yml,把config文件分开保存,可以避免一个文件写错然后全军覆没的风险。还有动态配置文件只能放在config里,不能是上级目录或者下级目录。
docker-compose
接下来是traefik的docker-compose:
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
这里应该都懂吧。
security_opt:
- no-new-privileges:true
这是不给traefik新权限,为了避免traefik被攻破后继续坏事。但是我觉得没什么用。![翻车的home server经验分享-反向代理 [traefik]](https://res.smzdm.com/images/emotions/82.png)
networks:
- traefik_proxy:
ipv4_address: 172.20.0.3
你们懂的吧,不固定ip会乱变的。然后traefik反代172.20.x.x段的容器就不用经过nat,减少损失。至于traefik_proxy,在同一网络下,像之前说的可以直接指向容器的名字。
ports:
- 80:80
- 443:443
- 8080:8080
在上面说过了。
environment:
- DUCKDNS_TOKEN=自己的TOKEN
- TZ=Asia/Shanghai
填了TOKEN才能挑战证书,每个支持的dns提供商的名字都不一样,具体上traefik官网看。
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /home/用户名/docker/traefik/traefik.yml:/traefik.yml:ro
- /home/用户名/docker/traefik/certs:/etc/traefik/certs
- /home/用户名/docker/traefik/logs:/etc/traefik/logs
- /home/用户名/docker/traefik/config:/etc/traefik/config
要用docker提供动态配置就需要mount docker.sock。
networks:
traefik_proxy:
external: true
用docker-compose的custom network必需要有指向的内容。至于external是因为traefik_proxy是已存在的网络,不设置为true那docker就会新建个网络。
动态配置
然后是file提供的动态配置。
http:
这里是http的反代,还有tcp和udp的,虽然我不会用。
routers:
router名:
router名必须是唯一的,如果相同,那么新的就会把旧的覆盖。
entryPoints:
- web
入口得选一个,这里是http的80端口。
rule: "Host(`域名`)"
rule是个复杂的东西,既能直接用域名,也能同时用多个域名,也能域名+路径,等等。不要把服务硬塞进路径里,会变得不幸。![翻车的home server经验分享-反向代理 [traefik]](https://res.smzdm.com/images/emotions/97.png)
middlewares:
- https-redirectscheme
为了让http自动转https才需要这个middleware。Middleware很复杂的,我看不懂几个,具体上traefik官网看。又翻车。
service: service名
service可以重复用。
新router名:
entryPoints:
- websecure
这里是https的443端口。
rule: "Host(`域名`)"
middlewares:
- default-headers
我完全不知道headers是干嘛用的。
tls:
certResolver: staging #production
domains:
- main: "域名"
sans:
- "*.域名"
用这个可以把域名和泛域名证书一起申请了,申请一次就够了,其它容器的tls就照portainer的做。
service: service名
services:
service名:
loadBalancer:
servers:
- url: https?://ip:端口
在servers可以填http或者https地址,在tcp服务填tcp,udp填udp。然后既然是loadBalancer,就能同时填多个服务地址。
middlewares:
https-redirectscheme:
redirectScheme:
scheme: https
permanent: true
这是一个叫redirectScheme的middleware。
default-headers:
headers:
frameDeny: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 15552000
customFrameOptionsValue: SAMEORIGIN
customRequestHeaders:
X-Forwarded-Proto: https
这是啥,天书吗,完全不知道从哪下手,也不知道怎么查相关资料,再次翻车。
一个容器翻了3次车,我也是不容易啊。
附件
接上篇的webmin和pihole。这2个反代是有坑的。记得域名绑定的对象是traefik所在机器的IP。
rp-webmin.yml:
http:
routers:
webmin:
entryPoints:
- web
rule: "Host(`webmin.子域名.duckdns.org`)"
middlewares:
- https-redirectscheme
service: webmin
webmin-secure:
entryPoints:
- websecure
rule: "Host(`webmin.子域名.duckdns.org`)"
middlewares:
- default-headers
tls: {}
service: webmin
services:
webmin:
loadBalancer:
servers:
- url: https://192.168.0.130:10000
在traefik只能做这么多,然后访问webmin会出现警告,具体是啥我也忘了,好像是非信赖域名的锅,我好像是去了networking那又跳提示,我跟着做,改了什么设置后就行了。
rp-pihole.yml:
http:
routers:
pihole:
entryPoints:
- web
rule: "Host(`pihole.子域名.duckdns.org`)"
middlewares:
- https-redirectscheme
service: pihole
pihole-secure:
entryPoints:
- websecure
rule: "Host(`pihole.子域名.duckdns.org`)"
middlewares:
- default-headers
- pihole-redirectprefix
tls: {}
service: pihole
services:
pihole:
loadBalancer:
servers:
- url: "http://192.168.0.140:80"
middlewares:
pihole-redirectprefix:
redirectRegex:
regex: "^(https?://pihole.子域名.duckdns.org/)$"
replacement: "/admin"
permanent: false
用ip访问pihole的ip:端口时不是会提示Did you mean to go to the admin panel?吗。反向代理后不会出现这页面,会出现error,不信你试试。解决方法就是加/admin这个路径。不会正则表达式我只能那么写了。
好了,下篇翻车的sso+mfa。

![翻车的home server经验分享-反向代理 [traefik]](https://qna.smzdm.com/202208/12/62f5e5e2dcc944267.jpg_e1080.jpg)
![翻车的home server经验分享-反向代理 [traefik]](https://am.zdmimg.com/202208/12/62f61606843cb2535.png_e1080.jpg)
![翻车的home server经验分享-反向代理 [traefik]](https://am.zdmimg.com/202208/12/62f61632457621986.png_e1080.jpg)
![翻车的home server经验分享-反向代理 [traefik]](https://qnam.smzdm.com/202208/12/62f617964bd4c3637.png_e1080.jpg)
![翻车的home server经验分享-反向代理 [traefik]](https://am.zdmimg.com/202208/12/62f6180b1fc7f7941.png_e1080.jpg)
![翻车的home server经验分享-反向代理 [traefik]](https://am.zdmimg.com/202208/12/62f619629483e5070.png_e1080.jpg)

![翻车的home server经验分享-反向代理 [traefik]](https://qnam.smzdm.com/202208/12/62f61bd5e326d3760.png_e1080.jpg)
![翻车的home server经验分享-反向代理 [traefik]](https://am.zdmimg.com/202208/12/62f61be84566b6359.png_e1080.jpg)
![翻车的home server经验分享-反向代理 [traefik]](https://qnam.smzdm.com/202208/12/62f61c097c4f18727.png_e1080.jpg)
![翻车的home server经验分享-反向代理 [traefik]](https://qnam.smzdm.com/202208/12/62f61c317e2999249.png_e1080.jpg)
![翻车的home server经验分享-反向代理 [traefik]](https://qnam.smzdm.com/202208/12/62f61c42efee69247.png_e1080.jpg)
martin
校验提示文案
破碎的冰
校验提示文案
usee00123
校验提示文案
小积木呀
校验提示文案
值友3445209220
校验提示文案
大地鼠
校验提示文案
我就是cy
校验提示文案
空调救我命
校验提示文案
tane274
校验提示文案
ferrets
校验提示文案
AkkunYo
校验提示文案
空调救我命
校验提示文案
空调救我命
校验提示文案
AkkunYo
校验提示文案
ferrets
校验提示文案
tane274
校验提示文案
值友3445209220
校验提示文案
usee00123
校验提示文案
我就是cy
校验提示文案
破碎的冰
校验提示文案
martin
校验提示文案
大地鼠
校验提示文案
小积木呀
校验提示文案
空调救我命
校验提示文案