Solved

How to construct an ssh tunnel inside a java program

Posted on 2012-12-26
8
1,229 Views
Last Modified: 2013-01-01
How to have a java program do the same thing as the ssh unix command (0) where the userName does not have a password associated with it?


(0) The unix command that works
 ssh -i ~/.ssh/pemFile.pem -L 8000:ec2-0-0-0-0.compute-1.amazonaws.com:8000 userName@ec2-0-0-0-0.compute-1.amazonaws.com
 


(1) The pem file
-----BEGIN RSA PRIVATE KEY-----
SOMETEXSOMETEXTALJDLAJFAJFLADSFJASDFFDA
ALDFJALFJASLDFASFDASJDLFJASLDFJAJSSDLF
-----END RSA PRIVATE KEY-----

(2) Java program that currently does not work ( i think i need a user info object or something also I do not have both a cert and key in my pem file do I need to generate one of these?)
public static void main (String args []) throws Exception {
            String pemPath = "/Users/username/.ssh/pemFile.pem";
            String ec2 = "userName@ec2-0-0-0-0.compute-1.amazonaws.com";
            SSLSocketFactory factory = null;
             factory = getSocketFactoryPEM(pemPath);
            InetAddress remote = InetAddress.getByName(ec2);
            InetAddress local = InetAddress.getByName("localhost");
            
            Socket socket = factory.createSocket(remote, 8000, local, 8000);
      }

      public static SSLSocketFactory getSocketFactoryPEM(String pemPath) throws Exception {  
            
          Security.addProvider(new BouncyCastleProvider());

          SSLContext context = SSLContext.getInstance("TLS");

          byte[] certAndKey = getBytesFromFile(new File(pemPath));

          String delimiter = "-----BEGIN RSA PRIVATE KEY-----";
          String[] tokens = new String(certAndKey).split(delimiter);

          byte[] certBytes = tokens[0].concat(delimiter).getBytes();
          //byte[] keyBytes = tokens[1].getBytes();

          PEMReader reader;

          reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(certBytes)));
          X509Certificate cert = (X509Certificate)reader.readObject();        

          //reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(keyBytes)));
          //PrivateKey key = (PrivateKey)reader.readObject();        

          KeyStore keystore = KeyStore.getInstance("JKS");
          keystore.load(null);
          keystore.setCertificateEntry("cert-alias", cert);
          //keystore.setKeyEntry("key-alias", key, "changeit".toCharArray(), new Certificate[] {cert});

          KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
          kmf.init(keystore, "changeit".toCharArray());

          KeyManager[] km = kmf.getKeyManagers();

          context.init(km, null, null);

          return context.getSocketFactory();
      }
0
Comment
Question by:RichardSDetsch
  • 3
  • 3
  • 2
8 Comments
 
LVL 25

Expert Comment

by:Tomas Helgi Johannsson
ID: 38723116
Hi!

Here are some examples to look at
http://www.example-code.com/java/ssh.asp
http://www.beanizer.org/site/index.php/en/Articles/Java-ssh-tunneling-with-jsch.html

Hope this helps.

Regards,
    Tomas Helgi
0
 

Assisted Solution

by:RichardSDetsch
RichardSDetsch earned 0 total points
ID: 38723897
Thanks for the links they are helpful.  I will try them tonight.

Here are some of my thoughts before though.

A. The JSCH does not show me what to do with the pem file and also I do not know what to put in the userInfo object, note the unix command (0) above does not require any user input after running. If there is a command in JSCH like I see "addIdentity" what format should I give my pem file do I have to trim the -----BEGIN RSA PRIVATE KEY----- and make it byte array form.

B. If I do privKey = key.loadText("myPrivateKey.pem"); can I just give it my pem the way it is.  For the below how can I verify that a public key is in the remote ~/.ssh directory and if it is not there can I generate it from the pem file?  Does it have to exist for my unix command (0) to work?

