We're using Fleck for our Websockets.
When we test our network program locally it all works fine. The process of a client connecting is:
Establish TCP connection
Send/receive infrequent TCP messages
Start sending/receiving UDP stream to server
The problem is on the live server which is far away geographically, clients can receive and send TCP messages, and they can send UDP messages, but they do not receive UDP messages.
We've investigated it as far as we can, and have found that the RemoteEndPoint property of the TCP connection on the server has the wrong IP address. It appears to be an IP address from our ISP. We use this IP address to attempt to send UDP messages back to the client. As it has the wrong IP, the client never receives these UDP messages.
The actual source IP address of the client must be known somewhere, as the TCP messages make it back OK. I've gone through the Fleck source and have printed out the RemoteEndPoint of the underlying System.Net.Socket but it keeps giving the wrong IP address.
Does anyone know what is going wrong and how we can expose the actual IP addresses of the clients?
The most likely reason is that your client does not have a public IP address, but a private address behind Network Address Translation (a very common setup). A common private addresses are of the form 10.X.X.X or 192.168.X.X.
NAT device replaces private address in a packet from your client with its IP address, which is public. For the outside world it seems that the traffic originates from the NAT device. The main advantage of NAT is that it allows many clients to use a single public IP address (IP addresses are sparse). But NAT introduces a problem: an incoming packet needs to be routed to a correct client, but it does not have a client IP address. Some other strategy needs to be used to recognize to which client a packet should be routed and such routing is not always possible.
For example, the most well known limitation of NAT is that you can't simply start a listening TCP server behind a NAT and then connect to it from the outside world. The reason is that NAT device has no idea that your server listens on a given port and thus, it has no way to known that TCP SYN packets from the outside world need to be passed to your client. A workaround for this is to explicitly configure the NAT device to route SYN packets directed to a given port to a specific client (port forwarding).
When a client behind a NAT initiates a TCP connection, a NAT device remembers state of the connection (client address, client port, remote address, remote port). Because of this, when a response arrives, the device knows to which client the response should be passed. When the connection is closed, the device discards state information. This is why your client can communicate over TCP.
But UDP is more difficult to handle because it is connectionless and stateless. When the device sees a UDP packet it does now known if a reply is expected and when, so not all NAT devices handle UDP traffic. Although there is a technique that allows to do it.
To summarize: the problem you are seeing is not C# specific. Setting IP address in packets from your server to the client IP address won't help, because it is most likely a private address that is not routable. To solve the problem you need to use a NAT device that can pass UDP traffic in both directions. But if you are developing a generic client to be used in many setups, you may want to reconsider if UDP is the best option. TCP connection forwarding is a basic feature that all NAT devices support, but some devices may not support UDP.
Related
I am trying to build a client server socket library that will abstract the complexities of sending and receiving data. I was wondering if you have a UDP server setup to have a multicast group. Can it still send and receive unicast requests to specific clients if needed? Or do you have to have to open two sockets to handle either type?
You can do multicast and unicast at the same time using the same socket.
You can send and receive any multicast and/or unicast UDP packets interleaved in anyway, so even if you want to talk to many different peers, some multicast, some unicast, you can use a single socket for this, and it fact it is often useful to do so in terms of complexity of the application.
Some things to consider:
On Linux you will want to bind() your UDP socket to your desired port and to the IP address 0.0.0.0 (INADDR_ANY). This will enable you to receive UDP packets targeted at any multicast address and any unicast address. Specifying a concrete IP address for bind() with UDP has a filtering effect and will only let UDP packets in targeted at that specific UDP address, which is rarely useful in practice, as all multicast servers usually also want to allow the same traffic to arrive as unicast, transparently.
On Windows binding to a fixed nonzero IP address has different semantics: It binds the UDP socket to a specific interface (the one with the given IP address). Sending and receiving UDP traffic for multicast/unicast should work on Windows even without binding to 0.0.0.0.
Here is my situation :
I have a WCF with TCP Binding Service behind NAT and I am not able
to reach it.
I can reach my service using BasicHttpBinding and Raw TCP Sockets.
At server side port forwarding is done.
What may cause this ?
My Network Topology: Picture Link
I'm not experienced with WCF and nettcpbinding but this could help.
Theoretically it is not possible because your service has a local IP address, corresponding to the LAN where it is attached, and not a public IP address. So it could not be reached from the Internet, outside the NAT. However, almost all NAT devices, maybe your router/Access Point, have a feature for "Port Forwarding". This feature allows you to define that all packets addressed to a specific port are forwarded to a specific machine within you LAN, with a private IP address.
This could be a solution for you if you can overcome two hinders:
1-I don't know how the node in the Internet will send a message to the callback server. If it uses the IP address from which it received the request, there is not problem. If it receives a callback-IP address, then you have to figure out how to find out the public IP address of you NAT (maybe router/Access Point) and send out that IP address.
2-Your service behind a NAT needs to open a client port, or ephemeral port, to communicate with the service outside the NAT. If the second sends the message to the client port from which it received the message, you have to find a way to determine the client port you want to open (must be the same you configured in port forwarding). Will it listen in port 808 by default?
I hope this helps.
Check with URI "net.tcp://0.0.0.0:8000", this will ensure that the service will accept connection from any inbound IP address. At server side, the IP address mentioned in the URI & address from which the connection is accepted differs so the server is dropping the connection.
I have a udp socket server written in C/C++ and a udp client written in C#. I can send packets back and forth, where the server simply echo's back the clients broadcasted message. However, when I send a udp packet to tell the server to reconfigure its network settings (IP, subnet, gateway, DNS) and rebind the adapter to refresh the settings, the client cannot receive the servers echo back anymore.
From what I have read so far, now that the server has different settings it could very well be on a different subnet on the same LAN. My question is how to send the packet back to the broadcasting client? I use the sendto() WIN32 api function, which sends the message to the IP Address and port it got from the broadcasted message. Is there another function that could send the packet back to the specific MAC of the client, therefore skipping the different subnet part? Or is there a different way to send the UDP packet across a local subnet?
I'm trying to make p2p connection using UDP hole punching method, but I always get ICMP packet with Destination unreachable status.
At first, there is created an UDP connection to server:
send = new IPEndPoint(IPAddress.Any, 0);
server = new UdpClient(send);
server.AllowNatTraversal(true);
without any direct connection (no ip, no port, just endpoint on random port).
I send some packets to server with direct server.send([..],[..],serverip,serverport) on server's ip and port and obtain information (remote IP, port used to connect to server) about another peer
Now I'm trying to make hole punch with sending simple UDP packets on peer's IP:PORT using server connection (but again with direct server.send([..], [..], peerip, peerport)). I know that the first packet is always dropped, so I'm sending it 50 in 100ms intervals, while remote peer does same thing.
If I understand UDP hole punching method, sending packet from first peer (A) opens NAT record in A's NAT and it is dropped by B's NAT because of no record in NAT. So when B send packet to A, there is record in A's NAT created with first packet (for B) and packet should be received by B. The NAT record in B's NAT is created. A should send another packet to B successfully.
P.S.: http://nattest.net.in.tum.de/test.php test was successful
http://nattest.net.in.tum.de/individualResult.php?hash=a5f229d156d4f5409a305c37729d9510
http://nattest.net.in.tum.de/individualResult.php?hash=3fd60e888721908a9480cd12836b97af - using VPN on second VM
P.P.S.: I'm using virtualized Windows in Virtual Box.
You should get a network capture trace from both endpoints and study the results. Pay close attention to port numbers on all sides, as the port number may be getting re-mapped as well as the IP address.
It is difficult to infer what are you asking. If you are getting an ICMP error, it's possible that the NAT or endpoint wasn't ready to receive your UDP packet. Repeating the hole punching test a few more times might clear this issue up.
I suspect the port number you think the remote peer is listening on is getting mapped differently from what you think it is. Such will be the case if you are on a symmetric NAT, which is very possible with VPN on VM.
I am attempting to create a server and client that utilizes both TCP and UDP. The server works very well in a LAN setting but the UDP messages are not being received when transmitted over a WAN. I believe it is because the UDP socket used to send the data is not remaining in the NAT tables long enough to return any information. Is there a way to either make the UDP port stay open in the router (without port forwarding) or use the same port for UDP as the already connected TCP connection? Thanks in advance.
If you're not getting any traffic it is probably simply blocked by the firewall. In this case it is not about forwarding, it is about opening the port.
Most (if not all) NAT/Firewall devices will allow UDP traffic in both directions once a hole is punched through the NAT. That is, if my laptop here, sitting behind a NAT/firewall, sends a UDP packet out to the Internet my NAT/firewall will allow return UDP traffic to the originating port number through. I work a lot with UDP and my experience is that this is the rule and very few exceptions.
Keep in mind though UDP packets are not guaranteed to be delivered.
Is your client behind a NAT? Do any packets the client send get to the server? Is the problem in the server to client direction?
If you use the same port number for UDP and TCP this will not change the situation. You can't piggyback on a TCP connection because it is a different protocol.
Network Address Translation (NAT) Behavioral Requirements for Unicast UDP
http://en.wikipedia.org/wiki/UDP_hole_punching