Workerman自身不暴露Server头,风险主要来自Nginx(server_tokens未关)、PHP(expose_php=On)及默认X-Powered-By头;需在Nginx中配置proxy_hide_header Server和X-Powered-By,关闭server_tokens,PHP中设expose_php=Off,并在Workerman中清除X-Powered-By。

Workerman 本身不主动在 HTTP 响应头中写入 Server 字段,也不像 Nginx/Apache/Tomcat 那样默认暴露版本号——所以你查不到 Server: workerman/4.0.21 这类响应头。但如果你用的是 WebServer 组件(即内置 HTTP 服务),或搭配了 Nginx/Apache 反向代理,实际暴露的版本信息往往来自**下游组件或错误页**,不是 Workerman 自己“泄露”的。
为什么 curl -I 看不到 Server 头,但扫描工具仍报风险?
常见误判来源有三:
- 你启用了
WebServer,但没禁用X-Powered-By—— 它默认会返回X-Powered-By: workerman,部分扫描器把它当指纹识别依据 - 反向代理(如 Nginx)没关
server_tokens,导致最终响应头是Server: nginx/1.22.1,而扫描器顺藤摸瓜发现后端是 PHP + Workerman - PHP 自身暴露了
X-Powered-By: PHP/8.3.5,配合workerman的路由行为(比如特定 404 模式、Worker 启动日志路径)被关联推测
禁用 X-Powered-By 和自定义响应头
Workerman 的 WebServer 支持显式控制响应头。关键点是:它不会自动加 Server,但默认加 X-Powered-By。
在启动脚本中(如 start.php),修改 WebServer 实例初始化部分:
$web = new WebServer('0.0.0.0:8080');
$web->onMessage = function($connection, $data) {
// ...
};
// 关键:移除默认 X-Powered-By,并可选加空/伪造头
$web->onWorkerStart = function() {
\Workerman\Protocols\Http\Response::setHeader('X-Powered-By', '');
};
注意:\Workerman\Protocols\Http\Response::setHeader() 是全局静态方法,必须在 onWorkerStart 中调用才对所有请求生效;放在 onMessage 里只影响单次响应。
搭配 Nginx 时,真正要改的是 Nginx 配置
绝大多数生产环境都用 Nginx 做反代。此时 Workerman 根本不处理 HTTP 响应头,Server 字段完全由 Nginx 控制。
务必检查你的 Nginx 站点配置(如 /etc/nginx/conf.d/your-site.conf)是否包含:
-
server_tokens off;—— 关闭 Nginx 自身版本号(必须加在http或server块) -
proxy_hide_header Server;—— 防止 Nginx 把后端(如 PHP-FPM)返回的Server头透传出来 -
proxy_set_header X-Powered-By "";—— 清空可能从后端带过来的X-Powered-By
完整反代片段示例:
location / {
proxy_pass http://127.0.0.1:8080;
proxy_hide_header Server;
proxy_hide_header X-Powered-By;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
别忽略 PHP 层和错误页的版本痕迹
Workerman 常跑在 PHP 上,而 PHP 默认开启 expose_php=On,会在响应头加 X-Powered-By: PHP/8.x,且错误页(如未捕获异常)会输出带版本的 PHP 致命错误。
编辑 php.ini,确认以下项已设置:
expose_php = Offdisplay_errors = Offlog_errors = On
同时,在 Workerman 入口脚本中统一捕获未处理异常,避免裸错输出:
set_exception_handler(function($e) {
\Workerman\Protocols\Http\Response::send(500, 'Internal Server Error');
});
这能防止堆栈里出现 in /path/to/workerman/.../Connection.php on line 123 这类暴露路径和框架结构的信息。
真正起作用的安全加固,从来不是靠“藏一个字符串”,而是切断所有可被自动化工具串联的线索:HTTP 头、错误页文本、目录结构、响应时序特征。Workerman 没有“版本号开关”,它的安全水位取决于你是否把整个链路(Nginx → PHP → Workerman → 应用逻辑)里的冗余标识全部归零。

















