I want to build "SIP sniffer" for my project to alert incoming call from VoIP communication.I try to call from my smartphone to my notebook and check incoming packet by wireshark. I see all SIP-message ( INVITE , BYE , TRYING ). I know basic of SIP ,it use UDP port 5060.
Next, I use this code from http://www.binarytides.com/python-packet-sniffer-code-linux/ <<--- last code , longest code ( I try to paste but I can't paste code in box ) run with Raspberry PI connect to notebook by LAN cable.
This program can sniff UDP packet, I check in wireshark it correct 90% ( IP address and IP destination not correct ) port and payload are correct. I checking header from ethernet header ===> ip header ===> udp header
it not different from SIP-INVITE , they different only payload ( check by wireshark ).
but i try to VoIP call to my notebook, It's not work , it never sniff 5060 or SIP packet ( one time i see outgoing call data : "sip:xxxx#linphone.org" )
Why i can sniff other but VoIP can't.
Sorry for my poor english.
thank you for your advice.
From the quick look , I see that your packets are UDP.
But the python code only sniffs for TCP.
#create an INET, raw socket s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
change socket.IPPROTO_TCP to socket.IPPROTO_UDP
#UDP packets
elif protocol == 17 :
u = iph_length + eth_length
udph_length = 8
udp_header = packet[u:u+8]
#now unpack them :)
udph = unpack('!HHHH' , udp_header)
source_port = udph[0]
dest_port = udph[1]
length = udph[2]
checksum = udph[3]
print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Length : ' + str(length) + ' Checksum : ' + str(checksum)
h_size = eth_length + iph_length + udph_length
data_size = len(packet) - h_size
#get data from the packet
data = packet[h_size:]
print 'Data : ' + data
#some other IP packet like IGMP
else :
print 'Protocol other than TCP/UDP/ICMP'
print
Related
I want to sending simple data with UDP protocol, I have tested on ubuntu and it worked, here's my code
import time
import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(("eno2", 0))
ethernet = b'\x7c\x10\xc9\x51\xb7\x7b' # MAC Address Destination
ethernet += b'\x7c\x10\xc9\x51\xb3\xd6' # MAC Address Source
ethernet += b'\x08\x00' # Protocol-Type: IPv4
ip_header = b'\x45\x00\x00\x2a' # Version, IHL, Type of Service | Total Length
ip_header += b'\xa0\x6a\x00\x00' # Identification | Flags, Fragment Offset
ip_header += b'\x80\x11\x0e\xe5' # TTL, Protocol | Header Checksum
ip_header += b'\xc0\xa8\x05\x0f' # Source Address
ip_header += b'\xc0\xa8\x05\x14' # Destination Address
udp_header = b'\xce\x55\xc3\x55' # Source Port | Destination Port
udp_header += b'\x00\x16\x1f\x83' # Sequence Number
data = b'\x68\x65\x6c\x6c'
data += b'\x6f\x20\x77\x6f'
data += b'\x72\x6c\x64\x20'
data += b'\x31\x31'
padding = b'\x00\x00\x00\x00'
packet = ethernet + ip_header + udp_header + data
while True:
s.send(packet)
time.sleep(0.5)
but when I running on windows AF_PACKET has no attribute on Socket module, so what similar AF_PACKET on windows? someone can help me?
I just want to send UDP RAW Data on windows
I followed the tutorial below to implement a packet sniffer in Python:
http://www.binarytides.com/python-packet-sniffer-code-linux/
On receiving each UDP packet, I would like to send an already saved pcap file (test.pcap). The following snippet shows my implementation:
# receive a packet
while True:
packet = s.recvfrom(65565)
#packet string from tuple
packet = packet[0]
#parse ethernet header
eth_length = 14
eth_header = packet[:eth_length]
eth = unpack('!6s6sH' , eth_header)
eth_protocol = socket.ntohs(eth[2])
print 'Destination MAC : ' + eth_addr(packet[0:6]) + ' Source MAC : ' +
eth_addr(packet[6:12]) + ' Protocol : ' + str(eth_protocol)
if eth_addr(packet[6:12]) != my_MAC_address:
#Parse IP packets, IP Protocol number = 8
if eth_protocol == 8 :
#Parse IP header
#take first 20 characters for the ip header
ip_header = packet[eth_length:20+eth_length]
#now unpack them :)
iph = unpack('!BBHHHBBH4s4s' , ip_header)
version_ihl = iph[0]
version = version_ihl >> 4
ihl = version_ihl & 0xF
iph_length = ihl * 4
ttl = iph[5]
protocol = iph[6]
s_addr = socket.inet_ntoa(iph[8]);
d_addr = socket.inet_ntoa(iph[9]);
print 'Version : ' + str(version) + ' IP Header Length : ' + str(ihl) + ' TTL : ' + str(ttl) + ' Protocol : ' + str(protocol) + ' Source Address : ' + str(s_addr) + ' Destination Address : ' + str(d_addr)
#UDP packets
if protocol == 17 :
u = iph_length + eth_length
udph_length = 8
udp_header = packet[u:u+8]
#now unpack them :)
udph = unpack('!HHHH' , udp_header)
source_port = udph[0]
dest_port = udph[1]
length = udph[2]
checksum = udph[3]
print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Length : ' + str(length) + ' Checksum : ' + str(checksum)
h_size = eth_length + iph_length + udph_length
data_size = len(packet) - h_size
#get data from the packet
data = packet[h_size:]
print 'Data : ' + data
my_pkt = rdpcap("test.pcap")
sendp(my_pkt)
Test.pcap contains a UDP packet with UDP_src=7777 and UDP_dest=9999.
Traffic is generated using netcat as follows:
nc -u -p 7777 ip_dst_addr 9999
The sniffer can receive only first netcat msg and send test.pcap in response. But subsequent netcat msgs are not received at all. However, using any other combination of UDP ports in netcat, the sniffer works fine. For example: running netcat as:
nc -u -p 8888 ip_dst_addr 9999
there is no problem and I am able to send test.pcap in response to each UDP packet/msg.
Any help would be greatly appreciated!
Scapy has several built-in sniffers, that are really easy to use.
>>> help(sniff)
Help on function sniff in module scapy.arch.windows.compatibility:
sniff(count=0, store=1, offline=None, prn=None, stop_filter=None, lfilter=None, L2socket=None, timeout=None, *arg, **karg)
Sniff packets
sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
Select interface to sniff by setting conf.iface. Use show_interfaces() to see interface names.
count: number of packets to capture. 0 means infinity
store: whether to store sniffed packets or discard them
prn: function to apply to each packet. If something is returned,
it is displayed. Ex:
ex: prn = lambda x: x.summary()
filter: provide a BPF filter
lfilter: python function applied to each packet to determine
if further action may be done
ex: lfilter = lambda x: x.haslayer(Padding)
offline: pcap file to read packets from, instead of sniffing them
timeout: stop sniffing after a given time (default: None)
L2socket: use the provided L2socket
stop_filter: python function applied to each packet to determine
if we have to stop the capture after this packet
ex: stop_filter = lambda x: x.haslayer(TCP)
Which means you could simply do:
packets = rdpcap("test.pcap")
sniff(lfilter=lambda x: x.haslayer(UDP) and x[Ether].src==sending_mac and x[UDP].sport==port, prn=lambda x: send(packets))
This will append all UDP packets to the test.pcap file
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 am trying to implement DHCP client in python.I used a raw socket.
s=socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
def ip_packet(source_ip,dest_ip):
ip_ihl = 5
ip_ver = 4
ip_tos = 0
ip_tot_len = 0
ip_id = 54321 #Id of this packet
ip_frag_off =0
ip_ttl = 255
ip_proto = socket.IPPROTO_UDP
ip_check = 0
ip_saddr = socket.inet_aton ( source_ip )
print ip_saddr.encode('hex')
ip_daddr = socket.inet_aton ( dest_ip )
ip_ihl_ver = (ip_ver << 4) + ip_ihl
ip_header = struct.pack('!BBHHHBBH4s4s' , ip_ihl_ver, ip_tos, ip_tot_len, ip_id, ip_frag_off, ip_ttl, ip_proto, ip_check, ip_saddr, ip_daddr)
return ip_header
s.sendto(packet,('255.255.255.255',67))
I sat the source ip address to 0.0.0.0 ,but when I sniffed the generated packet in wireshark ,I was surprised to see that the source ip address is sat to my real ip address.
But when I used Scapy everything worked as expacted
sendp(Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=hw)/DHCP(options=[("message-type","request")]),count=3)
So, how dose Scapy manage to set the source ip address to 0.0.0.0?? Is it possible to do that using raw socket ??
Intro:
I have an exercise where I need to send a file from S to D through a third party T only.
T is run on port 10000 or 11000 depending if i use UDP or TCP; i use UDP, and T's ip is given both to S and D.
T is given and all it does is echo messages it got back to the sender.
One of the fields in the header of T's echo message is called ip_id - a counter that goes up by one with each message T receives; in order to view the ip_id value i need to use raw sockets.
S/D sends a message to T and is then supposed to receive back a message. S/D needs to check that the ip and port that it got the message from matches the one it sent to (that is, if S/D sends a message to 1.1.1.1:5 it should receive a message from 1.1.1.1:5).
First I open a socket and a raw socket once
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.raw_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
I then get my port by doing:
self.s.sendto("1", (self.remote_server, UDP_PORT))
self.myPort = self.s.getsockname()[1]
UDP_PORT is 10000 and is the port to send messages to.
remote_server is the ip to send messages to.
I also have the following method:
def send_value(self, number_of_packets):
for i in range(0,number_of_packets):
self.s.sendto(BOGUS_DATA, (self.remote_server, UDP_PORT))
self.raw_socket.recvfrom(1024)
#self.raw_socket.recv(1024)
And as well as this one:
def recieve_ip_id(self):
try:
sent = 0
continueFlag = True
while continueFlag:
self.s.sendto(BOGUS_DATA, (self.remote_server, UDP_PORT))
#mypacket = self.raw_socket.recv(1024)
mypacket = self.raw_socket.recvfrom(1024)
mypacket = mypacket[0]
continueFlag = False
if (256*ord(mypacket[20])+ord(mypacket[21]) != UDP_PORT):
continueFlag = True
if (256*ord(mypacket[22])+ord(mypacket[23]) != self.myPort):
continueFlag = True
sent = sent + 1
ip_id = 256 * ord(mypacket[4]) + ord(mypacket[5])
print "packet 20 21 " + str(256*ord(mypacket[20])+ord(mypacket[21])) + " packet 4 5 " + str(256 * ord(mypacket[4]) + ord(mypacket[5])) + " packet 22 23 " + str(256*ord(mypacket[22])+ord(mypacket[23]))
print ip_id
return (ip_id, 0)
except socket.timeout:
# dummy
return (0, 0)
It works good enough in the sense that it checks correctly who it got the message from; The problem is that the ip_id wont advance as expected. after some time the programs are running they each get ip_id as if it was not shared anymore.
am i not checking something correctly, or is it something else?
Thanks.