Using JSch to create a SOCKS proxy tunneled through SSH - java

As far as I heave read, it is possible to create a SSH tunnel using JSch, and then put the settings in Firefox as a SOCKS5 proxy and all the traffic would go through the machine JSch is connected to. I have found the the following code but there is somethings I don't understand about it.
String host = "my ssh server ip";
String user = "root";
String password = "mypass";
int port = 22;
int tunnelLocalPort = 9080;
String tunnelRemoteHost = "YYY.YYY.YYY.YYY";
int tunnelRemotePort = 80;
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
localUserInfo lui = new localUserInfo();
session.setUserInfo(lui);
session.connect();
session.setPortForwardingL(tunnelLocalPort, tunnelRemoteHost, tunnelRemotePort);
System.out.println("Connected");
tunnelLocalPort would be the port that my java program would be listening on? this is the port I put the Firefox SOCKS5 proxy settings?
I don't understand what tunnelRemoteHost is for, I want this to act like a SOCKS5 proxy, just like PuTTY does when tunneling is setup on it.

JSch indeed allows creating an SSH tunnel. But the "dynamic" port forwarding feature of PuTTY (which, I assume, you are referring to) is a lot more than an SSH tunnel. It particularly implements the SOCKS proxy (what you are after). That's something that JSch does not implement.
For a plain SSH tunnel/port forwarding, you have to specify the target address, to connect the other end of the tunnel to (tunnelRemoteHost). That's obviously not necessary in the PuTTY "dynamic" mode, as there a proxy protocol (SOCKS) takes case of that.

Related

Getting "com.jcraft.jsch.JSchException: Auth fail" – but "ssh" can login using public key authentication

I am trying to connect a remote server using JSch but I am getting "Auth fail" exception. Below is my code:
String user = "user.name";
String host = "hostip";
try
{
JSch jsch = new JSch();
Session session = jsch.getSession(user, host);
session.setConfig("StrictHostKeyChecking", "no");
System.out.println("Establishing Connection...");
session.connect();
int assinged_port=session.setPortForwardingL(lport, rhost, rport);
System.out.println("localhost:"+assinged_port+" -> "+rhost+":"+rport);
}
catch(Exception e){System.err.print(e);}
However when I try to ssh from iTerm using the command ssh user.name#hostip I can successfully access the remote server using public key authentication.
Your OpenSSH ssh command automatically uses the private key you have configured for OpenSSH in your .ssh folder.
JSch won't automatically use OpenSSH keys. You have to explicitly tell it what key to use.
See Can we use JSch for SSH key-based communication?
Also note that JSch does not support all key formats that OpenSSH do.
See "Invalid privatekey" when using 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 the correct (and secure) approach, see: How to resolve Java UnknownHostKey, while using JSch SFTP library?
Others might be getting the same error for very different reasons. For example when connecting to a modern server that is JSch is no longer compatible with:
Public key authentication fails with JSch but work with OpenSSH with the same key
As #martin prikryl says:
JSch won't automatically use OpenSSH keys.
File file = new File(SystemUtils.getUserHome() + "/.ssh/id_rsa");
String knownHosts = SystemUtils.getUserHome() + "/.ssh/known_hosts";
jsch.setKnownHosts(knownHosts);
jsch.addIdentity(file.getPath());
SystemUtils belongs to Apache Commons Lang3
or you can use:
new File(System.getProperty("user.home"))

operation time connecting openshift in java

I want to connect to my mysql database cartridge in openshift through java.
So I create a ssl connection using jsch in my java file. When I run it, give me error operation timed out. Can any one help me out with this. My java code is :
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
JSch jsc = new JSch();
jsc.addIdentity("/Users/Adhirajchoudhary/.ssh/id_rsa1");
session=jsc.getSession(sshUserName, sshHostName, 3306);
session.setPassword(sshPassword);
session.setConfig(config);
session.connect();
System.out.println("Connected");
It looks like we are missing some key information in the code you provided, and it also looks like you are trying to ssh to port 3306? That's not going to work. You would have to ssh to port 22, then try to create a tunnel over that connection. You could also try using the OpenShift Java Client and have it setup a port forward for you to use.

Connecting to an FTP server via a proxy using Apache FTPClient

Using the Apache FTPClient, i can usually connect using the following statements:
FTPClient client = new FTPClient();
client.connect("ftp.myhost.com");
client.login("myUsername", "myPassword");
client.changeWorkingDirectory("/fileFeed");
client.setFileType(FTPClient.BINARY_FILE_TYPE);
client.setFileTransferMode(FTPClient.BLOCK_TRANSFER_MODE);
The above works fine but now i am to connect to the FTP site, i have to use a proxy server. The instructions i got is that i should connect to the proxy server and specify the actual ftp server in the username. So to log on i would use the following details to connect:
ftp ftp.myProxyServer.com
username myUsername#ftp.myhost.com
password myPassword
I tried connecting directly using the command prompt and i can connect to the ftp.myProxyServer.com host and it does forward me to the intended ftp site if i specify myUsername#ftp.myhost.com as the host username. The problem is that the above type of connection is not accepted in Java using Apache FTPClient:
FTPClient client = new FTPClient();
client.connect("ftp.myProxyServer.com");
client.login("myUsername#ftp.myhost.com", "myPassword");
client.changeWorkingDirectory("/fileFeed");
client.setFileType(FTPClient.BINARY_FILE_TYPE);
client.setFileTransferMode(FTPClient.BLOCK_TRANSFER_MODE);
Is there anything i am missing or would the above not work? I tried a direct connection and that works fine.
The FTPClient usually is in active ftp mode, and in case your proxy is not able to initiate a tcp connection back to your client computer (for firewall/DMZ reasons) then you have to switch to passive mode:
FTPClient client = new FTPClient();
client.connect("ftp.myProxyServer.com");
client.login("myUsername#ftp.myhost.com", "myPassword");
client.enterLocalPassiveMode(); //switch from active to passive
client.changeWorkingDirectory("/fileFeed");
...
(Furthermore I would like to recommend to always check the return codes of the method calls, but probably they are ommitted for sake of clarity)
Sorry for the late attempt to answer your question...

