原本打算将这个文章分成三篇来水的,但是发现如果分成三篇文章,篇幅有些太短,还是一篇出来吧。这篇文章主要介绍三个方面:

  • 使用 Nginx 正向身份验证,出现 500 错误
  • 正向身份验证 不验证路径性能差
  • 部分服务不验证路径配置

其中两个问题,一个参考配置。说实话折腾了很久,搜烂了百度还是谷歌都没找到具体的解决方案。但后来还是通过 GPT 通过遍历法,才解决了其中的两个问题。


使用 Nginx 正向身份验证,出现 500 错误

如果你看了我之前的 《AuthenTik - 开源的身份验证服务》的话,在文章的最后预告了这篇文章。

当你无论是使用官方文档里的配置,还是配置应用程序完成之后 AuthenTik 给出你的配置,如果将验证的请求地址设置为公网地址,对不起,它就会发生 500 Error,反而配置为内网的 IP 就不会出现这个问题。

在此之前,你需要检查一下是否为该应用添加到前哨之中,并且尝试将 Nginx 配置文件中的外部的 AuthenTik 服务地址更换为 内网IP,如果使用内网IP并未出现这个问题,那么恭喜你,这个方法很可能就能解决你的问题。

检查日志的时候并不难发现,当你访问需要前置验证的地址时,Nginx 并没有没有访问正确的 AuthenTik 的服务地址:

https://123.123.123.123/outpost.goauthentik.io/auth/nginx

因为配置了 HTTPS 所有服务都走的是 443 端口(反向代理),而一台服务器不可能仅仅只配置一个服务,最最重要的是并没有告诉服务器,你需要访问的是哪个服务,所以就造成了这种错误。

解决方法

解决方法也非常简单,在监听/outpost.goauthentik.io路径中,将Host替换为 X-Forwarded-Host 头即可。

location /outpost.goauthentik.io {
	# When using the embedded outpost, use:
	proxy_pass          https://sso.home.roywang.cn/outpost.goauthentik.io;
	# For manual outpost deployments:
	# proxy_pass          http://outpost.company:9000;

	# Note: ensure the Host header matches your external authentik URL:
	# proxy_set_header      Host $host; 原本文档自带的。
	proxy_set_header	  X-Forwarded-Host $host;

    proxy_set_header    X-Original-URL $scheme://$http_host$request_uri;
    add_header          Set-Cookie $auth_cookie;
    auth_request_set    $auth_cookie $upstream_http_set_cookie;
    proxy_pass_request_body off;
    proxy_set_header    Content-Length "";
}

官方的文档中默认 AuthenTik 独占了一个端口,所以并没有考虑 X-Forwarded-Host 头,导致 Nginx 访问直接通过 IP 进行访问了 AuthenTik 服务,而我们配置了反向代理,这肯定是访问不到的。

特别注意:

而如果直接添加X-Forwarded-Host头,与proxy_set_header Host $host共存也会导致这个错误。

添加后即解决了这个问题。

正向身份验证 不验证路径性能差

由于我的一些文档都是通过WebDAV协议进行同步的。但是部署完正向身份验证后,有些时候同部文件的时候会出现超时错误,看了下 GoodSync,同步时间翻了 10 倍。经过实验确定是 AuthenTik 的性能问题。

其实看一下对比,390个文件、463个文件夹,这是使用了 AuthenTik 的不验证路径配置的性能:

172238 变更:0, 冲突:0, 复制时间:0, 复制状态:0, 错误: 0, All: 882
172238 -- 分析已结束。历时 00:02:16, 速度: 53 文件/秒

这是不使用 AuthenTik 的不验证路径配置的性能:

172338 变更:0, 冲突:0, 复制时间:0, 复制状态:0, 错误: 0, All: 882
172338 -- 分析已结束。历时 00:00:14, 速度: 61 文件/秒

其实解决方法也很简单,就是通过 Nginx 接管这部分 URI,不去走 AuthenTik。

