yanchang
yanchang
发布于 2026-02-12 / 18 阅读
0
0

Authentik 实战笔记:优雅隐藏各类敏感服务

在折腾 Homelab 的过程中今天中毒了,如何保护敏感服务(如青龙面板、Portainer 等)始终是一个核心问题。直接将端口暴露在公网无异于“裸奔”,哪怕加了密码也容易被扫描和爆破。

最近我部署了 Authentik 作为统一身份认证中心,目标是:公网只开放 Authentik 的端口,所有敏感服务隐藏在后端,必须通过 Authentik 验证才能访问。

但在配置过程中,我遇到了一个经典的“网络不通”的坑。本文记录了从踩坑到完美解决的全过程,以及 Authentik 的详细配置指南。

目标是:

  • 外网只访问一个“不常用端口”(例如 9001

  • 青龙在 127.0.0.1:5700(宿主机回环)不对外开放

  • 通过 Authentik 原生 Proxy 去访问青龙

下面给你一套只用 Authentik 自带代理的做法(不引入额外反代软件),并且不使用 80/443


部署步骤(Docker Compose)

你需要先知道的两个关键点

  1. Authentik 默认端口是 9000(HTTP)/9443(HTTPS),Outpost 也在这两个端口上工作。

  2. 官方 compose 支持把“对外暴露端口”改成你想要的端口(通过 .env 里的 COMPOSE_PORT_HTTP/COMPOSE_PORT_HTTPS)。

1) 下载官方 compose

按官方文档下载 docker-compose.yml

mkdir -p /opt/authentik && cd /opt/authentik
curl -O https://docs.goauthentik.io/docker-compose.yml

生成 .env 里的必需项(官方也给了 openssl 方式):

echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env

2) 改成“不常用端口”

/opt/authentik/.env 追加(示例用 9000,你可以换成别的):

COMPOSE_PORT_HTTP=9000

这样外网访问 Authentik 就会变成:
http://你的域名或IP:9000
结束之后可以使用nginx配合泛域名,将9001代理到9000实现HTTPS访问,编辑/etc/nginx/sites-available/authentik.conf 

server {
    # 1. 监听端口
    listen 9001 ssl;
    # 2. 域名 (请确保这里和 Authentik 后台填写的域名一致,是 www 还是 ql?)
    server_name yanchang.cc *.yanchang.cc;

    # SSL 证书配置 (路径请确认无误)
    ssl_certificate     /etc/nginx/ssl/www.yanchang.pem;
    ssl_certificate_key /etc/nginx/ssl/www.yanchang.key;

    # SSL 协议优化
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # Authentik 不需要太大的上传限制,但为了上传头像/图标,保留适量大小
    client_max_body_size 100M;

    location / {
        # 指向 Authentik 的 HTTP 端口
        proxy_pass http://127.0.0.1:9000;

        # ========================================================
        # 【关键修复】解决重定向死循环的核心
        # ========================================================
        # 使用 $http_host 会带上端口号 (如 :9001),而 $host 不会。
        # Authentik 必须知道端口号才能生成正确的跳转链接。
        proxy_set_header Host $http_host;

        # ========================================================
        # 【关键修复】WebSocket 支持 (Authentik 必须)
        # ========================================================
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # 标准代理头 (告诉 Authentik 真实 IP 和协议)
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 增加超时时间防止后台操作断开 (可选)
        proxy_connect_timeout 300;
        proxy_send_timeout 300;
        proxy_read_timeout 300;
    }
}
sudo ln -s /etc/nginx/sites-available/authentik.conf  /etc/nginx/sites-enabled/
sudo nginx -t   # 检查配置有没有写错
sudo systemctl reload nginx

3)启动

docker compose pull
docker compose down
docker compose up -d

3) 让容器能访问宿主机的 127.0.0.1:5700解决方案:Docker 互联网络 (Bridge Network)

最干净的方案是利用 Docker 原生网络。让 Authentik 和青龙在同一个 Docker 网络中,这样 Authentik 就可以通过容器名直接访问青龙,完全不需要走宿主机 IP。

3.1 创建共享网络

Bash

docker network create authentik-internal

3.2 修改 Authentik 的 docker-compose.yml

将 Authentik 的 serverworker 服务加入该网络:

YAML

services:
  server:
    # ... 其他配置
    networks:
      - default
      - authentik-internal
  worker:
    # ... 其他配置
    networks:
      - default
      - authentik-internal

# 在文件底部声明网络
networks:
  authentik-internal:
    external: true

3.3 修改青龙面板的 docker-compose.yml

这是最关键的一步:

  1. 端口映射:依然只绑定 127.0.0.1,死守宿主机大门。

  2. 加入网络:加入 authentik-internal,为 Authentik 开“后门”。

YAML

services:
  qinglong:
    image: whyour/qinglong:latest
    container_name: qinglong  # 【关键】记住这个容器名,它是内网的主机名
    ports:
      - "127.0.0.1:5700:5700" # 依然只对本机开放
    networks:
      - authentik-internal
    # ... 其他配置

networks:
  authentik-internal:
    external: true

3.4 验证连通性

重启容器后,在 Authentik 容器内直接测试:

Bash

docker compose exec server sh -lc 'curl -sv --max-time 5 http://qinglong:5700/ >/dev/null'

返回 HTTP 200302,说明内网已打通!

这样你在 Authentik 的 Proxy Provider 里就可以把青龙后端写成:

  • http://qinglong:5700

4) 启动

docker compose down
docker compose up -d

Authentik 初始配置

1) 打开初始化页面

官方初始化入口是:
http://<host>:9000/if/flow/initial-setup/(注意末尾 /

你改了端口后就是:

  • http://<你的域名或IP>:19000/if/flow/initial-setup/

设置 akadmin 密码后登录后台。