Java - Perform a FTP command through a SSH tunnel with JSch

I am developing a Java tool which uploads a file from one remote server to another.
The program will run on a laptop. The software needs to connect to serverA with SSH protocol then once it is connected to serverA, it has to transfer files to serverB through FTP.
Files to be transfered are hosted on serverA.
I cannot directly connect to serverB because of a firewall.
Here is a summary:
Is it possible to do that with JSch? Something like the following:
JSch client = new JSch();
Session session = client.getSession("login", "serverA", 22);
// test purpose
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword("password");
session.connect();
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand("ftp -i ftp://username:password#serverB; put file.txt; close; quit;");
EDIT
What about writing a script and upload it on the serverA?
#!/bin/sh
ftp -n -i <<ENDOFINPUT
open serverB
user root password
cd /home/root
put xxx
close
bye
ENDOFINPUT

how tunnel all RMI traffic over SSH

I'm working on tunnelling the cajo rmi traffic through a SSH tunnel.
For that I have a server running an SSH deamon (apache Mina) and a client running an SSH client (Trilead SSH).
The shh connection between these machines can be established and by applying local and remote port forwarding I can tunnel rmi traffic, however this works only in the outging (to server) direction.
The setup:
Active SSH connection (port 22)
client: forwarding local port 4000, to remote host port 1198 (this traffic actually goes trhough the tunnel)
server: forwarding server port 4000, to client port 1198 (this part of the tunnel is not being used by cajo)
The server exports an object using:
Remote.config(null, 1198, null, 0);
ItemServer.bind(new SomeObject(), "someobject");
The client does an object lookup using:
ObjectType someObject = (ObjectType)TransparentItemProxy.getItem(
"//localhost:4000/someobject",
new Class[] { ObjectType.class });
logger.info(someObject.getName());
Port forwarding is invoked using the trilead ssh library on the client side:
conn.createLocalPortForwarder(4000, "Server-IP", 1198);
conn.requestRemotePortForwarding("localhost" 4000, "Client-IP", 1198);
When analysing the ip traffic between the two machines with WireShark, I see that the lookup is being redirected throug the tunnel, but the response is not.
The respons is ordinarily send to port 1198 of the client.
How can I force the server to send the response of a remote invocation to a local port, in order to get it tunneled back to the client?
UPDATE: The problem here was that the ports for RMI objects are different then the registry port and therefore also need to be forwarded.
In short, client 10.0.0.1 makes lookup to //10.0.0.1:4000 which is forwarded to the RMI port on the server (through the tunnel).
Subsequently the server responds to 10.0.0.1:1198 where I would like the server to send its traffic to its local port 4000 instead, in order to use the tunnel.
I have tried to fiddle with the cajo Remote.config(ServerAddress, ServerPort, ClientAddress, ClientPort) settings, however when I set the clientaddress to 10.0.0.1 or 127.0.0.1 for this method, I'm unable to get response back and I don't see any responding traffic at all...
I did find a solution to this problem, in which I omitted the cajo framework from the setup and use pure java rmi. This makes things more transparent.
On both client and server I placed a security policy file: C:\server.policy
grant {
permission java.security.AllPermission;
};
Then on the server, set security permissions and start registry on desired port:
System.setProperty("java.rmi.server.hostname", "127.0.0.1");
System.setProperty("java.security.policy","C:\\server.policy");
System.setSecurityManager(new RMISecurityManager());
new SocketPermission("*:1024-", "accept,connect,listen");
createRMIRegistry(Property.getProperty("rmi.registry.port"));
Notice the hostname 127.0.0.1, this makes sure we are always pointing to localost,
this tricks the client in thinking the object got from the remote registry is local and then connects to its local forwarded ports.
On the client I give the same permissions as above, I don't start the register, but bind an extra socket factory to use for the registry lookup.
RMISocketFactory.setSocketFactory(new LocalHostSocketFactory());
This socket factory creates a SSHClientSocket to the localhost ssh port (to the remote registry).
The remote objects are exported with a custom ClientSocketFactory, which is therefore implemented on the clientside. (On the serverside it needs to be disabled, otherwise you will ssh to your own machine :$)
It then creates a ssh socket and port forwarder on the fly.
public class SSHClientSocketFactory implements RMIClientSocketFactory, Serializable {
public Socket createSocket(String host, int port) throws IOException {
try {
Connection conn = new Connection(hostname, 22);
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(username, password);
LocalPortForwarder lpf1 = conn.createLocalPortForwarder(port, serverAddress, port);
return new Socket(host, port);
catch (Exception e) {System.out.println("Unable to connect")};
}
}
This automatic port formwarding ensures that whatever port is being used to bind an RMI object, it goes through the SSH tunnel and points to localhost for that.
Remote port forwarding is not needed for this setup.

Categories