具体的配置会在下面给出,但是需要说明的是,有些服务的 URI 是不固定的,只能通过 AuthenTik 的正则去匹配(比如 Gitea)

部分服务不验证路径(放行 URI )配置

这一部分介绍一些服务的 API 路径的配置,毕竟如果 API 还需要验证,很多服务就失去了它的意义。

有些服务有些特殊,比如 Gitea。就像前面所说,在使用 git 命令时,中间有一段 URI 是仓库名,而 Nginx 是无法匹配相关的 URI 的,只能使用 AuthenTik 的正则去匹配,虽然性能有些差,但是勉强能用,体感不会像 Alist 的 WebDAV 的差距那么巨大。

AuthenTik 不验证路径正则配置

Gitea

开始就是给出 Gitea 服务的正则,这是我使用的服务中唯一使用 AuthenTik 正则去配置不验证路径的。

这套正则,在使用 git 命令时,是完全没问题的,但其他方面没有测试。

^/api/.*$
^/[^/]+/[^/]+\.git/info/refs$
^/[^/]+/[^/]+\.git/git-receive-pack$
^/[^/]+/[^/]+\.git/git-upload-pack$

Nginx 不验证路径配置

主要还是监听相关路径,配置auth_request off;取消对于该路径的验证,然后去反代相关目录。

Alist WebDAV

location /dav/ {
    auth_request off;
    proxy_pass http://127.0.0.1:12345/dav/;
    proxy_set_header Host $host;
}

Vaultwarden(Bitwarden)

location /api/ {
    auth_request off;
    proxy_pass https://127.0.0.1:12345/api/;
    proxy_set_header Host $host;
}
location /icons/ {
	auth_request off;
    proxy_pass https://127.0.0.1:12345/icons/;
    proxy_set_header Host $host;
}
location /identity/connect/token {
    auth_request off;
    proxy_pass https://127.0.0.1:12345/identity/connect/token;
    proxy_set_header Host $host;
}
location /identity/accounts/prelogin {
    auth_request off;
    proxy_pass https://127.0.0.1:12345/identity/accounts/prelogin;
    proxy_set_header Host $host;
}
location /rest/ {
    auth_request off;
    proxy_pass https://127.0.0.1:12345/rest/;
    proxy_set_header Host $host;
}
location /api/ {
    auth_request off;
    proxy_pass https://127.0.0.1:12345/api/;
    proxy_set_header Host $host;
}
location /auth/ {
    auth_request off;
    proxy_pass https://127.0.0.1:12345/auth/;
    proxy_set_header Host $host;
}

Memos

location /api/v1/ {
    auth_request off;
    proxy_pass https://127.0.0.1:12345/api/v1/;
    proxy_set_header Host $host;
}

WireGuard DoH

使用X-Forwarded-For头替换掉Host可以保证 Docker 部署的 WireGuard DoH 正确的获取客户IP。

location /private-doh-service/code-01 {
    auth_request off;
    proxy_pass https://127.0.0.1:12345/dns-query/code-01;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Artalk

使用X-Forwarded-For头替换掉Host可以保证 Docker 部署的 Artalk 正确的获取客户IP。

location /api/ {
    auth_request off;
    proxy_pass http://127.0.0.1:12345/api/;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /sidebar/ {
    auth_request off;
    proxy_pass http://127.0.0.1:12345/sidebar/;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static/images {
	auth_request off;
	proxy_pass http://127.0.0.1:12345/static/images;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Umami

使用X-Forwarded-For头替换掉Host可以保证 Docker 部署的 Umami 正确的获取客户IP。

location /api {
    auth_request off;
    proxy_pass http://127.0.0.1:12345/api;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

后语

这篇文章规划了一个多月了,但是一直没时间写,终于抽空写了出来。

关于一些服务的不验证 URI 配置,可能在使用中在某些方面出现一些问题,如果有问题可以在评论区留言。或者有些别的服务,我这里没有列出的,也可以留言,我会尽力回答。