本地开发连公司数据库,在家连公司测试环境,远程运维生产库...
MySQL远程连接是刚需,但配置不当就是安全隐患。这篇整理一下远程连接的正确姿势。
为什么连不上?
先说最常见的问题:MySQL装好了,远程连不上。
原因通常就这几个:
1. MySQL没有监听外网
bash
# 查看MySQL监听地址
netstat -tlnp | grep 3306
# 如果显示 127.0.0.1:3306,说明只监听本地
# 需要改成 0.0.0.0:3306 或具体IP
修改配置:
ini
# /etc/mysql/mysql.conf.d/mysqld.cnf 或 /etc/my.cnf
[mysqld]
bind-address = 0.0.0.0
重启MySQL:
bash
systemctl restart mysql
2. 用户没有远程权限
sql
-- 查看用户权限
SELECT user, host FROM mysql.user;
-- 如果host是localhost,就只能本地连
-- user: root, host: localhost ← 只能本地
-- user: root, host: % ← 可以任意IP连接
创建远程用户或修改权限:
sql
-- 方式1:创建新用户
CREATE USER 'dev'@'%' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON your_db.* TO 'dev'@'%';
FLUSH PRIVILEGES;
-- 方式2:修改现有用户(不推荐直接改root)
-- MySQL 8.0
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';
3. 防火墙拦截
bash
# 查看防火墙状态
ufw status
# 或
firewall-cmd --list-all
# 开放3306端口
ufw allow 3306
# 或
firewall-cmd --permanent --add-port=3306/tcp
firewall-cmd --reload
4. 云服务器安全组
如果是云服务器,还要在控制台开安全组:
makefile
入站规则:
协议: TCP
端口: 3306
来源: 0.0.0.0/0 (或指定IP)
远程连接的几种方式
1. 直接连接(不推荐)
bash
mysql -h 公网IP -P 3306 -u dev -p
问题:
- 3306端口暴露在公网,容易被扫描攻击
- 密码在网络上明文传输(除非用SSL)
- 安全隐患很大
2. SSH隧道(推荐)
通过SSH建立加密隧道,MySQL流量走SSH通道:
bash
# 本地执行
ssh -L 3307:localhost:3306 user@server_ip
# 然后连接本地3307端口
mysql -h 127.0.0.1 -P 3307 -u dev -p
或者用Navicat/DataGrip等工具的SSH隧道功能:
makefile
SSH主机: server_ip
SSH用户: user
SSH密钥: ~/.ssh/id_rsa
MySQL主机: localhost (注意是localhost,不是server_ip)
MySQL端口: 3306
优点:
- MySQL端口不用暴露公网
- 流量加密
- 可以用SSH密钥认证
3. VPN/组网方案
如果经常需要连接,每次建SSH隧道挺麻烦的。
更好的方式是组建虚拟局域网,让你的电脑和服务器像在同一个内网:
scss
你的电脑(192.168.100.2) ←→ 虚拟网络 ←→ 服务器(192.168.100.1)
└── MySQL(192.168.100.1:3306)
这样直接连内网IP就行:
bash
mysql -h 192.168.100.1 -P 3306 -u dev -p
我自己用的是星空组网,配置比较简单,装个客户端就能用。特别是公司有多台服务器的情况,组好网后运维方便很多,不用每台机器都配SSH隧道。
安全配置
远程连接开了,安全措施得跟上。
1. 限制访问IP
sql
-- 只允许特定IP连接
CREATE USER 'dev'@'192.168.1.%' IDENTIFIED BY 'password';
-- 只允许192.168.1.x网段
-- 或者更精确
CREATE USER 'dev'@'192.168.1.100' IDENTIFIED BY 'password';
2. 最小权限原则
sql
-- 别给ALL PRIVILEGES,按需授权
GRANT SELECT, INSERT, UPDATE ON app_db.* TO 'app_user'@'%';
-- 开发环境可以宽松点
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP ON dev_db.* TO 'dev'@'%';
-- 只读用户
GRANT SELECT ON prod_db.* TO 'readonly'@'%';
3. 强密码
sql
-- MySQL 8.0 密码策略
SHOW VARIABLES LIKE 'validate_password%';
-- 设置密码策略
SET GLOBAL validate_password.policy = MEDIUM;
SET GLOBAL validate_password.length = 12;
4. 开启SSL
ini
# my.cnf
[mysqld]
require_secure_transport = ON
ssl-ca = /path/to/ca.pem
ssl-cert = /path/to/server-cert.pem
ssl-key = /path/to/server-key.pem
连接时指定SSL:
bash
mysql -h server_ip -u dev -p --ssl-mode=REQUIRED
5. 修改默认端口
ini
# my.cnf
[mysqld]
port = 13306
不能防住专业攻击,但能挡住大部分自动化扫描。
6. 禁用危险功能
ini
# my.cnf
[mysqld]
local-infile = 0 # 禁用LOAD DATA LOCAL
skip-symbolic-links = 1 # 禁用符号链接
连接工具推荐
命令行
bash
# 基础连接
mysql -h host -P port -u user -p
# 指定数据库
mysql -h host -u user -p database_name
# 执行SQL文件
mysql -h host -u user -p database_name < script.sql
GUI工具
Navicat:功能全,收费
DBeaver:免费开源,支持多种数据库
DataGrip:JetBrains出品,IDE级别体验
MySQL Workbench:官方工具,免费
配置SSH隧道(以DBeaver为例):
markdown
1. 新建连接 → MySQL
2. SSH标签页:
- 勾选 Use SSH Tunnel
- Host: 服务器公网IP
- Port: 22
- User: SSH用户名
- Authentication: Public Key
- Private key: 选择私钥文件
3. Main标签页:
- Host: localhost
- Port: 3306
- Database: 数据库名
- Username: MySQL用户名
常见问题
1. Host 'xxx' is not allowed to connect
sql
-- 查看用户的host设置
SELECT user, host FROM mysql.user WHERE user = 'your_user';
-- 修改或新增
CREATE USER 'your_user'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'your_user'@'%';
FLUSH PRIVILEGES;
2. Authentication plugin 'caching_sha2_password' cannot be loaded
MySQL 8.0默认用新的认证方式,老客户端可能不支持:
sql
-- 改成旧的认证方式
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
或者升级客户端。
3. Lost connection to MySQL server
可能原因:
- 网络不稳定
- 查询执行时间过长
- 连接超时
ini
# my.cnf 调整超时
[mysqld]
wait_timeout = 28800
interactive_timeout = 28800
net_read_timeout = 60
net_write_timeout = 60
4. Too many connections
sql
-- 查看当前连接数
SHOW STATUS LIKE 'Threads_connected';
-- 查看最大连接数
SHOW VARIABLES LIKE 'max_connections';
-- 临时调大
SET GLOBAL max_connections = 500;
永久修改要改my.cnf。
总结
MySQL远程连接的安全姿势:
- 不要把3306直接暴露公网
- 用SSH隧道 或组网方案连接
- 限制用户访问IP
- 最小权限原则
- 开启SSL加密
记住:方便和安全往往是矛盾的。图方便开放所有权限,迟早出事。
有问题评论区聊。