Linux – Udp port binding in VMware Linux

bindingslinuxudpvirtual-machines

In my application, there're two physical computers, both in Windows environment. Computer 2 (with IP "192.168.2.2") has a VMware Linux virtual machine (with IP "192.168.80.129") installed on it. What I want to do is to send UDP socket from the virtual machine to computer 1 (with IP "192.168.2.1").

As required by my application, when the udp sent through virtual machine to computer 2, the ports should be specified.

Now my situation is that, when I create and configure udp sockets in Linux, I specify two ports LOCAL_PORT(9000) and REMOTE_PORT(9001).

When I open WireShark to monitor, in the Linux VM, the source port is LOCAL_PORT(9001), however, the destination port is "iua(9900)". Source IP is "192.168.80.129" and destination IP is "192.168.2.1", which is correct.

When I open Wireshark in Windows on either computer 1 or computer 2, Source IP shown is "192.168.2.2", while destination IP is "192.168.2.1". This seems understandable, because the sender is a virtual machine, thus Udp is actually sent by the host computer(computer 2). The destination port is correct as 9001, however, the source port seems to be arbitrary.

Does anyone know what I can do in the VM so that the source port can be the number (9900) as assigned instead of an arbitrary number? Thanks!

int sock1;
struct sockaddr_in slAddr, myAddr;
memset(&slAddr, 0, sizeof(slAddr));
memset(&myAddr, 0, sizeof(myAddr));
slAddr.sin_family = AF_INET;
slAddr.sin_port = htons(RM_PORT);//RM_PORT=9900
slAddr.sin_addr.s_addr = inet_addr(SL_IP);//SL_IP="192.168.2.1"
myAddr.sin_family = AF_INET;
myAddr.sin_port = htons(LC_PORT);//LC_PORT=9901
myAddr.sin_addr.s_addr = inet_addr(MY_IP);//MY_IP="192.168.80.129"
sock1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bind(sock1, (struct sockaddr *)&myAddr, sizeof(myAddr));
sendto(sock1, packeddata, 8, 0, (struct sockaddr*)&slAddr, sizeof(slAddr));

Best Answer

Your code seems OK (except for sometimes writing port 9901 and sometimes 9001).

Your problem is that your VMWare host is NATting all the outbound packets.

You need NAT to rewrite the source IP of your VM to correspond to the 192.168.2.* network. To do this for many source IPs (here you have two, your VM and your physical machine), NAT also needs to be able to rewrite the source port. It uses the source port to remember where the packet came from. You do not need that because you only had one application, but NAT does not know that.

(Actually, according to classic Cisco terminology, you are doing PAT and non-overloading NAT would solve your problem by requiring a 192.168.2.* IP dedicated to your VM, but I don't think anyone uses that any more . . .)

I do not think that VMWare can do NAT while keeping the source port. You therefore need to turn NAT off (making a layer 2 bridge between your physical LAN and your virtual machine's network adapter). That means that you will have to give your virtual computer an IP in the same 192.168.2.* as the physical servers (or else you will have to do routing, which would be a lot more complicated.)

What you have done (as per your comment) is to write a proxy, that binds to port 9901 on the host computer. It is your proxy that is translating the IP from 192.168.80.129 to 192.168.2.2 and back, and it is keeping the source port because you wrote it that way.

If that solution is good for you, in your case, then that's good!

Usually on the Internet programs and protocols are written not to care about the source port; the source port is just a number > 1023 that is to be used as destination port for the reply packet. The protocols that did otherwise (DNS and NTP come to mind) have evolved to permit non-fixed source ports.