I talked to a jboss user who indicated he needed to create a custom invoker to deal with firewall routing issues because the remoting layer did not have the notion of allowing the client endpoint to specify the connection info as an override. The basic scenario is pulling down a transport endpoint/proxy across a nating firewall where the server has no idea of the topology the client is going to be using.
This is something we support in the uil2 jms transport using a client side property for the server address/name and port.
We need something similar in the remoting layer as well. In talking to the jxta people, they have support for even more totorous types of paths so maybe there is an abstraction there we can incorporate.
NAT only works if the firewall understands the protocol.
You can't just embed an ip address in a tcp/ip stream and expect the firewall
to automagically replace it.
Things like RMI have system properties to override the hostname seen by the
clients on the other side of the firewall, e.g. java.rmi.server.hostname
The advantage of using the hostname is that it can be resolved to different ip addresses
on different subnets based on dns configuration.
The disadvantage is that you have more complicated dns configuration.
In general, it is not a good idea to transport an InetAddress like UIL2 does,
since it is pre-resolved on the server and it will usually prefer the ip address.
I'm not talking about replacing a marshalled InetAddress. There simply needs to be an ability to override any connection parameters passed to the connection factory the client endpoint is using to establish its connection. When we override the uil2 settings using system properties, the marshalled InetAddress is ignored.
I'm not too concerned about the jxta details which may be good or bad, just whether or not there is abstraction in the form of the client side connection setup that works with firewalls or even non-dns aware envs where the participants need to be located at runtime when the connection is to be created.
Yes, I know.
My point was that the system property should be unnecessary in most cases.
If we didn't resolve the network address on the server and
instead just allowed something to be configured/transported that might only make
sense to resolve on the client.
bind address == nic that the service accepts requests on (could be 0.0.0.0)
connect address == host name used by client that could resolve to the firewall
with port forwarding enabled or might resolve to different nics on different subnets even without a firewall.
Ok, I see what your saying, but the problem is that the server may not have any meaningful name. We do have a notion of an "external" interface for the client, but it is sometimes resolved too early in our current usage, and sometimes its simply not known.
If the remoting layer had a tiered approach to resolving a name that first tried to use the name as a hostname/ip address, and then a system property of even a transformed system property (e.g., given a name of host1 use system property org.jboss.remoting.address.host1) then there is the ability to handle any situation while allowing for a purely server side configuration. In the future we could even have a locator service to deal with names that may not be in dns as is the case for redevuouz, and some sip names.
and "connect address" might resolve to the "relay" in the JXTA example.
For DNS environments there would have to be a fallback ip address for when the
hostname could not be resolved. Or you just manually configure the ip address as the
Also I think jboss-remoting has the notion of a discovery service that serves as an
abstraction for resolving locators.
i.e. the discovery can be anything from dynamic discovery, to preconfigured, a reference
server like a DNS or a jgroups gossip service.
Remoting has the ability to set the bind address and port for both the client and server for all transports (see http://wiki.jboss.org/wiki/Wiki.jsp?page=Remoting_Transports_Configuration).
This is only useful if know what the NAT will use for the external address and port for the server.
For a long time I have been thinking about how to detect this automatically. The problem is have to be able to either query the router(executing the NAT), which is not practical, or having something external to the network that can identify the ip/port to get back to the server externally. The later approach is fairly easy, but then have an issue of reliability. Am open to suggestions for this.
The issue is how is the connection handled when the connection endpoint that the client needs to use is not known on the server side. It may not even be meaningful to have a name for the clientConnectAddress. If there is a name, we need a multi-step approach to resolving it at the time the client is making the connection. We can either code a multi-step behavior, or introduce an interface to externalize the resolution:
public interface EndpointResolver
public InetSocketAddress resolve(String name, int port);
We could also have a resolver chain notion to tier prioritize and stack the resolution process.
This is all fine. The problem is I still don't understand how anyone on the client side is going to be able to resolve how to access the server during runtime without some extra information being provided from somewhere.
The only way I can see this working is if the server broadcasts some type of message that is picked up by something external to the network and resolves where it came from (and uses that routing path to get back to the server). This can be done via detection, but means the detector has to run outside the server network, which won't work for multicast and is probably not practical for JNDI.
I am guessing I am missing something somewhere?
Right, there is info needed, but this info is not availble on the server side. I put up a service on X, and have no control over the path the client has to navigate to get to me. Its his net admin that says to connect to service X, use endpoint Y in order to get through the firewall.
The simplest way to handle this on the client is via system properties that are specified on the client command line. Adrian's point is what we should allow for more sophisticated name resolution on the client rather than having to require system properties.
Ok. I understand the problem well. Remoting allows for system property settings on the client already.
What I am not getting is what this "more sophisticated name resolution" would be? I am just unaware of any mechanism to do this. If there are any, would love to know what they are and will try to implement it. Know this is a serious issue for those wanting to run fat clients using remoting in unknown environments.
more sophisticated name resolution:
- Trying to resolve the name bound on the server as the client address as a dns name in the client. Either a client specific dns server, or even hosts file entries will be selected.
- Querying a Rendezvous like server
- Querying a Sipp server
- Looking up the name to address binding in JNDI
Just anything that allows for centralized management of the client side name resolution as opposed to having to enter the bindings in each client application.