1
votes

I have a two-node cluster running a custom UDP server. The cluster has a public IP address, and each node has its own private IP address in the same subnet.

The UDP server is bound to the wildcard address so it can receive datagrams from either public or private IP. The problem is that I have no control over IP choice for sending reply. It seems that it uses private IP by default for whatever reason.

Now, if a client just sends commands to the server and listen for replies on the same port, it isn't a problem. However, some clients use a connect() call instead, which limits them to receiving replies from the address the command was sent to in the first place. If they send a command to the public IP and receive the answer on another IP, they just ignore it. Notable example is the check_udp plugin for Nagios.

The server is written in Java using plain old java.net.DatagramSocket. I don't see any methods in the DatagramPacket class for getting the local IP address the packet was received on.

What I could do:

  1. Rewrite check_udp to use bind() instead of connect(). It's a pain, and nobody guarantees there won't be any similar clients in the future.
  2. Bind the server to the public IP only. Possible, but requires some additional cluster setup to only start the server after the IP has been brought up. It will both increase failover time and introduce otherwise unnecessary server restart. Right now, the server always runs on both nodes, ready to accept requests.
  3. Modify the server to reply from the same address the request was received. This is the best way, but I need to figure out the address in question to do it. And I'll need a way to send the reply from that address too - is there a way to do it without closing and reopening the socket?
  4. Modify the server to try to bind to the public IP from time to time. Possible, but troublesome. What to do with the clients already active on the socket?

Is there something I'm missing here? It doesn't seem like it should be a terribly hard task, but I just doesn't seem to find an easy solution.

1

1 Answers

0
votes

I would modify (or wrap into a transport message) the message that is being sent across the UDP socket to include who sent it (an identity).

This is the same way other network libraries (0MQ to name one specifically) handle the whole where did this message come from and where to respond issue.