开发者

如何利用SSH隧道连接远程MySQL数据库

目录
  • 一、前言
  • 二、mysql服务端
  • 三、MySQL客户端
    • 3.使用jsch进行端口转发(springboot 代码示例)
  • 四、SSH隧道的建立方式
    • 总结

      一、前言

      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数据库

      如何利用SSH隧道连接远程MySQL数据库

      如何利用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 vphpersion="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.springfrawww.devze.commework.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 projecthttp://www.devze.com 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发来的消息后,js使用私钥进行解密,然后将解密后的字符串发送给Server B。Server B进行和生成的对比,如果一致,则允许免登录。

      6.得到server B发来的消息后,会使用私钥进行解析,然后将机密后的字符串发给server B。

      7.接收到机密后的字符串会跟先前生成的字符串进行对比,如果一致就允许免密登陆。

      总之:A要免密码登录到B,B首先要拥有A的公钥,然后B要做一次加密验证。对于非对称加密,公钥加密的密文不能公钥解开,只能私钥解开。

      如何利用SSH隧道连接远程MySQL数据库

      总结

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新数据库

      数据库排行榜