Advertisement

Troubles with the NAT - solved

Started by May 14, 2006 12:43 PM
12 comments, last by MikeyO 18 years, 9 months ago
I've been scouring the internet for solutions for nat punch through, but most of the resources I've found have not been able to answer some of the questions I have.. I am using C#, and am trying to send a UDP packet over the internet (through a NAT) to a remote server which does not have a NAT. The server gets my packets, and tries to send replies, but the replies never reach my machine. The program works fine if I route the ports Im using to my local machine. I use Socket.SendTo() to send messages and ReceiveFrom() to receive them. ReceiveFrom gets an EndPoint, which I am using in my SendTo() instruction, but the EndPoint that is retrieved apparently does not contain the 'source port' of the packet, where it got sent out of the router from. As I understand it, I send a packet from local address 192.168.1.100 to a remote address (232.53.xxx.xxx) destination port: 9001, my router captures the packet, changes the source address of the packet to its outside address (lets say 66.150.xxx.xxx), and changes the source port from 9000 to some open port on the router (lets say 10), adds it to the routing table, and sends it to the remote server (232.54.xxx.xxx). When the remote server gets the packet, it checks who sent it, it sees 66.150.xxx.xxx as the address and destination port 9001. My question is: How do I send the packet from the server such that the client actually receives it when the router does? [Edited by - MikeyO on May 16, 2006 11:03:25 AM]
I don't think the problem is with your routers. A router will make sure the packets are sent to your machine on the return. I would suggest you put up a packet sniffer and see what is going on. Look to see what the real traffic is doing.

theTroll
Advertisement
I have actually been sniffing packets (with Ethereal), and they are not reaching my computer at all, the router just drops them.

I have a Linksys router (and they pretty much invented NAT).
Linksys did not invent NAT it was invented by Paul Francis (but he credits Van Jacobson for the concept), then it was adopted by Cisco all of this happened in the early 90s. Only after Cisco did it did others follow.

As for why your router is not doing it right, maybe you should try from someone elses system or try with a different router. I do not believe that it has anything to do with program.

theTroll
Linksys is a division of Cisco, and I said "pretty much".

It seems sort of like I am getting the Packet's destination port # rather than the source port.. but I am still unclear whether I should return it on the same port it came in on or on the port it was sent from.
Cisco didn't get Linksys until June 2, 2003. Most of Linksys code on it's routes is still Linksys code, I know of no Linksys Router that is running Cisco IOS. Linksys had nothing to do with NAT.

You return it on the virtual port that it was sent on. Do not try to do the routers job it will just mess things up.

theTroll
Advertisement
How do you send the reply from the server ?

Do you take the info about the source machine from the structure that RecvFrom() returns ? On the server RecvFrom() should say that the source has IP = 66.150.xxx.xxx and port = 10
So if you send the reply to that address and port, and if your NAT keeps the port open long enough (which it should), then the reply should arrive just fine.

Are you storing the port of the source machine in the actual packet data and then reading it on the server ?
When the server receives the packet, it stores all the data returned into a buffer, along with the EndPoint that is returned, it is essentially:

remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
bytesReceived = udpSocket.ReceiveFrom(buffer, SocketFlags.None, ref remoteEndPoint);
remoteIPEndPoint = (IPEndPoint)remoteEndPoint;
udpSocket.SendTo(data, remoteIPEndPoint);

(I simplified it a little bit..)
Quote:
I am using C#, and am trying to send a UDP packet over the internet (through a NAT) to a remote server which does not have a NAT. The server gets my packets, and tries to send replies, but the replies never reach my machine.


Then either your sever has a bug, or your NAT is broken, or your NAT is firewalling too tightly.

In Berkeley socket terms, when you call recvfrom() on the server, it returns to you the IP address and port that the "source" field of the outgoing packet was using. When you reply, you simply sendto() that same address, and the NAT will return the packet to the original sender.

In C#/.NET terms, when you call UdpClient.EndReceive(), it returns to you a ref endpoint which is the address that the server should send data back to.
enum Bool { True, False, FileNotFound };
I believe you are probably trying to open the connection fresh from the server. This is incorrect from what I understand of the NAT-dilemma. The typical "solution" to dealing with NATs is:

1) client opens socket to server
2) server holds on to socket (never closing it) and uses it to send info to client
3) happy interactions with NAT

here's what I gather you are doing:

1) client opens connection to server
2) server saves IP address of client
3) when server needs to send info, create a new socket
4) NAT sadness

implement the former architecture and you'll be fine.

[EDIT: re-read your post and you may already be doing the "correct" thing. but i'll keep this post here just in case. My guess is that you probably implemented the former incorrectly, or there's a trivial syntax error in your code. Why don't you post the relevant server-side logic code.]

-me

This topic is closed to new replies.

Advertisement