正在显示
9 个修改的文件
包含
264 行增加
和
2 行删除
lh-jar/lh-jar-ssh-proxy/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 5 | + <modelVersion>4.0.0</modelVersion> | ||
| 6 | + <parent> | ||
| 7 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 8 | + <artifactId>lh-jar</artifactId> | ||
| 9 | + <version>1.0-SNAPSHOT</version> | ||
| 10 | + </parent> | ||
| 11 | + | ||
| 12 | + <artifactId>lh-jar-ssh-proxy</artifactId> | ||
| 13 | + | ||
| 14 | + <properties> | ||
| 15 | + <maven.compiler.source>8</maven.compiler.source> | ||
| 16 | + <maven.compiler.target>8</maven.compiler.target> | ||
| 17 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| 18 | + </properties> | ||
| 19 | + | ||
| 20 | + <dependencies> | ||
| 21 | + <dependency> | ||
| 22 | + <groupId>com.jcraft</groupId> | ||
| 23 | + <artifactId>jsch</artifactId> | ||
| 24 | + </dependency> | ||
| 25 | + <dependency> | ||
| 26 | + <groupId>org.springframework.boot</groupId> | ||
| 27 | + <artifactId>spring-boot</artifactId> | ||
| 28 | + </dependency> | ||
| 29 | + | ||
| 30 | + </dependencies> | ||
| 31 | +</project> |
| 1 | +package com.zhonglai.luhui.ssh.proxy; | ||
| 2 | + | ||
| 3 | +public class PortForwarding { | ||
| 4 | + private int localPort; | ||
| 5 | + private String remoteHost; | ||
| 6 | + private int remotePort; | ||
| 7 | + | ||
| 8 | + // Getters and Setters | ||
| 9 | + public int getLocalPort() { | ||
| 10 | + return localPort; | ||
| 11 | + } | ||
| 12 | + | ||
| 13 | + public void setLocalPort(int localPort) { | ||
| 14 | + this.localPort = localPort; | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + public String getRemoteHost() { | ||
| 18 | + return remoteHost; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + public void setRemoteHost(String remoteHost) { | ||
| 22 | + this.remoteHost = remoteHost; | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + public int getRemotePort() { | ||
| 26 | + return remotePort; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + public void setRemotePort(int remotePort) { | ||
| 30 | + this.remotePort = remotePort; | ||
| 31 | + } | ||
| 32 | +} |
| 1 | +package com.zhonglai.luhui.ssh.proxy; | ||
| 2 | + | ||
| 3 | +import com.jcraft.jsch.Channel; | ||
| 4 | +import com.jcraft.jsch.JSch; | ||
| 5 | +import com.jcraft.jsch.JSchException; | ||
| 6 | +import com.jcraft.jsch.Session; | ||
| 7 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 8 | +import org.springframework.scheduling.annotation.Scheduled; | ||
| 9 | +import org.springframework.stereotype.Component; | ||
| 10 | + | ||
| 11 | +import javax.annotation.PostConstruct; | ||
| 12 | +import javax.annotation.PreDestroy; | ||
| 13 | + | ||
| 14 | +@Component | ||
| 15 | +public class SSHChunnel { | ||
| 16 | + @Autowired | ||
| 17 | + private SSHConfig sshConfig; | ||
| 18 | + private JSch jsch; | ||
| 19 | + private Session session = null; | ||
| 20 | + private Channel channel; | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 创建SSH隧道 | ||
| 24 | + */ | ||
| 25 | + public void createChunnel() | ||
| 26 | + { | ||
| 27 | + try { | ||
| 28 | + jsch = new JSch(); | ||
| 29 | + | ||
| 30 | + session = jsch.getSession(sshConfig.getUser(),sshConfig.getHost() ,sshConfig.getPort() ); | ||
| 31 | + session.setPassword(sshConfig.getPassword()); | ||
| 32 | + // 设置不进行主机密钥检查 | ||
| 33 | + java.util.Properties config = new java.util.Properties(); | ||
| 34 | + config.put("StrictHostKeyChecking", "no"); | ||
| 35 | + session.setConfig(config); | ||
| 36 | + | ||
| 37 | + // 建立SSH连接 | ||
| 38 | + session.connect(); | ||
| 39 | + | ||
| 40 | + } catch (JSchException e) { | ||
| 41 | + throw new RuntimeException(e); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + public void closeChunnel() | ||
| 47 | + { | ||
| 48 | + if (channel != null) { | ||
| 49 | + channel.disconnect(); | ||
| 50 | + } | ||
| 51 | + if (session != null) { | ||
| 52 | + session.disconnect(); | ||
| 53 | + } | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 建立端口转发服务 | ||
| 58 | + */ | ||
| 59 | + public void startChunnel() throws JSchException { | ||
| 60 | + // 设置端口转发 | ||
| 61 | + if (sshConfig.getPortForwardingList() != null) { | ||
| 62 | + for (PortForwarding portForwarding : sshConfig.getPortForwardingList()) { | ||
| 63 | + int assignedLocalPort = session.setPortForwardingL(portForwarding.getLocalPort(), portForwarding.getRemoteHost(), portForwarding.getRemotePort()); | ||
| 64 | + System.out.println("Local port " + assignedLocalPort + " is now forwarding to " + portForwarding.getRemoteHost() + ":" + portForwarding.getRemotePort()); | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + // 保持连接打开 | ||
| 69 | + channel = session.openChannel("shell"); | ||
| 70 | + channel.connect(); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * 在Bean初始化完成后启动SSH隧道 | ||
| 75 | + */ | ||
| 76 | + @PostConstruct | ||
| 77 | + public void init() { | ||
| 78 | + if(sshConfig.isEnabled()) | ||
| 79 | + { | ||
| 80 | + try { | ||
| 81 | + createChunnel(); | ||
| 82 | + startChunnel(); | ||
| 83 | + } catch (JSchException e) { | ||
| 84 | + throw new RuntimeException("Failed to start SSH tunnel", e); | ||
| 85 | + } | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * 定期检查SSH连接状态并重连 | ||
| 92 | + */ | ||
| 93 | + @Scheduled(fixedRate = 10000) // 每10秒检查一次 | ||
| 94 | + public void checkAndReconnect() { | ||
| 95 | + if (sshConfig.isEnabled()) | ||
| 96 | + { | ||
| 97 | + if (session == null || !session.isConnected()) { | ||
| 98 | + System.out.println("SSH tunnel is disconnected, attempting to reconnect..."); | ||
| 99 | + try { | ||
| 100 | + closeChunnel(); // 先关闭旧的连接 | ||
| 101 | + createChunnel(); | ||
| 102 | + startChunnel(); | ||
| 103 | + System.out.println("SSH tunnel reconnected successfully."); | ||
| 104 | + } catch (JSchException e) { | ||
| 105 | + System.err.println("Failed to reconnect SSH tunnel: " + e.getMessage()); | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + /** | ||
| 112 | + * 在Bean销毁前关闭SSH隧道并取消定时任务 | ||
| 113 | + */ | ||
| 114 | + @PreDestroy | ||
| 115 | + public void destroy() { | ||
| 116 | + if (session != null && session.isConnected()) { | ||
| 117 | + closeChunnel(); | ||
| 118 | + System.out.println("SSH tunnel closed on application shutdown."); | ||
| 119 | + } | ||
| 120 | + sshConfig.setIsEnabled(false); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | +} |
| 1 | +package com.zhonglai.luhui.ssh.proxy; | ||
| 2 | + | ||
| 3 | +import org.springframework.boot.context.properties.ConfigurationProperties; | ||
| 4 | +import org.springframework.stereotype.Component; | ||
| 5 | + | ||
| 6 | +import java.util.List; | ||
| 7 | + | ||
| 8 | +@Component | ||
| 9 | +@ConfigurationProperties(prefix = "ssh") | ||
| 10 | +public class SSHConfig { | ||
| 11 | + private boolean isEnabled ; | ||
| 12 | + private String user ; //用户名 | ||
| 13 | + private String password ; //密码 | ||
| 14 | + private String host; // 主机地址 | ||
| 15 | + private int port; // 默认SSH端口 | ||
| 16 | + private List<PortForwarding> portForwardingList; // 多个端口转发配置 | ||
| 17 | + | ||
| 18 | + public boolean isEnabled() { | ||
| 19 | + return isEnabled; | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + public void setIsEnabled(boolean isEnabled) { | ||
| 23 | + this.isEnabled = isEnabled; | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + public String getUser() { | ||
| 27 | + return user; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + public void setUser(String user) { | ||
| 31 | + this.user = user; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + public String getPassword() { | ||
| 35 | + return password; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + public void setPassword(String password) { | ||
| 39 | + this.password = password; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + public String getHost() { | ||
| 43 | + return host; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + public void setHost(String host) { | ||
| 47 | + this.host = host; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + public int getPort() { | ||
| 51 | + return port; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + public void setPort(int port) { | ||
| 55 | + this.port = port; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + public List<PortForwarding> getPortForwardingList() { | ||
| 59 | + return portForwardingList; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + public void setPortForwardingList(List<PortForwarding> portForwardingList) { | ||
| 63 | + this.portForwardingList = portForwardingList; | ||
| 64 | + } | ||
| 65 | +} |
| @@ -19,6 +19,7 @@ | @@ -19,6 +19,7 @@ | ||
| 19 | <module>lh-jar-sys-service</module> | 19 | <module>lh-jar-sys-service</module> |
| 20 | <module>lh-jar-order-service</module> | 20 | <module>lh-jar-order-service</module> |
| 21 | <module>lh-jar-plugins-init</module> | 21 | <module>lh-jar-plugins-init</module> |
| 22 | + <module>lh-jar-ssh-proxy</module> | ||
| 22 | </modules> | 23 | </modules> |
| 23 | 24 | ||
| 24 | <properties> | 25 | <properties> |
| @@ -54,7 +54,10 @@ | @@ -54,7 +54,10 @@ | ||
| 54 | <groupId>com.zhonglai.luhui</groupId> | 54 | <groupId>com.zhonglai.luhui</groupId> |
| 55 | <artifactId>lh-jar-order-service</artifactId> | 55 | <artifactId>lh-jar-order-service</artifactId> |
| 56 | </dependency> | 56 | </dependency> |
| 57 | - | 57 | + <dependency> |
| 58 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 59 | + <artifactId>lh-jar-ssh-proxy</artifactId> | ||
| 60 | + </dependency> | ||
| 58 | <!-- 数据库驱动 --> | 61 | <!-- 数据库驱动 --> |
| 59 | <dependency> | 62 | <dependency> |
| 60 | <groupId>mysql</groupId> | 63 | <groupId>mysql</groupId> |
| @@ -7,6 +7,7 @@ import org.springframework.context.annotation.ComponentScan; | @@ -7,6 +7,7 @@ import org.springframework.context.annotation.ComponentScan; | ||
| 7 | import org.springframework.context.annotation.EnableAspectJAutoProxy; | 7 | import org.springframework.context.annotation.EnableAspectJAutoProxy; |
| 8 | 8 | ||
| 9 | @ComponentScan(basePackages = { | 9 | @ComponentScan(basePackages = { |
| 10 | + "com.zhonglai.luhui.ssh.proxy", | ||
| 10 | "com.ruoyi.common", | 11 | "com.ruoyi.common", |
| 11 | "com.ruoyi.system", | 12 | "com.ruoyi.system", |
| 12 | "com.ruoyi.framework", | 13 | "com.ruoyi.framework", |
| 1 | -# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 实例演示开关 demoEnabled: true # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) profile: D:/ruoyi/uploadPath # 获取ip地址开关 addressEnabled: false # 验证码类型 math 数组计算 char 字符验证 captchaType: math # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 18080 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn com.zhonglai.luhui: debug # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: 8.129.224.117 # 端口,默认为6379 port: 6379 # 数据库索引 database: 1 # 密码 password: # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-api # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain,com.zhonglai.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* mqtt: client: device_life: 180 sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login/ApiLogin/*,/content/**,/test/**,/fish/FishPriceCollection/*,/iot/IotTerminal/listByDeviceId/* # NameServer地址 rocketmq: name-server: 47.115.144.179:9876 # 默认的消息组 producer: group: deviceCommand send-message-timeout: 30000 send-topic: lh-mqtt-service-deviceCommand-test send-tags: 1 | ||
| 1 | +# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 实例演示开关 demoEnabled: true # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) profile: D:/ruoyi/uploadPath # 获取ip地址开关 addressEnabled: false # 验证码类型 math 数组计算 char 字符验证 captchaType: math # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 18080 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn com.zhonglai.luhui: debug # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: localhost # 端口,默认为6379 port: 6379 # 数据库索引 database: 1 # 密码 password: # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-api # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain,com.zhonglai.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* mqtt: client: device_life: 180 sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login/ApiLogin/*,/content/**,/test/**,/fish/FishPriceCollection/*,/iot/IotTerminal/listByDeviceId/* # NameServer地址 rocketmq: name-server: 8.129.224.117:9876 # 默认的消息组 producer: group: deviceCommand send-message-timeout: 30000 send-topic: lh-mqtt-service-deviceCommand-test send-tags: 1 ssh: isEnabled: true host: 119.23.218.181 port: 22 user: root password: Luhui586 portForwardingList: - localPort: 6379 remotePort: 6379 remoteHost: 127.0.0.1 - localPort: 3306 remotePort: 3306 remoteHost: 127.0.0.1 |
| @@ -379,6 +379,12 @@ | @@ -379,6 +379,12 @@ | ||
| 379 | <artifactId>lh-jar-plugins-init</artifactId> | 379 | <artifactId>lh-jar-plugins-init</artifactId> |
| 380 | <version>${ruoyi.version}</version> | 380 | <version>${ruoyi.version}</version> |
| 381 | </dependency> | 381 | </dependency> |
| 382 | + <!-- ssh代理 --> | ||
| 383 | + <dependency> | ||
| 384 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 385 | + <artifactId>lh-jar-ssh-proxy</artifactId> | ||
| 386 | + <version>${ruoyi.version}</version> | ||
| 387 | + </dependency> | ||
| 382 | <!-- 支持data --> | 388 | <!-- 支持data --> |
| 383 | <dependency> | 389 | <dependency> |
| 384 | <groupId>org.projectlombok</groupId> | 390 | <groupId>org.projectlombok</groupId> |
-
请 注册 或 登录 后发表评论