How can I trigger my python script to automatically run via a ping?

2024/10/5 18:24:16

I wrote a script that recurses through a set of Cisco routers in a network, and gets traffic statistics. On the router itself, I have it ping to the loopback address of my host PC, after a traffic threshold, however now I need the script to run. Now I have one of two options. To either trigger the python script via a ping from the router to the loopback, or from an FTP upload to a folder on my PC. Problem with the folder idea is I'm not sure if I can make it run without constantly scanning through the folder. Since network traffic jumps up and down, I'd like to monitor it immediately as the router sends a message(whether it's ftp or ping etc).

Today, i tried a socket listener, but the router doesn't have native support for sending UDP datagrams. Also ping doesn't work with ports. I tried a ip address listener without using a port, currently my knowledge isn't good enough to know how to implement this. I've done socket programming before but not simply listening for ICMP pings(even still I'd have to capture the packet and look at the source IP address to make sure it's sourced from the router.)

Could anyone give me a clue how to implement this? My best preference would be a loopback listening script that captures packets and triggers the script once a source IP is from the router. Any ideas?

Ok, so by reading chapter 3 of Black Hat Python i borrowed their code and am almost done with a working solution. Everything works , except for 1 snag - The listener is printing out both the source ip and destination ip as resolved back to the loopback(in this case the destination). I've tried pinging from the routers, and from cmd by changing the source, the source address always resolved to my loopback address. I checked with wireshark and it showed a different source address, the one I was expecting. I attempted to see if I was looking at echo replies (although this should mean my source pops up as dest), and changed some socket.IPPROTO_ICMP parameters around, as well as toy around with header lengths. It's doing just that. it's printing my source address as my destination loopback. Any thoughts?

class IP:
def __init__(self, buff=None):header = struct.unpack('<BBHHHBBH4s4s4s', buff)self.ver = header[0] >> 4self.ihl = header[0] & 0xFself.tos = header[1]self.len = header[2]self.id = header[3]self.offset = header[4]self.ttl = header[5]self.protocol_num = header[6]self.sum = header[7]self.src = header[8]self.dst = header[9]self.trash = header[10]self.src_address = ipaddress.ip_address(self.src)self.dst_address = ipaddress.ip_address(self.dst)self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}try:self.protocol = self.protocol_map[self.protocol_num]except Exception as e:print('%s No protocol for %s' % (e, self.protocol_num))self.protocol = str(self.protocol_num)def sniff(host):socket_protocol = socket.IPPROTO_ICMPsniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)sniffer.bind((host, 0))sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)if os.name == 'nt':sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)try:while True:raw_buffer = sniffer.recvfrom(65535)[0]ip_header = IP(raw_buffer[0:24])print(f'Version: {ip_header.ver}')print(f'Header Length: {ip_header.ihl} TTL: {ip_header.ttl}')offset = ip_header.ihl * 4buf = raw_buffer[offset:offset + 8]icmp_header = ICMP(buf)print('ICMP -> Type: %s Code: %s\n' %(icmp_header.type, icmp_header.code))print('Protocol: %s %s -> %s' % (ip_header.protocol,ip_header.src_address,ip_header.dst_address))
host = '192.168.56.1'
IP.sniff(host)
Answer

You were pretty close in the code you have included in your previous (self-deleted) question, so with apologies, I will pull out the relevant part:

Can someone give me an idea of how to listen for incoming packets from 10.0.0.1 from my loopback address of 192.168.56.1? I've done some socket programming a good while ago, and haven't done much since, so having lots of trouble with this one.

You can in fact listen for ICMP from a Python process, provided that the process has the permission to open a raw socket to deal with that. The code you had included was basically there, this is the most minimal code that may demonstrate how this works:

import socket
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)if sys.platform == 'win32':# bind on the actual host is required on Windowshost = socket.gethostbyname(socket.gethostname())s.bind((host, 0))  # bind on everything# on Windows, including the IP headers...s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)# ... and listening to everything is required for ICMPs.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)(payload, (ip_src, _)) = s.recvfrom(65535)
# skip the first 28 bytes of IP/ICMP headers
print("payload %r from %s" % (payload[28:].decode('latin1'), ip_src))

