I spent a lot of time developing an application that would use JSch and connect to a remote machine thru ssh to perform some command-line operations. However I learned that these operations can be performed at the localhost as well (my app is running on localhost). Now... I am too lazy to rewrite all the code and honestly I feel bad since I got really attached to JSch. Is there a way to trick JSch to connect to localhost instead or tell it in some way to just use localhost even though the code says otherwise? :)
P.S. in case it's not possible, how come the regular Proccess class doesnt support setOutputStream and setErrStream like JSch does, but only getInputStream and getErrorStream ??
As long as your local machine has an SSH server running (and your application has the necessary login credentials), you can use JSch to connect to your local machine, too - simply indicate localhost (or 127.0.0.1) as the host name for the connection.
This will have some overhead, though, since you are encrypting and decrypting all the data, which is not really necessary to execute some command locally. (On the other hand, this would allow you to run the commands as another user, for which you otherwise would need something like sudo or su, or RunAs under Windows.)
JSch implements the setOutputStream and setErrStream on top of the corresponding get... methods - it uses something similar to a PipedInputStream internally and a separate thread which shovels the data between those streams.
As JSch is open source, you can simply look how this is done (in the Channel class, if I remember right), and copy the relevant methods to your class which does the same things for a Process.
Is there a way to tell JSch not to encrypt the data?
You can use the none cipher, e.g. no encryption. This is by default disabled in all general-purpose clients and servers (as it defeats half of the purpose of SSH), but with the right configuration you can enable it. In JSch you can use
session.setConfig("cipher.s2c", "none,..."); // server to client
session.setConfig("cipher.c2s", "none,..."); // client to server
(This configuration option is the list of all options the client supports - see the documentation of setConfig for all supported values. The server will normally select the first one of this list that it also supports. To force no encryption (or canceling the connection), list only none.)
I don't know how to enable this in the SSH server - read your server's documentation. (And enable it only for localhost, if possible.)
The recommended way of using it is to switch to the none cipher only after authentication (so the authentication is still encrypted), but for localhost this might not be necessary. (You can use session.rekey() to switch the cipher (and key) after changing the configuration.)
Related
So, I want to create my own SSH Client, not just sending commands but a full on ssh client for me to use like you would use PuTTy or mobaxterm, can someone here point me in the right direction.
Things I tried / thought of:
- Using Jsch to send and execute commands (If its possible I would love to know if this is able to be done without using Jsch).
SSH is a protocol that is defined to run on top of TCP, and you can make TCP connections in java using the java.net.Socket class.
So, yes, it can be done.
You'd have to implement the protocol yourself (or use JSch to do it, but given that all these tools already exist, and it's security, where in general relying on widely used tools is orders of magnitude more intelligent than relying on hand-written stuff, given that a security bug is very hard to test for – I assume this is some sort of exercise in sheer dogged arrogance, or, more likely, a learning exercise, which'd mean that you wouldn't want to use jsch here).
ssh works by sending any number of streams across the network, encrypted. By default, there is one stream (a two-way stream), with the user's shell being on one end (so, the /bin/bash executable, for example), and a terminal (where what you type forms the input, and any output is echoed to the terminal window) on the other.
ssh does NOT wait for you type a command then run it; that's /bin/bash doing this. This is basic linux info and has no direct bearing on ssh (the protocol), that's just what you're used to, because sshd (the linux executable that forms an ssh server) by default hooks your terminal up to the target server's shell executable. Usually bash.
Given that you know nothing of this, this sounds like a project that's a bit too far fetched as a starter experiment, but I'm going by incomplete information to make this assessment.
I'd start by making a trivial telnet client and server. telnet is at this point extremely outdated but it is basically ssh without the multiplexing of streams nor the encryption. If you can't write a telnet client, you can't write an ssh client either. And you can still start telnet servers on linux machines for testing purposes.
Once you've got that down, start figuring out the crypto and the multiplexing*.
*) With ssh you can, whilst having a shell open, also port forward and such; check out the -R and -L and -D options in standard ssh. Each such option allows for another stream to be sent along. (whilst you're sending shell commands and seeing their results, at the same time, over the same ssh connection, you are, say, sending a print job to a printer in the network of the other machine). Sending multiple streams through a single connection is called 'multiplexing', and it is part of the ssh specification.
when I run kinit ganesh#abc.com it asks for the password when I run through the terminal. I am trying to build same as web application using java
Acceptance criteria:-
password should pass through UI and we should able connect to the server. i.e password which we pass through UI should assign asa password.
I would recommend you to use Jsch, you can find this library here
http://www.jcraft.com/jsch
And an example or ssh connection here
http://www.jcraft.com/jsch/examples/Shell.java.html
If you're using OpenSSH ssh client, you can try implementing passing password via a companion program, specified via SSH_ASKPASS variable. Basically, you need SSH_ASKPASS to point to a binary ssh would run, and that binary must output the password on stdout.
Check this answer: How to make ssh receive the password from stdin for more details and a concrete example.
The downside is, you need an external binary - and you need to think about its security. For example, if the binary is a dynamically-generated shell script in /tmp - you need strict filesystem permissions so no one but your ssh child process can read or execute it. And if the binary itself is static and takes password from, for example, an environment variable, you must make sure that SSH won't accidentally pass this variable to remote host (e.g. via accidentally specified SendEnv).
You can use some Java SSH library (like suggested Jsch - there is a list here: SSH library for Java), if that fits your requirements. It should be the most flexible option - in terms of control you have over SSH client behavior, unless you want something Jsch doesn't support.
Also, I'd strongly suggest to consider not using passwords, but your server having a private key, and servers you connect to appending its public key to ~/.ssh/authorized_keys (unless you need password-based logins for exactly this purpose, of course). If that's a feasible scenario, you can avoid sharing any sensitive information entirely, significantly improving the security.
I'm currently trying to create an automated test using Java that runs some commands in a remote server the problem is that this remote server has a firewall. Manually I can ssh into the first server (firewall) using putty. Then I enter the details to the Server I wish to execute the commands. I've seen some article with code that mention how to use java code (jsch.jar) that I can ssh into a remote client but I haven't found a good enough explanation when a firewall is present. Can someone give me an explanation of what I should be trying to do and with some code snippet if possible
Not a complete answer, just an idea.
OpenSSH has a feature called ProxyCommand. It allows one to automatically issue a command on a target system, presumably another ssh.
So I have several entries of this sort in my .ssh/config:
Host the.private.host.behind.firewall.net
Hostname 10.0.100.106
User username_on_the_private_host
Compression yes
ProxyCommand ssh the.firewall.net nc -q 1 %h %p
Now I can issue ssh the.private.host.behind.firewall.net and first get to the SSH authentication on the.firewall.net, and then to the second authentication on the target host.
Likely Java implements SSH protocol on its own, but perhaps you could create a construction like this one.
Scenario
I'm in a Java project where we have to communicate with the CLIs of other machines. Unfortunately, we can't connect to these other machines directly and another bad luck is that they only support telnet. So we have the following setup, which is carved in stone (of course):
application <---- telnet or ssh ----> gateway <---- telnet ----> machine_001
(10.0.0.1) (192.168.1.1) (192.168.2.1)
(192.168.2.2)
( ... )
It's possible to connect via SSH or telnet to the gateway manually (e.g. using PuTTY), telnet from this shell to one of the machines and work with its CLI. As we want the communication to happen automatically, the application must be able to talk to the machines by itself; so I need a programmatic solution.
What I've tried so far
After some research on the internet I've found a library called JSch which looked promising, but I've encountered an evil problem. When the applications connects to the gateway, the telnet command and therefore the whole CLI of the target machine is one single command from application's viewpoint. So I'd have to struggle with a non-terminating InputStream, unsynchronized OutputStream and Threads if necessary.
The next try was to establish a SSH tunnel from L127.0.0.1:1234 to 192.168.2.1:23 (via the gateway), but with this configuration it's not possible to telnet to 127.0.0.1:1234 (neither programmatically nor manually).
The actual question
How can I get my application to talk to the machines via the gateway using telnet?
I have embedded a JSCH SSH Java applet in a web page and need to know if it's possible to run a script (of any language like PHP) to automate logging in and running commands. I have heard of expect4j and java robot but cannot see any way to implement it. Keep in mind, I'm not great with Java so I don't know everything about it. Any help is appreciated.
JSch is an SSH client library, and by itself only allows programmatically steered connections to another server. The user interaction has to be build around it by users of the library.
The JCTerm applet provided on the website also contains a terminal emulator in form of a Java GUI. If you only want to automatically execute some command (and maybe show its output in the web page), you could do everything on the server side, and don't need the applet with its terminal emulator. (You would need either some PHP-Java bridge on the server side or some Java-enabled webserver with a Servlet or similar, though.)
(If the web server would be the same machine as the server you'll run the command on you wouldn't even need the SSH connection, but could execute the stuff directly.)
If the server can't do anything (i.e. a "static server"), an applet is the way to go, yes. You can either modify JCTerm or create a new applet from scratch (using JCTerm's connection code as an example on how to connect to to the server).
If you don't have to fear any malicious users in your LAN (i.e. between web server and user, the SSH server doesn't matter), you can embedd the password (or preferably a private key for public-key authentication) into the applet's jar file, and pass it to the library for connection. (You should also include the server's public key for easier checking.)
Provide the command(s) to a ChannelExec (instead of a ChannelShell), this makes it easier to provide input (if necessary) and capture the output. Pipe the output in a text area, or simply use a green/red label saying if the command was successfully executed.
(I might have a look at this in the next days and try to do it. No promise, though.)