翻车的home server经验分享-反向代理 [traefik]

2022-08-14 16:38:30 12点赞 156收藏 21评论

创作立场声明:仅个人折腾

home server 篇一:翻车的home server经验分享-DNS [bind9][webm创作立场声明:仅个人折腾事先声明,我没学过代码,所有都是在网上找来自学的,我懂个锤子,电脑出问题了拍两下,没问题继续用。所以各位可以把我当成不明原因的吃瓜群众。吐槽当初家里无线信号不好,想换路由器,在冲浪的时候无意间碰到了张大妈。说真的,我没法鉴定这是好事还是坏事。我的确买到了合适的路由器,但是被安空调救我命| 1 评论0 收藏8查看详情

接着上篇,反向代理选的是traefik,为啥不选nginx,因为我没找到新手教程。还有,用traefik有个好处,比如traefik的ip和端口是192.168.0.3:80,直接访问这个是会出现404的。只有用域名才能正常访问。翻车的home server经验分享-反向代理 [traefik]

欢迎各位直接去看traefik官网说明,谁能一次性看明白我就拜谁为师。总之先去看看,看完后就能明白我学得是多么辛苦了。甚至不用看我写的,快点去看官网。翻车的home server经验分享-反向代理 [traefik]

介绍

首先介绍下啥是反向代理,事实上我也不清楚,我就知道它们是怎么干活的,举个不恰当的例子:反向代理就像小餐馆的服务员,服务就像厨房。你向服务员点菜,他们把菜端上来,你是不能进厨房的,虽然没进到厨房但是你吃到了要吃的菜。所以把反向代理当成中间人就行了。在http服务是这样的,假设你有3个服务,然后你反向代理的ip是192.168.0.3,反向代理的端口是80,然后在没有证书的情况下。

翻车的home server经验分享-反向代理 [traefik]

懂了吧,你以为你访问域名时访问的是服务的真实ip,其实你访问的是反向代理的ip。所以反向代理所在的机器需要消耗cpu性能进行解码。

翻车的home server经验分享-反向代理 [traefik]

接下来就是安装和使用traefik了,对于搭建traefik来说,用docker-compose更方便一点。对了,用的是traefik 2.x版本,1.x的我不会用,好像过不久就会出3.x了,会不会给我gui呢,不懂。总之先从简单的http反代开始吧。虽然是这么说,但是traefik得读取静态配置才能用的下去,然后静态配置有3种方式,1是用文件,就是等下要用的,2是命令行,我经常把它和下一种方式混淆,3是环境变量,用过docker的都懂吧。

安装

在安装traefik前先装portainer,方便管理容器。

翻车的home server经验分享-反向代理 [traefik]

先创建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

翻车的home server经验分享-反向代理 [traefik]

然后开始安装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也能看到详细。恭喜你,你学会最简单的反代了。

翻车的home server经验分享-反向代理 [traefik]

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就会出现熟悉的自签证书的味道。

翻车的home server经验分享-反向代理 [traefik]

翻车的home server经验分享-反向代理 [traefik]

看看证书先。

翻车的home server经验分享-反向代理 [traefik]

现在把acme.json清空了,然后把浏览器的cookie清了,换production挑战。有可能需要重启traefik 。

翻车的home server经验分享-反向代理 [traefik]

翻车的home server经验分享-反向代理 [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不能用,换个端口就行了。翻车的home server经验分享-反向代理 [traefik]

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过来就和闭眼过独木桥一样。翻车的home server经验分享-反向代理 [traefik]

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]

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]

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。

展开 收起
21评论

  • 精彩
  • 最新
  • 这个我也一直在搞,在unraid上搞,不过我看楼主这个事搞的复杂了,traefik最牛*的地方就是自动注册实现动态代理,看楼主都是静态文件来配置就有点累了,如果docker多的话变动频繁这么搞太累了,仅仅个人见解

    校验提示文案

    提交
    我知道可以用label啊,但我就是喜欢yaml [不好意思] ,而且就我一个人用,容器也没有50个,管理起来并不复杂

    校验提示文案

    提交
    哈哈好吧

    校验提示文案

    提交
    收起所有回复
  • 看着一堆yaml头都大了,感觉还是npm简单方便

    校验提示文案

    提交
    不用yaml也行,直接docker-compose上把label写上就行了。我只是喜欢用yaml,因为一大串代码看起来很厉害的样子 [傻笑]

    校验提示文案

    提交
    收起所有回复
  • 直接用宝塔就行了,nginx很多操作都可以给你界面搞定,证书续签各种,对小白友好。

    校验提示文案

    提交
    我用traefik是因为没有看到nginx的教程 一开始就写了

    校验提示文案

    提交
    我看到了呀,所以我补充了说小白用宝塔图形化配置对新手友好,他简化了很多配置项,不是说traefik就不好。

    校验提示文案

    提交
    收起所有回复
  • 我是 k3s 里用 traefik,证书用 cert manager,按需使用 ingress 接入,感觉挺方便的

    校验提示文案

    提交
    不会用k3s,连ingress都不知道是啥,我连代码都没学过,我只是个单纯的小白 [害羞]

    校验提示文案

    提交
    还这没有在k8s里面用过traefik,一直用ingress-nginx

    校验提示文案

    提交
    收起所有回复
  • 和cloudflared一样,有什么难?

    校验提示文案

    提交
    对你不难,对我这个完全没有相关知识的小白很难

    校验提示文案

    提交
    收起所有回复
  • 反代用npm很方便。

    校验提示文案

    提交
    是的,推荐npm,小白很容易上手

    校验提示文案

    提交
    收起所有回复
  • 我还是选择npm吧,这个看着头大 [尴尬]

    校验提示文案

    提交
  • [狂汗] 额,yaml格式全毁,我下篇把traefik.yml for https,docker-compose.yml for traefik-https,rp-traefik.yml for https,docker-compose.yml for nginx,rp-nginx.yml for https,rp-portainer.yml for https的图片补上

    校验提示文案

    提交
  • 反向代理用nginx最好,不会用可以装个宝塔面板。宝塔面板使用很简单。其实nginx配置也不复杂。

    校验提示文案

    提交
  • Nginx可以选择 nginx proxy manager,或者我在用的OPNsense里面nginx的插件,简单多了 [高兴]

    校验提示文案

    提交
  • 看了一遍,原理懂了,配置没记住,所以我用caddy

    校验提示文案

    提交
  • 更新:traefik默认使用UTC时间,会导致accesslog上也使用UTC时间而不是Asia/Shanghai时间,所以fail2ban和crowdsec会ban不了对象。按照下面的改traefik.yml,把回车改成回车,*改成空格:accessLog:回车**filePath: /etc/traefik/logs/traefik-access.log回车**fields:回车****names:回车******StartUTC: drop

    校验提示文案

    提交
提示信息

取消
确认
评论举报

相关文章推荐

更多精彩文章
更多精彩文章
最新文章 热门文章
156
扫一下,分享更方便,购买更轻松