真正禁用tcp、仅保留unix socket需同时设置skip-networking=on并注释bind-address,重启后ss -tln应无3306监听;客户端用-h localhost或-s指定socket路径方可走本地socket连接。

MySQL 不能“只允许”Unix Socket连接,但可以禁用 TCP/IP 监听,从而让本地连接只能走 socket —— 这是实际可行的加固手段。
停掉 MySQL 的 TCP/IP 监听(bind-address = 127.0.0.1 不够)
很多人误以为设 bind-address = 127.0.0.1 就能“只限本地”,其实它仍启用 TCP/IP,只是限制了监听地址。真正关闭 TCP 连接,必须显式禁用:
- 编辑
/etc/mysql/my.cnf或/etc/my.cnf,在[mysqld]段添加:skip-networking<br>bind-address = 127.0.0.1
(skip-networking是关键,它彻底关掉 TCP 监听;bind-address在这里只是兜底,防止某些旧版本忽略skip-networking) - 如果使用 MySQL 8.0+ 且启用了
mysqlx(X Protocol),还需加:mysqlx=0
,否则 X Plugin 仍可能开 TCP 端口(默认 33060) - 改完必须重启服务:
sudo systemctl restart mysql(或mariadb) - 验证是否生效:
ss -tln | grep :3306应无输出;netstat -tlnp | grep mysqld也不应看到 3306 端口
确认 socket 路径并确保客户端默认走 socket
即使关了 TCP,客户端仍可能因配置错误尝试连 127.0.0.1 导致失败。要让 mysql -u root -p 自动走 socket,需满足两个条件:
- 服务端
socket路径已明确配置(如socket = /var/run/mysqld/mysqld.sock),且该文件存在、属主为mysql、权限为srwxrwxrwx(套接字文件权限通常宽松,但目录如/var/run/mysqld/必须是drwxr-xr-x且属主mysql) - 客户端不显式指定
-h 127.0.0.1或--protocol=TCP;只要用-h localhost或完全不写-h,MySQL 客户端就会自动 fallback 到 socket(这是硬编码行为) - 可手动验证:
mysql -u root -p -h localhost -e "SELECT @@socket;"返回路径,且Connection显示Localhost via UNIX socket
避免 auth_socket 插件导致的“免密却连不上”问题
Ubuntu/Debian 默认用 auth_socket 插件给 root@localhost 用户授权,它只认 socket 连接,不接受密码。这看似符合“只走 socket”,但容易踩坑:
- 如果你用
mysql -u root -p -S /var/run/mysqld/mysqld.sock却输错密码,会报Access denied for user 'root'@'localhost'—— 因为插件根本不验密码,只检查连接方式 - 若你希望保留密码登录,又只走 socket,得把用户认证方式切回
mysql_native_password:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';
- 执行后记得
FLUSH PRIVILEGES;,否则变更不生效
Java/Python 等应用客户端要额外处理
命令行 mysql 工具天然支持 socket,但 JDBC、PyMySQL 等库默认只走 TCP。想让它们也只走 socket,必须显式适配:
- JDBC 不原生支持 Unix socket;必须引入
junixsocket第三方驱动,并在连接 URL 中用unixSocketPath参数指定路径,例如:jdbc:mysql://localhost:3306/db?unixSocketPath=/var/run/mysqld/mysqld.sock
(注意:URL 里仍写localhost:3306,实际由 junixsocket 拦截并转成 socket 连接) - PyMySQL 不支持 socket;推荐换用
mysql-connector-python,它支持unix_socket参数:conn = mysql.connector.connect(unix_socket='/var/run/mysqld/mysqld.sock', user='root', password='...')
- Go 的
github.com/go-sql-driver/mysql同样不支持;需用file://前缀或改用github.com/ziutek/mymysql等替代驱动
最关键的其实是权限和路径一致性:服务端 socket 文件存在且可访问,客户端不主动触发 TCP,应用层驱动不默认 fallback 到网络——三者缺一不可。很多“配置完了还是连不上”的问题,都卡在目录权限没设对,或者应用代码里硬编码了 127.0.0.1。











