2 Replies Latest reply: Oct 28, 2010 9:58 PM by 808678 RSS

    RMI Through Firewall

    808678
      Hello,

      I am developing a Java client application that is using RMI to connect to resources on a server application that is being hosted behind a firewall. I am attempting to to get around the firewall at present by using an SSH tunnel. I have learned that while RMI uses port 1099 to listen for incoming connections it by default uses some random port to actually handle the connection. So, from my understanding, I can set the handle port by using the export object method:
         UnicastRemoteObject.exportObject(obj,1098)
      where I want to use port 1098 to handle connections.

      The server system I am connecting to is the head node of an HPC cluster and has two IP addresses (a local one and one visible to the internet) so I set the rmi hostname to to the world-visible address when I start rmiregistry:

      rmiregistry -J-Djava.rmi.server.hostname=<world-visible-ip>

      Next, I start the RMI server application (this is currently just Java Hello World RMI tutorial) with a wide-open security policy (defined in file /home/user/wideopen.policy) for testing and also pointing to the correct RMI server hostname:

      java -Djava.security.policy=/home/user/wideopen.policy -Djava.rmi.server.hostname=<world-visible-ip>

      For the client I, launch it with the appropriate security policy like above. Now, I can run the client on the server side and everything works fine. Also, if I run the client on another machine inside the server's firewall it also works fine. However, I want to run it outside the firewall so I set up an SSH tunnel from my local machine to the server machine for ports 1098 and 1099. However, whenever I do this I get a connection refused exception. What am I missing in this setup that it will work just fine within the firewall, but not outside?? I am a bit new to RMI so I might have confused a few things in here, any guidance would be appreciated. Thanks.

      Also, I have posted my server and client code below:


      Server:
      import java.io.*;
      import java.rmi.*;
      import java.rmi.server.*;
      import java.rmi.registry.*;
      
      public class HelloImpl implements Hello {
      
          public HelloImpl() {}
      
          public String sayHello() {
              return  "Hello World!";
          }
      
          public static void main(String args[]) {
      
           if (System.getSecurityManager() == null) {
               System.setSecurityManager(new SecurityManager());
           }
      
           try {
               /*
                * Create remote object and export it to use
                * custom socket factories.
                */
               HelloImpl obj = new HelloImpl();
               Hello stub =
                (Hello) UnicastRemoteObject.exportObject(obj,1098);
      
               /*
                * Create a registry and bind stub in registry.
                */
               Registry registry = LocateRegistry.getRegistry();
               registry.rebind("Hello", stub);
               System.out.println("HelloImpl bound in registry");
      
           } catch (Exception e) {
               System.out.println("HelloImpl exception: " + e.getMessage());
               e.printStackTrace();
           }
          }
      }
      Client:
      import java.rmi.*;
      import java.rmi.registry.*;
      
      public class HelloClient {
      
          public static void main(String args[]) {
      
           if (System.getSecurityManager() == null) {
               System.setSecurityManager(new SecurityManager());
           }
      
              try {
               Registry registry = LocateRegistry.getRegistry("localhost",1099);
                  Hello obj = (Hello) registry.lookup("Hello");
                  String message = obj.sayHello();
                  System.out.println(message);
      
              } catch (Exception e) {
               System.out.println("HelloClient exception: " +
                                     e.getMessage());
                  e.printStackTrace();
              }
          }
      
      }
      The first line of the exception is:

      HelloClient exception: Connection refused to host: <world-visible-ip>; nested exception is:
           java.net.ConnectException: Connection refused: connect
        • 1. Re: RMI Through Firewall
          EJP
          I have learned that while RMI uses port 1099 to listen for incoming connections
          No. It uses port 1099 for the Registry to listen at.
          it by default uses some random port to actually handle the connection.
          No. It uses a system-allocated port for your remote objects to listen at, unless you specify a port number when exporting them.
          So, from my understanding, I can set the handle port
          The object's listening port.
          by using the export object method:
          Or, if your class extends UnicastRemoteObject, by calling super(post).
          where I want to use port 1098 to handle connections.
          Listen for connections.
          I set up an SSH tunnel from my local machine to the server machine for ports 1098 and 1099.
          That will work for the Registry port 1099 but it won't work for 1098 because the objects contain their own IP addresses. So, as your exception shows, your client will still attempt to connect to the remote object via <world-visible-ip>:1098 rather than localhost:1098.

          This technique will not work. You need to arrange for port 1098 to be opened in the server-side firewall.

          NB you aren't using custom socket factories, contrary to a comment in your code.
          • 2. Re: RMI Through Firewall
            808678
            EJP,

            Thanks for the response, I think that I understand the port layout a bit more now, I will try and talk to my system admin to open up some ports in our VPN. Since I am able to run the RMI application inside the firewall I am guessing that doing this will solve my problems. Thanks again.

            P.S. The comments in my code regarding socket factories were accidental. I was using some example code which utilized socket factories but them removed them...sorry for the confusion.