关键需三步验证:一查响应头(curl -i),server字段不得含斜杠+数字;二看错误页源码(curl /xxx),确保无nginx/、version等字样;三扫二进制(strings nginx | grep),清除所有残留版本字符串。

直接在源码编译后验证 Nginx 版本号是否真正隐藏,关键不是“改没改”,而是“改得全不全、生效没生效”。下面分三步排查,覆盖响应头、错误页、服务标识三大暴露点:
一、检查 HTTP 响应头是否干净
这是最基础也是最容易漏掉的一环。即使改了源码,若未清除所有 Server 字符串定义,curl 仍可能返回带版本或异常标识的响应头。
- 执行
curl -I http://your-server-ip/,观察Server:行 —— 理想结果是Server: nginx或自定义值(如Server: happy),**不能含斜杠+数字**(如nginx/1.26.3、happy/1.0) - 如果看到版本号,说明
src/http/ngx_http_header_filter_module.c中的ngx_http_server_string未修改,或修改后未重新编译生效 - 注意:该测试必须在
server_tokens on;状态下进行(即配置不干预),才能验证源码层是否真正起效
二、触发错误页面看是否泄露
很多只改了响应头,却忘了 404/502 等错误页底层也硬编码了版本字符串,攻击者访问不存在路径即可探测。
- 用 curl 请求一个不存在的路径:
curl http://your-server-ip/xxx - 查看返回的 HTML 源码,搜索
nginx、version、1.26等关键词 - 重点检查两个文件是否被修改:
-
src/http/ngx_http_special_response.c中的错误页模板(如ngx_http_error_404_page相关字符串) -
src/core/nginx.h中NGINX_VER和NGINX_VERSION定义 —— 若仍为"nginx/" NGINX_VERSION,错误页就会拼出完整版本
-
三、确认二进制中无残留字符串
编译后的 nginx 可执行文件里可能还埋着原始版本字符串,nmap 或 strings 工具能直接扫出来,属于“静态泄露”。
- 运行:
strings /usr/local/nginx/sbin/nginx | grep -i "nginx\|1\.26\|version" - 若输出含
nginx/1.26.3、built by gcc后跟明显版本痕迹,说明源码中还有未覆盖的字符串(常见于日志模板、调试信息、第三方模块兼容字段) - 重点关注以下位置是否清理:
-
src/core/nginx.h(主版本宏) -
src/http/ngx_http_header_filter_module.c(响应头) -
src/http/ngx_http_special_response.c(错误页 HTML) -
src/os/unix/ngx_process_cycle.c(部分版本会在启动日志打印,影响 strings 扫描)
-











