gpt4 book ai didi

java - 使用 SSHj 进行 SSH 端口转发

转载 作者:行者123 更新时间:2023-11-30 09:35:39 26 4
gpt4 key购买 nike

我正在尝试创建一个隧道以使用支持 SSH 的防火墙后面的服务。我想要一个完整的 java 解决方案,但我似乎无法让它工作。我找到了这个 github snip并基于此我创建了以下代码来保持后台线程给我隧道:

// property on surrounding class
// static final SSHClient sshclient = new SSHClient();

Thread thread = new Thread(new Runnable() {

@Override
public void run() {
try {
String host = "10.0.3.96";
sshclient.useCompression();
sshclient.addHostKeyVerifier("30:68:2a:20:21:9f:c8:e8:ac:b4:a7:fc:2d:a7:d0:26");
sshclient.connect(host);
sshclient.authPassword("messy", "messy");
if (!sshclient.isAuthenticated()) {
throw new RuntimeException(String.format("Unable to authenticate against '%s'", host));
}
Forward forward = new Forward(8111);
InetSocketAddress addr = new InetSocketAddress("google.com", 80);
SocketForwardingConnectListener listener = new SocketForwardingConnectListener(addr);

sshclient.getRemotePortForwarder().bind(forward, listener);
sshclient.getTransport().setHeartbeatInterval(30);

HttpURLConnection con = (HttpURLConnection) new URL("http://localhost:8111").openConnection();
con.setRequestMethod("GET");
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line = null;
while( (line = reader.readLine()) != null) {
System.out.println(line);
}

sshclient.getTransport().join();

} catch (IOException e) {
e.printStackTrace();
}

try {
if (sshclient != null && sshclient.isConnected()) {
sshclient.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.setDaemon(true);
thread.start();

问题是,如果我连接到“10.0.3.96”这样的远程 SSH 服务器,它就无法工作。如果我在本地主机上使用本地 SSH 服务器,它就可以工作。幸运的是,我一直在进行不同的配置并尝试调试,但我无法掌握 SSHj 包内部发生的事情。

现在它不一定是 SSHj 解决方案,但这是首选,因为代码的其他部分已完全实现并使用 SSHj,我不想在一个项目中混合使用两个 SSH 包。

感谢您的帮助。

最佳答案

尝试这样的事情。它接收要连接的服务器列表。它会将每个中间连接隧道连接到最后一个服务器。我没有测试超过 2 个服务器,但它应该可以工作。这个答案改编自 overthere 项目并用 groovy 编写。您应该只需要导入即可使其在 groovyconsole 中工作。

@Grab(group='net.schmizz', module='sshj', version='0.8.1')
@Grab(group='org.bouncycastle', module='bcprov-jdk16', version='1.46')

//the sequence of hosts that the connections will be made through
def hosts = ["server1", "server2"]
//the starting port for local port forwarding
def startPort = 2222
//username for connecting to all servers
def username = 'user'
def pw = 'pass'

//--------------------------------------------------------------------------//

final TunnelPortManager PORT_MANAGER = new TunnelPortManager()

//list of all active port forwarders
List<PortForwarder> portForwarders = []

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

/**
* Established the actual port forwarder
*/
class PortForwarder extends Thread implements Closeable {
private final SSHClient sshClient;
private final InetSocketAddress remoteAddress;
private final ServerSocket localSocket;
private CountDownLatch latch = new CountDownLatch(1);

public PortForwarder(SSHClient sshClient, InetSocketAddress remoteAddress, ServerSocket localSocket) {
this.sshClient = sshClient;
this.remoteAddress = remoteAddress;
this.localSocket = localSocket;
}

private static String buildName(InetSocketAddress remoteAddress, Integer localPort) {
return "SSH local port forward thread [${localPort}:${remoteAddress.toString()}]"
}

@Override
public void run() {
LocalPortForwarder.Parameters params = new LocalPortForwarder.Parameters("127.0.0.1", localSocket.getLocalPort(),
remoteAddress.getHostName(), remoteAddress.getPort());
LocalPortForwarder forwarder = sshClient.newLocalPortForwarder(params, localSocket);
try {
latch.countDown();
forwarder.listen();
} catch (IOException ignore) {/* OK. */}
}

@Override
public void close() throws IOException {
localSocket.close();
try {
this.join();
} catch (InterruptedException e) {/* OK.*/}
}
}

/**
* Will hand out local ports available for port forwarding
*/
class TunnelPortManager {
final int MAX_PORT = 65536

Set<Integer> portsHandedOut = new HashSet()

ServerSocket leaseNewPort(Integer startFrom) {
for (int port = startFrom; port < MAX_PORT; port++) {
if (isLeased(port)) {
continue;
}

ServerSocket socket = tryBind(port);
if (socket != null) {
portsHandedOut.add(port);
println "handing out port ${port} for local binding"
return socket;
}
}
throw new IllegalStateException("Could not find a single free port in the range [${startFrom}-${MAX_PORT}]...");
}

synchronized void returnPort(ServerSocket socket) {
portsHandedOut.remove(socket.getLocalPort());
}

private boolean isLeased(int port) {
return portsHandedOut.contains(port);
}

protected ServerSocket tryBind(int localPort) {
try {
ServerSocket ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress("localhost", localPort));
return ss;
} catch (IOException e) {
return null;
}
}
}


PortForwarder startForwarder(PortForwarder forwarderThread) {
forwarderThread.start();
try {
forwarderThread.latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return forwarderThread;
}


SSHClient getSSHClient(username, pw, String hostname, int port=22){
SSHClient client = new SSHClient()
client.addHostKeyVerifier(new PromiscuousVerifier())
client.connect(hostname, port)
client.authPassword(username, pw)
return client
}

int hostCount = hosts.size()
String hostname = hosts[0]

SSHClient client = getSSHClient(username, pw, hostname)
println "making initial connection to ${hostname}"

Session session

//create port forwards up until the final
for (int i=1; i<hostCount; i++){
hostname = hosts[i]
println "creating connection to ${hostname}"
ServerSocket ss = PORT_MANAGER.leaseNewPort(startPort)
InetSocketAddress remoteAddress = new InetSocketAddress(hostname, 22)

PortForwarder forwarderThread = new PortForwarder(client, remoteAddress, ss)
forwarderThread = startForwarder(forwarderThread)
session = client.startSession()

println "adding port forward from local port ${ss.getLocalPort()} to ${remoteAddress.toString()}"
portForwarders.add(forwarderThread)

client = getSSHClient(username, pw, "127.0.0.1", ss.getLocalPort())
}

session = client.startSession()

//shut down the running jboss using the script
Command cmd = session.exec("hostname")
String response = IOUtils.readFully(cmd.getInputStream()).toString()
cmd.join(5, TimeUnit.SECONDS)
println "response -> ${response}"

portForwarders.each { pf ->
pf.close()
}

session.close()
client.disconnect()

关于java - 使用 SSHj 进行 SSH 端口转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11261162/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com