I want to check the connection to a remote machine using UDPClient. Heard that it will return an icmp packet if failure occurs. How we can catch it?
How it is possible to check for a remote machine?
UdpClient receivingUdpClient = new UdpClient();
receivingUdpClient.Connect(IPAddress.Parse("10.2.2.13"), 80);
Byte[] sendBytes = Encoding.ASCII.GetBytes("0");
Var b=receivingUdpClient.Send(sendBytes, sendBytes.Length);
With UDP, there is no definite way of knowing whether the packet reached its destination or not (compare with TCP, which sends ack packets to let the sender know its packet was received).
It is true that in some cases, ICMP packets are sent, but what if the packet was filtered out (or simply dropped) somewhere along the routing path? As far as I have seen, most home routers are pre-configured to drop all ICMP on external ports, for example.
Instead of relying on ICMP packets, you could investigate if the protocol you are using has a PING packet (or some equivalent no-op packet, or if you created the protocol -- add it!) and use that with a timeout/retry logic to verify if the service is available.
Related
I am struggling with a bit of network magic and hoped someone would be able to explain me what is happening.
I am trying to reuse udp ports. So if I have multible programs listening on the same udp port i want both of the applications to receive the data send by a different device.
Using the following code I'am able to achive just that:
IPEndPoint localEndoint = new IPEndPoint(IPAddress.Any, 67); //the local endpoint used to listen to port 67
//Create a new UDP Client and bind it to port 67
DhcpSniffer = new UdpClient();
DhcpSniffer.ExclusiveAddressUse = false; //Allow multible clients to connect to the same socket
DhcpSniffer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // Connect even if socket/port is in use
DhcpSniffer.Client.Bind(localEndoint);
DhcpSniffer.Client.ReceiveTimeout = Timeout;
//receive on port 67
dhcpPacket = DhcpSniffer.Receive(ref localEndoint);
Both of my programs can listen to DHCP messages in the network and don't block each other.
Now i want to do the same thing with port 15120 where a RTP video stream is streamed to. However this does not work. I am using the same code but with no success only one application at a time can receive the stream, the other will run in a timeout.
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, port);
//Create a new UDP Client and bind it to port 15120
udpReceiver = new UdpClient();
udpReceiver.ExclusiveAddressUse = false; //this is an attempt to receive the stream on mutlible instances...this works for DHCP but not for RTP for some reason....
udpReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // Connect even if socket/port is in use
udpReceiver.Client.ReceiveTimeout = timeout; //set the sockete timeout
udpReceiver.Client.Bind(RemoteIpEndPoint); //bind to the port from any IP
//receive packets on port 15120
Byte[] receiveBytes = udpReceiver.Receive(ref RemoteIpEndPoint);
I hope somebody is able to shine a light on my confusion
Update:
I found out it works with DHCP because it is send to the broadcast IP (255.255.255.255). Now I need to find out how i can change the Socket behaviour to treat my RTP stream as if it was broadcasted so i can see it in two application at the same time. (Yes I could configure my stream-source to broadcast, but this is not the goal of this).
The goal is to reconfigure the Socket to behave as explained. Not to save the stream on a harddrive or redirect it using the local host.
First, its not possible to have multiple programs listen on the same port (As far as I know it's a big security conflict)
What you can do tough, is use a NetworkManager that listen on you port (Lets call it port 8080) who will then redirect the information to you apps ports (App1 could use port 8081 and App2 use port 8082). Either you write your own, using Flask to listen on 8080 and then rerouting the package to localhost:8081 and localhost:8082 could be a simple and fast solution.
Doing this would help you secure the network and you can redirect to as many ports as you need, pretty much like a docker swarm would balance the incoming network to its cluster.
It is not possible with multible programs to access the data from a unicast UDP package, it works only with multicast, there is no "easy" way around this by reconfiguring the UdpClient
I have an embedded device which is connected to my PC directly through ethernet.
The device is streaming audio to pc through UDP and it sends 4096 bytes UDP packet.
Given that, the MTU for ethernet is 1500 bytes the packet will be fragmented.
At PC I have a c# program that tries to receive packets and decode it. UDP receiver can receive packets very well when they have under 1500 bytes payload but it cannot receive fragmented packets.
I've monitored incoming packet by Wireshark and I can see that there is not any failure in packets nor discarded.
I don't know the problem is in my code or C# socket is Unable to receive these kinds of packets. in both cases what would be the solution?
1st Attempt: (usinfg Socket)
Socket sokcet = new Socket(SocketType.Dgram, ProtocolType.Udp);
IPEndPoint ep = new IPEndPoint(IPAddress.Any,5222);
sokcet.Bind(ep);
int counter = 0;
while (true)
{
if(sokcet.Available > 0){
byte[] bytes = new byte[sokcet.Available];
int receivedBytes = sokcet.Receive(bytes);
string print = String.Format("Packet Received : {0},{1}", receivedBytes, counter);
Console.WriteLine(print);
}
}
2nd Attempt: (using UDPClient)
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
UdpClient listener = new UdpClient(listenPort,AddressFamily.InterNetwork);
while (!done)
{
byte[] bytes = listener.Receive(ref groupEP);
}
None of them are working for packets larger than 1500 bytes.
Update 1:
I tested the scenario in Loopback(127.0.0.1) and I can receive 4k UDP message very well.
Update 2:
#Evk I tested the scenario from another pc connected to mine over a Switch and also over a router. now I am sure that C# does not have any problem. not sure about OS (win7 ultimate 64x).
My embedded device uses LWIP and there are some reports of a similar situation that happened when users used LWIP for sending large UDP packets. but I'm not sure this is my case.
I even checked UDP packet's Source and Destination address, Checksum and ... and I can't figure out why OS dropping my packets. is there any tools that can analyze network packet to tell if they have any problem?
I would make certain that the messages are in fact, being delivered to your processes' UDP receive queue. You may see it wireshark, but that is not a guarantee that it did not later get dropped or filtered at the UDP protocol level.
I would open a command window (CMD) and run this in a loop as you send your traffic and run your decoding application (Also, stop other applications that may use UDP as they may interfere with these figures):
> netstat -s -p udp
UDP Statistics for IPv4
Datagrams Received = 48775 <======= [This *should* increase]
No Ports = 83823
Receive Errors = 16367 <====== [ WATCH THIS]
Datagrams Sent = 130194
If you notice receive errors going up while your application sits there and does not seem to processing...then there is chance that the > 1500 byte packets are getting dropped by UDP for some reason. You may need to either increase your application's socket receive buffers or look for windows UDP network configuration options that would cause > MTU packets to be dropped on receive..
I've to detect if a remote host is UP, based on it's a service(IP+Port) running. I can't use a ping because we need to make it works even the ICMP port is blocked.
Sometime the service is using TCP, sometimes UDP(but when I've to check, I know if the server has to run on UDP or TCP, it's depending of it's type). I've no issue checking the TCP port(based on https://stackoverflow.com/a/7605428/397830 ). But since UDP is not a connection oriented protocol, how could I be sure that the remote host is listening on UDP on this port?
Thank you!
Excerpt from nmap documentation:
UDP scan works by sending a UDP packet to every targeted port. For some common ports such as 53 and 161, a protocol-specific payload is sent, but for most ports the packet is empty. The --data-length option can be used to send a fixed-length random payload to every port or (if you specify a value of 0) to disable payloads. If an ICMP port unreachable error (type 3, code 3) is returned, the port is closed. Other ICMP unreachable errors (type 3, codes 1, 2, 9, 10, or 13) mark the port as filtered. Occasionally, a service will respond with a UDP packet, proving that it is open. If no response is received after retransmissions, the port is classified as open|filtered. This means that the port could be open, or perhaps packet filters are blocking the communication. Version detection (-sV) can be used to help differentiate the truly open ports from the filtered ones.
You can read the full article here:
NMAP port scanning
For UDP you can integrate a "hello packet" into your protocol, once that is received on the Serverside, the server sends back another "hello packet", once the client receives that packet, it knows that the server is Up and running.
UDP is mostly fire and forget. If you do not get a port unreachable response, then the port may be open... try this python script:
import socket
IP = "172.16.0.1"
PORT = 1900
MESSAGE = "Hello"
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(MESSAGE, (IP, PORT))
While executing this, run $(tcpdump icmp and host 172.17.0.1) as root
If the port is closed, you should see something like this
IP 172.16.0.1 > xxx.local: ICMP 172.16.0.1 udp port 1900 unreachable, length 49
The absense of this indicates the port may be open
I'm trying to develop a transparent proxy which forwards unsecured http traffic from the clients as secured https traffic to the server, and back again. To better illustrate my point, take a look at the following image.
Let's suppose that for various reasons the clients will be using HTTP only, they can't use port 443 for HTTPS. Since some servers don't accept traffic from port 80, my proxy needs to reroute them to port 443. This is a possible scenario:
Receive data from client which are headed to port 80 towards www.google.com
Initialize connection with https://www.google.com to port 443 (Do the handshake and so on)
Encrypt data from client and send them to https://www.google.com to port 443.
Receive response from https://www.google.com, decrypt them and send them back to the client to port 80.
Since this is a transparent proxy, the clients (in my case lots of them) shouldn't need any extra configuration. The network is already configured so that their traffic go through my node. Currently my node simply reroutes the data and blocks some if they contain viruses. This is done using WinPcap to get access to low networking layers but I'm willing to change my approach if it's too hard to be done using raw packets (mainly concerned about the handshake).
What I've tried:
Note: www.google.com could be any site on the web. It's merely used as an example.
Iridium's suggestion. This doesn't work for the reason that TcpListener only accepts a new connection if another application uses a TcpClient to connect to it. Since this is a transparent proxy, it doesn't work.
Using HttpListener instead. However, it seems that this doesn't work since it only accepts connections to my own IP (not www.google.com).
Using HttpListener as before but this time I'm forwarding packets to my own IP so that HttpListener accepts the connection. For some reason, this doesn't seem to work (Inspected through wireshark and TCP SYN packets keep re-sending, not sure why or how to fix it).
Using SslStream to connect to https://www.google.com, then getting the contents from the raw packets received from the clients and writing them to the stream. This doesn't work since SslStream handles TCP packets (Such as ACK or SYN) on its own. The stream expects only Http requests. Another reason why it doesn't work is because I can't read the contents of TCP packets from the stream, only the contents of HTTP responses (So the client is sat there waiting for an ACK).
Forwarding TCP packets from the client as they are to port 443 and from the server to port 80 (Since only HTTP requests and responses are encrypted with SSL, it wouldn't make a difference) and using the HttpRequest class to make all the http requests and responses (Since the class handles the handshake on its own). This doesn't work because the ACKs are wrong on both sides.
What would be the best way to go into developing such a proxy?
Edit: Is there ANY way that TcpListener or HttpListener can act as a transparent proxy? (Without configuration on the clients' computers). When exactly does HttpListener recognize that a client is trying to connect?
I don't really understand why you need to read the encrypted data from the SslStream. If I'm reading your description correctly, you should simply need to:
Wait for a client connection
When a client connects, connect to the server
Wrap the server connection's NetworkStream in an SslStream and AuthenticateAsClient
Once authenticated, in parallel:
Read data from the client and write it to the SslStream
Read data from the SslStream and write it to the client
I don't see anywhere in this process that you'd need to see the encrypted data from the SslStream.
The following is a very basic sample (though completely untested):
static void Main(string[] args)
{
var listener = new TcpListener(IPAddress.Any, 11180);
var clientConnection = listener.AcceptTcpClient();
// When we get here, the client has connected, initiate the server connection
var serverConnection = new TcpClient("your.server.name", 443);
var serverStream = serverConnection.GetStream();
var secureStream = new SslStream(serverStream);
secureStream.AuthenticateAsClient("your.server.name");
ConnectStreams(clientConnection.GetStream(), secureStream);
}
private static void ConnectStreams(Stream streamA, Stream streamB)
{
ForwardStream(streamA, streamB, new byte[1024]);
ForwardStream(streamB, streamA, new byte[1024]);
}
private static void ForwardStream(Stream source, Stream destination, byte[] buffer)
{
source.BeginRead(buffer, 0, buffer.Length, r => Forward(source, destination, r, buffer), null);
}
private static void Forward(Stream source, Stream destination, IAsyncResult asyncResult, byte[] buffer)
{
var bytesRead = source.EndRead(asyncResult);
if (bytesRead == 0)
{
destination.Close();
return;
}
destination.Write(buffer, 0, bytesRead);
ForwardStream(source, destination, buffer);
}
I've got a strange problem. I have a client sending packets to my server, but my servers UDP socket never receives them. Same thing happens the other way around, if I send and he tries to receive.
Check this image, captured from wireshark:
http://img263.imageshack.us/img263/2636/bokus.png
I hav bound my UDP socket to EndPoint 192.168.2.3, which is the internal IP of the server, and port 9998.
The client sends data to my IP, which should then be forwarded to the local server machine..
As you can see wireshark clearly detects incomming packets for 192.168.2.3 with destination port 9998 but nothing gets delivered!
(...why does it say distinct32 btw in destination port?)
Something else to watch for is make sure any firewall you might running has a rule setup to allow communications on your port 9998.
If I had to guess (would need to see your recieving C# code to know), It looks like you might be trying to receive UDP packets but using TCP protocol on the client side. (Or i might just be misunderstanding some of the text of your screenshot.)
Theres no need to 'listen' for a connection when using UDP. UDP packets don't have a connect/disconnect protocol. Nor do they guarantee that packets are received in the same order they're sent.
try using something along these lines in your C# client and see if you get data.
var udpClient = new System.Net.Sockets.UdpClient(9998);
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);