直接禁用TCP/IP监听只保留Unix socket需同时满足skip-networking=ON且注释或删除bind-address;否则bind-address=127.0.0.1仍开放TCP端口,无法真正隔离。

直接禁用 TCP/IP 监听,只保留 Unix socket 是可行的,但必须同时满足两个硬性条件:skip-networking=ON 且 bind-address 行被注释或删除;否则任何“只限本地”的配置都只是假象。
为什么 bind-address = 127.0.0.1 不等于只走 socket
这是最常见的误解。设 bind-address = 127.0.0.1 只是让 mysqld 监听 TCP 回环地址,仍开放 127.0.0.1:3306 端口——所有本机进程(包括恶意脚本)都能通过 TCP 连接,完全绕过 socket 权限控制。
-
skip-networking=ON才真正关闭 TCP 协议栈监听,mysqld 启动后不会绑定任何 TCP 端口 -
bind-address在skip-networking=ON下会被忽略,所以必须删掉或注释它,避免旧版本行为不一致 - MySQL 8.0+ 若启用 X Plugin(默认开
mysqlx=1),还需显式加mysqlx=0,否则仍可能监听:33060
服务端配置:socket 路径与重启验证
Unix socket 是否可用,取决于服务端是否生成了对应文件、路径权限是否正确,而非客户端怎么连。
- 在
[mysqld]段明确设置socket = /var/run/mysqld/mysqld.sock(路径需存在,属主为mysql用户,目录权限为drwxr-xr-x) - 改完配置必须重启:
sudo systemctl restart mysql(Ubuntu/Debian)或sudo systemctl restart mysqld(RHEL/CentOS) - 验证是否生效:
ss -tln | grep :3306应无输出;ls -l /var/run/mysqld/mysqld.sock应显示套接字文件(类型为srwxrwxrwx)
客户端连接:localhost ≠ 127.0.0.1,协议选择有优先级
MySQL 客户端对 -h localhost 和 -h 127.0.0.1 的处理完全不同——前者强制 fallback 到 socket(只要 socket 文件存在),后者强制走 TCP。
- 用
mysql -u root -p -h localhost或直接mysql -u root -p(不写-h),才会尝试 socket 连接 - 用
mysql -u root -p -h 127.0.0.1必然失败(TCP 已关),报错Can't connect to MySQL server on '127.0.0.1' - 可显式指定 socket:
mysql -u root -p -S /var/run/mysqld/mysqld.sock,绕过 hostname 解析逻辑 - 执行
SELECT @@socket;或STATUS命令,Connection 行显示Localhost via UNIX socket才算真正走 socket
用户权限陷阱:@'localhost' 是特例,不是 DNS 结果
MySQL 对 'user'@'localhost' 的匹配是硬编码行为,仅当连接来源为 Unix socket 时才命中——它和 DNS 无关,也不是通配符。
- 不要创建
'user'@'127.0.0.1'或'user'@'::1',它们强制走 TCP,会破坏隔离 - 删掉或
DROP USER所有@'%'、@'127.0.0.1'类账号,否则用户换种方式连就逃逸 - 创建账号必须用字面量:
CREATE USER 'app'@'localhost' IDENTIFIED BY 'xxx'; - Ubuntu/Debian 默认 root 用
auth_socket插件,它只认 socket 连接,但会导致mysql -u root -p报错——此时应改用sudo mysql -u root或重置密码并切回caching_sha2_password
真正的难点不在配置项本身,而在于服务端 socket 文件是否存在、客户端是否无意触发了 TCP fallback、以及用户 host 字段是否被其他宽泛规则覆盖。每一步都得单独验证,不能靠“应该可以”来判断。


















