7 Replies Latest reply on Aug 30, 2005 7:36 AM by mc340

    Accessing EJB through HTTPS Invoker...

    benoitx

      Hello

      I am stuck on a problem with accessing an EJB through a firewall via HTTP tunnelling.

      Our client application is accessing the JNDI service using HTTPS and I seem to get the HOME interface. Unfortunately when I call create() on it to create the remote interface, I get the following exception:

      java.rmi.ConnectException: Connection refused to host: myServer.com; nested
       exception is:
       java.net.ConnectException: Connection refused: connect
       at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:574)
       at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:185
      )
       at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:171)
       at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:94)
       at org.jboss.invocation.jrmp.server.JRMPInvoker_Stub.invoke(Unknown Source)
       at org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxy.invoke(JRMPInvo
      kerProxy.java:118)
       at org.jboss.invocation.InvokerInterceptor.invokeInvoker(InvokerIntercep
      tor.java:227)
       at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.jav
      a:167)
       at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.
      java:46)
      ....
      


      Which PORT is it trying to use? Only port 8443 is open! I have assumed, may be incorrectly, that by using JNDI over HTTPs, the EJB references would also go through the same port??? Is it the case?

      How is a client supposed to be access the EJBs via HTTPs? Could anyone post an example? end-to-end? Many thanks!!!

      Here my client code:

      When I run it, I can see:
      About to connect to JNDI HTTPS
      Got the HOME interface
      

      but not "Got the REMOTE interface"!

      System.out.println("Connect HTTPS");
      Properties prop = System.getProperties();
      
      prop.put("java.naming.factory.initial","org.jboss.naming.HttpNamingContextFactory");
      prop.put("org.jboss.security.ignoreHttpsHost","true");
      final int newPort = ConsoleMenu.getInt("Enter the port (current:" + 8443 +")", 8443);
      prop.put("java.naming.provider.url","https://"+host+":"+newPort+"/invoker/JNDIFactory");
      
      // Create a trust manager that does not validate certificate chains
      TrustManager[] trustAllCerts = new TrustManager[]{
       new X509TrustManager() {
       public java.security.cert.X509Certificate[] getAcceptedIssuers() {
       return null;
       }
       public void checkClientTrusted(
       java.security.cert.X509Certificate[] certs, String authType) {
       }
       public void checkServerTrusted(
       java.security.cert.X509Certificate[] certs, String authType) {
       }
       }
      };
      
      // Install the all-trusting trust manager
      try {
       SSLContext sc = SSLContext.getInstance("SSL");
       sc.init(null, trustAllCerts, new java.security.SecureRandom());
       HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
      } catch (Exception e) {
      }
      
      try {
       System.err.println("About to connect to JNDI HTTPS");
       InitialContext context = new InitialContext(prop);
      
       final Object objref = context.lookup("RefBean");
       EJBHome anEJBHome = (EJBHome) PortableRemoteObject
       .narrow(objref, RefBean.class);
       System.err.println("Got the HOME interface");
       remote = anEJBHome.create();
       System.err.println("Got the REMOTE interface");
      } catch (NamingException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      } catch (RemoteException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      } catch (CreateException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
      


      The server expose the Naming service via http, here is the config for jboss-4.0.3RC1/server/default/deploy/http-invoker.sar/META-INF/jboss-service.xml
      <!-- Expose the Naming service interface via HTTPS -->
      <mbean code="org.jboss.invocation.http.server.HttpProxyFactory"
       name="jboss:service=invoker,type=http,target=Naming">
       <!-- The Naming service we are proxying -->
       <attribute name="InvokerName">jboss:service=Naming</attribute>
       <!-- Compose the invoker URL from the cluster node address -->
       <attribute name="InvokerURLPrefix">https://</attribute>
       <attribute name="InvokerURLSuffix">:8443/invoker/JMXInvokerServlet</attribute>
       <attribute name="UseHostName">true</attribute>
       <attribute name="ExportedInterface">org.jnp.interfaces.Naming</attribute>
       <attribute name="JndiName"></attribute>
       <attribute name="ClientInterceptors">
       <interceptors>
       <interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor>
       <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
       <interceptor>org.jboss.naming.interceptors.ExceptionInterceptor</interceptor>
       <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
       </interceptors>
       </attribute>
      </mbean>
      


      and Tomcat is configured to have a https connector in jboss-4.0.3RC1/server/default/deploy/jbossweb-tomcat55.sar/server.xml
       <!-- SSL/TLS Connector configuration using the admin devl guide keystore -->
       <!-- see http://www.huihoo.com/jboss/online_manual/3.2.3/Chap8.html -->
       <Connector port="8443" address="${jboss.bind.address}"
       maxThreads="100" strategy="ms" maxHttpHeaderSize="8192"
       emptySessionPath="true"
       scheme="https" secure="true" clientAuth="false"
       keystoreFile="${jboss.server.home.dir}/conf/chap8.keystore"
       keystorePass="rmi+ssl" sslProtocol = "TLS" />
      


      Furthermore, JBoss is started with the following properties:
      -Djava.rmi.server.hostname=myServer.com -Djava.rmi.server.useLocalHostname=false

      This is to ensure that the server responds with its external address.

      The main question is must I open extra ports in the firewall?, is there any way to use only HTTP over 8443?
      How to access the EJB via https?

      Any help would be greatly appreciated!
      Thanks

      Benoit

        • 1. Re: Accessing EJB through HTTPS Invoker...
          miani

          Benoit,

          I've been fighting the same issue. Encrypting the EJB calls with SSL is nice but what's the point if you can't go over https? Customers aren't going to open a bunch of ports on their firewall for us.

          Anyway, I couldn't have typed up your post better myself. Anyone out there have an example for us? Or can someone even tell us if it is possible to do this?

          If I come up with a solution I will be sure to post it. Hopefully the weekend will bring some enlightenment.

          Jim[/url]

          • 2. Re: Accessing EJB through HTTPS Invoker...
            benoitx

            Hi Jim & all,

            Following my previous post, I got it to work by opening port 4444 (the RmiObject port).

            I guess that the scenario specified above allow only JNDI access via HTTPs but the RMI is not encrypted. I then have setup RMI over SSL without too much trouble (see Chap 8 of the Jboss Admin & Dev guide). And, yes you will require a port to be open 14445 in the example.

            The trick is that the client application MUST have access to a trustore if your server certificate is self-signed. You may want to create your public/private keys then export the X509 certificate and then import it in another keystore and distribute that one instead of the original (as it would only contain the public key through the certificate). I can post a bit more if you want.

            Best regards from London
            (yeah, then English one)

            Benoit

            • 3. Re: Accessing EJB through HTTPS Invoker...
              miani

              Benoit,

              That is great that you got it working. But, we had already gotten RMI over SSL working. I just don't see much value to it (at least for us) unless you can actually tunnel the packets over port 443. Even if I could get them to agree to it, I don't feel comfortable advising my customers to open up extra, non-standard ports in their firewall.

              I know RMI can be tunneled over HTTP. Does anyone know why not over HTTPS? I realize there is a performance drag, but I can live with that for remote clients. It seems like all the pieces exist, but no one has put them together in quite this way.

              Can anyone out there tell me if it is possible to configure JBoss so that EJB/RMI calls are tunneled over HTTPS?

              TIA,

              Jim

              • 4. Re: Accessing EJB through HTTPS Invoker...
                olli_ger

                Hello,

                I just got it working: Access EJBs and the JNDI via HTTP.
                I'm, able to access the Enterprise Beans via ONE PORT.
                My advices are of course without warranty! ;-)

                I think Benoit is right, the scenario specified allows only JNDI via http(s).
                Remember, in my requirements HTTP is all right!
                You need to confige a container-configuration with a http-invoker.
                There are two possibilities:
                1. For all Enterprise Beans
                2. Only for EBeans you selected, via the jboss-Deployment-Descriptor of your application.

                In my case, I used the first one.
                Attention: We are using Hibernate, so I only configured SessionBeans for http-calls. (Stateless + Statefull)

                I changed the configuration in /server/default/conf/standardjboss.xml

                 <invoker-proxy-binding>
                 <name>stateless-http-invoker</name>
                 <invoker-mbean>jboss:service=invoker,type=http</invoker-mbean>
                 <proxy-factory>org.jboss.proxy.ejb.ProxyFactory</proxy-factory>
                 <proxy-factory-config>
                ......
                

                I modified the name from "stateless-rmi-invoker" to "stateless-http-invoker" and the type in "type=http"

                You have to do that for all type of Beans you want to access via http.

                After that, you have to change the container configuration in the same file.
                Example for the Stateless-SessionBeans:

                 <container-configuration>
                 <container-name>Standard Stateless SessionBean</container-name>
                 <call-logging>false</call-logging>
                 <invoker-proxy-binding-name>stateless-http-invoker</invoker-proxy-binding-name>
                ........
                

                I just changed the value of "invoker-proxy-binding-name" to "stateless-http-invoker" (we just changed the name of this invoker proxy and its type to "http")

                And of course, you need to expose the naming-service via http.
                I'm using this client-jndi-properties:
                System.setProperty("java.naming.factory.initial", "org.jboss.naming.HttpNamingContextFactory");
                System.setProperty("java.naming.provider.url", "http://IP_OF_MACHINE:PORT_OF_MACHINE/invoker/JNDIFactory");
                System.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
                

                Hope this helps!

                Regards,

                Oliver

                • 5. Re: Accessing EJB through HTTPS Invoker...
                  martinh

                  Hi, i don't kno wif this could help, but i've a JBoss behind a Firewall, i'm using JNDIFactory (JNDI over HTTP) and there is no documentation abot this, you have to open the 4444 port in your firewall pointing to Jboss server, i didn't know that, i've noticed scanning the port acces while trying to resolve jndi names and saw connect to 8080 port and 4444 port.

                  • 6. Re: Accessing EJB through HTTPS Invoker...
                    benoitx

                    Hi Oliver

                    Thanks for your reply (only read it today,...just back from a few days off...) It looks very promising, I will try your solution and try to use HTTPs with it. I shall report my findings here!

                    regards from London
                    Benoit

                    • 7. Re: Accessing EJB through HTTPS Invoker...
                      mc340

                      Hi,
                      i am working on this problem too. If you have running JNDI over HTTPS and EJB over HTTP it's only a small step to have EJB over HTTPS too. Now i'm running JNDI and EJB over a single HTTPS port(8443). So far so good. But now the connection is VERY, VERY slow, it's not usable anymore. I don't know where to search the Problem. I tried to figure it out with a profiler, but if i run my application with a profiler the connection is much faster, so i can't see the bottleneck. Without the profiler it's slow again. Don't know why. Had anyone a similar problem? I'm running JBoss 3.2.6 and a standalone client on Windows 2000.

                      Regards,
                      Michael