Python\C\iptables block UDP - python

I'm dealing with a DDoS issue on my server. It's actually called a spoof/flood attack.
So, I came up with the idea to create a couple of scripts to collect valid IPs and detect the attack on the specific IP: port, but I have no idea how to drop incoming packets so the port never receives them.
There were a couple of suggestions, like:
Create a rule in IP tables that will block all UDP packets and create another rule to map whitelisted ip's and allow them. And it looks like this:
iptables -A INPUT -p udp --dport [PORT] -j DROP
So that should drop all UDP packets to the specific port. (I would need to define ip as well in the future). So after that, we should have whitelist.txt file with ips, and allow them like so:
while read IP; do iptables -I INPUT -p udp --dport [PORT] -s $IP -j ACCEPT done < /etc/whitelist.txt
As a second suggestion (that I'm not really confident writing it), is to create a program with Python and C, with BPF compiler. But we already have that solution, and it's causing performance issues with high traffic.
So, the question is. Is there any way that I could block it directly with python (without tables and C), or maybe just C or iptables, so I could prevent using them all in one (again, performance issues).
What do you think about that?

Related

How to capture martian packets without letting the linux kernel to drop them and then catching them using raw sockets

I'm trying to setup a network to simulate an Edge computing scenario with LTE. But the question here is more pertaining to IP tables and raw sockets on the server.
I have the following setup:
PC-A is the Tower, PC-C is the LTE Core, PC-B is acting as intermediary and routing data using proxy ARPs
Cell phone wants to connect to a TCP server on PC-B(IP: 172.17.1.3)
Cell phone(IP:192.172.0.2) sends packets to PC-A(IP: 172.17.1.1)
The data from PC-A(172.17.1.1) generally has to reach LTE-EPC on 172.17.1.4 which is connected via PC-B(172.17.1.2 - 172.17.1.3 with proxy ARPs). And the data comes in the form of UDP packets to PC-B(IP: 172.17.1.2)
I use NAT table and python script with raw sockets to send all of these UDP packets to a local port, do some filtering, decapsulate the GTP headers and send the TCP/IP packet to the TCP server on PC-B interface(172.17.1.3). I use the below iptables settings to do this
iptables -t nat -A PREROUTING -p udp -d 172.17.1.4 --dport 2152 -j DNAT --to-destination 172.17.1.2:7000
Until here everything works, the extracted TCP/IP packet also reaches the TCP server on 172.17.1.3. The server responds to these packets. For example, for the SYN packet from the cell phone, the server now sends out SYN, ACK. However, the server responds to the original source address 192.172.0.2.
I want to catch these response TCP/IP packets from the TCP server 172.17.1.3 to 192.172.0.2 and do some GTP encapsulation before sending them back to PC-A.
Can anyone tell me how I can use the iptables to tell the kernel to stop dropping these martian packets with destination address 192.172.0.2, but instead forward to a local ip and port, so I can read the same.
I can see the SYN, ACK responses from the server on wireshark. But I assume that these are dropped as I already tried to route it to local ip:port using a similar iptables rule from above.
Any help is much appreciated, Thank you.
It sounds like a tun/tap interface could be useful here. Here's the official Linux kernel documentation.
Both these interface types allow a program to create a virtual network interface. This is designed for tunnels and VPNs and it seems like that is exactly what you are creating.
According to the linked documentation, you may create an interface by opening /dev/net/tun (O_RDWR) and issuing this ioctl to initialize it:
struct ifreq req;
memset(&req, 0, sizeof(req));
req.ifr_flags = IFF_TUN; // or IFF_TAP
strncpy(req.ifr_name, "tunnel%d", IFNAMSIZ); // optional; leave it blank to get a default name; you don't have to have a %d
ioctl(fd, TUNSETIFF, &req); // error check omitted for demonstration
// req.ifr_name now contains the name that was actually selected
After the ioctl you have a virtual network interface in your system. You can configure IP addresses, routes, whatever.
Any time the kernel sends a packet out through your interface it will go into a queue and you'll be able to read it. Any time you write to the interface the kernel will process it as if it's a real packet that just arrived.
You will need to configure networking like it's a real interface. Set up a static route so that 192.172.0.0/16 (or whatever your subnet is) is reached through the tunnel interface. I'm not sure if Linux will let you do this without giving it an address; you might have to give it a dummy address like 192.172.255.254. Or a completely unrelated address like 1.2.3.4 and then let Linux think there's another router in front of your cellphone subnet. Or maybe it will just work without an address - not sure.
The difference between "tun" and "tap" is whether Ethernet processing happens or not (IP tunnel vs Ethernet tap). I expect tun is right for your application. If you choose tap then Linux will also use ARP and so on, and the interface will certainly need an address.
You might find it convenient to use the tunnel interface in both directions, or just one. IP packets aren't required to take the same route in both directions. This is the "correct" way to implement a tunnel, so you might find that a lot of mysterious bugs go away by using it.

How to bind ports for TCP clients when using raw packet sending TCP packets in Python? [duplicate]

Ok, I realize this situation is somewhat unusual, but I need to establish a TCP connection (the 3-way handshake) using only raw sockets (in C, in linux) -- i.e. I need to construct the IP headers and TCP headers myself. I'm writing a server (so I have to first respond to the incoming SYN packet), and for whatever reason I can't seem to get it right. Yes, I realize that a SOCK_STREAM will handle this for me, but for reasons I don't want to go into that isn't an option.
The tutorials I've found online on using raw sockets all describe how to build a SYN flooder, but this is somewhat easier than actually establishing a TCP connection, since you don't have to construct a response based on the original packet. I've gotten the SYN flooder examples working, and I can read the incoming SYN packet just fine from the raw socket, but I'm still having trouble creating a valid SYN/ACK response to an incoming SYN from the client.
So, does anyone know a good tutorial on using raw sockets that goes beyond creating a SYN flooder, or does anyone have some code that could do this (using SOCK_RAW, and not SOCK_STREAM)? I would be very grateful.
MarkR is absolutely right -- the problem is that the kernel is sending reset packets in response to the initial packet because it thinks the port is closed. The kernel is beating me to the response and the connection dies. I was using tcpdump to monitor the connection already -- I should have been more observant and noticed that there were TWO replies one of which was a reset that was screwing things up, as well as the response my program created. D'OH!
The solution that seems to work best is to use an iptables rule, as suggested by MarkR, to block the outbound packets. However, there's an easier way to do it than using the mark option, as suggested. I just match whether the reset TCP flag is set. During the course of a normal connection this is unlikely to be needed, and it doesn't really matter to my application if I block all outbound reset packets from the port being used. This effectively blocks the kernel's unwanted response, but not my own packets. If the port my program is listening on is 9999 then the iptables rule looks like this:
iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP
You want to implement part of a TCP stack in userspace... this is ok, some other apps do this.
One problem you will come across is that the kernel will be sending out (generally negative, unhelpful) replies to incoming packets. This is going to screw up any communication you attempt to initiate.
One way to avoid this is to use an IP address and interface that the kernel does not have its own IP stack using- which is fine but you will need to deal with link-layer stuff (specifically, arp) yourself. That would require a socket lower than IPPROTO_IP, SOCK_RAW - you need a packet socket (I think).
It may also be possible to block the kernel's responses using an iptables rule- but I rather suspect that the rules will apply to your own packets as well somehow, unless you can manage to get them treated differently (perhaps applying a netfilter "mark" to your own packets?)
Read the man pages
socket(7)
ip(7)
packet(7)
Which explain about various options and ioctls which apply to types of sockets.
Of course you'll need a tool like Wireshark to inspect what's going on. You will need several machines to test this, I recommend using vmware (or similar) to reduce the amount of hardware required.
Sorry I can't recommend a specific tutorial.
Good luck.
I realise that this is an old thread, but here's a tutorial that goes beyond the normal SYN flooders: http://www.enderunix.org/docs/en/rawipspoof/
Hope it might be of help to someone.
I can't help you out on any tutorials.
But I can give you some advice on the tools that you could use to assist in debugging.
First off, as bmdhacks has suggested, get yourself a copy of wireshark (or tcpdump - but wireshark is easier to use). Capture a good handshake. Make sure that you save this.
Capture one of your handshakes that fails. Wireshark has quite good packet parsing and error checking, so if there's a straightforward error it will probably tell you.
Next, get yourself a copy of tcpreplay. This should also include a tool called "tcprewrite".
tcprewrite will allow you to split your previously saved capture files into two - one for each side of the handshake.
You can then use tcpreplay to play back one side of the handshake so you have a consistent set of packets to play with.
Then you use wireshark (again) to check your responses.
I don't have a tutorial, but I recently used Wireshark to good effect to debug some raw sockets programming I was doing. If you capture the packets you're sending, wireshark will do a good job of showing you if they're malformed or not. It's useful for comparing to a normal connection too.
There are structures for IP and TCP headers declared in netinet/ip.h & netinet/tcp.h respectively. You may want to look at the other headers in this directory for extra macros & stuff that may be of use.
You send a packet with the SYN flag set and a random sequence number (x). You should receive a SYN+ACK from the other side. This packet will have an acknowledgement number (y) that indicates the next sequence number the other side is expecting to receive as well as another sequence number (z). You send back an ACK packet that has sequence number x+1 and ack number z+1 to complete the connection.
You also need to make sure you calculate appropriate TCP/IP checksums & fill out the remainder of the header for the packets you send. Also, don't forget about things like host & network byte order.
TCP is defined in RFC 793, available here: http://www.faqs.org/rfcs/rfc793.html
Depending on what you're trying to do it may be easier to get existing software to handle the TCP handshaking for you.
One open source IP stack is lwIP (http://savannah.nongnu.org/projects/lwip/) which provides a full tcp/ip stack. It is very possible to get it running in user mode using either SOCK_RAW or pcap.
if you are using raw sockets, if you send using different source mac address to the actual one, linux will ignore the response packet and not send an rst.

how to dump http traffic?

I am working with webservices, and I need to get a dump of all the HTTP requests and responses, so that I can debug the interoperability between the devices.
I have a small pc with 3 nics that are bridged, so that it acts as an hub and I can tap the traffic. I am looking for a way to easily dump the HTTP traffic, so that I can analyze the SOAP messages exchanged by the two devices.
For I would prefer to implement that with python, I tried scapy with the HTTP extension, but it does not seem to work, because I see the request parsed three times (I wonder if this is due to the used of a bridge) and I am not able to see the responses.
Is there any other way to implement such a tool? I prefer python, but it is not mandatory.
Another small question
I add a subquestion: by using the HTTP interpreter that I linked in the previous question, I see that I sometimes get packets that are only recognized as HTTP and not as HTTPRequest or HTTPResponse. Such packets look gzipped, and I think they are related to the fact that a response body does not fit in a single packet. It there a way with scapy to have these packets merged together? I need a way to get the body of the messages. Again, not only in python, and not only with scapy.
I finally solved my problem by using tshark in pipe and by parsing its output with a python script. Most of the decoding activity is performed by the following command
tshark -l -f "tcp port 80" -R "http.request or http.response " -i br0 -V
which outputs the decoded HTTP packets. and my script performs all the necessary operations.
For the raw sniffing I'd go with tcpdump writing to a pcap file.
tcpdump -i <interface> -s 65535 -w file.pcap port 80
The -s says write the whole packet out and -w is save. I'm assuming your http goes over port 80, but you can make an arbitrarily complex filter expression. Make sure the interface is the one that leads to the server so you see what it's sending and receiving vs how traffic gets to your bridge host.
You can then parse the pcap with scapy at your leisure, knowing that the capture is happening in a well tested, fast, and reliable manner.
rdpcap("/tmp/file.pcap")
There are some respectable traffic sniffers around already, so you probably have no need to implement one of your own. Wireshark is amongst the most popular. Not only it allows you to capture traffic, but also has some great tools for filtering and analyzing the packets.
sharktools allows you to use Wireshark packet dissection engine from Python, e.g. to filter the packets.
If you have very specific needs or just want to learn something new, pylibpcap is a Python interface for libpcap library, which is used by (almost) every traffic capture program out there.
UPD: Fixed typo in URL for pylibpcap.

Python: how to calculate data received and send between two ipaddresses and ports

I guess it's socket programming. But I have never done socket programming expect for running the tutorial examples while learning Python. I need some more ideas to implement this.
What I specifically need is to run a monitoring program of a server which will poll or listen to traffic being exchange from different IPs across different popular ports. For example, how do I get data received and sent through port 80 of 192.168.1.10 and 192.168.1.1 ( which is the gateway).
I checked out a number of ready made tools like MRTG, Bwmon, Ntop etc but since we are looking at doing some specific pattern studies, we need to do data capturing within the program.
Idea is to monitor some popular ports and do a study of network traffic across some periods and compare them with some other data.
We would like to figure a way to do all this with Python....
You probably want to use scapy for that. Just sniff all ethernet traffic on a particular interface, drop everything that is not TCP and doesn't match the port.
Not sure if scapy can already track TCP connections (stuff like recognizing duplicate sequence numbers, extracting just the payload stream) but I would guess it probably can, and if not it's not too hard to hack together a good-enough TCP connection tracker that works for 95% of the traffic.
Alternatives would be to use sockets directly (look for raw sockets) or libpcap, which can both be done from Python. You may also want to check out the filter experssion syntax of the 'tcpdump' commandline tool, maybe it can do what you want already.
I bet there are more specialized high-level tools for this, but I don't know them.
PS: if you don't know wireshark yet, go check it out and play around with it first. It can follow TCP streams and will teach you what TCP connection tracking means. Maybe its commandline binary, tshark, can be used to extract TCP streams for what you want.
IPTraf is an ncurses based IP LAN monitoring tool. Has a capability to generate network statistics including TCP,UDP,ICMP and some more.
Since you're thinking to execute it from python, you may consider to use screen (screen manager with VT100/ANSI terminal emulation) to overcome ncurses issues and you may want to pass logging and interval parameters to IPTraf which forces iptraf to log to a file in a given interval. Little bit tricky but eventually you can have what you are looking for by basically parsing the log file.

Weird network behaviors with UDP sockets and python

I made some python script and ran it both on my computer and some distant shell (some website that provides shell access).
I'm using threads, pipes and UDP sockets to transfer data in a P2P fashion, so each script can both receive and send through the same socket. To test if this works, I open one terminal on my computer and one other terminal with ssh, connected to my shell. I make sure the script is the same on both machines, and feed it with an ip address.
Here is the script: http://codepad.org/V9Q1KcDT
(I don't know if I should paste it directly here or not)
My problem is this: strings I send seems to land something 20% of the time, sometimes often, sometimes not, and it seems to be random...
What am I doing wrong ?
Are UDP so unreliable ?
Are python thread+pipe+socket too slow ?
Could it be some kind of network problem with my shell provider ?
Is my program flawed ?
Are pipes a good solution to communicate with threads ?
I have no problem not using a shell and I have not tried, but it's useful for testing purposes.
BTW if i'm behing a router, how does the router knows where to send the packet if I'm not the only computer connected ? (I tried when I was the only one, it behaved identically).
User Datagram Protocol(UDP) could easily stand for Unreliable Datagram Protocol. UDP provides no guarantees regarding delivery so if you need reliability you have to implement it yourself by resending messages.
That said, threading and multiprocessing and remote machines and networks are a lot of variables to diagnose at once. I'd advise you to step back and try to boil the problem down to something simpler.
For instance:
first try TCP instead of UDP
instead of threads, run 2 processes (one doing nit_send, one doing nit_recv)
run them both on your local machine (use localhost: 127.0.0.1)
Once you have this basic test working then add features back in. For instance, switch to UDP. Once you've got your UDP issues sorted out locally try introducing remote machines or threads, etc.
Regarding the router question all machines connected to your router are most likely NAT'd so they all appear to have the same IP address (the IP address of your router) to machines on the internet. Look into NAT and port-forwarding if you want to route traffic to a specific machine on your local subnet.

Categories

Resources