Where are the missing TCP packets? - linux

I observed a surprising thing that when there are both udp-based and tcp-based applications sending packets, if the upd-based application sent the packets so fast that the bandwith are nearly filled with udp packets, then the tcp packets would be very hard to send out.
The surprising thing is that though tcp-based application is able to send a few packets out (observed by the return value of write()), the receiver of the tcp packets never receives them. Why? Is that because the tcp-packets arenot finally sent out by the network card? or the tcp packets are actually dropped by routers?
Thanks,
Steve

First, the return value of write() is not an indicator of whether packets were sent. It just indicates that the data was buffered.
Second, if you are saturating the network with UDP packets there will be a lot of packet loss, and TCP being adaptive will adapt to that by sending packets out more slowly. If the packet loss gets too high TCP can basically stop altogether. The solution is not to saturate the network with UDP packets.

This is a simplified answer. There are many articles you can read up on.
UDP is a layer built upon IP. Ditto for TCP. The network card just sends out IP packets. You can look up the various structures for these packets.
TCP is a protocol that uses IP packets but uses a mechanism to try to ensure delivery and rearranges packets in the correct order. See the article on Wikipedia.
Routers are free to drop packets. This can occur when the network is overloaded, network connections are down or the IP packet is corrupted.
So to answer your question their is no preference between UDP or IP to be transmitted from one end to the other.

Related

Linux Raw Sockets: Block Packets?

