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
Related
I want to build a DSR load balancer for an application I am writing. I wont go into the application because it is irrelevant for this discussion. My goal is to create a simple load balancer that does direct server response for TCP packets. The idea is to receive all packets at the load balancer, then using something like round robin, select a server from a list of available servers which are defined in some config file. The next step would be to alter the packer received and change the destination ip to be equal to the chosen backend server. Finally, the packet will be sent over to the backend server using normal system calls for sending packets. Theoretically the backend server should receive the packet, and send one back to the original requester, and then the requester can communicate directly with the backend server rather than going through the load balancer.
I am concerned that this design will not work as I expect it to. The main question is, what happens when computer A send a packet to IP Y, but receives a packet back in the same TCP stream from a computer at IP X? Will it continue to send packets to IP Y? Or will it switch over to IP X?
So it turns out this is possible, but only halfway so, and I will explain what I mean by this. I have three processes, one which is netcat, used to initiate an tcp request, a second process, the dsr-lb, which receives packets on a certain port, changes the destination ip to a backend server(passed in via command line arg), and forwards it off using raw sockets, and a third process which is a basic echo server. I got this working on a local setup. The local setup consists of netcat running on my desktop, and dsr-lb and echo servers running on two different linux VMs on the desktop as well. The path of the packets was like this:
nc -> dsr-lb -> echo -> nc
When I said it only half works, what I meant was that outgoing traffic has to always go through the dsr-lb, but returning traffic can go directly to the client. The client does not send further traffic directly to the backend server, but still goes through the dsr-lb. This makes sense since the client opened a socket to the dsr-lb ip, and internally still remembers this ip, regardless of where the packet came from.
The comment saying "if its from a different IP, it's not the same stream. tcp is connection-based" is incorrect. I read through the linux source code, specifically the receive tcp packet portion, and it turns out that linux uses source ip, source port, destination ip, and destination port to calculate a hash which is uses to find the socket that should receive the traffic. However, if no such socket matches the hash, it tries again using only the destination ip and destination port and that is how this "magic" works. I have no idea if this would work on a windows machine though.
One caveat to this answer is that I also spun up two remote VMs and tried the same experiment, and it did not work. I am guessing it worked while all the machines were on the same switch, but there might be a little more work to do to get it to work if it goes through different routers. I am still trying to figure this out, but from using tcpdump to analyze the traffic, for some reason the dsr-lb is forwarding to the wrong port on the echo server. I am not sure if something is corrupted, or if the checksum is wrong after changing the destination ip and some router along the way is dropping it or changing it somehow(I suspect this might be the case) but hopefully I can get it working over an actual network.
The theory should still hold though. The IP layer is basically a packet forwarding layer and routers should not care about the contents of the packets, they should just forward packets based on their routing tables, so changing the destination of the packet while leaving the source the same should result in the source receiving any answer. The fact that the linux kernel ultimately resolves packets to sockets just using destination ip and port means the only real roadblock to this working does not really exist.
Also, if anyone is wondering why bother doing this, it may be useful for a loadbalancer in front of websocket servers. Its not as great as a direct connection from client to websocket server, but it is better than a loadbalancer that handles both requests and responses, which makes it more scalable, and more able to run on less resources.
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'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"
I am working on a small linux socket project. The goal is to have multiple servers (ie. 1,2,3,4,5) that listen for send get and ACK packets from each of their respective clients. I am currently attempting to implement a routing table protocol whereby 2 servers (A, B) exchange their routing tables (vectors containing respective clients, server name, and number of hops). The issue I am having is with binding a socket to B's external address from A and vice-versa. From what I have read you do not bind to anything other than a local address except in certain cases. What I am wondering is how do I simply fire off a UDP packet from one server to another knowing the (static) IP address of each server?
What I am wondering is how do I simply fire off a UDP packet from one
server to another knowing the (static) IP address of each server?
The short answer is, you can't. At least on the Internet proper, only unicast is widely supported, which means that in order to send a UDP packet to another machine, you'll need to know its IP address (somehow).
The longer answer is: The first thing you often need to do is discover the target machines' IP addresses. That might be a matter of having the user manually enter a list of IP addresses, or if the target machines are on the same LAN, you can program a mechanism for auto-discovering them by having your program send out a broadcast or multicast UDP query packet. Make sure any instances of your program running on the same LAN receive that packet and respond to it by sending back a response UDP packet (the responses can be sent by by unicast or multicast or broadcast, your choice), and then your query-originating computer can know from the responses it receives which other IP addresses your program is presently also running on.
Note that a lot of computers and network devices run firewalls that reject incoming UDP packets by default, so if you packets don't seem to be getting through that is a likely reason why.
I am trying to verify a new functionality added to the router kernel. So lets assume I added a filter,iptable and such. I have live traffic. I tried to use tcp dump and look into the packet header and see if the new values in the header are there but I am getting random traffic passing through.
I wonder if it is possible to have tcpdump send traffic and dump it so I have specific packets I sent ? or any other linux commands I can use to do the process. I have a destination port that has no traffic but I don't know how I can send to it and capture those packets. I did some reading on sendip and tcpdump and couldnt help myself.
Send packets, tcpdump it or something like that, verify the packet header has what I want and move on with my life.
I hope I was clear enough.