下面是把 Docker Compose 转化为 Systemd 服务管理的详细步骤。

第一步:清理当前运行的容器

在接管之前,我们需要先停止当前正在手动运行的容器,防止冲突。

Bash

cd /opt/authentik
docker compose down

第二步:创建 Systemd 服务文件

我们需要创建一个 .service 文件来告诉系统如何启动和停止这个服务。

创建并编辑文件:

Bash

sudo nano /etc/systemd/system/authentik.service

将以下内容复制进去(假设你的配置文件在 /opt/authentik,如果不是请修改 WorkingDirectory):

Ini, TOML

[Unit]
Description=Authentik Identity Provider
# 确保在 Docker 服务启动且网络通畅后再启动
After=docker.service network-online.target
Requires=docker.service

[Service]
Type=simple
# 设定工作目录,docker compose 会自动找这个目录下的 docker-compose.yml
WorkingDirectory=/opt/authentik

# 启动命令:使用前台模式 (up),这样 Systemd 能捕获日志
ExecStart=/usr/bin/docker compose up --remove-orphans

# 停止命令:优雅关闭所有容器
ExecStop=/usr/bin/docker compose down

# 崩溃重启策略
Restart=always
RestartSec=10

# 只有 root 才能操作,保证安全性(也可以指定其他用户,但 Docker 通常需要 root 权限或 docker 组)
User=root
Group=root

[Install]
# 开机自启的目标级别
WantedBy=multi-user.target

注意:如果你的 Docker 版本较老(使用 docker-compose 命令而不是 docker compose),请将 ExecStartExecStop 里的命令改为 /usr/local/bin/docker-compose ...。你可以用 which dockerwhich docker-compose 检查路径。

第三步:加载并启动服务

保存文件退出后(Ctrl+O -> Enter -> Ctrl+X),执行以下命令:

  1. 重载 Systemd 配置(让系统识别新文件):

    Bash

    sudo systemctl daemon-reload
    
  2. 设置开机自启

    Bash

    sudo systemctl enable authentik
    
  3. 立即启动服务

    Bash

    sudo systemctl start authentik
    

第四步:验证状态与管理指南

现在,你可以享受到“系统级服务”的便利了。

1. 查看服务状态: 可以看到服务运行了多久,以及最新的几行日志。

Bash

sudo systemctl status authentik

2. 查看详细日志(非常方便): 这会显示 Authentik 下所有容器(Server, Worker, Redis, PG)混合在一起的实时日志,排错神器。

Bash

# 查看实时日志
sudo journalctl -u authentik -f

# 查看最近 100 行日志
sudo journalctl -u authentik -n 100

3. 重启服务: 当你修改了 docker-compose.yml.env 文件后,直接重启服务即可生效:

Bash

sudo systemctl restart authentik

4. 停止服务:

Bash

sudo systemctl stop authentik

这样配置后,Authentik 就彻底变成了你系统的一部分,完全不用操心 Docker 容器的启停细节了。

一、 踩坑现场:为什么代理一直“转圈圈”?

1.1 初始配置

我最初的想法很简单:Authentik 在 Docker 容器里,青龙面板也在宿主机上跑,那我直接让 Authentik 访问宿主机的 IP 不就行了?

  • 青龙监听127.0.0.1:5700 (为了安全,不绑定 0.0.0.0)

  • Authentik Proxy 配置Internal Host 填了 http://host.docker.internal:5700

1.2 故障现象

配置完成后,访问应用 URL,浏览器一直在加载中(Pending),最后超时。Authentik 似乎根本连不上后端。

1.3 排查过程

为了搞清楚发生了什么,我通过以下命令层层排查:

  1. 宿主机确认监听状态:

    Bash

    ss -lntp | grep 5700
    # 输出:127.0.0.1:5700
    

    确实只监听了回环地址。

  2. 进入 Authentik 容器内部测试:

    Bash

    # 查看 host.docker.internal 解析到了哪里
    docker compose exec server getent hosts host.docker.internal
    # 输出:172.17.0.1
    

    这里暴露了问题:host.docker.internal 解析到的是 Docker 网桥的网关 IP(172.段),而不是宿主机的 127.0.0.1

  3. 容器内 Curl 测试:

    Bash

    docker compose exec server sh -lc 'curl -sv --max-time 5 http://host.docker.internal:5700/'
    # 结果:Timeout
    

1.4 根本原因

SSH 隧道能访问 ≠ Docker 容器能访问。

  • 我在宿主机用 SSH 访问 127.0.0.1:5700 能通,是因为我本身就在宿主机上。

  • Docker 容器通过 172.17.0.1 访问宿主机时,请求来源于“外部网络”。而青龙面板被配置为仅监听 127.0.0.1,它会拒绝来自 172.17.0.1 的连接请求。


最终效果与收益

完成以上配置后,当你访问 https://ql.yanchang.cc 时:

  1. 请求首先到达 Authentik。

  2. Authentik 检查你是否登录。未登录 -> 跳转登录页。

  3. 登录成功后,Authentik 通过 Docker 内网将流量转发给 http://qinglong:5700

  4. 青龙面板的界面呈现在你面前。

这套方案的收益是非常明显的:

  • 隐身模式:公网扫描不到青龙的端口(5700),只有 Authentik 的端口对外。

  • 统一入口:以后再加 Portainer、Alist 等服务,都可以照葫芦画瓢,所有应用都汇聚在 Authentik 的 Portal 页面,体验类似企业的 SSO(单点登录)。

  • 安全加固:即使青龙面板本身有漏洞,黑客也必须先突破 Authentik 的验证(支持 2FA、WebAuthn 等)才能接触到青龙。

现在,我的 Homelab 既保持了外网访问的便利性,又最大程度地确保了安全性。


评论