Specify RMI endpoint address when having two interfaces - java

I have an rmi server on a box with two public interfaces. When a client connects, it always returns the wrong ip address in the UnicastServerRef2 [liveRef: [endpoint:[192.x.x.x:xxxx .... The connection from the client goes to the other interface with ip 10.x.x.x. Does anybody know how to solve this? I do not want to specify the ip when binding the stub. It works then, but I would like it to listen on all interfaces (0.0.0.0).
If I specify java.rmi.server.hostname=myhostname and use a RMIServerSocketFactory to create a ServerSocket[addr=myhostname/10.x.x.x,localport=xxxx], it still returns the 192.x.x.x adress to the client as remote endpoint. Weird enough I have two UnicastRemoteObjects objects on diffrerent ports and one of them returns the right address, the other not.
Any Ideas how to make it to return the endpoint with the ip of the interface the connection was made to?

That's what the java.rmi.server.hostname property is for. Set it at the exporting JVM to whatever IP address you want the clients to use to connect to it.

Related

How to get Client IP with ktor

Hey i tried to get the ip of the client with ktor.
I used the method
this.context.request.local.remoteHost
(this.context is an Instance of ApplicationCall)
How can i get the real ip an not something like "********.dip0.t-ipconnect.de"
You can also get a remote host from the request's origin: call.request.origin.remoteHost but it returns IP address in not every case too.
I've created an issue in Ktor's bug tracker to address this problem.

SCTP INIT missing IPv4 address parameter

I have been testing the SCTP support on Java + lksctp.
I wrote a simple client in order to see just the inital setup of a SCTP association which is basically the "INIT" and "INIT ACK".
I have tested 2 ways for a Client to send the "INIT" to a SERVER which is basically:
create the SctpChannel object with "open(SocketAddress)"
try {
InetSocketAddress socketAddress = new InetSocketAddress("192.168.52.197", 2905);
SctpChannel sctpChannel = SctpChannel.open(socketAddress,1,1);
sctpChannel.bind(new InetSocketAddress("192.168.1.251",2906));
sctpChannel.connect(socketAddress, 1 ,1);
so in this way, I can see in Wireshark that I have the "IPv4 Address parameter" for all my network interfaces (3 as you can see bellow), but the Source Port is getting a aleatory port number instead the 2906 as I would like to have and it's in the bind.
So... once the bind of local IP/Port is happening after the "open"... so I have changed the code to:
create the SctpChannel object which just "open()"
binding the local client IP and Port
"connect" to the remote Server IP and Port
try {
InetSocketAddress socketAddress = new InetSocketAddress("192.168.52.197", 2905);
SctpChannel sctpChannel = SctpChannel.open();
sctpChannel.bind(new InetSocketAddress("192.168.1.251",2906));
sctpChannel.connect(socketAddress, 1 ,1);
In this way, I can see in wireshark that Source/Destination ports are expected (2906/2905), but the INIT does not have the "IPv4 Address parameter".
So does anyone know why the 2nd code I'm missing the "IPv4 address parameter" in the INIT ? Do I miss something?
Any help would be really welcome.
Thanks.
IP addresses within INIT/INIT_ACK chunks are optional parameters. In case your endpoints are signglehomed IP address might not be included in the INIT/INIT_ACK chunk. The remote end still can retrieve information about peer address from the IP header.
Fundamentally the reason of this behaviour is what parameters you pass to open(). Open() without any parameters and open() with remote address specified works in a different way.
If you call SctpChannel.open(socketAddress,1,1) with socket address for the remote end it effectively open channel and connects to remote end (see open documentation. Your bind() and connect() calls in this case are pretty useless. So since there were no bind() call prior to establishing the connection you are sort of using "default" endpoint with random port (56044) and IP addresses of all available interfaces.
In second case, when you don't specify socketAddress for open() it just open the channel but does not connect to remote end at this stage. So your bind() call successfully specify endpoint details (port and IP address) and when you call connect() it is actually using the endpoint you just created (192.168.1.251:2906) to setup connection with remote end.

JAIN SIP: Identify inbound IP for SIP message when listening on 0.0.0.0

When using the JAIN SIP API, I create a ListeningPoint instance with an address of 0.0.0.0 (ie. listen on all interfaces):
sipStack.createListeningPoint("0.0.0.0", 5060, "TCP");
Is there a way for me to identify which IP interface an incoming SIP message arrived on (in order to derive an appropriate Contact header address in the response message, amongst other uses)?
It's not a good idea to listen to 0.0.0.0, there are cases where the SIP stack will have to guess what address to use too and it may guess wrong. I think it's not possible to tell the address using the standard APIs, but you can almost always use private APIs from implementations. For example https://jsip.ci.cloudbees.com/job/jsip/javadoc/gov/nist/javax/sip/message/SIPMessage.html#getLocalAddress()
You can also guess by the Via headers etc. But again not a good idea.

In which case the getRemoteHost method returns an IP address instead of the hostname?

On a server of our private network we have an HttpServlet which is contacted by a PC of the same network.
We need to know the hostname of the client which contacts the server. To do this we call the
getRemoteHost method of the HttpServletRequest.
Some times this method returns the PC name of the client (wanted behavior) and some other the method returns the IP address. (same client, same server, same private network)
The API says:
java.lang.String getRemoteHost()
Returns the fully qualified name of the client or the last proxy that sent the request. If the engine cannot or chooses not to resolve the hostname (to improve performance), this method returns the dotted-string form of the IP address. For HTTP servlets, same as the value of the CGI variable REMOTE_HOST
Returns:
a String containing the fully qualified name of the client
I see that for HTTP servlet that value is the same of the CGI variable REMOTE_HOST. What does it mean? Is it up to the server to decide to resolve the address or not? Is there a way to force this behavior?
In Tomcat, for example, the connector has a setting "enableLookups" which is disabled by default for performance reasons. See http://tomcat.apache.org/tomcat-7.0-doc/config/http.html
Other containers may have different methods of doing the same thing.

RMI Server to Client call fails when Client machine has more than one IP Address

First off, I'd love to post some real code for this question, but I can't because it's far too many lines. That said, here's my situation:
Server Side
I have an RMI Server that waits for Clients to connect and "register" themselves, so that the Server can make function calls on Clients. Basically, the server has a published function that works like the following pseudo-code:
public class Server extends UnicastRemoteObject implements ServerInterface{
public Server(){ /* Server publishes itself here */ }
...
/** One of many methods visible to a remote Client */
public void registerClient(Client c) throws RemoteException{
//1. Make some remote calls on 'c' for book-keeping purposes
//2. Store reference to c to make calls on it later
}
}
Client Side
On Startup, the Client makes a call to Naming.lookup([url]) to get a stub to the Server that I'll call serverRef, then calls serverRef.registerClient(this). The problem happens the first line of the server's registerClient(Client c) method.
Problem
When the server makes its first remote method call to the Client inside the registerClient method, a RemoteException is thrown. While client and server machines are on the same subnet, the client's machine has a secondary IP address. So the IPs look something like this:
Server Machine IPs: 123.45.67.1
Client Machine IPs: 123.45.67.2, 192.168.67.2
The RemoteException that gets thrown during the Server's first remote call back to the client indicates that the Server is trying to connect to the Client's 192.168.67.2 address, which is what's causing the failure. The Server should be trying to connect to the 123.45.67.1 address. I know that disabling the network interface that belongs to the second IP address would fix the problem, but this isn't really an option for me.
Is there any way to "tell" server-side RMI which IP address to connect on when opening a connection to a new client-side object stub?
There are several possible solutions, including
write a custom client socket factory
specify addresses in java.rmi.server.hostname property
-Djava.rmi.server.hostname=ip_address
etc
Check out this link:
http://weblogs.java.net/blog/emcmanus/archive/2006/12/multihomed_comp.html
These links are also useful:
java rmi -Djava.rmi.server.hostname=localhost still opens a socket listening on 0.0.0.0
http://www.chipkillmar.net/2011/06/22/multihomed-hosts-and-java-rmi/4/java-rmi-djava-rmi-server-hostname-localhost-still-opens-a-socket-listening-on
*

Categories