使用 Authentik 保护任何通过 Traefik 反代的应用
推荐观看 Christian Lempa 的视频,然后跳过阅读这篇文章
动机
Traefik 是我很喜欢的反代程序,Authentik 是一个我最近开始尝试的支持自建的身份认证系统。Authentik 的 Outpost是一种可以部署在外部的组件,提供了非常大的灵活性。通过与 Traefik 的集成,可以为任何被 Traefik 反代的应用提供认证。
假设
- 有一个 Authentik 服务
- 在服务器 A 上,部署了不同的 Docker 容器,并通过 Traefik 反代
*如果所有东西都是部署在同一台主机上的话,简单的创建一个本地 Outpost 即可
通过HTTPS连接Docker Socket
Authentik需要通过"integration"与Docker进行通信,因此我们首先需要在服务器 A 上配置Docker守护进程,使其支持安全的HTTPS连接。这遵循Docker官方的保护Docker守护进程安全的最佳实践。
准备证书
在运行Traefik的服务器上,我们需要创建一套TLS证书,包括CA证书、服务端证书和客户端证书。
1. 创建证书存储目录
mkdir -p /docker/certs
cd /docker/certs
2. 创建CA证书和密钥
# 创建CA私钥
openssl genrsa -out ca-key.pem 4096
# 创建CA证书,有效期10年(自行调整)
openssl req -new -x509 -days 3650 -key ca-key.pem -sha256 -out ca.pem
在创建CA证书时,系统会提示您输入一些信息。特别注意Common Name (CN)字段,填入服务器的FQDN。
3. 创建服务端证书和密钥
# 创建服务端私钥
openssl genrsa -out server-key.pem 4096
# 创建签名请求,将CN替换为您的服务器FQDN
openssl req -subj "/CN=host1.example.com" -sha256 -new -key server-key.pem -out server.csr
# 添加签名配置
echo subjectAltName = DNS:host1.example.com,IP:1.2.3.4,IP:127.0.0.1 > extfile.cnf
echo extendedKeyUsage = serverAuth >> extfile.cnf
# 签发服务端证书,有效期10年(3650天)
openssl x509 -req -days 3650 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
重要提示:请将
DNS:host1.example.com,IP:1.2.3.4
替换为您服务器的实际域名和IP地址。保留IP:127.0.0.1
以支持本地连接。
4. 创建客户端证书和密钥
# 创建客户端私钥
openssl genrsa -out client-key.pem 4096
# 创建签名请求
openssl req -subj "/CN=client" -sha256 -new -key client-key.pem -out client.csr
# 添加客户端扩展配置
echo extendedKeyUsage = clientAuth > extfile-client.cnf
# 签发客户端证书,有效期10年(3650天)
openssl x509 -req -days 3650 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile-client.cnf
5. 清理临时文件
生成所有证书后,您应该有以下文件:
├── ca-key.pem # CA私钥
├── ca.pem # CA证书
├── ca.srl # CA序列号文件
├── cert.pem # 客户端证书
├── client-key.pem # 客户端私钥
├── client.csr # 客户端证书请求(可删除)
├── extfile-client.cnf # 客户端扩展配置(可删除)
├── extfile.cnf # 服务端扩展配置(可删除)
├── server-cert.pem # 服务端证书
├── server-key.pem # 服务端私钥
└── server.csr # 服务端证书请求(可删除)
接下来,删除不再需要的临时文件:
rm -v client.csr server.csr extfile.cnf extfile-client.cnf
6. 设置正确的文件权限
为了安全起见,设置适当的文件权限:
chmod -v 0400 ca-key.pem client-key.pem server-key.pem # 仅所有者可读
chmod -v 0444 ca.pem server-cert.pem cert.pem # 所有用户可读
为Docker守护进程配置远程访问
接下来,我们需要配置Docker守护进程,使其支持TLS加密的远程访问。我们将通过systemd的override机制修改Docker的配置,而不是直接编辑原始的服务文件。
1. 创建override目录
mkdir -p /etc/systemd/system/docker.service.d
2. 创建override配置文件
vim /etc/systemd/system/docker.service.d/override.conf
3. 添加配置内容
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://YOUR_SERVER_IP:PORT --tlsverify --tlscacert=/docker/certs/ca.pem --tlscert=/docker/certs/server-cert.pem --tlskey=/docker/certs/server-key.pem
重要提示:
- 请将
YOUR_SERVER_IP
替换为您服务器的实际IP地址- 确保证书路径正确对应您存储证书的位置
- 端口
PORT
可以根据需要自定义,但请确保防火墙允许此端口的TCP连接
4. 重载systemd配置并重启Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
5. 验证Docker守护进程是否正在监听
sudo netstat -lntp | grep dockerd
在Authentik中配置集成
现在Docker守护进程已经配置为支持TLS连接,我们需要在Authentik中配置相应的证书和集成。
添加证书到Authentik
- 登录到Authentik管理界面
- 导航到
System
>Certificates
- 点击
Create
按钮
添加CA证书
- Name:
host1-docker-ca
- Certificate: 复制
ca.pem
的内容 - Private Key: 复制
ca-key.pem
的内容 - 点击
Create
保存
添加客户端证书
- Name:
host1-docker-client
- Certificate: 复制
cert.pem
的内容 - Private Key: 复制
client-key.pem
的内容 - 点击
Create
保存
创建Docker集成
- 导航到
System
>Outpost Integrations
- 点击
Create
>Docker Service-Connection
- 填写以下信息:
- Name:
host1-docker
- Docker URL:
https://YOUR_SERVER_IP:PORT
- TLS Verification Certificate: 选择
host1-docker-ca
- TLS Authentication Certificate/SSH Keypair: 选择
host1-docker-client
- Name:
- 点击
Create
保存 - 点击
Refresh
按钮,状态(State)应显示绿色
创建Provider和Application
我们以Traefik自带的Dashboard为例,配置一个受Authentik保护的应用。
创建Provider
- 导航到
Applications
>Providers
- 点击
Create
- 选择
Forward auth (single application)
- 填写以下信息:
- Name:
traefik-host1
- 根据需要配置其他选项如外部主机、转发身份验证URL等
- Name:
- 点击
Create
保存
创建Application
- 导航到
Applications
>Applications
- 点击
Create
- 填写以下信息:
- Name:
Traefik Dashboard
- Slug:
traefik-dashboard
- Provider: 选择刚才创建的
traefik-host1
- Name:
- 配置其他选项如策略、元数据等
- 点击
Create
保存
创建Outpost
Outpost是Authentik的代理组件,负责处理认证请求。
导航到
Applications
>Outposts
点击
Create
填写以下信息:
- Name:
host1-authentik-outpost
- Type:
Proxy
- Integration: 选择前面创建的
host1-docker
- Applications: 将
traefik-host1
添加到右侧列表
- Name:
点击
Advanced settings
,添加以下配置:authentik_host: https://authentik.your-domain.com/ object_naming_template: host1-authentik-outpost docker_network: frontend
注意:请将
authentik.your-domain.com
替换为您的Authentik实例的实际URL点击
Create
保存
创建完成后,Docker集成会在远程服务器上自动创建一个名为host1-authentik-outpost
的容器。刷新页面后,Outpost的状态应显示为绿色对勾。
注意:有时容器创建可能需要一些时间。如果容器已创建但未自动启动,可在远程服务器上运行
docker ps -a
查看状态,并通过docker start host1-authentik-outpost
手动启动。
配置Traefik集成
最后,我们需要配置Traefik以使用Authentik进行身份验证。
添加Authentik中间件
参考Authentik官方文档,在Traefik配置中添加以下中间件定义:
http:
middlewares:
authentik:
forwardAuth:
address: http://host1-authentik-outpost:9000/outpost.goauthentik.io/auth/traefik
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-entitlements
- X-authentik-email
- X-authentik-name
- X-authentik-uid
- X-authentik-jwt
- X-authentik-meta-jwks
- X-authentik-meta-outpost
- X-authentik-meta-provider
- X-authentik-meta-app
- X-authentik-meta-version
重要提示:请将 host1-authentik-outpost替换为实际的Outpost容器名称。
应用中间件到Traefik路由
如果使用 Docker Compose 管理Traefik,在Traefik服务的标签中添加中间件配置:
services:
traefik:
# ... 其他配置 ...
labels:
# ... 其他标签 ...
- traefik.http.routers.traefik-dashboard.middlewares=authentik@file
添加另一个应用?
通过上面的步骤,我们就将 Authentik 认证添加到了 Traefik Dashboard。
如果想要将同在 A 服务器上另一个被 Traefik 反代的应用 App1
也用 Authentik 保护起来的话,需要:
- 为
App1
创建另一个 Application (和 Provider),比如叫做app1-host1
- 进入
Application/Outposts
,编辑host1-authentik-outpost
,将app1-host1
也添加到右边