一、前言
mysql数据库漏洞频出,不适合直接将3306端口开放到公网。
而实际情况,可能通过公网访问数据库的需求,可考虑利用ssh隧道连接远程mysql数据库。
二、mysql服务端
mysql服务端无须额外配置,只需要开放ssh公网端口
即可!
为了进一步增加安全性,强烈建议,增加密码重试策略、密码复杂度规则。
另外,确认mysql访问权限,mysql.user表中是否存在host=’%’;的记录,删除并刷新权限。
delete from mysql.user where host='%'; flush privileges;
示例:
- 服务器ip(公网ip): 192.168.1.200
- ssh端口:10022
- ssh用户名:test1
- ssh密码:flzx3000c
- mysql端口:3306
- mysql用户名:root
- mysql密码:ysyhl9t
三、mysql客户端
1.通过navicat工具利用ssh隧道连接mysql数据库
注意:127.0.0.1
为192.168.1.200的本地地址,而非客户端的本地地址,此地址必须在mysql.user表中host里存在。
2.手动建立端口转发规则(以linux为例)
# 端口转发 ssh -ncpf test1@192.168.1.200 -p 10022 -l 3388:127.0.0.1:3306 # 查看端口状态 netstat -ano |grep 3388 # 测试mysql连接 mysql -p 3388 -u root -p >show databases;
参数解释:
- c 使用压缩功能,是可选的,加快速度。
- p 用一个非特权端口进行出去的连接。
- f ssh完成认证并建立port forwarding后转入后台运行。
- n 不执行远程命令。该参数在只打开转发端口时很有用(v2版本ssh支持)
3.使用jsch进行端口转发(springboot 代码示例)
<?xml version="1.0" encoding="utf-8"?> <project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.4.4</version> <relativepath/> <!-- lookup parent from repository --> </parent> <groupid>com.example</groupid> <artifactid>demo</artifactid> <version>0.0.1-snapshot</version> <name>demo</name> <description>demo project for spring boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-jdbc</artifactid> </dependency> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <scope>runtime</scope> </dependency> <dependency> <groupid>com.jcraft</groupid> <artifactid>jsch</artifactid> <version>0.1.55</version> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifactid> </plugin> </plugins> </build> </project>
spring: datasource: url: jdbc:mysql://127.0.0.1:3388/mysql username: root password: ysyhl9t driver-class-name: com.mysql.jdbc.driver
package com.example.demo; import com.jcraft.jsch.jsch; import com.jcraft.jsch.session; import org.springframework.boot.commandlinerunner; import org.springframework.stereotype.component; @component public class runner implements commandlinerunner { /** * 测试代码变量暂不提取 * @param args */ @override public void run(string... args) throws exception { jsch jsch = new jsch(); session session = null; try { session = jsch.getsession("test1", "192.168.1.200", 10022); session.setpassword("flzx3000c"); session.setconfig("stricthostkeychecking", "no"); session.connect(); // 设置ssh本地端口转发,本地转发到远程 session.setportforwardingl(3388, "127.0.0.1", 3306); } catch (exception e) { if (null != session) { //关闭ssh连接 session.disconnect(); } e.printstacktrace(); } } }
package com.example.demo; import org.junit.jupiter.api.test; import org.springframework.boot.test.context.springboottest; import org.springframework.jdbc.core.jdbctemplate; import org.springframework.jdbc.core.rowmapper; import javax.annotation.resource; import java.sql.resultset; import java.sql.sqlexception; import java.util.list; @springboottest class demoapplicationtests { @resource private jdbctemplate jdbctemplate; @test void contextloads() { string sql = "select host from mysql.user"; final list<string> list = jdbctemplate.query(sql, (resultset, i) -> resultset.getstring("host")); system.out.println(list); } }
四、ssh隧道的建立方式
方式1.用户名和密码
方式2.密钥(推荐)
免密登录(客户端):
ssh-keygen -t rsa ssh-copy-id -i ~/.ssh/id_rsa.pub test1@192.168.1.200
免密登录原理
1.在a上生成公钥私钥。
2.将公钥拷贝给server b,要重命名成authorized_keys(从英文名就知道含义了)
3.server a向server b发送一个连接请求。
4.server b得到server a的信息后,在authorized_key中查找,如果有相应的用户名和ip,则随机生成一个字符串,并用server a的公钥加密,发送给server a。
5.server a得到server b发来的消息后,使用私钥进行解密,然后将解密后的字符串发送给server b。server b进行和生成的对比,如果一致,则允许免登录。
6.得到server b发来的消息后,会使用私钥进行解析,然后将机密后的字符串发给server b。
7.接收到机密后的字符串会跟先前生成的字符串进行对比,如果一致就允许免密登陆。
总之:a要免密码登录到b,b首先要拥有a的公钥,然后b要做一次加密验证。对于非对称加密,公钥加密的密文不能公钥解开,只能私钥解开。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论