How to send ICMP packet through sockets? - python

I'm trying to send a message through ICMP packets but I don't know how to do it.
This is the code I currently have, but obviously doesn't work:
s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
s.setsockopt(IPPROTO_IP, IP_HDRINCL, 1)
s.settimeout(3.0)
s.sendto("Hello!" + "\r\n", (server, 7))
msg = s.recvfrom(buff_size)
s.close()
I have to receive an answer from server if string "Hello!" is sent, but I don't get it.
I suppose, that "Hello!" string will be encapsulated into Data field:

In order to construct an ICMP packet, you have to create the whole packet yourself using a raw socket. The struct module is useful for this.
Secondly, in order to even use raw sockets in the first place, you need to have permission to do so—you should be running as root (I know this is a sufficient condition, but I'm not 100% certain that it's a necessary condition). The ping(1) executable is able to do this because it's a setuid executable that runs as root when you run it. Since scripts cannot be made setuid on Linux, you'll have to make a wrapper setuid program in C that just executes your Python script.

I don't think that SOCK_RAW is going an ICMP datagram for you just because you set the protocol field to IPPROTO_ICMP! You have to construct the packet yourself.
Take a look at the source of ping.
There are (at least) two popular packages that provide ping in GNU/Linux operating systems. One is netkit and the other iputils. (netkit-combo is a tarball which has all the netkit utilities in one: telnet, FTP, ...) The *BSD guys probably have their own.

Related

How to solve this simple one-way local machine messaging problem

I have a first sender script in Python 3.10 which needs to send some data
def post_updates(*args):
sender.send_message("optional_key", args)
Then a second receiver script in Python 3.7 which needs to receive this data
while True:
args = receiver.get_message("optional_key", blocking=True)
print("args received:", args)
Constraints:
Each script should not depend on the presence of the other to run.
The sender should try to send regardless if the receiver is running.
The receiver should try to receive regardless if the sender is running.
The message can consist of basic python objects (dict, list) and should be serialized automatically.
I need to send over 100 messages per second (minimizing latency if possible).
Local PC only (Windows) and no need for security.
Are there 1-liner solutions to this simple problem? Everything I look up seems overly complicated or requires a TCP server to be started beforehand. I don't mind installing popular modules.
UDP and JSON look perfect for what you're asking for, as long as
you don't need there to be more than one receiver
you don't need very large messages
you just need to send combinations of dicts, lists, strings, and numbers, not Python objects of arbitrary classes
you're not being overly literal about finding a "1-liner": it's a very small amount of code to write, and you're free to define your own helper functions.
Python's standard library has all you need for this. Encoding and decoding from JSON is as simple as json.dumps() and json.loads(). For sending and receiving, I suggest following the example on the Python wiki. You need to create the socket first with
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
regardless of if you're making the sender or the receiver. The receiver will then need to bind to the local port to listen to it:
sock.bind(('127.0.0.1', PORT))
And then the sender sends with sock.sendto() and the receiver receives with sock.recvfrom().
The good old pipe might do the job, but you need to assess how big the buffer size needs to be (given the async nature of your sender/receiver), and change the default pipe buffer size.

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.

Listening on port being used

Is there any way to listen to traffic on a specific port that another program is currently using, through the python socket module? For example:
|--> my program
external request -> Host ->|--> intended program
I am not looking to send back a response to the request, I simply want the traffic. I was looking at using the socket.SO_REUSEADDR method, but I think that's simply to avoid having to wait for the socket's timeout, not to allow another listener.
You can do that with scapy
see http://www.secdev.org/projects/scapy/doc/usage.html#sniffing
to use it in your own python program, you'd have to import the sniff command
from scapy.all import sniff
a=sniff("tcp and port 1337")
sniff has various options (callback functions, timeout, number of packets etc)
The socket.SO_REUSEADDR option helps both applications to be bound to the same port and to receive packets destined for that port. So, I am not sure what you mean by your timeout note in the question. The only catch is that for some of the platforms, including Linux, both the sockets must set SO_REUSEADDR, else, the second socket not be able to bind. So, if you cannot modify the intended program (let us say, it is a standard third-party program), then using SO_REUSEADDR might be a problem.

twisted - print IP datagrams from/to proxy

