You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

关于NGINX实现IP校验结合二选一认证方式的配置困境咨询

关于NGINX实现IP校验结合二选一认证方式的配置困境咨询

老哥,看你这配置里的注释,明显是踩了Nginx satisfy any 和 access阶段规则的坑了对吧?现在只要请求来自xxxxx/24这个IP段,直接就绕开了所有Basic Auth和Authentik的认证逻辑,完全没达到你想要的「IP校验和认证二选一」的效果,我来给你拆解下问题,再给你对应需求的解决方案。

问题根源拆解

你现在的配置里,allow xxxxx/24; deny all;属于Nginx的access阶段规则,而auth_basicauth_request这些认证逻辑属于auth阶段规则。satisfy any的运行逻辑是:只要access阶段的规则通过,就直接跳过后面所有的auth阶段检查。所以来自信任IP段的请求,在access阶段就被allow规则直接放行,后面的Basic Auth、Authentik认证根本不会触发,这就是你现在困境的核心原因。

先明确你的核心需求

不同的需求对应不同的配置方案,你得先搞清楚你要的是哪种效果:

  • 情况1:信任IP直接放行,非信任IP必须走认证(Basic Auth或Authentik)
  • 情况2:不管IP是否在信任段,用户都可以选择「用IP放行」或者「用认证放行」(两种方式并行,满足其一即可)

针对情况1的配置方案(信任IP免认证,非信任IP强制认证)

这种需求下,我们可以用geo模块定义一个信任IP标识变量,然后根据这个变量来控制认证规则是否生效:

# 记得把这段放到http块里,全局生效
geo $trusted_ip {
    default 0; # 默认是0,表示非信任IP
    xxxxx/24 1; # 把你的信任IP段填在这里,匹配到的话变量值为1
}

server {
    # 这里放你的server块原有配置,比如监听端口、域名等

    location / {
        proxy_pass $forward_auth_target;

        # 只有非信任IP才触发认证逻辑
        if ($trusted_ip = 0) {
            auth_basic "内部系统请认证"; # 这里替换成你的认证提示语
            auth_basic_user_file "/etc/nginx/basic_auth/$forward_auth_bypass";

            auth_request     /outpost.goauthentik.io/auth/nginx;
            error_page       401 = @goauthentik_proxy_signin;
        }

        # 以下保持你原有的Authentik头部传递配置,不用改
        auth_request_set $auth_cookie $upstream_http_set_cookie;
        add_header       Set-Cookie $auth_cookie;

        auth_request_set $authentik_username $upstream_http_x_authentik_username;
        proxy_set_header X-authentik-username $authentik_username;

        auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
        proxy_set_header X-authentik-groups $authentik_groups;

        auth_request_set $authentik_email $upstream_http_x_authentik_email;
        proxy_set_header X-authentik-email $authentik_email;

        # 把你没写完的auth_request相关配置补在这里就行
    }
}

这个方案逻辑很直白:信任IP直接跳过所有认证,非信任IP必须走Basic Auth或Authentik认证才能访问。


针对情况2的配置方案(IP校验和认证二选一,两种方式都可用)

如果想要不管IP是否信任,用户都可以自主选择用IP放行或者用认证放行,那得把IP校验的逻辑也放到auth阶段,避免access阶段的规则直接跳过认证。我们可以写一个内部的专用location来做IP校验,然后用satisfy any把IP校验、Basic Auth、Authentik认证这几个规则绑定起来:

server {
    # 这里放你的server块原有配置,比如监听端口、域名等

    # 内部专用location,用来做IP校验,注意这个location只能被Nginx内部调用
    location /_check_trusted_ip {
        internal;
        access_by_lua_block {
            # 这里替换成你的信任IP段正则,比如"^192.168.1.0/24$"
            if ngx.var.remote_addr:match("^xxxxx/24$") then
                ngx.exit(200) # IP合法,返回200表示校验通过
            else
                ngx.exit(403) # IP不合法,返回403
            end
        }
    }

    location / {
        proxy_pass $forward_auth_target;

        satisfy any; # 满足以下任一条件即可放行

        # 条件1:通过IP校验
        auth_request /_check_trusted_ip;
        # 条件2:通过Basic Auth
        auth_basic "内部系统请认证";
        auth_basic_user_file "/etc/nginx/basic_auth/$forward_auth_bypass";
        # 条件3:通过Authentik认证
        auth_request     /outpost.goauthentik.io/auth/nginx;

        # 不管是IP校验失败还是认证失败,都跳转到登录页
        error_page 401 403 = @goauthentik_proxy_signin;

        # 以下保持你原有的Authentik头部传递配置,不用改
        auth_request_set $auth_cookie $upstream_http_set_cookie;
        add_header       Set-Cookie $auth_cookie;

        auth_request_set $authentik_username $upstream_http_x_authentik_username;
        proxy_set_header X-authentik-username $authentik_username;

        auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
        proxy_set_header X-authentik-groups $authentik_groups;

        auth_request_set $authentik_email $upstream_http_x_authentik_email;
        proxy_set_header X-authentik-email $authentik_email;

        # 把你没写完的auth_request相关配置补在这里就行
    }
}

这个方案里,satisfy any会同时检查三个条件,只要满足其中一个(IP信任、Basic Auth通过、Authentik认证通过)就会放行请求,完美实现了「二选一/三选一」的认证效果。


备注:内容来源于stack exchange,提问作者user1955545

火山引擎 最新活动