2

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?

11
  • Unless it absolutely has to be cross-platform, you would be better using standard command-line ssh operations for this. In any case, definitely practise with the ssh client before you try to do this in Java. Commented May 19, 2014 at 14:00
  • As a hint, you can use ssh -D1080 <remote host> which will create a SOCKS5 proxy on localhost. Then set the HTTPS client to use that proxy. Commented May 19, 2014 at 14:01
  • @artbristol: I want the program to be cross-platform, and I want it to be runnable on Windows, which doesn't have most of the fancy Linux cmd commands. Incidentally, I don't have Linux installed, so I'd have trouble trying out the command line stuff you recommend. Is there a way to use ssh -D1080 <remote host> in jsch? Commented May 19, 2014 at 14:07
  • If you have putty, the equivalent is to select 'Dynamic' when setting up a port forward Commented May 19, 2014 at 14:15
  • @artbristol: I've googled dynamic port forwarding on JSCH, and it appears to be missing it, sadly. I'll check out code.google.com/p/ssh-persistent-tunnel/source/browse/src/org/… which seems to be the dynamic port forwarding option built on top of JSCH, which is, I am pretty sure, quite ineffective. Commented May 19, 2014 at 14:39

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, I know how to deal with certificate validation problems, I have some ready code for that. However, I don't really understand your answer. If I estabilish a HttpsURLConnection to 127.0.0.1, how would I be able to use the port forwarding to browse the internet?
Your post specifically mentioned HttpsURLConnection, I assumed you wanted to connect this to the tunnel you had setup with Jsch. It appears you want a dynamic proxy. There is a commercial API that support this, J2SSH Maverick link.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.