I want to add TLS support to my SFTP connection. Currently using JSch to achieve it.
But I am not sure how to use it.
private void connection() {
JSch jsch = new JSch();
try {
session = jsch.getSession(username, host, port);
session.setPassword(password);
session.setConfig(MAX_SESSIONS_PROP, MAX_SESSIONS_DEFAULT);
session.setConfig(MAX_STARTUPS_PROP, MAX_STARTUPS_DEFAULT);
session.setTimeout(DEFAULT_TIMEOUT_MS);
session.connect();
channel = session.openChannel(CHANNEL);
channel.connect();
channelSftp = (ChannelSftp) channel;
} catch (JSchException e) {
throw new ConnectException("Can not get connection to SFTP: ", e);
}
}
Please help me out.
TLS has nothing to do with SFTP.
TLS is used for example to encrypt FTP connections.
SFTP uses SSH for encryption. And you do not need to do anything for it. SFTP is virtually never used without SSH. And JSch does not even allow using SFTP without SSH (the same is true for majority of other SSH clients/libraries).
Related
I want to communicate to a virtual Serial Port of my server . Steps involved in this is.
1.SSH in to iLO
2.enter vsp command
3.A virtual serial port session is opened
4.it asks for server credentials and then
it gives us a server terminal experience we can send any
command as we do in a terminal opened in the server itself
So my aim is to automate all the above steps in any way from java.
I have completed the first two steps via jsch but once it enters into virtual serial port session im not able to communicate .
I also tried automating the terminal commands using expect for linux in expect even I see the same pattern once it enters into VSP session I'm not able to communicate I tried autoexpect also it didn't work
Below is my jsch code
public static void main(String[] args) {
String host="10.10.100.209";
String user="administrator";
String password="2xR3M0t3$$";
String command1="vsp";
try{
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
JSch jsch = new JSch();
Session session=jsch.getSession(user, host, 22);
session.setPassword(password);
session.setConfig(config);
session.connect();
System.out.println("Connected");
ChannelExec channel = (ChannelExec) session.openChannel("exec");
InputStream in = channel.getInputStream();
channel.setCommand("vsp");
OutputStream out = channel.getOutputStream();
channel.connect();
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print("out"+new String(tmp, 0, i));
}
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
}
channel.disconnect();
Now my question is how to communicate to virtual serial port after I ssh into my iLO.
Use ChannelShell instead of ChannelExec.
ChannelShell is like using interactive shell.
ChannelExec is like executing shell script.
Your use case seems to be interactive.
My task is to copy some files from server to local, I have searched a lot about connectivity libraries and found JSch. I have used below code but it is taking too much time to read or move the file. I don't know whether it is working or not.
JSch jsch = new JSch();
Session session = null;
try {
// set up session
session = jsch.getSession("userName","hostIP");
// use private key instead of username/password
session.setConfig(
"PreferredAuthentications",
"publickey,gssapi-with-mic,keyboard-interactive,password");
jsch.addIdentity("***.ppk");
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
// copy remote log file to localhost.
ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
channelSftp.setInputStream(System.in);
channelSftp.setOutputStream(System.out);
System.out.println("shell channel connected....");
ChannelSftp c = (ChannelSftp) channelSftp;
System.out.println("done");
channelSftp.get("report.xml", "C:\\Users\\akrishnan");
channelSftp.exit();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.disconnect();
}
Is there any library that I can use to connect the servers from my Java code using private key file (**.ppk)?
This is most likely, what causes the hang:
channelSftp.setInputStream(System.in);
channelSftp.setOutputStream(System.out);
Doing that for an "sftp" channel breaks everything. It makes no sense. Just remove those two lines.
Check the official JSch SFTP example – There are no such calls.
For a correct code for file transfers using JSch, see:
SFTP file transfer using Java JSch.
Obligatory warning: Do not use StrictHostKeyChecking=no to blindly accept all host keys. That is a security flaw. You lose a protection against MITM attacks.
For a correct (and secure) approach, see:
How to resolve Java UnknownHostKey, while using JSch SFTP library?
I'm trying to write to write to a named pipe over a connection facilitated by jsch.
// connect to server
JSch ssh = new JSch();
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
System.out.println("Establishing Connection...");
session.connect();
System.out.println("Connection established.");
System.out.println("Crating SFTP Channel.");
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
System.out.println("SFTP Channel created.");
// write to pipe
OutputStream strm = sftpChannel.put(remoteFile);
// failed attempts
// BufferedWriter wrtr = new BufferedWriter(new PrintWriter(new OutputStreamWriter(strm)));
// PrintWriter wrtr = new PrintWriter(new BufferedOutputStream(strm));
// Current version
BufferedWriter wrtr = new BufferedWriter(new PrintWriter(strm));
wrtr.write("hello world");
wrtr.flush();
session.disconnect();
sftpChannel.disconnect();
wrtr.close();
The connect to server part is essentially an exact copy from: SSH connection with Java
The code will even wait for something to be reading the pipe on the other side, meaning that if I don't use:
cat pipe
It will wait till I do so, and then once I have it will print out nothing and the cat pipe call will be over. Essentially it appears that I'm writing "" to the pipe instead of "hello world"
Any help would be much appreciated, thanks.
I suspect that if you talked to any SFTP server software author, he'd tell you that interacting with named pipes through SFTP isn't supported, and that you're on your own. Having said that, you could try requesting append mode for the put operation:
OutputStream strm = sftpChannel.put(remoteFile, ChannelSftp.APPEND);
^^^^^^^^^^^^^^^^^^
BufferedWriter wrtr = new BufferedWriter(new PrintWriter(strm));
wrtr.write("hello world");
It might work, or it might not. It depends on the SFTP server.
At the protocol level, an SFTP write request specifies what file to write to, where in the file to write it, and what data to write. Based on the the OpenSSH 5.8 source code that I have at hand, that version of the SFTP server program will always seek to the correct location in the file before writing data to it. Pipes don't support seeking, so the sftp-server program would report a seek failure to the client without trying to write the data.
However, the OpenSSH 6.6 version of sftp-server will omit the seek if the file was opened in append mode. I haven't tested it, but it may be possible to write to a named pipe using that version of the server, if the client requests append mode for the file in the first place. And by extension, it may work for some other versions of the OpenSSH server as well.
I'm trying to realize a bot that simulates an user that write/read on a ssh console in Java.
I'm using the JSCH library to manage the ssh connection.
This is the code from which I started:
JSch jsch = new JSch();
Session session = jsch.getSession(username, ipAddress, port);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect(connectionTimeoutInMillis);
Channel channel = session.openChannel("shell");
InputStream is = new InputStream();
OutputStream out= new OutputStream();
channel.setInputStream(is);
channel.setOutputStream(out);
channel.connect();
channel.disconnect();
is.close();
out.close();
session.disconnect();
Obviously the InputStream and OutputStream in the code are wrong, I need to use something that the bot can use to send a String (a command line) and to receive a String(the result of the command execution), what type of streams should I use to obtain this?
Furthermore I noticed that if I send a command and use the System.out as output stream in many cases the output is empty because (I'm almost sure about this) the Java application terminates before that the command execution has produced the result. What is the best practice to tell to JSCH channel listener "wait till the command execution has completed" and then go on? I could use a Thread.sleep(someTime) after the command execution but I don't like much it for obvious reasons.
Consider using a third-party Expect-like Java library to ease the interaction with a remote shell. Here is a good set of options you can try:
Expect4J
ExpectJ
Expect-for-Java
You can also take a look at my own open source project which I created some time ago as the successor to the existing ones. It's called ExpectIt. The advantages of my library are stated on the project home page.
Here is an example of interacting with a public remote SSH service using JSch. It should be easy to adopt it for your use case.
JSch jSch = new JSch();
Session session = jSch.getSession("new", "sdf.org");
session.connect();
Channel channel = session.openChannel("shell");
Expect expect = new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
.withErrorOnTimeout(true)
.build();
try {
expect.expect(contains("[RETURN]"));
expect.sendLine();
String ipAddress = expect.expect(regexp("Trying (.*)\\.\\.\\.")).group(1);
System.out.println("Captured IP: " + ipAddress);
expect.expect(contains("login:"));
expect.sendLine("new");
expect.expect(contains("(Y/N)"));
expect.send("N");
expect.expect(regexp(": $"));
expect.send("\b");
expect.expect(regexp("\\(y\\/n\\)"));
expect.sendLine("y");
expect.expect(contains("Would you like to sign the guestbook?"));
expect.send("n");
expect.expect(contains("[RETURN]"));
expect.sendLine();
} finally {
session.close();
ssh.close();
expect.close();
}
Here is the link to the complete workable example.
fellow Java coders. I have recently been faced with an interesting task - to create software that would use an SSH tunnel as a proxy for browsing webpages (over HTTPS). After reading some docs on JSCH (http://www.jcraft.com/jsch/, a Java SSH tunneling library), which all gave database connections as an example, I decided to try it myself. Here is the connection code I copied from http://kahimyang.info/kauswagan/code-blogs/1337/ssh-tunneling-with-java-a-database-connection-example
int assigned_port;
int local_port=3309;
// Remote host and port
int remote_port=3306;
String remote_host = "<SSH host goes here>";
String login = "<SSH login goes here>";
String password = "<SSH password goes here>";
try {
JSch jsch = new JSch();
// Create SSH session. Port 22 is your SSH port which
// is open in your firewall setup.
Session session = jsch.getSession(login, remote_host, 22);
session.setPassword(password);
// Additional SSH options. See your ssh_config manual for
// more options. Set options according to your requirements.
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
config.put("Compression", "yes");
config.put("ConnectionAttempts","2");
session.setConfig(config);
// Connect
session.connect();
// Create the tunnel through port forwarding.
// This is basically instructing jsch session to send
// data received from local_port in the local machine to
// remote_port of the remote_host
// assigned_port is the port assigned by jsch for use,
// it may not always be the same as
// local_port.
assigned_port = session.setPortForwardingL(local_port,
remote_host, remote_port);
} catch (JSchException e) {
System.out.println("JSch:" + e.getMessage());
return;
}
if (assigned_port == 0) {
System.out.println("Port forwarding failed!");
return;
}
Now, I am not exactly experienced with all the port forwarding stuff, but, if I understand it correctly, the code is supposed to forward all connections incoming to 127.0.0.1:3309 (or whatever the assigned_port is) through the SSH server. Now I'm stuck. How am I supposed to send a HttpsURLConnection through 127.0.0.1:3309? I tried defining it as an HTTP or HTTPS or SOCKS proxy, but neither works. Can anybody help me?
The code you have posted will forward all traffic from 127.0.0.1:3309 to port 3306 on the SSH server you have connected to.
When using port forwarding you treat the listening address:port as if it were the actual destination. So if you need to use a HttpsURLConnection you would construct it with a URL of
https://127.0.0.1:3309/
Obviously you also need to append a path to the URL depending on what you are trying to achieve. I would suggest modifying your code to use more standard HTTP ports, try with HTTP first and once that is working move to HTTPS
int local_port=8080;
// Remote host and port
int remote_port=80;
The URL for above will be
http://127.0.0.1:8080
You can always test the URL by pasting it into a browser.
One of the problems you may encounter using HTTPS is certificate validation so this is why I suggest testing plain HTTP first to prove your code is working.