I have a twisted proxy from here: Python Twisted proxy - how to intercept packets .
It prints the HTTP data, and I would like also to intercept and examine the raw IP datgrams. How to hook the callback for the IP packets?
http://twistedmatrix.com/documents/11.0.0/api/twisted.pair.ip.IPProtocol.html
Twisted doesn't have a built-in friendly way to hook in a listener on a raw IP socket (SOCK_RAW). This is for several reasons:
using SOCK_RAW can be tricky and it can work in non-obvious ways;
in most environments, using such a socket requires elevated privileges;
and the packets you actually get through a raw socket differ a lot between operating systems (e.g., you won't get any raw TCP-protocol IP packets on *BSD/Darwin through a raw socket, even if you're root).
The best way to capture raw datagrams in general, in a remotely portable manner, is with libpcap. Here is a link to someone who appears to have combined pcap and Twisted in a reasonably intelligent way; that may help.
Twisted doesn't include comprehensive support for operating at the IP level. There is some support for parsing IP datagrams, as you found, but no built-in support for hooking into platform support for sending or receiving these.
You might want to take a look at scapy.

How can I perform a ping or traceroute using native python?

I would like to be able to perform a ping and traceroute from within Python without having to execute the corresponding shell commands so I'd prefer a native python solution.
If you don't mind using an external module and not using UDP or TCP, scapy is an easy solution:
from scapy.all import *
target = ["192.168.1.254"]
result, unans = traceroute(target,l4=UDP(sport=RandShort())/DNS(qd=DNSQR(qname="www.google.com")))
Or you can use the tcp version
from scapy.all import *
target = ["192.168.1.254"]
result, unans = traceroute(target,maxttl=32)
Please note you will have to run scapy as root in order to be able to perform these tasks or you will get:
socket.error: [Errno 1] Operation not permitted
Running interpreters as root is often frowned upon on security grounds (and of course you DO need to have root permission to access the "raw" socked as needed by the ICMP specs of ping and traceroute!), but if you have no problems with that it's not hard -- e.g., this post(dead?) or this post give a workable ping, and Jeremy Hylton's old page has still-usable underlying code for ICMP (both ping and traceroute) though it's written for very old Python versions and needs a litte facelift to shine with modern ones -- but, the concepts ARE all there, in both the URLs I gave you!
The Webb Library is very handy in performing all kinds of web related extracts...and ping and traceroute can be done easily through it. Just include the URL you want to traceroute to:
import webb
webb.traceroute("your-web-page-url")
If you wish to store the traceroute log to a text file automatically, use the following command:
webb.traceroute("your-web-page-url",'file-name.txt')
Similarly a IP address of a URl (server) can be obtained with the following lines of code:
print(webb.get_ip("your-web-page-url"))
Hope it helps!
The mtrpacket package can be used to send network probes, which can perform either a ping or a traceroute. Since it uses the back-end to the mtr commandline tool, it doesn't require that your script run as root.
It also uses asyncio's event loop, so you can have multiple ongoing traceroutes or pings simultaneously, and deal with their results as they complete.
Here is a Python script to traceroute to 'example.com':
import asyncio
import mtrpacket
async def trace():
async with mtrpacket.MtrPacket() as mtr:
for ttl in range(1, 256):
result = await mtr.probe('example.com', ttl=ttl)
print(result)
if result.success:
break
asyncio.get_event_loop().run_until_complete(trace())
The loop with 'ttl' is used because the 'time-to-live' of an outgoing packet determines the number of network hops the packet will travel before expiring and sending an error back to the original source.
you might want to check out the scapy package. it's the swiss army knife of network tools for python.
ICMP Ping is standard as part of the ICMP protocol.
Traceroute uses features of ICMP and IP to determine a path via Time To Live values. Using TTL values, you can do traceroutes in a variety of protocols as long as IP/ICMP work because it is the ICMP TTL EXceeded messages that tell you about the hop in the path.
If you attempt to access a port where no listener is available, by ICMP protocol rules, the host is supposed to send an ICMP Port Unreachable message.
I wrote a simple tcptraceroute in python which does not need root privileges http://www.thomas-guettler.de/scripts/tcptraceroute.py.txt
But it can't display the IP addresses of the intermediate hops. But sometimes it is useful, since you can guess where the blocking firewall is: Either at the beginning or at the end of the route.

Categories

Resources