Java通过跳板机远程连接数据库

以下列举了程序使用 ssh 到跳板机,通过跳板机连接 mysql 数据库的过程。

首先是 maven 依赖

<dependency>
			<groupId>com.jcraft</groupId>
			<artifactId>jsch</artifactId>
			<version>0.1.53</version>
		</dependency>

看了下基本都是用这个包,但是这里有一个问题,就是现在通过 ssh-keygen 生成的私钥,都是无法通过这个 jar 包使用的。此时需要将本地的私钥换成经典的加密方式。打开本地的 id_rsa 文件,如头部为以下文本,则需要执行命令 ssh-keygen -p -f id_rsa -m pem -P "" -N "" (id_rsa 为 id_rsa 文件的路径)

-----BEGIN OPENSSH PRIVATE KEY-----

执行完后,id_rsa 文件的第一行为

-----BEGIN RSA PRIVATE KEY----- 

然后是程序,不细说了,该封装的已经封装好,有不明白的可以留言。


@Slf4j
@WebListener
@Component
public class MyContextListener implements ServletContextListener {

    @Autowired
    private SSHDataBaseConfig dataBaseConfig;

    /**
     * 监听Servlet初始化事件
     */
    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        // 建立连接
        try {
            dataBaseConfig.createSSH();
        } catch (Throwable e) {
            e.printStackTrace(); // error connecting SSH server
        }
    }

    /**
     * 监听Servlet终止事件
     */
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        // 断开连接
        try {
            dataBaseConfig.closeSSH(); // disconnect
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
@Component
@EnableConfigurationProperties(SSHProperties.class)
@Slf4j
public class SSHDataBaseConfig implements ServletContextListener {

    @Autowired
    private SSHProperties sshConfig;

    //represents each ssh session
    private Session session;

    public void createSSH() {
        if (sshConfig == null || sshConfig.getEnabled == null || !sshConfig.getEnabled()) {
            return;
        }
        try {

            log.info("ssh forward is opend.");
            log.info("ssh init ……");
            JSch sch = new JSch();
            if (null != sshConfig.getSshKnownHosts() && !"".equals(sshConfig.getSshKnownHosts())) {
                sch.setKnownHosts(sshConfig.getSshKnownHosts());
            }
            if (null != sshConfig.getSshKeyPath() && !"".equals(sshConfig.getSshKeyPath())) {
                sch.addIdentity(sshConfig.getSshKeyPath());
            }

            session = sch.getSession(sshConfig.getUsername(), sshConfig.getHost(), sshConfig.getPort());
            session.setConfig("StrictHostKeyChecking", "no");
            if (null != sshConfig.getPassword() && !"".equals(sshConfig.getPassword())) {
                session.setPassword(sshConfig.getPassword());
            }
            session.connect();
            session.setPortForwardingL(sshConfig.getFromHost(),sshConfig.getFromPort(), sshConfig.getToHost(), sshConfig.getToPort());

            log.info("ssh init sucessful……");
        } catch (JSchException e) {
            log.error("ssh JSchException failed.", e);
        } catch (Exception e) {
            log.error("ssh settings is failed. skip!", e);
        }

    }

    /**
     * 关闭SSH连接
     */
    public void closeSSH() {
        if (sshConfig == null || sshConfig.getEnabled == null || !sshConfig.getEnabled()) {
            return;
        }
        session.disconnect();
    }




}

@ConfigurationProperties(prefix = "spring.datasource.ssh.forward")
@Data
public class SSHProperties {

    private Boolean enabled;
    private String sshKeyPath;
    private String sshKnownHosts;
    private String host;
    private Integer port = -1;
    private String username;
    private String password;
    private String fromHost;
    private Integer fromPort = -1;
    private String toHost;
    private Integer toPort = -1;
}
spring:
  datasource:
    ssh:
      forward:
        enabled: true
        ssh-key-path: ~/.ssh/id_rsa
        ssh-known-hosts:
        host: 跳板机IP
        port: 跳板机SSH端口
        username: 跳板机SSH用户名
        password: 跳板机SSH密码(没有不填)
        from-host: 127.0.0.1(就填本地就行,mysql连接那里就写这个)
        from-port: 3307(随便写,不冲突就行,mysql连接那里就写这个)
        to-host: mysql服务器真实IP
        to-port: mysql服务器真实端口
      druid:
       datasource:
        master:
          url: jdbc:mysql://127.0.0.1:3307/xxxx?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
          username: xxx
          password: xxx          
          driver-class-name: com.mysql.cj.jdbc.Driver

-------------------20211230-------------------------

ssh 是有命令做到这种遂道的,如下

ssh -f root@{host} -p 22 -L {from-port}:{from-host}:{to-port} -N

以上示例,

假设mysql服务器在云上一台没开外网的服务器上,假设这台服务器IP为 10.0.0.0,数据库端口3306

假设现在有一台跳板机开了ssh权限,假设该服务器IP为 20.0.0.0,ssh端口为 22

需要连接数据库的这台服务器,只有跳板机的ssh权限,假设这台服务器为 30.0.0.0,此时应如何在这台机器连接数据库?

在 30.0.0.0 这台服务器执行命令 ssh -f root@20.0.0.0 -p 22 -L 9999:127.0.0.1:3306

此时30.0.0.0这台服务器,可以使用 127.0.0.1:9999 这个连接访问数据库。

参考链接

springboot 使用SSH 通过A服务器跳板机 连接B服务器Mysql(安全策略)_李虹柏的博客-CSDN博客_springboot ssh连接服务器

java - "Invalid privatekey" when using JSch - Stack Overflow

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值