Skip to content

Commit 15d6924

Browse files
authored
ProxyCommand support (Issue 970) (#971)
* Added SocketClient.connectVia(InputStream, OutputStream) method for ProxyCommand support (#970) * Added ProxyCommand example (#970) * Comment only (#970) * NullPointerException (#970) * small change to trigger workflow
1 parent 4be5228 commit 15d6924

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package net.schmizz.sshj.examples;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.io.OutputStream;
6+
import java.util.concurrent.TimeUnit;
7+
8+
import net.schmizz.sshj.SSHClient;
9+
import net.schmizz.sshj.common.IOUtils;
10+
import net.schmizz.sshj.connection.channel.direct.Session;
11+
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
12+
13+
/**
14+
* This example uses a separate process to handle I/O, similar to the "ProxyCommand" directive in openssh.
15+
*
16+
*/
17+
public class ProxyCommand {
18+
public static void main(String... args)
19+
throws IOException {
20+
21+
/*
22+
for testing, uses a locally-installed ssh client,
23+
24+
but for AWS SSM, once you've negotiated the OAuth/SAML login for SSO,
25+
then called StsClient.getCallerIdentity() to check that worked
26+
then called Ec2Client.describeInstances() to convert an IP to an instanceId/availableZone combo
27+
then called Ec2InstanceConnectClient.sendSSHPublicKey() to open a 60-second login window
28+
you'd create an SSM ssh session via something like
29+
30+
ProcessBuilder pb = new ProcessBuilder("aws", "ssm", "start-session", "--region", "ap-southeast-2", "--target", instanceId,
31+
"--document-name", "AWS-StartSSHSession",
32+
"--parameters", "portNumber=22"
33+
34+
and wire up the inputStreams/outputStreams from that instead.
35+
*/
36+
37+
38+
// for testing only
39+
String jumpBox = "localhost"; // this would typically be something remote
40+
String targetBox = "localhost"; // this would typically be something even more remote
41+
ProcessBuilder pb = new ProcessBuilder("ssh", jumpBox, "-W", targetBox + ":22");
42+
Process proc = pb.start();
43+
InputStream recvStream = proc.getInputStream();
44+
OutputStream xmitStream = proc.getOutputStream();
45+
46+
SSHClient ssh = new SSHClient();
47+
ssh.addHostKeyVerifier(new PromiscuousVerifier());
48+
ssh.connectVia(recvStream, xmitStream);
49+
50+
try {
51+
ssh.authPublickey(System.getProperty("user.name"));
52+
final Session session = ssh.startSession();
53+
try {
54+
final Session.Command cmd = session.exec("ping -c 1 google.com");
55+
System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
56+
cmd.join(5, TimeUnit.SECONDS);
57+
System.out.println("\n** exit status: " + cmd.getExitStatus());
58+
} finally {
59+
session.close();
60+
}
61+
} finally {
62+
ssh.disconnect();
63+
ssh.close();
64+
}
65+
}
66+
}

src/main/java/net/schmizz/sshj/SocketClient.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ public void connectVia(Channel channel, String hostname, int port) throws IOExce
9494
onConnect();
9595
}
9696

97+
/** Connect using the supplied InputStream and OutputStream. */
98+
public void connectVia(InputStream input, OutputStream output) throws IOException {
99+
this.hostname = "localhost";
100+
this.port = 65535;
101+
this.input = input;
102+
this.output = output;
103+
this.tunneled = true;
104+
onConnect();
105+
}
106+
97107
/** Connect to a remote address via a direct TCP/IP connection from the server. */
98108
public void connectVia(DirectConnection directConnection) throws IOException {
99109
connectVia(directConnection, directConnection.getRemoteHost(), directConnection.getRemotePort());

0 commit comments

Comments
 (0)