I've written my own packet sniffer in Linux.
I open a socket with socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) and then process the Ethernet packets - unpacking ARP packets, IP packets (and ICMP / TCP / UDP packets inside those).
This is all working fine so far.
Now I can read packets like this - and I can also inject packets by wrapping up a suitable Ethernet packet and sending it.
But what I'd like is a means to block packets - to consume them, as it were, so that they don't get further delivered into the system.
That is, if a TCP packet is being sent to port 80, then I can see the packet with my packet sniffer and it'll get delivered to the web server in the usual fashion.
But, basically, I'd like it that if I spot something wrong with the packet - not coming from the right MAC address, malformed in some way, or just breaking security policy - that I can just "consume" the packet, and it won't get further delivered onto the web server.
Because I can read packets and write packets - if I can also just block packets as well, then I'll have all I need.
Basically, I don't just want to monitor network traffic, but sometimes have control over it. E.g. "re-route" a packet by consuming the original incoming packet and then writing out a new slightly-altered packet to a different address. Or just plain block packets that shouldn't be being delivered at all.
My application is to be a general "network traffic management" program. Monitors and logs traffic. But also controls it too - blocking packets as a firewall, re-routing packets as a load balancer.
In other words, I've got a packet sniffer - but if it sniffs something that smells bad, then I'd like it to be able to stop that packet. Discard it early, so it's not further delivered anywhere.
(Being able to alter packets on the way through might be handy too - but if I can block, then there's always the possibility to just block the original packet completely, but then write out a new altered packet in its place.)
What you are looking for is libnetfilter_queue. The documentation is still incredibly bad, but the code in this example should get you started.
I used this library to develop a project that queued network packets and replayed them at a later time.
A bit of a tangent, but it was relevant when I was resolving my problem. Blocking raw packets is relatively complicated, so it might make sense to consider doing that at a different layer. In other words, does your cloud provider let you set up firewall rules to drop specific kind of traffic?
In my case it was easier to do, which is why I'm suggesting such a lateral solution.

Linux drops UDP packets

I have written a C++ tool for my linux machine which receives UDP (OSC) packets and sends them back immediately (thats the only thing it does). But it seems that there is some amount of dropped packets. When I send 100 packets to my linux (from another machine), mostly only 64 packets are returned. I have looked at the incoming packets with tcpdump. It tells me the following:
64 packets captured
64 packets received by filter
0 packets dropped by kernel
So where are they?
UDP, by design, does not guarantee that the packets arrive at the destination. The packets missing might no have reached your machine at all, and thus will not appear in the incoming packets.
UDP is mostly used for streams and games, as loosing a few packets does not really matter.
If you want to be sure that all the packets arrive, you should use TCP.
Let me know if this helps.

use scapy to send UDP ping with a high frequency, why only receive the first few ICMP port unreachable message?

In a linux system, I use scapy to send a high frequency UDP ping. For example: each 20 milliseconds, send a UDP packet; a total of 100. But I can only get the first few ICMP port unreachable answer.
pkt = IP(dst=dst)/UDP(dport=RandShort())
ans,_ = sr(pkt*100, inter=0.02, timeout=3)
I tried to use tcpdump to capture packet and found that all UDP packets have been sent to the target machine, but only a few ICMP packet came back to the source machine. What would cause this?
If I use ICMP pingļ¼Œthis does not happen.
I guess:
may be caused by the target machine's system kernel parameter which process icmp packet
may be caused by the icmp packet routing switch strategies.
The rate of ICMP packets is hard limited by the kernel to prevent DDOS attacks. Usually to only 1 packet per second. Almost impossible to get anything faster than that in any external (internet) router. Example

Convert UDP header to TCP header

I have a typical requirement, I want to have a converter module, that can convert UDP packet to TCP packet.
And I need to do it before the packet can be processed in IP layer.
I will explain this complete scenario using an example
Lets say we have 3 machines A, B and C.
A sent an UDP packet
B received UDP packet
At B, when packet is being given to IP layer (from Link / MAC / Ethernet layer) , I want to get hold of packet. I want to delete the UDP and IP header in packet. I want to add TCP and IP header (assuming C is the destination host).
Now from B machine, packet is sent to C machine
Can somebody help me how this can be done.
I am using linux machines.
Though libpcap can be one of the option (from wireshark), but it is not suitable for me because of performance reasons.
I want a very light weight solution for this problem.
Can't be done. TCP is a stateful, reliable, connection-oriented byte-stream protocol. UDP is a stateless, unreliable, unconnected packet protocol.
The best you can do is, on machine B, open a new socket/TCP connection to C, accept socket/UDP packets from A, and write the contents of those packets to the TCP stream. Data flowing the other direction is a bit more difficult because you have to create UDP packets to A no larger than the maximum UDP packet size supported by your systems.
You can not do it directly but if you will use a UDP VPN than you can do it very easily.
Just connect you system/PC with UDP VPN network and it work as you are want.
check below my image for more information, i am also using same.

Create VPN over TCP connection

I need to create a virtual IP network over TCP connection. The hosting system is Linux, with the TUN/TAP kernel driver, it's quite easy to receive & re-inject IP packets of the virtual network.
The difficult part is to transmit the received IP packets to another host. For some non-technical reasons, I can only transmit the packets over TCP protocol but not UDP. Transmit IP packets over UDP is easy, but with TCP it becomes tricky, here's the reason:
UDP protocol doesn't support retransmission/reordering, just like IP. So, if one UDP packet is sent for every received virtual IP packet, the kernel TCP/IP protocol stack would still see virtual IP packet loss/duplication/reordering(those are required for TCP/IP to work well, if those "features" are missing, the TCP connection speed on the virtual network would suffer). If IP packets are transmitted over TCP all required "features" will be missing, unless they are simulated some how.
It seems I have to fake some kind of packet duplication/loss/reordering on TCP connection, or patch the kernel TCP/IP protocol stack. Both options aren't easy.
Is there any other simpler solution to my problem ? or did I just go into a completely wrong direction ? I'm all ears.
==== UPDATE ====
I'm thinking about using raw IP socket (which could get rid of all the TCP retransmission/reordering stuff on the physical network easily while still using TCP packets) to transmit the received virtual network IP packets. But on the receiving host, how can I only receive the packets I'm interested in and return all other IP packets to the kernel TCP/IP stack ?
First of all, you do not want to make a VPN over TCP because you would end up with tcp-over-tcp eventually. The main issue is that the timers of your inner TCP and outer TCP might differ significantly which negatively impacts your TCP session reliability. You can find a bit longer explanation here.
UDP protocol doesn't support retransmission/reordering, just like IP. So, if one UDP packet is sent for every received virtual IP packet, the kernel TCP/IP protocol stack would still see virtual IP packet loss/duplication/reordering(those are required for TCP/IP to work well, if those "features" are missing, the TCP connection speed on the virtual network would suffer). If IP packets are transmitted over TCP all required "features" will be missing, unless they are simulated some how.
This does not make sense, if your outer layer uses TCP as a transport mechanism, nothing stops your inner layer to still use the full ip/tcp stack, including those features. They can conflict badly like I said, but it's not that this functionality disappears or breaks completely.
It seems like you actually want to use TCP just to have the headers and ignore the actual protocol, this would indeed avoid the issues with tcp over tcp. However, once again this is a very bad idea. Flow processing for firewalls, NAT, DPI, tcp boosters, becomes more and more common, if you fake TCP packets you might up stressing those boxes, possibly detoriating your own connection once again.
So you should ask yourself why you can't use UDP, and if no alternative protocol (header) is okay, like GRE or L2TP.

Resources