2
votes

fellow Java programmers. I have been faced with the task of using an SSH connection to a server to load webpages from another server. Pretty soon I found out that my knowledge of networking protocols is extremely limited. First, I tried dynamic port forwarding - to no avail, it is available only in commercial libraries (and all of them are FAR out of my financial reach). Then I learned that with JSch, you can actually create something called a direct tcp-IP channel (the concept of which I am still trying ot grasp), and I found some code here on stackoverflow that is supposed to use it to send an HTTP request to a remote server through an SSH connection to another server using JSch. Here is the code (slightly modified from the original at TCP Connection over a secure ssh connection)

    String host = "66.104.230.49";
    String user = "admin";
    String password = "default";
    int port = 22;

    String remoteHost = "souzpp.ru";
    int remotePort = 80;

    int localPort = 5001;
    int assignedPort;
    String localHost = "127.0.0.1";

    Properties config = new Properties();
    config.put("StrictHostKeyChecking", "no");

    try { 
        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, port);
        session.setPassword(password);
        session.setConfig(config);
        session.connect();
        assignedPort = session.setPortForwardingL(localPort, remoteHost, remotePort);
        Channel channel = session.openChannel("direct-tcpip");  

        System.out.println(assignedPort);
        ((ChannelDirectTCPIP)channel).setHost(localHost);
        ((ChannelDirectTCPIP)channel).setPort(assignedPort);

        String cmd = "GET /files/inst HTTP/1.0\r\n\r\n";

        InputStream in = channel.getInputStream();
        OutputStream out = channel.getOutputStream();

        channel.connect(10000);

        byte[] bytes = cmd.getBytes();          
        InputStream is = new ByteArrayInputStream(cmd.getBytes("UTF-8"));

        int numRead;

        while ((numRead = is.read(bytes)) >= 0)
              out.write(bytes, 0, numRead);

        out.flush();
        channel.disconnect();
        session.disconnect();

        System.out.println("Request supposed to have been sent");

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            for (String line; (line = reader.readLine()) != null;){
                System.out.println(line);
            }
        } catch (java.io.IOException exc) {
            System.out.println(exc.toString());
        }

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

This code throws the following exception: com.jcraft.jsch.JSchException: channel is not opened. What might be wrong here? Please, if the answer is related to a mistake in networking logic, not an error in implementation, I would be really happy if you gave me a link with good information on whatever I got wrong.

(EDIT: added port forwarding as suggested by JavaCoderEx)

2

2 Answers

1
votes
InputStream in = channel.getInputStream();
[...]
channel.disconnect();
session.disconnect();
[...]
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
for (String line; (line = reader.readLine()) != null;){

You are closing the TCP stream channel, and then closing the entire SSH session, then trying to read from the channel.

Don't close the SSH session or the channel until you're actually finished with them.

-1
votes

Do you have the option of setting up an SSH tunnel first?

I created a script that contains: sudo ssh -i /Users/myuser/.ssh/id_rsa -2 -f -N myuser@remotehost -L 8080/127.0.0.1/80

The above code creates a reverse SSH tunnel, requests made of the localhost on 8080 go through the tunnel and end up being a request on 80 on the other side. Now you can create a stream to respond to the user request and open a stream (url connection) to the other server - in essence you are now creating a proxy.