Little bit confused on this issue :-). I have some code running on Ubuntu 10.04, which is using the recvmsg call to receive Audio UDP packets. This piece is part of a bigger SIP client which I've been testing with a remote system across the net.
Typically I am able to establish a call no problem and audio happily travels from the remote source to my program. However after a random amount of time I'm running into a read error on the port. When this happens I get the errno EHOSTUNREACH. On this error I shutdown my port and kill the connection.
The strange thing about this is that I was under the impression that this would happen in response to an ICMP message. Perhaps due to a momentary network glitch. However after reproducing this issue and doing a full packet capture, all I saw where ICMP pings and responses. I didn't see any of the ICMP error messages that the kernel interprets as EHOSTUNREACH.
My UDP port is pretty basic. I can post the code if its really needed. But this is just a basic SOCK_DGRAM. The socket is able to receive data for upwards of 8 hours sometimes before it hits this error condition.
Any ideas how I can further tackle this issue. I'm trying to understand why I'm receiving this errno with no ICMP message to correlate it with.
Are you using the same socket to send packets out with? Or a different socket sharing the same port? I'm curious if it's possible another socket is actually generating the error.
I remember years ago dealing with ICMP messages causing both sendto and recvfrom to fail
intermittently like you describe. And if I recall, the workaround is to just ignore it and do another recvfrom/recvmsg.
As to why you are getting that error code in the absence of seeing an ICMP message on the wire is beyond me. Are you certain you are dismissing the ICMP messages you observed as "pings and responses" correctly? ICMP messages don't have port numbers, so it's possible that all sockets (or a random one) associated with that remote host return this error code.
I thought there might be an ioctl to disable this behavior, but I couldn't find it.
A similar discussion here.
Related
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.
I am trying to work out what could be causing a strange issue I have been observing when testing a system.
The system under test recieves HTTP requests via UDP from an external source. For testing I have mocked out this source using Python sending the UDP packets over a local network for testing I send 1, 20, 133 and 1000 messages.
When I run the test on my local windows machine I regularily get a drop out of UDP packets with sometimes even the single message failing to be recieved. however when I create a virtual Linux Box (Centos) using Virtual Box and run the same tests from there I get 100% success rate 100% of the time.
Are there any know issues with sending UDP messages from Windows, any strange buffering differences between Windows and Linux I could adjust for on my machine?
UDP stacks of operating systems usually drops a received UDP packet, if the incoming packet does not fit to receive buffer. The receive buffer may be 'full', if the receiving application does not read it (=socket) fast enough.
Default size of receive buffer of your Windows may be smaller than in the Linux.
For handling bursts of incoming UDP packets better, you could increase size of the receiving buffer:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
You can also use getsockopt for checking the size.
having researched and investigated it seems that despite my efforts to try and prove otherwise the answer is, it's just Windows. Windows Network Buffering is causing the problem. As fixing this is outside the remit of this question i will close this and if necessary open a new question, thanks for your help.
I'm working on Linux 4.13.x. And I'm considering to send a packet response in the kernel.
Consider an echo TCP or UDP server running in the userland and there is also another node running a TCP or UDP client. Clients are sending requests to the server. I want to send the packet response back to the client without any involvement of server application running at userspace.
Here is my thoughts about this problem:
I started thinking how it is possible and I come across to a solution like netfilter. If I can capture the packets in NF_INET_PRE_ROUTING and then try to swap the source and destination IP addresses of IP header and also swapping the ports in the TCP header, then according to this answers and this presumably modified packet should be forwarded to the originator throughout the routing system.
Actually, I tried this scenario and it seems it is not possible to do so from netfilter hooks, however, I'm not sure of it. I thought that it is not working since it has problem with checksums because I'm manipulating packets so I did another experiment to figure this issue out. I just change the packet data and everything worked well. I think checksums don't have any problem since they will be check at NIC while receiving and also same situation while sending so manipulation in between doesn't make anything wrong. I also activate the IPv4 forwarding at the server host(sysctl.config) still nothing changes.
I don't want to create new packet, I only want to alter this packet and send it back. There is another similar question which is creating another packet. Moreover, I'm just thinking why this scenario is not working? But based on the netfilter's architecture it should work.
Thank you
I am also working on this, actually kernel validate the source ip address after ip_rcv function in NF_HOOK which check the source ip address. So just try below command:-
sudo sysctl -w "net.ipv4.conf.all.rp_filter=0"
after doing this also disable your interface from which you send and receive packet just like below:-
sudo sysctl -w "net.ipv4.conf.enp2s0.rp_filter=0"
As a way to learn how raw sockets work, I programmed a dummy firewall which drops the packets based on the TCP destination port. It is working but the problem is that the client retries for quite some time until the time out is finally reached.
I was wondering if perhaps the client retries for so long because it does not receive any answer. In that case, would it help if the firewall replies with a TCP RST to the TCP SYNC messages from the client? If not, is there any way to force the client to stop retrying (not reducing the timeout time in the Linux but more, getting a specific answer to its packets which will make the client stop)?
You can think of your firewall as the same case as if the port were closed on the host OS. What would the host OS's TCP/IP stack do?
RFC 793 (original TCP RFC) has the following to say about this case:
If the connection does not exist (CLOSED) then a reset is sent
in response to any incoming segment except another reset. In
particular, SYNs addressed to a non-existent connection are rejected
by this means.
You should read the TCP RFCs and make sure your TCP RST packet conforms to the requirements for this case. A malformed RST will be ignored by the client.
RFC 1122 also indicates that ICMP Destination Unreachable containing codes 2-4 should cause an abort in the connection. It's important to note the codes because 0, 1, and 5 are listed as a MUST NOT for aborting the connection
Destination Unreachable -- codes 2-4
These are hard error conditions, so TCP SHOULD abort
the connection.
Your firewall is behaving correctly. It is a cardinal principle of information scurity not to disclose any information to the attacker. Sending an RST would disclose that the host exists.
There were firewalls that did that 15-20 years ago but there were frowned on. Nowadays they behave like yours: they just drop the packet and do nothing in reply.
It is normal for the client to retry a few times before giving up if there is no response, but contrary to what you have been told in comments, a client will give up immediately with 'connection refused' if it receives an RST. It only retries if there is no response at all.
I'm an Automation Developer and lately I've taken it upon myself to control an IP Phone on my desk (Cisco 7940).
I have a third party application that can control the IP phone with SCCP (Skinny) packets. Through Wireshark, I see that the application will send 4 unique SCCP packets and then receives a TCP ACK message.
SCCP is not very well known, but it looks like this:
Ethernet( IP( TCP( SCCP( ))))
Using a Python packet builder: Scapy, I've been able to send the same 4 packets to the IP Phone, however I never get the ACK. In my packets, I have correctly set the sequence, port and acknowledge values in the TCP header. The ID field in the IP header is also correct.
The only thing I can imagine wrong is that it takes Python a little more than a full second to send the four packets. Whereas the application takes significantly less time. I've tried raising the priority for the Python shell with no luck.
Does anyone have an idea why I may not be receiving the ACK back?
This website may be helpful in debugging why on your machine you aren't seeing the traffic you expect, and taking steps to modify your environment to produce the desired output.
Normally, the Linux kernel takes care of setting up and sending and
receiving network traffic. It automatically sets appropriate header
values and even knows how to complete a TCP 3 way handshake. Uising
the kernel services in this way is using a "cooked" socket.
Scapy does not use these kernel services. It creates a "raw" socket. The
entire TCP/IP stack of the OS is circumvented. Because of this, Scapy
give us compete control over the traffic. Traffic to and from Scapy
will not be filtered by iptables. Also, we will have to take care of
the TCP 3 way handshake ourselves.
http://www.packetlevel.ch/html/scapy/scapy3way.html