How do you get raw TCP packet in C#? - c#

I want to received raw TCP packet and then send it back with same workload.
It should look something like this:
void OnPacketReceived(TcpPacket p)
{
byte [] body = p.GetBody();
}
NOTE : I need the TCP packet and not the Ethernet frame.

If you implement the socket as a raw socket, you have access to the whole packet (and in fact must handle everything about the packet yourself).
Use SocketType.Raw and ProtocolType.Raw when creating the socket.
Just be aware that you're going to have to handle the details of TCP if you implement your socket this way.
For reference, here is the MSDN documentation about the Socket class:
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx

You can use the pcapDotNet library.
https://pcapdotnet.codeplex.com/

you need to use Packet sniffer where you can put filters of your choice and on the basis of that can respond also.
.Net wrapper around WinPcap can prove to be helpful for you.

Related

Communicating with a classic TCP socket

I'm writing my first application with NetMQ (ZeroMQ implementation for .NET).
I also need to listen to information sent from a client using a traditional TCP socket (a.k.a a non-0MQ socket).
I've seen references to the availability of this socket type in the official ZeroMQ documentation here, (look for ZMQ_STREAM), but there's very few details on how to use it (and that doesn't help much either, the .NET API is quite a bit different from the C++ API).
The offical NetMQ documentation also makes no mention of the Streaming socket type.
Finally I had a look over to the Test suite for NetMQ on Github, and found a partial answer to my question in the method RawSocket.
The following snippet works:
using (NetMQContext context = NetMQContext.Create())
{
using (var routerSocket = context.CreateRouterSocket())
{
routerSocket.Options.RouterRawSocket = true;
routerSocket.Bind("tcp://127.0.0.1:5599");
byte[] id = routerSocket.Receive();
byte[] message = routerSocket.Receive();
Console.WriteLine(Encoding.ASCII.GetString(id));
Console.WriteLine(Encoding.ASCII.GetString(message));
}
}
When using standard TCP/IP test-tools, the byte[] message is printed out nicely, e.g. like this:
Hello World!
but the byte[] id is printed out like this:
???♥
In other words, I have no clue what's up with the id part. Why is routerSocket.Receive called twice? What is contained within the id? Is this something ZeroMQ/NetMQ specific, or is something TCP/IP specific information being extracted here?
Thanks to #Mangist for pointing this out.
The answer is in the RouterSocket documentation:
An identity, sometimes called an address, is just a binary string
with no meaning except "this is a unique handle to the connection".
Then, when you send a message via a ROUTER socket, you first send an
identity frame.
When receiving messages a ZMQ_ROUTER socket shall prepend a message
part containing the identity of the originating peer to the message
before passing it to the application. Messages received are
fair-queued from among all connected peers. When sending messages a
ZMQ_ROUTER socket shall remove the first part of the message and use
it to determine the identity of the peer the message shall be routed
to.
Identities are a difficult concept to understand, but it's essential
if you want to become a ZeroMQ expert. The ROUTER socket invents a
random identity for each connection with which it works. If there are
three REQ sockets connected to a ROUTER socket, it will invent three
random identities, one for each REQ socket.
This image illustrates the core concept of the ID frames:

UDP and port randomisation

I'm currently programming a UDP application which allows clients to login. After that, their endpoint gets stored in a list.
private void socket_Callback(IAsyncResult result_)
{
EndPoint remote = new IPEndPoint(IPAddress.Any, 0);
socket.EndReceiveFrom(result_, ref remote);
if (!listOfEndPoints.Contains(remote))
{
// registration process
// add it to list
listOfEndPoints.Add(remote)
}
else
{
// process packet
}
}
However, sometimes a client's NAT will assign every packet a different external end point. If the registration packet's source end point is 12.34.56.78:1000, that end point gets added to the list. If the same client then however sends another packet, the NAT will assign it a different port, so its source end point will be 12.34.56.78:1001.
This results in the server assuming the client is not registered and try to process the packet as a registration one. Needless to say this won't work.
A way of fixing this would be to send an ID (which could however be faked easily, if it's not super-cryptic) to the client. However, the client would have to add it to each packet it sends to the server.
So it wouldn't be very effective to do it like that.
Is there any other way of telling that the packet has come from the same client as the registration packet?
You should definitely not use the source IP address and port of a UDP packet to associate it with a logical connection. You should include the ID of the connection in each packet and update the IP and port you respond to if you receive a new IP and port for the same logical connection. If connection hi-jacking is an issue, you may need to implement some form of security, such as a secure checksum in the datagram.
TCP handles associating packets with connections for you. With UDP, you must associate datagrams with logical sessions yourself. I don't know why you think it "wouldn't be very effective to do it like that".
One of the tradeoffs of UDP is that if you need anything TCP provides, you have to code it yourself.
By the way, I've never seen ports shift in this way. Are you sure the client code isn't broken, perhaps opening a new socket for each datagram it sends.

Send Raw IP packet in C#, everything above the ethernet layer

I don't want to modify the ethernet portions of the frame, but I need to modify the IP packet and the data portion of the frame.
I try sending a raw frame and it still puts in the IP information. I basically need to send a frame without defining the endpoint except in the bits I'm sending.
Here's what I got:
Socket s = new Socket(AddressFamily.Unspecified, SocketType.Raw, ProtocolType.Raw);
EndPoint ep = new IPEndPoint(IPAddress.Parse("205.188.100.58"),80);
s.SendTo(GetBytes(""),ep); //im sending nothing, so i expect the frame to just have ethernet stuff
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, false);
My question:
Using SendTo adds the IP portion of the frame, I don't want that as I want to spoof the source IP. Using "Send" will crash because it says I need to specify an endpoint. Any suggestions on what to do? I just want to send a packet and define the IP section and data section myself.
Note: No I'm not making a DOS attack, I need this for a legitimate use!
I know how to define the IP portion, its just a matter of actually sending the data without a generated IP portion.
Your question is very well answered here: How send raw ethernet packet with C#?
Using Pcap.Net sort of a library, you can easily modify individual data packets in any way you want (as it uses the underlaying WinPcap implementation which is very powerful).
You can also completely skip the IP layer and send to MAC addresses as in: http://www.codeproject.com/KB/IP/sendrawpacket.aspx where I used a similar approach to communicate with a micro-controller (Atmel ATmega) over Ethernet which provides almost realtime communications.
"Using Pcap.Net sort of a library, you can easily modify individual data packets in any way you want (as it uses the underlaying WinPcap implementation which is very powerful)."
Wrong! WinPcap cant do filtering/packet dropping/ create packet. By other words, its just lets you monitor the packet in an async fashion...
Raw packet /Promiscuous mode/ Driver filter / packet routing is another talk.

Getting started with socket programming in C# - Best practices

I have seen many resources here on SO about Sockets. I believe none of them covered the details which I wanted to know. In my application, server does all the processing and send periodic updates to the clients.
Intention of this post is to cover all the basic ideas required when developing a socket application and discuss the best practices. Here are the basic things that you will see with almost all socket based applications.
1 - Binding and listening on a socket
I am using the following code. It works well on my machine. Do I need to take care about something else when I deploy this on a real server?
IPHostEntry localHost = Dns.GetHostEntry(Dns.GetHostName());
IPEndPoint endPoint = new IPEndPoint(localHost.AddressList[0], 4444);
serverSocket = new Socket(endPoint.AddressFamily, SocketType.Stream,
ProtocolType.Tcp);
serverSocket.Bind(endPoint);
serverSocket.Listen(10);
2 - Receiving data
I have used a 255 sized byte array. So when I am receiving data which is more than 255 bytes, I need to call the receive method until I get the full data, right? Once I got the full data, I need to append all the bytes received so far to get the full message. Is that correct? Or is there a better approach?
3 - Sending data and specifying the data length
Since there is no way in TCP to find the length of the message to receive, I am planning to add the length to the message. This will be the first byte of the packet. So client systems knows how much data is available to read.
Any other better approach?
4 - Closing the client
When client is closed, it will send a message to server indicating the close. Server will remove the client details from it's client list. Following is the code used at client side to disconnect the socket (messaging part not shown).
client.Shutdown(SocketShutdown.Both);
client.Close();
Any suggestions or problems?
5 - Closing the server
Server sends message to all clients indicating the shutdown. Each client will disconnect the socket when it receives this message. Clients will send the close message to server and close. Once server receives close message from all the clients, it disconnects the socket and stop listening. Call Dispose on each client sockets to release the resources. Is that the correct approach?
6 - Unknown client disconnections
Sometimes, a client may disconnect without informing the server. My plan to handle this is: When server sends messages to all clients, check the socket status. If it is not connected, remove that client from the client list and close the socket for that client.
Any help would be great!
Since this is 'getting started' my answer will stick with a simple implementation rather than a highly scalable one. It's best to first feel comfortable with the simple approach before making things more complicated.
1 - Binding and listening
Your code seems fine to me, personally I use:
serverSocket.Bind(new IPEndPoint(IPAddress.Any, 4444));
Rather than going the DNS route, but I don't think there is a real problem either way.
1.5 - Accepting client connections
Just mentioning this for completeness' sake... I am assuming you are doing this otherwise you wouldn't get to step 2.
2 - Receiving data
I would make the buffer a little longer than 255 bytes, unless you can expect all your server messages to be at most 255 bytes. I think you'd want a buffer that is likely to be larger than the TCP packet size so you can avoid doing multiple reads to receive a single block of data.
I'd say picking 1500 bytes should be fine, or maybe even 2048 for a nice round number.
Alternately, maybe you can avoid using a byte[] to store data fragments, and instead wrap your server-side client socket in a NetworkStream, wrapped in a BinaryReader, so that you can read the components of your message direclty from the socket without worrying about buffer sizes.
3 - Sending data and specifying data length
Your approach will work just fine, but it does obviously require that it is easy to calculate the length of the packet before you start sending it.
Alternately, if your message format (order of its components) is designed in a fashion so that at any time the client will be able to determine if there should be more data following (for example, code 0x01 means next will be an int and a string, code 0x02 means next will be 16 bytes, etc, etc). Combined with the NetworkStream approach on the client side, this may be a very effective approach.
To be on the safe side you may want to add validation of the components being received to make sure you only process sane values. For example, if you receive an indication for a string of length 1TB you may have had a packet corruption somewhere, and it may be safer to close the connection and force the client to re-connect and 'start over'. This approach gives you a very good catch-all behaviour in case of unexpected failures.
4/5 - Closing the client and the server
Personally I would opt for just Close without further messages; when a connection is closed you will get an exception on any blocking read/write at the other end of the connection which you will have to cater for.
Since you have to cater for 'unknown disconnections' anyway to get a robust solution, making disconnecting any more complicated is generally pointless.
6 - Unknown disconnections
I would not trust even the socket status... it is possible for a connection to die somewhere along the path between client / server without either the client or the server noticing.
The only guaranteed way to tell a connection that has died unexpectedly is when you next try to send something along the connection. At that point you will always get an exception indicating failure if anything has gone wrong with the connection.
As a result, the only fool-proof way to detect all unexpected connections is to implement a 'ping' mechanism, where ideally the client and the server will periodically send a message to the other end that only results in a response message indicating that the 'ping' was received.
To optimise out needless pings, you may want to have a 'time-out' mechanism that only sends a ping when no other traffic has been received from the other end for a set amount of time (for example, if the last message from the server is more than x seconds old, the client sends a ping to make sure the connection has not died without notification).
More advanced
If you want high scalability you will have to look into asynchronous methods for all the socket operations (Accept / Send / Receive). These are the 'Begin/End' variants, but they are a lot more complicated to use.
I recommend against trying this until you have the simple version up and working.
Also note that if you are not planning to scale further than a few dozen clients this is not actually going to be a problem regardless. Async techniques are really only necessary if you intend to scale into the thousands or hundreds of thousands of connected clients while not having your server die outright.
I probably have forgotten a whole bunch of other important suggestions, but this should be enough to get you a fairly robust and reliable implementation to start with
1 - Binding and listening on a socket
Looks fine to me. Your code will bind the socket only to one IP address though. If you simply want to listen on any IP address/network interface, use IPAddress.Any:
serverSocket.Bind(new IPEndPoint(IPAddress.Any, 4444));
To be future proof, you may want to support IPv6. To listen on any IPv6 address, use IPAddress.IPv6Any in place of IPAddress.Any.
Note that you cannot listen on any IPv4 and any IPv6 address at the same time, except if you use a Dual-Stack Socket. This will require you to unset the IPV6_V6ONLY socket option:
serverSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, 0);
To enable Teredo with your socket, you need to set the PROTECTION_LEVEL_UNRESTRICTED socket option:
serverSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)23, 10);
2 - Receiving data
I'd recommend using a NetworkStream which wraps the socket in a Stream instead of reading the chunks manually.
Reading a fixed number of bytes is a bit awkward though:
using (var stream = new NetworkStream(serverSocket)) {
var buffer = new byte[MaxMessageLength];
while (true) {
int type = stream.ReadByte();
if (type == BYE) break;
int length = stream.ReadByte();
int offset = 0;
do
offset += stream.Read(buffer, offset, length - offset);
while (offset < length);
ProcessMessage(type, buffer, 0, length);
}
}
Where NetworkStream really shines is that you can use it like any other Stream. If security is important, simply wrap the NetworkStream in a SslStream to authenticate the server and (optionally) the clients with X.509 certificates. Compression works the same way.
var sslStream = new SslStream(stream, false);
sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
// receive/send data SSL secured
3 - Sending data and specifying the data length
Your approach should work, although you probably may not want to go down the road to reinventing the wheel and design a new protocol for this. Have a look at BEEP or maybe even something simple like protobuf.
Depending on your goals, it might be worth thinking about choosing an abstraction above sockets like WCF or some other RPC mechanism.
4/5/6 - Closing & Unknown disconnections
What jerryjvl said :-) The only reliable detection mechanism are pings or sending keep-alives when the connection is idle.
While you have to deal with unknown disconnections in any case, I'd personally keep some protocol element in to close a connection in mutual agreement instead of just closing it without warning.
Consider using asynchronous sockets. You can find more information on the subject in
Using an Asynchronous Server Socket
Using an Asynchronous Client Socket