Do note that raw sockets generally need root on Linux, or go through the dance to enable CAP_NET_RAW for the spawned Python process.

As for Windows, that ioctl call is needed to configure the socket to receive all packets (borrowed from the example from the official documentation) - likewise, administrator privileges is required to modify the interface like so.

On Linux, I initiated this command (in a separate terminal):

$ ping 192.168.178.50 -p 68656c6c6f20776f726c64 -s11 -c1
PATTERN: 0x68656c6c6f20776f726c64
PING 192.168.178.50 (192.168.178.50) 11(39) bytes of data.
19 bytes from 192.168.178.50: icmp_seq=1 ttl=64--- 192.168.178.50 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms

This is the output that gets produced:

payload 'hello world' from 192.168.178.50

Now to handle inputs triggers, the following bare bone listener is a skeleton that may be used to start building with:

import socket
import syss = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)if sys.platform == 'win32':# Windows require this addition to make this all workhost = socket.gethostbyname(socket.gethostname())s.bind((host, 0))  # bind on everythings.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)while True:(payload, (ip_src, _)) = s.recvfrom(65535)text = payload[28:].decode('latin1')# skip the first 28 bytes of IP/ICMP headersprint("payload %r from %s" % (text, ip_src))if ip_src == b'10.0.0.1':print('Received packet from 10.0.0.1, doing something...')# do_something()# unconditionally quit if the quit sequence was receivedif text == 'quit':print('quit received, terminating')break

If one were to send a payload (e.g. ping 192.168.178.50 -p 71756974 -s4 -c1) to the server, it will quit - if the source address is 10.0.0.1, the specific condition may be triggered.

https://en.xdnf.cn/q/119041.html

Related Q&A

How do I make my bot delete a message when it contains a certain word?

Okay so Im trying to make a filter for my bot, but one that isnt too complicated. Ive got this:@bot.event async def on_message(ctx,message):if fuck in Message.content.lower:Message.delete()But it gives…

pyinstaller cant find package Tix

I am trying to create an executable with pyinstaller for a python script with tix from tkinter. The following script also demonstrates the error: from tkinter import * from tkinter import tixroot = ti…

form.validate_on_submit() doesnt work(nothing happen when I submit a form)

Im creating a posting blog function for social media website and Im stuck on a problem: when I click on the "Post" button(on create_post.html), nothing happens.In my blog_posts/views.py, when…

How to find determinant of matrix using python

New at python and rusty on linear Algebra. However, I am looking for guidance on the correct way to create a determinant from a matrix in python without using Numpy. Please see the snippet of code belo…

How do I pass variables around in Python?

I want to make a text-based fighting game, but in order to do so I need to use several functions and pass values around such as damage, weapons, and health.Please allow this code to be able to pass &qu…

How to compare an item within a list of list in python

I am a newbie to python and just learning things as I do my project and here I have a list of lists which I need to compare between the second and last column and get the output for the one which has t…

Make for loop execute parallely with Pandas columns

Please convert below code to execute parallel, Here Im trying to map nested dictionary with pandas column values. The below code works perfectly but consumes lot of time. Hence looking to parallelize t…

Pre-calculate Excel formulas when exporting data with python?

The code is pulling and then putting the excel formulas and not the calculated data of the formula. xxtab.write(8, 3, "=H9+I9")When this is read in and stored in that separate file, it is sto…

Validating Tkinter Entry Box

I am trying to validate my entry box, that only accepts floats, digits, and operators (+-, %). But my program only accepts numbers not symbols. I think it is a problem with my conditions or Python Rege…

Imaplib with GMail offsets uids

Im querying my gmail inbox using pythons ImapLib with a range parameter, but my returned uids are offset from what I request. My request is as follows:M = imaplib.IMAP4_SSL(imap.gmail.com) M.login(USER…