I'm trying to write a socket server in Python that can receive ICMP packets.
Here's my code:
s = socket.socket(socket.AF_INET,socket.SOCK_RAW, socket.IPPROTO_ICMP)
host = socket.gethostbyname(socket.gethostname())
s.bind((host,0))
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
However, I dont know how to receive the packets - I tried using s.listen but it failed.
What am I missing or am I completly in the wrong direction?
Thanks!
I've done this before in twisted and I set the socket up like this:
import socket
def listen():
s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)
s.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
while 1:
data, addr = s.recvfrom(1508)
print "Packet from %r: %r" % (addr,data)
Building on the accepted answer, this code unpacks the received ICMP header and displays its data (ICMP type, code, etc)
s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)
s.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
while 1:
recPacket, addr = s.recvfrom(1024)
icmp_header = recPacket[20:28]
type, code, checksum, p_id, sequence = struct.unpack('bbHHh', icmp_header)
print "type: [" + str(type) + "] code: [" + str(code) + "] checksum: [" + str(checksum) + "] p_id: [" + str(p_id) + "] sequence: [" + str(sequence) + "]"
Related
i have a client will send some string to my server. However, i need to send twice so that the server get the package. So for every package client wants to send the server, it needs to send twice. I do not understand why it went in this way.
my server's code that does listening:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
myIp = "0x2A"
myPort = 2222
targetPort = 0
myAddress = ("localhost",myPort)
bufferSize = 1024
def listen():
print('starting up on {} port {}'.format(*myAddress))
sock.bind(myAddress)
# sock.listen(1)
print("waiting for message")
# connection, client_address = sock.accept()
while True:
received = sock.recvfrom(bufferSize)[0]
address = sock.recvfrom(bufferSize)[1]
received = json.loads(received.decode())
source = received.get("source")
destination = received.get("destination")
length = received.get("length")
message = received.get("message")
protocol = received.get("protocol")
print("the source is: " + source)
if destination == myIp:
print("the message is: " + message)
print('sending back to sender...')
sock.sendto(message.encode(),address)
if protocol == 0:
print("protocol is: " + str(protocol))
elif protocol == 1:
print("protocol is: " + str(protocol))
print("write data to log file....")
f = open("log.txt","w")
f.write(message)
print('done!')
elif protocol == 2:
print("protocol is: " + str(protocol))
# sock.close()
print("exit")
sock.close()
sys.exit()
else:
print("this is not my package: \n" + "destination Ip is: " + destination + "\n my Ip is: " + myIp)
if not received:
break
my client's code that does the sending:
def send():
try:
sock.sendto(message.encode(),serverAddress)
print("message: " + message + " is sent")
finally:
print('closing socket')
sock.close()
received = sock.recvfrom(bufferSize)[0]
address = sock.recvfrom(bufferSize)[1]
The first recvfrom will do the first read. The second recvfrom will do another read. Voila: you need two reads. Instead you should do a single read:
received, address = socket.recvfrom(bufferSize)
I'm attempting to read incoming/outgoing TCP packets through an interface on the host for a project I'm working on. I really want this to be done using sockets instead of using a library like scapy or pypcap. To have a better understanding of what is happening as well as more control over what is happening. This is on a Windows10 system.
import socket
import threading
from PacketParse import PacketParse
host = socket.gethostbyname(socket.gethostname())
sniff = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
sniff.bind((host, 0))
#include ip headers - IP PROTOCOL, IP HEADER INCLUDE
sniff.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
#receive all packages - INPUT OUTPUT CONTROL
sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
def start_sniffing():
while True:
raw_packet = sniff.recvfrom(2000)
packet = PacketParse(raw_packet)
if packet:
print(packet.src_addr + ":" + str(packet.src_port) + " --> " + packet.dst_addr + ":" + str(packet.dst_port) + " Protocol: " + packet.ip_prot + "(" + str(packet.ip_prot_raw) + ")")
print("Data(" + str(packet.data_size) + "): " + str(packet.data))
#file.write(packet.src_addr + ":" + str(packet.src_port) + " --> " + packet.dst_addr + ":" + str(packet.dst_port) + " Protocol: " + packet.ip_prot + "(" + str(packet.ip_prot_raw) + ")")
#file.write("Data(" + str(packet.data_size) + "): " + str(packet.data))'''
file = open("dump.txt", "a")
t = threading.Thread(target=start_sniffing)
t.start()
t.join()
file.close()
sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
PacketParse is a class I made to 'unpack' the packet. I've been using Python documentation for most of this script and tutorials for sniffing packets from many sources.
from struct import unpack
class PacketParse:
def __init__(self, packet):
self.extract(packet)
def extract(self, packet):
# extract ip header
packet = packet[0]
self.packet_raw = packet
'''
eth_raw = packet[:14]
eth_hdr = unpack('!6s6sH', eth_raw)
self.eth_prot = socket.ntohs(eth_hdr[2])
self.src_mac =
'''
ip_raw = packet[0:20]
ip_hdr = unpack('!BBHHHBBH4s4s', ip_raw)
#self.ip_length = ip_hdr[5]
self.ip_prot_raw = ip_hdr[6]
self.ip_prot = self.ip_prot_parse(ip_hdr[6])
self.src_addr = socket.inet_ntoa(ip_hdr[8])
self.dst_addr = socket.inet_ntoa(ip_hdr[9])
version = ip_hdr[0] >> 4
ihl_length = version & 0xF
iph_len = ihl_length * 4
tcp_raw = packet[20:40]
tcp_hdr = unpack('!HHLLBBHHH', tcp_raw)
self.src_port = tcp_hdr[0]
self.dst_port = tcp_hdr[1]
self.seq_num = tcp_hdr[2]
self.ack_num = tcp_hdr[3]
doff_reserved = tcp_hdr[4]
tcp_length = doff_reserved >> 4
header_size = (iph_len) + (tcp_length * 4)
self.data_size = len(packet) - header_size
self.data = packet[header_size:]
def ip_prot_parse(self, num):
return {
1: 'ICMP',
6: 'TCP',
17: 'UDP',
}.get(num, "Unknown")
The issue is this only shows packets being sent out from this host. Incoming packets are not displayed. A different script I've tried using scapy is capable of displaying incoming packets as well. Why is this happening? SIO_RCVALL should be allowing ALL packets being touched by the interface to be seen. I haven't tried a Linux equivalent of this script... so I don't know if the problem is specific on Windows. Most TCP reading scripts I've found have been Linux specific.
Alright... so it seems the problem was my firewall. When I turn it off, I can see all incoming packets just fine. That was a bit annoying. I believe there is a python library that allows you to edit firewall settings.
https://github.com/austin-taylor/bluewall
I haven't played around with it yet... it could be interesting. I haven't read into it enough yet to understand if this is what it seems. I believe it only gives you the configuration on Windows without changing anything. It could be fun on a Linux system.
I'm creating a log server, that write incoming and outgoing connections (any type) to a TXT file . everything is working fine and here is my code :
from scapy.all import *
import datetime
from threading import Thread
from Queue import Queue, Empty
from scapy.layers.dns import DNS, DNSQR
firstime = 0
times = time.time()+86400
def print_summary(pkt):
global firstime
global times
if IP in pkt:
ip_src=pkt[IP].src
ip_dst=pkt[IP].dst
else:
ip_src="Null"
ip_dst="Null"
mac_src="Null"
mac_dst="Null"
if TCP in pkt:
tcp_sport=pkt[TCP].sport
tcp_dport=pkt[TCP].dport
else:
tcp_sport="Null"
tcp_dport="Null"
if DNSQR in pkt:
dns = pkt.qd.qname
else:
dns = "NULL"
if Ether in pkt:
mac_src = pkt[Ether].src
mac_dst = pkt[Ether].dst
else:
mac_src = "Null"
mac_dst = "Null"
Clog = " IP src: " + str(ip_src) +" ,MAC src: " + str(mac_src) + " , IP dst: " + str(ip_dst) +" ,MAC dst: "+str(mac_dst)+" ,TCP sport: " + str(tcp_sport) + ",TCP dport: " + str(tcp_dport) +", Time: " + str(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(pkt.time))) + " Dns: "+dns
if(times > pkt.time):
if(firstime == 0):
f = open("/root/Desktop/LOG-SERVER/"+time.strftime('%Y-%m-%d %H:%M:', time.localtime(time.time()))+".txt",'a')
f.write(Clog+"\n")
f.close()
else:
f.write(Clog+"\n")
f.close()
else:
f = open("/root/Desktop/LOG-SERVER/"+time.strftime('%Y-%m-%d %H:%M:', time.localtime(time.time()))+".txt",'a')
f.write(Clog+"\n")
f.close()
times=times+86400
def startsnif():
sniff(prn=print_summary, store=0)
# you can filter with something like that
#if ( ( pkt[IP].src == "192.168.0.1") or ( pkt[IP].dst == "192.168.0.1") ):
# print("!")
#def writing(log,indexp):
#if(indexp == 0):
#f = open("/root/Desktop/LOG-SERVER/"+time.strftime('%Y-%m-%d %H:%M:', time.localtime(time.time()))+".txt",'a')
#f.write(log+"\n")
#f.close()
#else:
#f.write(log+"\n")
#f.close()
thread.start_new_thread(startsnif,());
while 1:
pass
# or it possible to filter with filter parameter...!
#sniff(filter="ip and host 192.168.0.1",prn=print_summary)
output is:
IP Src: 192.168.10.1 MAC Src: 54:55:12:FC:2D:CA IP Dst:192.168.10.15 MAC Src: 54:55:12:FC:1F:3A TCP sport: 80 TCP dport: 51233 Time:2015-12-16 13:25:11 DNS:Null(IF available DNS Name)
the problem is that the company got mikrotics, mikrotics mirror traffic through a technique called TZSP Sniff which encapsulate the packet with the IP of the router and MAC of the router IP of the destination PC MAC of the destination pc, i was searching and i couldn't find any appropriate solution but i read that you need to strip first 5 bytes of a packet.
is there a way to strip the TZSP encapsulation live(without saving PCAP), could you please explain the process because I'm new to this stuff?
please if you have any question ask I'm not very good in explaining stuff.
Thank you!
After examining the binary of the TZSP packet header it appears that TZSP strip original mac address after adding it's own, so the project was closed thank you for the help.
I'm currently working with twisted in python and I'm trying to make a multicast between many peers(each of them can send and receive messages, send acks etc). My main looks like this :
if __name__ == '__main__':
serial_process_num, address = parse_args()
if serial_process_num == '0':
factory = PeerFactory('0', 'log')
reactor.listenTCP(address[1], factory)
reactor.listenTCP(address[1]+1, factory)
print "Process 0 is listening #" + address[0] + " port " + str(address[1])
print "Process 0 is listening #" + address[0] + " port " + str(address[1]+1)
elif serial_process_num == '1':
factory = PeerFactory('1', '')
host, port = address
print "Connecting to process 0 " + host + " port " + str(port)
reactor.connectTCP(host, port, factory)
print "Process 1 is listening #" + address[0] + " port " + str(address[1]+2)
reactor.listenTCP(port+2, factory)
else:
factory = PeerFactory('2', '')
host, port = address
print "Connecting to process 0 " + host + " port " + str(port+1)
reactor.connectTCP(host, port+1, factory)
print "Connecting to process 1 " + host + " port " + str(port+2)
reactor.connectTCP(host, port+2, factory)
reactor.run()
I kept this one simple because I want to understand my mistake, so im using only 3 peers.I start the first one with serial_process_num 0 from the cmd (ex py example.py 0), then the 1 and 2.Am I setting up the listeners/connecttcp correctly? Whenever I send messages between those 3, I only receive half of them in every peer. (i use self.transport.write('example')
Is there an alternative way to multicast through TCPconnect in twisted?(im following krondos tutorial) and how can I make multiple connections between multiple peers with twisted?
Multicast is a datagram protocol, which means that you do not have a stream of bytes in the same way that you do with TCP; in other words, it's a kind of UDP. So no, you cannot use TCP with it, in Twisted or otherwise.
if data.find('!scan') != -1:
nick = data.split('!')[ 0 ].replace(':','')
targetip = str(socket.gethostbyname(args))
sck.send('PRIVMSG ' + chan + " :" ' scanning host' + " " + targetip + '\r\n')
for i in range(20, 1025):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = s.connect_ex((targetip, i))
if (result == 0) :
s.send('PRIVMSG ' + chan + " :" 'port %d: OPEN' % (i,) + '\r\n')
s.close()
The script works, but it ping timeout before it can get an open port, how can I make it so it can scan a few ports then check for a ping from the server and send a pong then scan a few more ports so that it wont ping timeout.
The best solution is to use multiple threads, with the main thread parsing input from IRC and responding to PINGs, while other threads do actual command processing and anything that could take a long time.
skybot, my IRC bot, spawns a new thread whenever a command is issued, and uses thread-safe queues to pass messages between them.