diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/Session.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/Session.java index 693db4c4d..58ebb1f6c 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/Session.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/Session.java @@ -36,26 +36,24 @@ public interface Session extends Wrapper, Closeable { /** * 绑定端口到本地。 一个会话可绑定多个端口
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort
- * 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等 + * 此方法用于访问本地无法访问但是服务器可以访问的地址,如只有服务器能访问的内网数据库等 * * @param localPort 本地端口 * @param remoteAddress 远程主机和端口 - * @return 成功与否 */ - default boolean bindLocalPort(final int localPort, final InetSocketAddress remoteAddress) { - return bindLocalPort(new InetSocketAddress(localPort), remoteAddress); + default void bindLocalPort(final int localPort, final InetSocketAddress remoteAddress) { + bindLocalPort(new InetSocketAddress(localPort), remoteAddress); } /** * 绑定端口到本地。 一个会话可绑定多个端口
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort
- * 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等 + * 此方法用于访问本地无法访问但是服务器可以访问的地址,如只有服务器能访问的内网数据库等 * * @param localAddress 本地主机和端口 * @param remoteAddress 远程主机和端口 - * @return 成功与否 */ - boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress); + void bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress); /** * 解除本地端口映射 @@ -73,5 +71,23 @@ public interface Session extends Wrapper, Closeable { * @param localAddress 需要解除的本地地址 */ void unBindLocalPort(final InetSocketAddress localAddress); + + /** + * 绑定ssh服务端的serverPort端口, 到本地主机的port端口上.
+ * 即数据从ssh服务端的serverPort端口, 流经ssh客户端, 达到host:port上.
+ * 此方法用于在服务端访问本地资源,如服务器访问本机所在的数据库等。 + * + * @param remoteAddress ssh服务端上要被绑定的地址 + * @param localAddress 转发到的本地地址 + * @throws SshException 端口绑定失败异常 + */ + void bindRemotePort(final InetSocketAddress remoteAddress, final InetSocketAddress localAddress); + + /** + * 解除远程端口映射 + * + * @param remoteAddress 需要解除的远程地址和端口 + */ + void unBindRemotePort(final InetSocketAddress remoteAddress); // endregion } diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/ganymed/GanymedSession.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/ganymed/GanymedSession.java index 24153f5df..6e19800ce 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/ganymed/GanymedSession.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/ganymed/GanymedSession.java @@ -18,7 +18,6 @@ import ch.ethz.ssh2.StreamGobbler; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.map.MapUtil; -import org.dromara.hutool.core.net.Ipv4Util; import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.extra.ssh.Connector; import org.dromara.hutool.extra.ssh.Session; @@ -92,7 +91,7 @@ public class GanymedSession implements Session { } @Override - public boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IORuntimeException { + public void bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IORuntimeException { final LocalPortForwarder localPortForwarder; try { localPortForwarder = this.connection.createLocalPortForwarder(localAddress, remoteAddress.getHostName(), remoteAddress.getPort()); @@ -106,8 +105,6 @@ public class GanymedSession implements Session { //加入记录 this.localPortForwarderMap.put(localAddress.toString(), localPortForwarder); - - return true; } @Override @@ -126,34 +123,20 @@ public class GanymedSession implements Session { } } - /** - * 绑定ssh服务端的serverPort端口, 到host主机的port端口上.
- * 即数据从ssh服务端的serverPort端口, 流经ssh客户端, 达到host:port上. - * - * @param bindPort ssh服务端上要被绑定的端口 - * @param host 转发到的host - * @param port host上的端口 - * @return 成功与否 - * @throws IORuntimeException 端口绑定失败异常 - */ - public boolean bindRemotePort(final int bindPort, final String host, final int port) throws IORuntimeException { + @Override + public void bindRemotePort(final InetSocketAddress remoteAddress, final InetSocketAddress localAddress) throws IORuntimeException { try { - this.connection.requestRemotePortForwarding(Ipv4Util.LOCAL_IP, bindPort, host, port); + this.connection.requestRemotePortForwarding(remoteAddress.getHostName(), remoteAddress.getPort(), + localAddress.getHostName(), localAddress.getPort()); } catch (final IOException e) { throw new IORuntimeException(e); } - return true; } - /** - * 解除远程端口映射 - * - * @param localPort 需要解除的本地端口 - * @throws IORuntimeException 端口解绑失败异常 - */ - public void unBindRemotePort(final int localPort) throws IORuntimeException { + @Override + public void unBindRemotePort(final InetSocketAddress remoteAddress) throws IORuntimeException { try { - this.connection.cancelRemotePortForwarding(localPort); + this.connection.cancelRemotePortForwarding(remoteAddress.getPort()); } catch (final IOException e) { throw new IORuntimeException(e); } diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSession.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSession.java index 58da85efd..77f77adb6 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSession.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSession.java @@ -74,16 +74,12 @@ public class JschSession implements Session { } @Override - public boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws SshException { - if (isConnected()) { - try { - this.raw.setPortForwardingL(localAddress.getHostName(), localAddress.getPort(), remoteAddress.getHostName(), remoteAddress.getPort()); - } catch (final JSchException e) { - throw new SshException(e, "From [{}] mapping to [{}] error!", localAddress, remoteAddress); - } - return true; + public void bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws SshException { + try { + this.raw.setPortForwardingL(localAddress.getHostName(), localAddress.getPort(), remoteAddress.getHostName(), remoteAddress.getPort()); + } catch (final JSchException e) { + throw new SshException(e, "From [{}] mapping to [{}] error!", localAddress, remoteAddress); } - return false; } @Override @@ -95,36 +91,20 @@ public class JschSession implements Session { } } - /** - * 绑定ssh服务端的serverPort端口, 到host主机的port端口上.
- * 即数据从ssh服务端的serverPort端口, 流经ssh客户端, 达到host:port上. - * - * @param bindPort ssh服务端上要被绑定的端口 - * @param host 转发到的host - * @param port host上的端口 - * @return 成功与否 - * @throws SshException 端口绑定失败异常 - */ - public boolean bindRemotePort(final int bindPort, final String host, final int port) throws SshException { - if (isConnected()) { - try { - this.raw.setPortForwardingR(bindPort, host, port); - } catch (final JSchException e) { - throw new SshException(e, "From [{}] mapping to [{}] error!", bindPort, port); - } - return true; + @Override + public void bindRemotePort(final InetSocketAddress remoteAddress, final InetSocketAddress localAddress) throws SshException { + try { + this.raw.setPortForwardingR(remoteAddress.getHostName(), remoteAddress.getPort(), + localAddress.getHostName(), localAddress.getPort()); + } catch (final JSchException e) { + throw new SshException(e, "From [{}] mapping to [{}] error!", remoteAddress, localAddress); } - return false; } - /** - * 解除远程端口映射 - * - * @param localPort 需要解除的本地端口 - */ - public void unBindRemotePort(final int localPort) { + @Override + public void unBindRemotePort(final InetSocketAddress remoteAddress) { try { - this.raw.delPortForwardingR(localPort); + this.raw.delPortForwardingR(remoteAddress.getHostName(), remoteAddress.getPort()); } catch (final JSchException e) { throw new SshException(e); } diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/mina/MinaSession.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/mina/MinaSession.java index 7c83c89b7..501a10747 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/mina/MinaSession.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/mina/MinaSession.java @@ -66,13 +66,12 @@ public class MinaSession implements Session { } @Override - public boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IORuntimeException { + public void bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IORuntimeException { try { this.raw.startLocalPortForwarding(new SshdSocketAddress(localAddress), new SshdSocketAddress(remoteAddress)); } catch (final IOException e) { throw new IORuntimeException(e); } - return true; } @Override @@ -84,6 +83,24 @@ public class MinaSession implements Session { } } + @Override + public void bindRemotePort(final InetSocketAddress remoteAddress, final InetSocketAddress localAddress) throws IORuntimeException { + try { + this.raw.startRemotePortForwarding(new SshdSocketAddress(remoteAddress), new SshdSocketAddress(localAddress)); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + } + + @Override + public void unBindRemotePort(final InetSocketAddress remoteAddress) throws IORuntimeException{ + try { + this.raw.stopRemotePortForwarding(new SshdSocketAddress(remoteAddress)); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + } + /** * 执行Shell命令 * diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/sshj/SshjSession.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/sshj/SshjSession.java index 8fd236d9a..1606a089d 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/sshj/SshjSession.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/sshj/SshjSession.java @@ -19,6 +19,7 @@ import net.schmizz.sshj.connection.channel.forwarded.SocketForwardingConnectList import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.map.MapUtil; +import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.extra.ssh.Connector; import org.dromara.hutool.extra.ssh.Session; @@ -39,7 +40,7 @@ import java.util.Set; */ public class SshjSession implements Session { - private SSHClient ssh; + private final SSHClient ssh; private final net.schmizz.sshj.connection.channel.direct.Session raw; private Map localPortForwarderMap; @@ -94,7 +95,7 @@ public class SshjSession implements Session { } @Override - public boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IORuntimeException { + public void bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IORuntimeException { final Parameters params = new Parameters( localAddress.getHostName(), localAddress.getPort(), remoteAddress.getHostName(), remoteAddress.getPort()); @@ -114,8 +115,6 @@ public class SshjSession implements Session { //加入记录 this.localPortForwarderMap.put(localAddress.toString(), ss); - - return true; } @Override @@ -127,38 +126,33 @@ public class SshjSession implements Session { IoUtil.closeQuietly(this.localPortForwarderMap.remove(localAddress.toString())); } - /** - * 绑定ssh服务端的serverPort端口, 到host主机的port端口上.
- * 即数据从ssh服务端的serverPort端口, 流经ssh客户端, 达到host:port上. - * - * @param bindPort ssh服务端上要被绑定的端口 - * @param host 转发到的host - * @param port host上的端口 - * @return 成功与否 - * @throws IORuntimeException 端口绑定失败异常 - */ - public boolean bindRemotePort(final int bindPort, final String host, final int port) throws IORuntimeException { + @Override + public void bindRemotePort(final InetSocketAddress remoteAddress, final InetSocketAddress localAddress) throws IORuntimeException { try { this.ssh.getRemotePortForwarder().bind( - new RemotePortForwarder.Forward(bindPort), - new SocketForwardingConnectListener(new InetSocketAddress(host, port)) + new RemotePortForwarder.Forward(remoteAddress.getHostName(), remoteAddress.getPort()), + new SocketForwardingConnectListener(localAddress) ); } catch (final IOException e) { throw new IORuntimeException(e); } - return true; } - /** - * 解除远程端口映射 - * - * @param localPort 需要解除的本地端口 - */ - public void unBindRemotePort(final int localPort) { + @Override + public void unBindRemotePort(final InetSocketAddress remoteAddress) { + final String hostName = remoteAddress.getHostName(); + final int port = remoteAddress.getPort(); + final RemotePortForwarder remotePortForwarder = this.ssh.getRemotePortForwarder(); final Set activeForwards = remotePortForwarder.getActiveForwards(); for (final RemotePortForwarder.Forward activeForward : activeForwards) { - if (localPort == activeForward.getPort()) { + if (port == activeForward.getPort()) { + final String activeAddress = activeForward.getAddress(); + if(StrUtil.isNotBlank(activeAddress) && !StrUtil.equalsIgnoreCase(hostName, activeAddress)){ + // 对于用于已经定义的host,做对比,否则跳过 + continue; + } + try { remotePortForwarder.cancel(activeForward); } catch (final IOException e) { diff --git a/hutool-extra/src/test/java/org/dromara/hutool/extra/ssh/JschTest.java b/hutool-extra/src/test/java/org/dromara/hutool/extra/ssh/JschTest.java index 16c9dd919..27bec7d4e 100644 --- a/hutool-extra/src/test/java/org/dromara/hutool/extra/ssh/JschTest.java +++ b/hutool-extra/src/test/java/org/dromara/hutool/extra/ssh/JschTest.java @@ -17,7 +17,6 @@ import org.dromara.hutool.core.lang.Console; import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.extra.ssh.engine.jsch.JschSession; import org.dromara.hutool.extra.ssh.engine.jsch.JschSftp; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -48,8 +47,7 @@ public class JschTest { // 建立会话 final JschSession session = new JschSession(new Connector("looly.centos", 22, "test", "123456")); // 绑定ssh服务端8089端口到本机的8000端口上 - final boolean b = session.bindRemotePort(8089, "localhost", 8000); - Assertions.assertTrue(b); + session.bindRemotePort(new InetSocketAddress(8089), new InetSocketAddress("localhost", 8000)); // 保证一直运行 }