Skip to content

SSH代理跳板方式,支持 “用户名 + 公钥”、“用户名 + 密码方式” 认证登录,建立本地端口与远程服务器端口之间的通信管道。

License

Notifications You must be signed in to change notification settings

minbox-projects/ssh-agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ssh-agent

提供SSH代理跳板方式,支持 “用户名 + 公钥”、“用户名 + 密码方式” 认证登录,建立本地端口与远程端口通信管道。

如何使用?

ssh-agent依赖已经上传到Maven Central,不同构件环境使用方式不同。

Maven方式:

pom.xml文件内添加如下依赖:

<dependency>
  <groupId>org.minbox.framework</groupId>
  <artifactId>ssh-agent</artifactId>
  <version>1.0.2</version>
</dependency>

Gradle方式:

build.gradle文件内添加如下依赖:

implementation 'org.minbox.framework:ssh-agent:1.0.2'

在SpringBoot项目内使用

使用示例项目访问:api-boot-sample-ssh-agent

步骤一:添加依赖

pom.xml文件内添加api-boot-starter-ssh-agent依赖:

<dependency>
  <groupId>org.minbox.framework</groupId>
  <artifactId>api-boot-starter-ssh-agent</artifactId>
</dependency>

如果添加的依赖找不到或者无法下载,请访问官网快速开始:快速使用手册

步骤二:配置转发代理端口

application.yml配置文件内进行配置,可以通过结合spring profiles激活不同配置环境的代理方式

# ApiBoot相关配置
api:
  boot:
    # 配置连接生产环境的SSH Agent
    ssh-agent:
      configs:
        # 连接生产MySQL
        - username: metadata
          server-ip: xxx.xxx.xx.xx
          local-port: 3307
          forward-target-port: 3306
        # 连接生产Mongo
        - username: metadata
          server-ip: xxx.xxx.xx.xx
          local-port: 27018
          forward-target-ip: 192.168.1.220
          forward-target-port: 27017
        # 连接生产Redis
        - username: metadata
          server-ip: xxx.xxx.xx.xx
          local-port: 6378
          forward-target-port: 6379

注意事项:如果不通过username/password方式代理认证,需要在远程服务登录用户Home目录下~/.ssh/authorized_keys文件内添加本机的SSH 公钥。

在Junit5中使用

步骤一:继承SshAgentJunitTest单元测试类

@SpringBootTest
class SimulationServiceApiApplicationTests extends SshAgentJunitTest {
    @Test
    void contextLoads() {
        //...
    }
}

单元测试类继承自SshAgentJunitTest后就可以在测试方法执行前开启ssh代理连接,执行后关闭代理连接。

步骤二:添加ssh-agent.yml配置文件

ssh-agent.yml用于配置ssh代理连接列表,位于src/test/resources目录下,如果不创建该配置文件运行单元测试方法时会抛出异常。

configs:
  # 代理转发MySQL
  - username: developer
    serverIp: x.x.x.x
    localPort: 3306
    forwardTargetPort: 59500
  # 代理转发Redis
  - username: developer
    serverIp: x.x.x.x
    localPort: 6379
    forwardTargetPort: 59504
  # 代理转发mongo
  - username: developer
    serverIp: x.x.x.x
    localPort: 27017
    forwardTargetPort: 59503

为什么要用?

服务器的安全性、数据的安全性对于我们来说异常的重要,有时服务器的运维人员仅通过SSH PublicKey给我们开通权限,我们只能通过已授权的公钥访问服务器,这种方式安全系数比较高。

为了安全起见,服务器的防火墙一般不会直接开放服务端口(如:MySQL => 3306),加上运维人员是通过Public Key的方式给我们授权,那我们该怎么在本机访问远程的数据库呢?

如果是数据库图形界面工具(DataGrip、Navicat)很简单就可以连接,因为他们都提供了基于SSH的连接方式,那如果我们想在本地的项目中使用远程数据库呢?该怎么去做呢?