//  Authenticate with the SSH server using the login and
    //  private key.  (The corresponding public key should've
    //  been installed on the SSH server beforehand.)
    success = ssh.AuthenticatePk("myLogin",key);
    if (success != true) {
        System.out.println(ssh.lastErrorText());
        return;
    }

Thanks, Shane
0
 
LVL 25

Accepted Solution

by:
Tomas Helgi Johannsson earned 500 total points
ID: 38723978
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 86

Expert Comment

by:CEHJ
ID: 38724080
For the below how can I verify that a public key is in the remote ~/.ssh directory
If it's not there how would this work?
(0) The unix command that works
0
 
LVL 25

Expert Comment

by:Tomas Helgi Johannsson
ID: 38724188
You will have to upload your keys to the remote server and put it into the .ssh directory for the ssh connection to work to that server.

Regards,
    Tomas Helgi
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 38724216
You will have to upload your keys to the remote server and put it into the .ssh directory
That's already done (see my last comment)

In fact, it's conceivable you might have to do the reverse if you're using Jsch, as the load methods for keys seem to want to work only with a pair of files
0
 

Author Comment

by:RichardSDetsch
ID: 38725122
Thanks the below works and was derived form http://stackoverflow.com/questions/7525679/how-to-get-the-java-security-privatekey-object-from-rsa-privatekey-pem-from-a-f

public static void main (String args []) throws Exception {
            String pemPath = "/Users/userName/.ssh/pemFile.pem";
            String ec2 = "ec2-xxxxxxxx-.compute-1.amazonaws.com";
            Session session = connect(ec2, pemPath);
            session.connect();
          Thread.sleep(60000);
            session.disconnect();
}
     
       public static Session connect(String dnsName, String privKey) throws IOException {
                JSch jSch = new JSch();

                Session session = null;
                try {
                    jSch.addIdentity(privKey);
                    session = jSch.getSession("someUser", dnsName, 22);
                    java.util.Properties config = new java.util.Properties();
                    config.put("StrictHostKeyChecking", "no");
                    session.setConfig(config);
                    System.out.println("Connecting SSH to " + dnsName + " - Please wait for few minutes... ");
                    System.out.println("Forwarding");
                        int assinged_port = session.setPortForwardingL(80, dnsName, 80);
                        System.out.println("localhost:"+assinged_port+" -> "+dnsName+":80");

                } catch (JSchException e) {
                    e.printStackTrace();
                }
                  return session;

            }
0
 

Author Closing Comment

by:RichardSDetsch
ID: 38734249
Thanks the below works and was derived form http://stackoverflow.com/questions/7525679/how-to-get-the-java-security-privatekey-object-from-rsa-privatekey-pem-from-a-f

public static void main (String args []) throws Exception {
            String pemPath = "/Users/userName/.ssh/pemFile.pem";
            String ec2 = "ec2-xxxxxxxx-.compute-1.amazonaws.com";
            Session session = connect(ec2, pemPath);
            session.connect();
          Thread.sleep(60000);
            session.disconnect();
}
      
       public static Session connect(String dnsName, String privKey) throws IOException {
                JSch jSch = new JSch();

                Session session = null;
                try {
                    jSch.addIdentity(privKey);
                    session = jSch.getSession("scbeCoreDevUsEast1", dnsName, 22);
                    java.util.Properties config = new java.util.Properties();
                    config.put("StrictHostKeyChecking", "no");
                    session.setConfig(config);
                    System.out.println("Connecting SSH to " + dnsName + " - Please wait for few minutes... ");
                    System.out.println("Forwarding");
                        int assinged_port = session.setPortForwardingL(8081, dnsName, 8080);
                        System.out.println("localhost:"+assinged_port+" -> "+dnsName+":8080");

                } catch (JSchException e) {
                    e.printStackTrace();
                }
                  return session;

            }
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
servlet  URL Rewriting 1 42
HashTable highest marks enumeration alternative 9 42
Crystal Reports Licensing Questions 4 34
java mysql insert application 14 25
Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question