An RMI client behind a NAT firewall can call a server which is not behind a NAT firewall. The server will not get the client's true IP address from RemoteServer.getClientHost(). No other configurations of NAT will work; specifically:
servers behind NAT firewalls are inaccessible
callbacks to clients behind NAT firewalls don't work.
For a solution to this see http://www.rmiproxy.com.
Sorry to contradict the previous reply, but just today I wrote a simple RMI application that connected fine from a client outside a NAT router to a server inside a NAT router. Mind you, there is no firewall filtering or port mapping, just address translation.
The trick for me was to simply set the java system property java.rmi.server.hostname="<server_host_name>", and make sure the <server_host_name> is correctly resolvable on both sides of the router. If you don't set this property, or the related java.rmi.server.useLocalHostname property, the RMI server will by default pick up the server machine's ip address (inside the NAT), which is meaningless to the client.
See the Java RMI FAQ at http://java.sun.com/j2se/1.4/docs/guide/rmi/faq.html#nethostname
I guess a lot of learning is being in the right place, at the right time. I have been struggling to get my RMI understanding to the next level for over a year now. NAT was the last piece of the puzzle for me. From your help, for the first time, I successfully created RMI clients and servers, who can synchronously call, and asynchronously callback, even when both are behind the unholy barrier; firewall NAT DHCP + port forwarding. This has been a source of long-term frustration, and now a tremendous relief.
Well if you can give me some insight as in what you did I would love it. I have an RMIserver sitting on a box which is behind a firewall. I only have about 6 ports open and none of them are the standard ones.
The client is NOT behind the firewall, just the server.
I tried starting my rmi server like this:
hostname aa.aa.aa.aa is the public address of the box that is behind the firewall (meaning when I connect to it from other IP's which have access I must use the address aa.aa.aa.aa) The private address is bb.bb.bb.bb (the ACTUAL IP of the box)..... The firewall takes request in to public address aa.aa.aa.aa and if the user is allowed access it routes them to the private address bb.bb.bb.bb (the server).
When I try
java -Djava.rmi.server.hostname=aa.aa.aa.aa MyRMIServer
or
java -Djava.rmi.server.hostname=bb.bb.bb.bb MyRMIServer
I get a connection refused at bb.bb.bb.bb
I get the private address bb.bb.bb.bb no matter which IP, (public or private) I give MyRMIServer at startup. ANy help is greatly appreciated!
A stack trace is below:
Exception in thread "main" java.rmi.ConnectException: Connection refused to host: bb.bb.bb.bb; nested exception is:
java.net.ConnectException: Connection refused: connect
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:567)
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.newCall(UnicastRef.java:313)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
at RMI_CPS_CFX.<init>(RMI_CPS_CFX.java:182)
at RMI_CPS_CFX.main(RMI_CPS_CFX.java:203)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:305)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:171)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:158)
at java.net.Socket.connect(Socket.java:426)
at java.net.Socket.connect(Socket.java:376)
at java.net.Socket.<init>(Socket.java:291)
at java.net.Socket.<init>(Socket.java:119)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFact
ory.java:22)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFact
ory.java:128)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:562)