You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Nginx Stream层HTTPS透传场景下基于主机名的IP访问限制配置咨询

Nginx Stream层HTTPS透传场景下基于主机名的IP访问限制配置咨询

兄弟,我明白你现在的困惑——用ssl_preread做Stream层HTTPS透传的时候,想针对不同主机名限制特定IP段,确实不像HTTP层那样直接用hostallow/deny那么直观。不过咱们可以通过Nginx的geomap模块结合起来实现,我给你捋清楚步骤和配置示例:

核心思路

因为是Stream层透传,没法直接解析HTTP请求头里的Host字段,所以得靠ssl_preread读取TLS握手阶段的SNI(服务器名称指示)字段,也就是客户端请求的主机名。然后结合geo模块定义IP限制规则,再用map把主机名和对应的IP规则关联起来,最后在Stream服务块里判断是否拒绝访问。

具体配置示例

stream {
    # 定义针对host1的IP黑名单:10.0.1.0/24段的IP标记为需要拦截
    geo $host1_blocked {
        default 0;
        10.0.1.0/24 1;
    }

    # 定义针对host2的IP黑名单:10.0.44.0/24段的IP标记为需要拦截
    geo $host2_blocked {
        default 0;
        10.0.44.0/24 1;
    }

    # 根据SNI(客户端请求的主机名)匹配对应的IP拦截规则
    map $ssl_preread_server_name $block_access {
        host1 $host1_blocked;
        host2 $host2_blocked;
        default 0; # 其他主机名不做IP限制
    }

    server {
        listen 443;
        ssl_preread on; # 必须开启这个才能读取SNI

        # 如果标记为需要拦截,直接关闭连接(return 444是Nginx特有的无响应关闭)
        if ($block_access = 1) {
            return 444;
        }

        # 这里放你原本的上游转发配置,比如根据SNI转发到不同上游
        # 举个例子,如果你原本就有根据SNI匹配上游的map:
        # map $ssl_preread_server_name $upstream {
        #     host1 upstream_host1;
        #     host2 upstream_host2;
        # }
        # proxy_pass $upstream;
    }

    # 如果你有单独的上游定义,放在这里
    # upstream upstream_host1 {
    #     server 192.168.1.10:443;
    # }
    # upstream upstream_host2 {
    #     server 192.168.1.20:443;
    # }
}

关键细节说明

  • geo模块用来定义IP段的匹配规则,匹配到的IP会返回1,其他返回0,这样我们就能标记哪些IP需要被拦截。
  • map模块把SNI($ssl_preread_server_name)和对应的geo规则绑定,比如当客户端请求的是host1时,就用host1的IP黑名单规则。
  • return 444是比较隐蔽的拦截方式,Nginx会直接关闭连接,不会给客户端返回任何错误信息,避免泄露服务器配置细节;如果你需要返回明确的错误,也可以用return 503之类的,但Stream层的错误码不像HTTP层那么直观。
  • 注意ssl_preread on必须开启,否则读不到SNI字段,整个规则就失效了。

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

火山引擎 最新活动