mysql tcp握手banner无法通过配置关闭,是协议层硬编码行为,server_version字段在认证前明文暴露;唯一有效干预方式为proxysql代理覆盖或源码级替换。

MySQL 的 TCP 握手 banner 无法通过配置关闭,这是协议层硬编码行为——只要建立连接,server_version 字段就会以明文形式暴露在初始响应包里。改 my.cnf、设 version_comment、启 version_tokens 插件,全都不影响这个 banner。真正能干预它的,只有代理层覆盖或源码级替换。
nc 或 nmap 一连就暴露版本?这是协议层行为,不是配置漏了
攻击者根本不需要登录:执行 nc -w1 localhost 3306 | head -c100 或 nmap -sV -p3306 target 就能拿到类似 8.0.33 或 5.7.42-log 的字符串。这不是错误配置导致的泄露,而是 MySQL 协议规定 handshake response packet 必须携带 server_version 字段,且该字段在认证前就已发出。所以:
-
show_version = OFF是无效配置项,写进my.cnf也没任何作用 -
SET GLOBAL version_comment = 'xxx'只改变SELECT @@version_comment输出 -
version_tokens插件只影响SELECT VERSION()返回值,对 TCP banner 零干预
ProxySQL 2.4+ 是唯一推荐的生产级方案
ProxySQL 作为 MySQL 协议感知代理,可通过 admin 变量直接覆盖 handshake 包中的 server_version 字段。其他代理(HAProxy、nginx stream、mysql-proxy)无法安全修改 handshake packet,容易导致客户端解析失败。
- 启动 ProxySQL 后,执行:
SET GLOBAL mysql-server_version='5.5.55' - 该值会出现在所有经过 ProxySQL 的握手响应中,客户端看到的就是你指定的字符串
- 必须用
mysql-server_version(注意是下划线),不是version_comment或version_token_remove - 验证方式:直连 ProxySQL 端口(默认 6033),再跑一次
nc -w1 127.0.0.1 6033 | head -c100
源码修改仅限可控内网环境,且必须谨慎
修改 mysqld 源码是唯一从服务端根除 banner 版本号的方式,但风险高、维护成本大,不适用于多数生产环境。
- MySQL 5.7:定位
sql/mysqld.cc中的全局变量server_version,改为固定非空字符串(如"5.7.0") - MySQL 8.0+:搜索
server_version_str,通常在sql/server_components/component_implementation.cc或sql/mysqld.h - 必须完整重新编译(
make && make install),仅 patch 二进制文件不可靠,且可能破坏 ABI 兼容性 - 替换后务必用
tcpdump -i lo port 3306 -A -c1抓包验证,确认握手响应中 ASCII 字符串已变更
真正容易被忽略的是:哪怕你把 server_version 改成 "mysql-server" 这样的泛化字符串,JDBC/ODBC 驱动仍可能因解析逻辑差异而报错;ProxySQL 方案虽稳定,但需额外运维一个组件——安全和可用性之间,从来不是单选题。