C#: How to deal with out-of-order TCP packets?

Can please someone one explain how to deal with out-of-order packets. I'm using raw socket to capture packets, and parse them as they come, but some of them come in wrong order, for example:
Id...........Flags
16390 : (PSH, ACK)
16535 : (PSH, ACK)
16638 : (ACK)
16640 : (PSH, ACK)
16639 : (ACK)
16695 : (PSH, ACK)
Packets with IDs: 16390, 16535, 16695 are separate packets and can be processed freely
Packets with IDs: 16638, 16640, 16639 are a sequence of packets and should be put in ascending order before parsing.
To make it worse packets with Push flag sometimes come first so I just pass them along to parser, and then packet that preceds it comes and parser just discards it as corrupted.
Is there any way to deal with it?
TCP segments will not be out of order because the next one will not be sent until you ACK the previous one.
TCP numbers the segments that it sends
to a particular destination port
sequentially, so that if they arrive
out of order, the TCP entity can
reorder them.
This happens on a transport layer below TCP so any TCP connections would never "see" this happen. In terms of TCP they are always in order. So if you see them out of order then you are not working on the TCP transport layer, you're at a lower level.
Also, FYI...
TCP data is a "segment"
IP data is a "datagram"
Network-level is a "packet"
Edit: The link you provided will provide you with a stream of IP datagrams so you would have to handle the TCP stream on your own. I'm not going to pretend like it's easy and try to explain that here.
TCP guarantees order. So I will just assume you are talking about IP.
One thing you could try is putting the packets in a min-heap and then waiting until the next packet ID number you want is available.
As for the push packets, those are supposed to be received as soon as possible without a restriction on ordering, so its up to you to decide how long you want to wait to see if you'll receive an earlier push packet.
Why don't you use the normal tcp socket so they come in order?
The Sequence number will show the order. It wraps at 4G so you will have to account for that. And you will have to use the same basic routine that TCP uses. Buffer out of order packets and discard duplicates. Sequence Number + Len of payload is the nexxt sequence number.
TCP/IP Illistrated vol 2
or TCP.c ?

Categories

Resources