Docker部署Nginx时server_name为localhost1仍可正常访问的原因
问题原因
这是Nginx server块的默认匹配规则导致的,匹配流程和默认兜底逻辑和你预期的不一致:
- Nginx处理请求的第一步是匹配监听端口:会先筛选出所有
listen配置和请求目标端口一致的server块作为候选池。你的配置里只有1个server块监听80端口,所有发到80端口的请求首先都会进入这个候选池。 - 端口筛选完成后才会匹配
server_name:Nginx会拿请求携带的Host头,按照「精确匹配 > 前置通配符匹配 > 后置通配符匹配 > 正则匹配」的优先级和候选池里的server_name做匹配。 - 核心兜底逻辑:如果候选池里没有任何server块的server_name和当前Host头匹配,Nginx不会直接拒绝请求,而是会选中该监听端口对应的默认server块来处理请求。
默认server块的判定规则非常简单:如果没有在listen指令后显式加default_server参数标记默认块,Nginx会直接选第一个监听对应端口的server块作为默认server。你的配置里仅有一个监听80的server块,它天然就是80端口的默认server,不管请求带的Host头是localhost、127.0.0.1还是任意随机字符串,只要请求发到80端口,都会被这个块处理,自然可以正常打开页面。
实现「Host不匹配则访问失败」的配置方法
你可以任选以下一种方案调整配置,达到预期的拦截效果:
方案1:显式定义拦截用的默认server块
在现有配置前新增一个返回错误状态码的默认server块,所有未匹配到正确server_name的请求都会被这个块拦截:
server { listen 80 default_server; return 404; } server { root /usr/share/nginx/html/; index index.html; server_name localhost1; listen 80; }
方案2:在现有server块内加Host校验
如果不想新增server块,可以直接在现有块内加判断逻辑,Host不符合要求就直接返回错误:
server { root /usr/share/nginx/html/; index index.html; server_name localhost1; listen 80; if ($host != "localhost1") { return 404; } }
注意:如果用方案2的
if判断,不要在if块内加复杂的代理、重写逻辑,Nginx的if指令存在已知的逻辑坑,仅做简单的状态码返回没有问题。
内容的提问来源于stack exchange,提问作者Unknown developer
相关产品推荐
相关产品推荐