那么请尝试使用ssh-agent

ssh-agent所能代理的不仅仅是MySQL => 3306,是服务器本身上 + 可通信局域网服务器的全部端口号的服务,比如:Mongo => 27017、Redis => 6379等。

实现原理

ssh-agent是通过建立本机与远程服务器之间的端口转发的形式来做的,类似于Docker的宿主机容器之间的通信方式。

首先需要登录到远程的服务器,ssh-agent目前支持两种方式:

用户名密码方式: 默认通过22端口号,通过提供的服务器用户名、密码来建立有效的通信会话

用户秘钥方式: 默认通过22端口号,通过用户名以及当前用户home目录下的ssh private key文件来建立安全有效的通信会话(默认方式)。

登录成功后,会建立指定的本机端口号与远程服务器端口号的转发通信管道。

AgentConfig

AgentConfig类中定义了代理连接远程服务器的全部参数。

参数名 默认值 描述
authenticationMethod SSH_PRIVATE_KEY 登录服务器的授权方式,默认为private key方式
username - 登录服务器的用户名
password - 登录服务器的密码,仅在USERNAME_PASSWORD授权登录方式下有效
serverIp - 服务器IP地址
sshPort 22 SSH端口号,默认为22
sshPrivateKeyPath 当前用户home目录/.ssh/id_rsa 默认使用RSA方式的private key,如果本机通过其他加密方式生成ssh秘钥文件,请修改该参数(请配置文件绝对路径)。仅在SSH_PRIVATE_KEY授权登录方式下有效。
sshKnownHostsPath 当前用户home目录/known_hosts 已知的主机文件,仅在SSH_PRIVATE_KEY授权登录方式下有效。
localPort - 本地端口号,最大值:65535
forwardTargetPort - 转发的目标端口号,最大值:65535
forwardTargetIp 127.0.0.1 转发的目标IP地址,默认为:127.0.0.1(本机),如果需要通过局域网IP地址访问其他服务器需要进行修改
addition - 附加的配置参数集合,用于JSch Session#config方法

AgentConnection

AgentConnection是用于本机与远程服务器建立连接的核心类,需要通过AgentConfig对象实例进行初始化。

该接口提供了#connect#disconnect两个方法,默认的实现类为org.minbox.framework.ssh.agent.jsch.JSchAgentConnection

Ssh Private Key连接示例:

/**
  * 使用ssh private key方式代理连接远程服务
  * <p>
  * 本地 "3307" 端口号绑定远程服务器 "3306"端口号,实现本地访问远程服务器上的MySQL服务
  */
static void sshPrivateConnect() {
  AgentConfig config2 = new AgentConfig();
  config2.setServerIp("xxx.xxx.xxx.xxx");
  config2.setUsername("root");
  config2.setLocalPort(3307);
  config2.setForwardTargetPort(3306);
  AgentConnection connection2 = new DefaultAgentConnection(config2);
  connection2.connect();
  // 连接成功后,访问本地3307的数据库,其实就是访问远程服务器的3306
}

用户名密码连接示例:

/**
  * 使用用户名密码方式代理连接远程服务
  * <p>
  * 本地 "3307" 端口号绑定远程服务器 "3306"端口号,实现本地访问远程服务器上的MySQL服务
  */
static void usernamePasswordConnect() {
  AgentConfig config = new AgentConfig();
  config.setServerIp("xxx.xxx.xxx.xxx");
  config.setUsername("root");
  config.setPassword("密码");
  config.setLocalPort(3307);
  config.setForwardTargetPort(3306);
  AgentConnection connection = new DefaultAgentConnection(config);
  connection.connect();
  // 连接成功后,访问本地3307的数据库,其实就是访问远程服务器的3306
}

About

SSH代理跳板方式,支持 “用户名 + 公钥”、“用户名 + 密码方式” 认证登录,建立本地端口与远程服务器端口之间的通信管道。

Topics

Resources

License

Stars

Watchers

Forks

Languages