Whenever I send a SYN packet using my program, I get no reply.I know the server is working because I can connect to it using the normal socket connect() method but when I try using RAW sockets to do it I get no reply, not even an RST.
Here is my packet according to Wireshark
Transmission Control Protocol, Src Port: 5173 (5173), Dst Port: 5005 n (5005), Seq: 0, Len: 0
Source Port: 5173
Destination Port: 5005
[Stream index: 15]
[TCP Segment Len: 0]
Sequence number: 0 (relative sequence number)
Acknowledgment number: 0
Header Length: 40 bytes
Flags: 0x002 (SYN)
000. .... .... = Reserved: Not set
...0 .... .... = Nonce: Not set
.... 0... .... = Congestion Window Reduced (CWR): Not set
.... .0.. .... = ECN-Echo: Not set
.... ..0. .... = Urgent: Not set
.... ...0 .... = Acknowledgment: Not set
.... .... 0... = Push: Not set
.... .... .0.. = Reset: Not set
.... .... ..1. = Syn: Set
.... .... ...0 = Fin: Not set
[TCP Flags: **********S*]
Window size value: 53270
[Calculated window size: 53270]
Checksum: 0x9f18 [incorrect, should be 0x90ae (maybe caused by "TCP checksum offload"?)]
Urgent pointer: 0
Options: (20 bytes), Maximum segment size, SACK permitted, Timestamps, No-Operation (NOP), Window scale
Maximum segment size: 65495 bytes
Kind: Maximum Segment Size (2)
Length: 4
MSS Value: 65495
TCP SACK Permitted Option: True
Kind: SACK Permitted (4)
Length: 2
Timestamps: TSval 378701, TSecr 0
Kind: Time Stamp Option (8)
Length: 10
Timestamp value: 378701
Timestamp echo reply: 0
No-Operation (NOP)
Type: 1
0... .... = Copy on fragmentation: No
.00. .... = Class: Control (0)
...0 0001 = Number: No-Operation (NOP) (1)
Window scale: 7 (multiply by 128)
[SEQ/ACK analysis]
And here is my Python code
#!/usr/bin/python
import socket
from struct import *
import random
s = socket.socket()
host = "127.0.0.1"
destination = "127.0.0.1"
CLRF = '\r\n'
#socket.gethostname()
print destination
port = 5173
#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#s.connect((host, 5005))
try:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
except socket.error , msg:
print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
ipSource = '192.168.0.106'
#IP header
ipIHL = 5 # Header Length
ipVersion = 4 # ipv4/v6
ipTOS = 0 # type of service
ipTotalLen = 0 ## Kernel will fill correct length apparently
ipPackID = random.randint(1,1000)
#Flags
ipReserved = 0
ipNoFrag = 1
ipMoreFrags = 0
ipFragOffset = 0 #Fragment offset
ipTTL = 64
ipProtocol = socket.IPPROTO_TCP
ipChecksum = 0 # Magic kernel filling in at work again
ipSource = socket.inet_aton (host)
ipDest = socket.inet_aton (destination)
#Packing IP flags
ipFlags = ipMoreFrags + (ipNoFrag << 1) + (ipReserved << 2)
ipFragOffset = (ipFlags << 13) + ipFragOffset
ipIHLVersion = (ipVersion << 4) + ipIHL
headerIP = pack('!BBHHHBBH4s4s',ipIHLVersion, ipTOS, ipTotalLen, ipPackID, ipFragOffset, ipTTL, ipProtocol, ipChecksum, ipSource, ipDest)
#Checksum function
def carry_around_add(a, b):
c = a + b
return (c & 0xffff) + (c >> 16)
def checksum(msg):
s = 0
for i in range(0, len(msg), 2):
w = ord(msg[i]) + (ord(msg[i+1]) << 8)
s = carry_around_add(s, w)
return ~s & 0xffff
#TCP Header
tcpSourcePort = port #Source Port
tcpDestPort = 5005 #Destination Port
tcpSeqNum = 0 #Packet sequence
tcpAckNum = 0 #Ackknowledge Number
tcpOffset = 10 #Size of tcp header 20 bytes
#tcpReserved = 0
#tcpECN = 0
#Control Flags
tcpURG = 0
tcpACK = 0
tcpPSH = 0
tcpRST = 0
tcpSYN = 1
tcpFIN = 0
tcpWindow = socket.htons (5840) #Dunno how this works
tcpChecksum = 0
tcpUrgentPointer = 0
#TCP Options
tcpMaxSegmentSize = (2 << 24) + (4 << 16) + 65495 # Kind + Length + Max Segment Size
tcpSACKPermitted = (4 << 8) + 2#Kind + Length
#Split TCP TImestamps into 2 because too large
tcpTimestampPartOne = (8 << 8) + (10) #Kind + Length
tcpTimestampPartTwo = (378701 << 32) + 0 #Timestamp Value + Timestamp echo reply
tcpNoOp = (0 << 7) + (0 << 5) + 1 #Copy on fragmentation + Class + Number
tcpWindowScale = (3 << 16)+ (3 << 8) + 7 #Kind + Length(Bytes) +Shift CountS
#Combine both due to length issues
tcpNoOpAndWindowScale = (tcpNoOp << 24) + tcpWindowScale
tcpOffsetResult = (tcpOffset << 4) + 0 #Shift 4 bytes to left
#Putting together all the TCP Control Flags
tcpFlags = tcpFIN + (tcpSYN << 1) + (tcpRST << 2) + (tcpPSH << 3) + (tcpACK << 4) + (tcpURG << 5)
#Packing the pseudo TCP header
headerTCP = pack('!HHLLBBHHHLHHQL', tcpSourcePort, tcpDestPort, tcpSeqNum, tcpAckNum, tcpOffsetResult, tcpFlags, tcpWindow, tcpChecksum, tcpUrgentPointer, tcpMaxSegmentSize, tcpSACKPermitted, tcpTimestampPartOne, tcpTimestampPartTwo, tcpNoOpAndWindowScale)
#headerTCP = pack('!HHLLBBHHH', tcpSourcePort, tcpDestPort, tcpSeqNum, tcpAckNum, tcpOffsetResult, tcpFlags, tcpWindow, tcpChecksum, tcpUrgentPointer)
#data = 'GET ./asd HTTP/1.1'
data = ''
#Checksum Calculation
#Pseudo Header Fields
sourceAddr = socket.inet_aton(host)
destAddr = socket.inet_aton(destination)
placeholder = 0
protocol = socket.IPPROTO_TCP
tcpLen = len(headerTCP) + len(data)
psh = pack('!4s4sBBH', sourceAddr, destAddr, placeholder, protocol, tcpLen);
psh = psh + headerTCP + data;
#Calc checksum
tcpChecksumReal = (checksum(psh) << 1)
print(tcpChecksumReal)
#Pack actual tcp header with checksum
headerTCP = pack('!HHLLBBH', tcpSourcePort, tcpDestPort, tcpSeqNum, tcpAckNum, tcpOffsetResult, tcpFlags, tcpWindow) + pack('!H', 40728) + pack ('!H', tcpUrgentPointer) + pack('!LHHQL', tcpMaxSegmentSize, tcpSACKPermitted, tcpTimestampPartOne, tcpTimestampPartTwo, tcpNoOpAndWindowScale)
#Build full packet / ip with tcp with data
packet = headerIP + headerTCP + data
#print [hex(ord(c)) for c in packet]
s.sendto(packet, (destination,0))
Any help would be appreciated, thanks in advance.
Credits to #KenCheung for the answer
Turns out it was the checksum, the checksum from the headers I used as reference also were incorrect but the network card was offloading them.
Related
I'm creating a function to calculate packet capture delay using Python and pcap, but this error happens. I'm taking this function from a C example as I'm new to Python. This is the error:
Traceback (most recent call last):
File "prototype_sniffer_v1.py", line 266, in processing_pkts
Bps = ((pkt + 8) * 8 * 1000000) / (delay) TypeError: unsupported operand type(s) for +: 'LP_c_ubyte' and 'int'
Exception ignored on calling ctypes callback function: <function processing_pkts at 0x7fbed299df70>
This link Gathering Statistics on the network traffic contain the C code example.
This is C example:
#include <stdlib.h>
#include <stdio.h>
#include <pcap.h>
#include <tchar.h>
BOOL LoadNpcapDlls()
{
_TCHAR npcap_dir[512];
UINT len;
len = GetSystemDirectory(npcap_dir, 480);
if (!len) {
fprintf(stderr, "Error in GetSystemDirectory: %x", GetLastError());
return FALSE;
}
_tcscat_s(npcap_dir, 512, _T("\\Npcap"));
if (SetDllDirectory(npcap_dir) == 0) {
fprintf(stderr, "Error in SetDllDirectory: %x", GetLastError());
return FALSE;
}
return TRUE;
}
void usage();
void dispatcher_handler(u_char *, const struct pcap_pkthdr *, const u_char *);
void main(int argc, char **argv)
{
pcap_t *fp;
char errbuf[PCAP_ERRBUF_SIZE];
struct timeval st_ts;
u_int netmask;
struct bpf_program fcode;
/* Load Npcap and its functions. */
if (!LoadNpcapDlls())
{
fprintf(stderr, "Couldn't load Npcap\n");
exit(1);
}
/* Check the validity of the command line */
if (argc != 2)
{
usage();
return;
}
/* Open the output adapter */
if ( (fp= pcap_open(argv[1], 100, PCAP_OPENFLAG_PROMISCUOUS,
1000, NULL, errbuf) ) == NULL)
{
fprintf(stderr,"\nUnable to open adapter %s.\n", errbuf);
return;
}
/* Don't care about netmask, it won't be used for this filter */
netmask=0xffffff;
//compile the filter
if (pcap_compile(fp, &fcode, "tcp", 1, netmask) <0 )
{
fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
/* Free the device list */
return;
}
//set the filter
if (pcap_setfilter(fp, &fcode)<0)
{
fprintf(stderr,"\nError setting the filter.\n");
pcap_close(fp);
/* Free the device list */
return;
}
/* Put the interface in statstics mode */
if (pcap_setmode(fp, MODE_STAT)<0)
{
fprintf(stderr,"\nError setting the mode.\n");
pcap_close(fp);
/* Free the device list */
return;
}
printf("TCP traffic summary:\n");
/* Start the main loop */
pcap_loop(fp, 0, dispatcher_handler, (PUCHAR)&st_ts);
pcap_close(fp);
return;
}
void dispatcher_handler(u_char *state,
const struct pcap_pkthdr *header,
const u_char *pkt_data)
{
struct timeval *old_ts = (struct timeval *)state;
u_int delay;
LARGE_INTEGER Bps,Pps;
struct tm ltime;
char timestr[16];
time_t local_tv_sec;
/* Calculate the delay in microseconds from the last sample. This value
* is obtained from the timestamp that the associated with the sample. */
delay = (header->ts.tv_sec - old_ts->tv_sec) * 1000000
- old_ts->tv_usec + header->ts.tv_usec;
/* Get the number of Bits per second */
Bps.QuadPart=(((*(LONGLONG*)(pkt_data + 8)) * 8 * 1000000) / (delay));
/* ^ ^
| |
| |
| |
converts bytes in bits -- |
|
delay is expressed in microseconds --
*/
/* Get the number of Packets per second */
Pps.QuadPart=(((*(LONGLONG*)(pkt_data)) * 1000000) / (delay));
/* Convert the timestamp to readable format */
local_tv_sec = header->ts.tv_sec;
localtime_s(<ime, &local_tv_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", <ime);
/* Print timestamp*/
printf("%s ", timestr);
/* Print the samples */
printf("BPS=%I64u ", Bps.QuadPart);
printf("PPS=%I64u\n", Pps.QuadPart);
//store current timestamp
old_ts->tv_sec=header->ts.tv_sec;
old_ts->tv_usec=header->ts.tv_usec;
}
void usage()
{
printf("\nShows the TCP traffic load, in bits per second and packets per second."
"\nCopyright (C) 2002 Loris Degioanni.\n");
printf("\nUsage:\n");
printf("\t tcptop adapter\n");
printf("\t You can use \"WinDump -D\" if you don't know the name of your adapters.\n");
exit(0);
}
This is my Python function:
import libpcap as pcap
import ctypes as ct
import socket
import getopt
import os
import time
import funcoes_auxiliares
from struct import *
from libpcap._platform import sockaddr, sockaddr_in, sockaddr_in6
from pcaptestutils import *
pd = ct.POINTER(pcap.pcap_t)()
if not is_windows:
breaksigint = False
#static void sigint_handler(int signum _U_)
def sigint_handler(signum):
global pd
global breaksigint
if breaksigint:
pcap.breakloop(pd)
def main(argv=sys.argv[1:]):
global program_name
program_name = os.path.basename(sys.argv[0])
global pd
global breaksigint
global ip_afinet
global ip_afinet6
# Exceção para os parâmetros
try:
opts, args = getopt.getopt(argv, "i:mnt:" if is_windows else "bi:mnrst:")
except getopt.GetoptError:
usage()
device = None
timeout = 1000
nonblock = 0
immediate = False
if not is_windows:
sigrestart = False
catchsigint = False
for opt, optarg in opts:
if not is_windows and opt == '-b':
breaksigint = True
elif opt == '-i':
device = optarg.encode("utf-8")
elif opt == '-m':
immediate = True
elif opt == '-n':
nonblock = 1
elif not is_windows and opt == '-r':
sigrestart = True
elif not is_windows and opt == '-s':
catchsigint = True
elif opt == '-t':
try:
timeout = int(optarg)
except:
error('Timeout value "{}" is not a number', optarg)
if timeout < 0:
error("Timeout value {:d} is negative", timeout)
if timeout > INT_MAX:
error("Timeout value {:d} is too large (> {:d})",
timeout, INT_MAX)
else:
usage()
expression = args
errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE)
# ----------------------------------------------------------
# Lista de dispositivos disponíveis
if device is None:
deviceList = ct.POINTER(pcap.pcap_if_t)()
if pcap.findalldevs(ct.byref(deviceList), errbuf) == -1:
error("{}", ebuf2str(errbuf))
if not deviceList:
error("Não há interfaces disponíveis para captura")
print('\nAvailable network devices:')
devices = deviceList
while devices:
device = devices.contents
print("\t[*] {}".format(device.name.decode("utf-8")))
devices = device.next
device = deviceList[0].name
ip_tuple = funcoes_auxiliares.getStdIp(deviceList[0])
(ip_afinet, ip_afinet6) = ip_tuple
# print(ip_afinet)
# print(ip_afinet6)
pcap.freealldevs(deviceList)
# ----------------------------------------------------------
errbuf[0] = b"\0"
# if not is_windows:
# # If we were told to catch SIGINT, do so.
# if catchsigint:
# action = sigaction()
# action.sa_handler = sigint_handler
# sigemptyset(ct.byref(action.sa_mask))
# # Should SIGINT interrupt, or restart, system calls?
# action.sa_flags = SA_RESTART if sigrestart else 0
# if sigaction(SIGINT, ct.byref(action), NULL) == -1:
# error("Can't catch SIGINT: {}", strerror(errno))
pd = pcap.create(device, errbuf)
if not pd:
error("{}", ebuf2str(errbuf))
# define o comprimento do instantâneo a ser usado
# em um identificador de captura quando o
# identificador é ativado para snaplen.
status = pcap.set_snaplen(pd, 65535)
if status != 0:
error("{}: pcap.set_snaplen failed: {}",
device2str(device), status2str(status));
if immediate:
try:
status = pcap.set_immediate_mode(pd, 1)
except AttributeError:
error("pcap.set_immediate_mode is not available on this platform")
if status != 0:
error("{}: pcap.set_immediate_mode failed: {}",
device2str(device), status2str(status))
status = pcap.set_timeout(pd, timeout)
if status != 0:
error("{}: pcap.set_timeout failed: {}",
device2str(device), status2str(status))
status = pcap.activate(pd)
if status < 0:
# pcap.activate() failed.
error("{}: {}\n({})",
device2str(device), status2str(status), geterr2str(pd))
elif status > 0:
# pcap.activate() succeeded, but it's warning us
# of a problem it had.
warning("{}: {}\n({})",
device2str(device), status2str(status), geterr2str(pd))
localnet = pcap.bpf_u_int32()
netmask = pcap.bpf_u_int32()
if pcap.lookupnet(device, ct.byref(localnet), ct.byref(netmask), errbuf) < 0:
localnet = pcap.bpf_u_int32(0)
netmask = pcap.bpf_u_int32(0)
warning("{}", ebuf2str(errbuf))
fcode = pcap.bpf_program()
cmdbuf = " ".join(expression).encode("utf-8")
if pcap.compile(pd, ct.byref(fcode), cmdbuf, 1, netmask) < 0:
error("{}", geterr2str(pd))
if pcap.setfilter(pd, ct.byref(fcode)) < 0:
error("{}", geterr2str(pd))
if pcap.setnonblock(pd, nonblock, errbuf) == -1:
error("pcap.setnonblock failed: {}", ebuf2str(errbuf))
# -----------------------------------------
# create a save file for write
savefile = 'testsavefile'
savefile = savefile.encode('utf-8')
pdd = pcap.dump_open_append(pd, savefile)
if not pdd:
error("{}", geterr2str(pd))
# -----------------------------------------
print("\nSniffing on device: \n\t*{}*".format(device2str(device)))
if os.path.exists("qtdPktpTime.txt"):
os.remove("qtdPktpTime.txt")
cont_i = 0
while cont_i <= 10:
# while True:
packet_count = ct.c_int(0)
status = pcap.dispatch(pd, -1, processing_pkts,
ct.cast(ct.pointer(packet_count), ct.POINTER(ct.c_ubyte)))
# execute for write in save file
pcap.dispatch(pd, -1, pcap.dump,
ct.cast(pdd, ct.POINTER(ct.c_ubyte)))
if status < 0:
break
if status != 0:
print("\n{:d} packets seen, {:d} packets counted after "
"pcap.dispatch returns".format(status, packet_count.value))
ps = pcap.stat()
pcap.stats(pd, ct.byref(ps))
print("{:d} ps_recv, {:d} ps_drop, {:d} ps_ifdrop".format(
ps.ps_recv, ps.ps_drop, ps.ps_ifdrop))
print("\n")
cont_i += 1
if status == pcap.PCAP_ERROR_BREAK:
# We got interrupted, so perhaps we didn't manage to finish a
# line we were printing. Print an extra newline, just in case.
print()
print("Broken out of loop from SIGINT handler")
sys.stdout.flush()
if status == pcap.PCAP_ERROR:
# Error. Report it.
print("{}: pcap.dispatch: {}".format(program_name, geterr2str(pd)),
file=sys.stderr)
pcap.freecode(ct.byref(fcode))
pcap.close(pd)
funcoes_auxiliares.plotGraf1()
return 1 if status == -1 else 0
# --------------------------------------------------------------------------------------
# AUXILIAR FUNCTIONS
# --------------------------------------------------------------------------------------
# Convert a string of 6 characters of ethernet address into a dash separated hex string
def eth_addr (a) :
b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]) , ord(a[1]) , ord(a[2]), ord(a[3]), ord(a[4]) , ord(a[5]))
return b
# Função callback usada no processamento dos pacotes
#pcap.pcap_handler
def processing_pkts(arg, hdr, pkt):
counterp = ct.cast(arg, ct.POINTER(ct.c_int))
counterp[0] += 1
old_ts_tv_sec = 0
old_ts_tv_usec = 0
pkt_addr = hdr.contents
pkt_time_cap = pkt_addr.ts
pkt_len = pkt_addr.len
pkt_caplen = pkt_addr.caplen
eth_length = 14
eth_header = pkt[:eth_length]
eth = unpack('!6s6sH' , bytes(eth_header))
eth_protocol = socket.ntohs(eth[2])
count_pkt = 0
delay = (pkt_time_cap.tv_sec - old_ts_tv_sec) * 1000000 - old_ts_tv_usec + pkt_time_cap.tv_usec
Bps = (ct.cast(pkt,ct.POINTER(ct.c_uint64))[1] * 8 * 1000000) / (delay)
Pps = (ct.cast(pkt,ct.POINTER(ct.c_uint64))[0] * 1000000) / delay
old_ts_tv_sec = pkt_time_cap.tv_sec
old_ts_tv_usec = pkt_time_cap.tv_usec
print('Bps: ' + str(int(Bps)))
print('Pps: ' + str(int(Pps)))
time_cap = time.ctime(pkt_time_cap.tv_sec)
# Parser IP packets
if eth_protocol == 8:
ip_header = pkt[eth_length:20+eth_length]
iph = unpack('!BBHHHBBH4s4s' , bytes(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) + ' | ' + 'length: ' + str(pkt_len) + ' | ' + 'cap length: ' + str(pkt_caplen) + ' | ' + 'Cap time: ' + str(pkt_time_cap))
print('\nVersion: ' + str(version) + '| IP Header Length: ' + str(ihl) + ' | ' + 'TTL: ' + str(ttl) + ' | ' + 'Protocol: ' + str(protocol) + ' | ' +'Source Address: ' + str(s_addr) + ' | ' +'Destination Address: ' + str(d_addr) + ' | ' + 'length: ' + str(pkt_len))
count_pkt = 0
if s_addr == ip_afinet:
# print('confirma ip')
count_pkt += 1
arq_qtdPktpTime = open("qtdPktpTime.txt", "a")
arq_qtdPktpTime.write(time_cap + ',' + str(counterp[0]) + '\n')
# funcoes_auxiliares.plotGraf1()
# TCP protocol
if protocol == 6:
t = iph_length + eth_length
tcp_header = pkt[t:t+20]
tcph = unpack('!HHLLBBHHH' , bytes(tcp_header))
source_port = tcph[0]
dest_port = tcph[1]
sequence = tcph[2]
acknowledgement = tcph[3]
doff_reserved = tcph[4]
tcph_length = doff_reserved >> 4
print('Source Port: ' + str(source_port) + ' >> Dest Port: ' + str(dest_port) + ' >> Sequence Number: ' + str(sequence) + ' >> Acknowledgement: ' + str(acknowledgement) + ' >> TCP header length: ' + str(tcph_length))
h_size = eth_length + iph_length + tcph_length * 4
# data_size = len(pkt) - h_size
# data_size = pkt_len - h_size
#get data from the packet
data = pkt[h_size:pkt_len]
# print('Data : ' + str(data))
# UDP procotol
elif protocol == 17:
u = iph_length + eth_length
udph_length = 8
udp_header = pkt[u:u+8]
udph = unpack('!HHHH' , bytes(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))
print('Source Port: ' + str(source_port) + ' >> Dest Port: ' + str(dest_port) + ' >> Checksum: ' + str(checksum))
h_size = eth_length + iph_length + udph_length
# data = pkt[h_size:pkt_len]
# print(data)
# pcap.dump
# função para captura e uso de parametros no execução do código no terminal
def usage():
print("Usage: {} [ {} ] [ -i interface ] [ -t timeout] "
"[ expression ]".format(program_name,
"-mn" if is_windows else "-bmnrs"), file=sys.stderr)
sys.exit(1)
# --------------------------------------------------------------------------------------
if __name__.rpartition(".")[-1] == "__main__":
sys.exit(main())
Can help me to solve this ?? I appreciate any tips
The C code the OP is porting and generating an error in Python is:
/* Calculate the delay in microseconds from the last sample. This value
* is obtained from the timestamp that the associated with the sample. */
delay = (header->ts.tv_sec - old_ts->tv_sec) * 1000000
- old_ts->tv_usec + header->ts.tv_usec;
/* Get the number of Bits per second */
Bps.QuadPart=(((*(LONGLONG*)(pkt_data + 8)) * 8 * 1000000) / (delay));
/* ^ ^
| |
| |
| |
converts bytes in bits -- |
|
delay is expressed in microseconds --
*/
/* Get the number of Packets per second */
Pps.QuadPart=(((*(LONGLONG*)(pkt_data)) * 1000000) / (delay));
The Python code is missing the casting and dereferencing of the pkt_data + 8 byte pointer calculation. Since *(LONGLONG*)(pkt_data + 8) == ((LONGLONG*)(pkt_data))[1], the Python code implements cast and dereference of the latter version:
delay = (pkt_time_cap.tv_sec - old_ts_tv_sec) * 1000000 - old_ts_tv_usec + pkt_time_cap.tv_usec
Bps = ct.cast(pkt,ct.POINTER(ct.c_uint64))[1] * 8 * 1000000 / delay
Pps = ct.cast(pkt,ct.POINTER(ct.c_uint64))[0] * 1000000 / delay
Since there isn't a functional example I'll demonstrate by creating a byte pointer to two 64-bit values to test the code is correct. The original code was adding 8 to a byte pointer, casting to a 64-bit pointer and dereferencing it. That's the same thing as casting directly to a 64-bit pointer and indexing the 2nd value, e.g. *(LONGLONG*)(pkt_data + 8) == ((LONGLONG*)(pkt_data))[1]:
>>> import ctypes as ct
>>> data = (ct.c_uint64 * 2)(100,200)
>>> pkt = ct.cast(ct.byref(data), ct.POINTER(ct.c_ubyte))
>>> pkt
<__main__.LP_c_ubyte object at 0x000002D38C9BA5C0>
>>> pkt + 8
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'LP_c_ubyte' and 'int'
Above demonstrates the same error as the OP due to pkt being a byte pointer. Below casts the pointer back to a 64-bit pointer and accesses the 2nd value:
>>> ct.cast(pkt,ct.POINTER(ct.c_uint64))[1]
200
I need to sniff DNS packets with scapy in python.
I have created a script that works, but when I run the script with my c++ code I am getting these warnings:
WARNING: wrong value: DNS.qdcount=6334
WARNING: DNS RR prematured end (ofs=7080, len=1460)
WARNING: wrong value: DNS.arcount=32966
and as a result, the packet is missing data. A packet that was sniffed using running the script with C++ :
WARNING: wrong value: DNS.qdcount=6334
WARNING: DNS RR prematured end (ofs=7080, len=1460)
WARNING: wrong value: DNS.arcount=32966
[ Ethernet ]
dst = 48:2c:a0:5f:bb:50
src = b8:81:98:86:ee:f3
type = 0x800
[ IP ]
version = 4
ihl = 5
tos = 0x0
len = 1500
id = 1659
flags = MF
frag = 0
ttl = 128
proto = udp
chksum = 0x670d
src = 192.168.43.127
dst = 54.194.132.159
\options \
[ UDP ]
sport = 50066
dport = domain
len = 1530
chksum = 0x40a1
[ DNS ]
id = 2564
qr = 0
opcode = QUERY
aa = 1
tc = 0
rd = 1
ra = 1
z = 1
ad = 1
cd = 0
rcode = 8
qdcount = 6334
ancount = 1
nscount = 0
arcount = 32966
qd = ''
\an \
|###[ DNS Resource Record ]###
| rrname = '.'
| type = 41326
| rclass = 58674
| ttl = 582309185
| rdlen = 1448
| rdata = b'Q\xdd\xa9\x87?\xe3w\x9c\x00F\xd9\x9a2\xd6\xd5\x9f\xd1;r\xfb\xe7S\x13\xecm\x19wP\xd8\xfd\xd8\xec\x9bA\xb0\xe1\xb0\xea\x8fNw\xc4\xf2\x12\x8b\x89J1n\xb8\xacc\x07M1\xe2\x18\x08\x8e\x9f\xb1\x01\xfb\xbe">\x0etq::F\xbfek\x94\xdcN\xa5s\xfd4\xf36\x96\xd7\xd8a\x8c\x1e1\xa6\x97\xd9\x1f\xeaz\x91\x0b\x93ZLI\x15`$\x1b\x96(\xe5\x02\xb0\n\x08\x82\xb6\xa7+4\xca\xc3\xf8\xe7\x05}T\x1c_{\x884E\xcd,#\x0emx&+h\xa1\xd2\x95\x04\xa7x\xb8\xeaD\xecS\xd7s,\xeb\xff\xa0M\xd5\xcb\x00\xe6\x0e\x1dqa\xdeo\x9c\xdc\xb6#\x02pA;,2]\xa7\xe7\xc79l\x02\xf4\xd2\x197Ccd\x0c\x8eU9\xc6\x9e\x9d\xad\xffa\xc6\xe3be\xce\xee\x94,\x973(\xac\xdak\xd2.w\x89O~\xfc\x99YSB\xb1W\x99F\x15/r\x81p\x8a{\x1b_}\xbb\x9c\x19\xca\xa4\x1a}\xdd\x99\xc0\xe3\x9c\xdf|\x81M\x04\xd1\t\xcb\xf4\x95\x17[\x9ej"M\x07\xec\x93\xb8DO.\x94W\xc3eg|\x9a\\\x8b\xa2\xf36\x82d\x80\xcd!\xb2\xcd\xe9:#\x103%\xfd\xfa\xd1\xe5\xe4\xd2\xbe\xb5\x7fF(`\x85\xedW\xd9\x98\xff\xe7A3\x92\x93\xd3\x19\x9f\xe7\x1b\x17\xaa\x81\x1cS\xee\xed\x94Q\xf1\x98\x02\x1fH\xba\xc5\x87\x03\x94\xa0\xee9\xb8\xc5_q\xe6P\xf7G\x0e\x12\x8b"C\xa7j\xf9\x19<\xd6\x8d+\xaf\x0c\x8c\xce\xbf\xfcN\xc8\xb4\xe8\xed\x18\xddShe\xb2T\x80\xfbAu\xb3kj\xc9\x1b\xcd\xa1\xde4>\xb3,\xb4\x8b\xa7\x1c7\ra\x19\x86\x94\x8f\xa7\xa3\xae-&\xac\xa1v\xd5Q\x94\x884\x1d&\xbf\xd4\xc9\xe6\x88\xd88\xca+\x9e\xd3\xe4\xdf\x83F\xf0\x16\x12\xf0\xb6\xdet\x1eCE\x9e\x1eQje\xa7\xc2\x13\xa79e\xbcUr\x8d#\x85c\xd0\x8f\t\x95\xa3\xf6\x84f\xfa\x9e\xc5\x1f\xd2\xdet\xc3\x17\xdb=\x92\xab\xfe\xa1\xf4sN\xbeH#\xe5\xc1\xd8\x04\xca\xca\xc8\xf9\xe3p-q.\x10\x1e|5^\xea8slX?\x86\xee,b\x9f\xe3L\xeaxTr\x86\x8c\xa1\xce\x9a\xc1\xcf\x82\x16p\xde\xe5\xc6\xb9\xf6\x03\x15\xfc\xea\x1f\x14az\r\xd9\xbd\x80`\x15\x12[\xfbW\xda\xab6\xd8\xfbZ\x00\xe5)\xae\xd0\x18\x97\x11\xd8\xfa\xe0\xec\x9a\xa7\x8f<\xb3\x98\xd7C\x08\x9cp1kj\x9f\x9a\xe08\xa0SR>\x95\x82\xcd\x12\xacD<\xdd\x1e\xec\x95q\x87}LE\xc6G\xf1\x12.\xe1\xbe\xdfG\x0cV\x1c\xfcr\xdfnW\x94\xfbVR\x16_\n\x83Qv\x04\x1e4\xc4\xfeHBi)\x1a\n\x06\xa5l#\x818\x11\x14!\xa0>\xcfv\\\nT\xb2\xe1\x89R\'\x90\xa5\x90\xb3\xd2\xc5)\xc0R\xf6\x99^\xe1\xf0\x0f(\xf4\\\xbex\x8aq\xbf\x8d\xdel#\x15<v4\xef]\xfdr\xe2\x11\x82\xe1\x03\x0e\x1f\xd1\xa5\xdf\xd1~\xe9\xdd\xfdAG\x7f\x7f\xbd\xac\xbb\x9c\x08\xe6LjsN\xf1\xf5G\xe8*6\x86\x8b\x1b\r\x9ck\xabOU\x91\xf1\xba\r[\xf7\x970\xc4\xdd\x84>\x859u\xe7\xa6[\xf5m\x9f\x1a\x8f\xc0\xc7y\xd2\x8b\x89Q\xa8\xfau\x12\xa3#\x84N\x0c/\x9akHp\x0c\x07\xd1j\x86\xf6\x04\x8f\x85\x00\xaa2\xfap\xb9\xd1\x00\xdb\x91R\xb2\xf3\xcc\xfc\xfdB\x1em\xb0\xd0\x88\x05\x0f\x0f\xae41\xbd\xffqA\x01\x8a\xd8D\xa0\xb7D\xcei\x91$p\r\xc4B\xe5\x98\xee\x9aX\x1c1\xcdc\xa0\\Ycy1\xbb`\x8f\x07\x1f\xef\xc6\x9c+3,\r\xd4cHnBDLw9\x8e,\xff=\x1d\x92\xbfw\xfbd\xbe\xc2~\x8dH\xc8Ht\xc1Om\xe1N\x00\xd4&\xb4\x07E\xf16\xaa\x00\xea(?%\xb8?\xf9/\xc5\x94\x84\xac\xcc`\xdd+\x02\xe1MOi\xd6e\xbc\x1c\x94o`\x8f\xcax#\x94\xc3\xf1b\xea\x8d\x1f\xc0Cg\x93\xe3\xd6\xf3<\xed$D\xf7\x82\x05\xe9\xa7\xcc\x19?\xb4b\xe3\xc4\x83\xb7}\xcf\x89O\xe4\xce\x1a\xfd`a\xbeGs\xb2\xc2\xa2\x8d\xfdFTXR\xf2\xab\xffF\x12v\n\x98\xe9\x90\xc1d\x01\x83W\xd7}[D\xee\x1fc\xefG\xa2\xbf\xdff\xa0.\xc7\xbf\x13/_\x1c\xc5L\xc5\x17b\xc5\xd3P\xad\xc4S\x07\x02\xfd\x85\x90g\x04u\x9fW\xda\x1fq\xb4\x06\xf4\xb9\x1b\x9e\xe2a/K\xd7b\xf2d\x03\xfba\x0e\xb4\x89\x16;0~V\xab\x95\xc3\x90\xd1\xee\xb7b\xfcp\x86As\xa3h\xf2$\x12\x9f\xa3\xa6i\xefl\xc6p~Ww\x95\xdcr\x17\xe0S\xd0\x8d\xee\xe1\x00\xe5A\xa1~\xceh\xf3(\x1cB\xba\x8e\xa8E7\rr>=:u\xecpz\xa2\x01L\x88\xb9\t\xe7\xec;\xef\xa1\xff\xdf%.9\xf4\x13\xcau\xa0\xb8H\x07`\xda\xe8T\xf3c\xb0\xf0\x17\xbc\xa5:\x8b\xb3\x9dFRM\xdd\ty:\xcd\xaa\x80~K:iy\xac=\xe5\xa2\xaca\xd6\xc7\xc87\xc4\x08\xad\x87\xe8h\xa3i\x89\xaa\xea\xb9\xf5\x10\xabsw\xf0\xae\xa0Q7\xb6\x11\x1b\xe9\x89\x94fU\x96i+^\xba\xa2\x9e\xf1\xe2R\xe5y_\xb0;\xa7\xe8B\x0ef\xb9\xaf\xa8\xba\xfa\xd6\xf1\xb6ta{\xd3\xe4QtC\x8b\x92\xe9\xc6\xe0)\x90\xdfP\xb5K\xf2n|\xf9\xba\xa5-o\xban\xddN\x96\xc4\xcaC\x93\x96\xf3\xf9\xe9N\x16\xdf\x80\t\x05\xee\xf7\xa2\x94\xe0\x02\xd3k\x102\xbe\xb7W/G\xc5\x96\x9d\x8a\xe3\xa2^\xc7,\xd4\xf3|\xafH\n\x15ftV\xb0\xef\xc5\xaf\xef`\x00_S\x89d\x0cbSa\xb4\x9cN\xde\xaeIM#:F\xcc\x00\x01\x1e\xd7P,\n\x07\xcd\xed\x9f\xd1\x92\xc2\xae\xec\x9a\xe5\xd2v\xff\xb2\xe5\xe4-JN\x02\xae\xfa\xd4m\x82\x9eL0V\xd8C\xd1GL\xdc'
ns = None
ar = ''
[ Raw ]
load = b'\xdb\xb4\xa1n\xe52"\xb5UA*\x9bQ\xdd\xa9\x87?\xe3w\x9c\x00F\xd9\x9a2\xd6\xd5\x9f\xd1;r\xfb\xe7S\x13\xecm\x19wP\xd8\xfd\xd8\xec\x9bA\xb0\xe1\xb0\xea\x8fNw\xc4\xf2\x12\x8b\x89J1n\xb8\xacc\x07M1\xe2\x18\x08\x8e\x9f\xb1\x01\xfb\xbe">\x0etq::F\xbfek\x94\xdcN\xa5s\xfd4\xf36\x96\xd7\xd8a\x8c\x1e1\xa6\x97\xd9\x1f\xeaz\x91\x0b\x93ZLI\x15`$\x1b\x96(\xe5\x02\xb0\n\x08\x82\xb6\xa7+4\xca\xc3\xf8\xe7\x05}T\x1c_{\x884E\xcd,#\x0emx&+h\xa1\xd2\x95\x04\xa7x\xb8\xeaD\xecS\xd7s,\xeb\xff\xa0M\xd5\xcb\x00\xe6\x0e\x1dqa\xdeo\x9c\xdc\xb6#\x02pA;,2]\xa7-\xe7\xc79l\x02\xf4\xd2\x197Ccd\x0c\x8eU9\xc6\x9e\x9d\xad\xffa\xc6\xe3be\xce\xee\x94,\x973(\xac\xdak\xd2.w\x89O~\xfc\x99YSB\xb1W\x99F\x15/r\x81p\x8a{\x1b_}\xbb\x9c\x19\xca\xa4\x1a}\xdd\x99\xc0\xe3\x9c\xdf|\x81M\x04\xd1\t\xcb\xf4\x95\x17[\x9ej"M\x07\xec\x93\xb8DO.\x94W\xc3eg|\x9a\\\x8b\xa2\xf36\x82d\x80\xcd!\xb2\xcd\xe9:#\x103%\xfd\xfa\xd1\xe5\xe4\xd2\xbe\xb5\x7fF(`\x85\xedW\xd9\x98\xff\xe7A3\x92\x93\xd3\x19\x9f\xe7\x1b\x17\xaa\x81\x1cS\xee\xed\x94Q\xf1\x98\x02\x1fH\xba\xc5\x87\x03\x94\xa0\xee9\xb8\xc5_q\xe6P\xf7G\x0e\x12\x8b"C\xa7j\xf9\x19<\xd6\x8d+\xaf\x0c\x8c\xce\xbf\xfcN\xc8\xb4\xe8\xed\x18\xddShe\xb2T\x80\xfbAu\xb3kj\xc9\x1b\xcd\xa1\xde4>\xb3,\xb4\x8b\xa7\x1c7\ra\x19\x86\x94\x8f\xa7\xa3\xae-&\xac\xa1v\xd5Q\x94\x884\x1d&\xbf\xd4\xc9\xe6\x88\xd88\xca+\x9e\xd3\xe4\xdf\x83F\xf0\x16\x12\xf0\xb6\xdet\x1eCE\x9e\x1eQje\xa7\xc2\x13\xa79e\xbcUr\x8d#\x85c\xd0\x8f\t\x95\xa3\xf6\x84f\xfa\x9e\xc5\x1f\xd2\xdet\xc3\x17\xdb=\x92\xab\xfe\xa1\xf4sN\xbeH#\xe5\xc1\xd8\x04\xca\xca\xc8\xf9\xe3p-q.\x10\x1e|5^\xea8slX?\x86\xee,b\x9f\xe3L\xeaxTr\x86\x8c\xa1\xce\x9a\xc1\xcf\x82\x16p\xde\xe5\xc6\xb9\xf6\x03\x15\xfc\xea\x1f\x14az\r\xd9\xbd\x80`\x15\x12[\xfbW\xda\xab6\xd8\xfbZ\x00\xe5)\xae\xd0\x18\x97\x11\xd8\xfa\xe0\xec\x9a\xa7\x8f<\xb3\x98\xd7C\x08\x9cp1kj\x9f\x9a\xe08\xa0SR>\x95\x82\xcd\x12\xacD<\xdd\x1e\xec\x95q\x87}LE\xc6G\xf1\x12.\xe1\xbe\xdfG\x0cV\x1c\xfcr\xdfnW\x94\xfbVR\x16_\n\x83Qv\x04\x1e4\xc4\xfeHBi)\x1a\n\x06\xa5l#\x818\x11\x14!\xa0>\xcfv\\\nT\xb2\xe1\x89R\'\x90\xa5\x90\xb3\xd2\xc5) \xc0R\xf6\x99^\xe1\xf0\x0f(\xf4\\\xbex\x8aq\xbf\x8d\xdel#\x15<v4\xef]\xfdr\xe2\x11\x82\xe1\x03\x0e\x1f\xd1\xa5\xdf\xd1~\xe9\xdd\xfdAG\x7f\x7f\xbd\xac\xbb\x9c\x08\xe6LjsN\xf1\xf5G\xe8*6\x86\x8b\x1b\r\x9ck\xabOU\x91\xf1\xba\r[\xf7\x970\xc4\xdd\x84>\x859u\xe7\xa6[\xf5m\x9f\x1a\x8f\xc0\xc7y\xd2\x8b\x89Q\xa8\xfau\x12\xa3#\x84N\x0c/\x9akHp\x0c\x07\xd1j\x86\xf6\x04\x8f\x85\x00\xaa2\xfap\xb9\xd1\x00\xdb\x91 R\xb2\xf3\xcc\xfc\xfdB\x1e-m\xb0\xd0\x88\x05\x0f\x0f\xae41\xbd\xffqA\x01\x8a\xd8D\xa0\xb7D\xcei\x91$p\r\xc4B\xe5\x98\xee\x9aX\x1c1\xcdc\xa0\\Ycy1\xbb`\x8f\x07\x1f\xef\xc6\x9c+3,\r\xd4cHnBDLw9\x8e,\xff=\x1d\x92\xbfw\xfbd\xbe\xc2~\x8dH\xc8Ht\xc1Om\xe1N\x00\xd4&\xb4\x07E\xf16\xaa\x00\xea(?%\xb8?\xf9/\xc5\x94\x84\xac\xcc`\xdd+\x02\xe1MOi\xd6e\xbc\x1c\x94o`\x8f\xcax#\x94\xc3\xf1b\xea\x8d\x1f\xc0Cg\x93\xe3\xd6\xf3<\xed$D\xf7\x82\x05\xe9\xa7\xcc\x19?\xb4b\xe3\xc4\x83\xb7}\xcf\x89O\xe4\xce\x1a\xfd`a\xbeGs\xb2\xc2\xa2\x8d\xfdFTXR\xf2\xab\xffF\x12v\n\x98\xe9\x90\xc1d\x01\x83W\xd7}[D\xee\x1fc\xefG\xa2\xbf\xdff\xa0.\xc7\xbf\x13/_\x1c\xc5L\xc5\x17b\xc5\xd3P\xad\xc4S\x07\x02\xfd\x85\x90g\x04u\x9fW\xda\x1fq\xb4\x06\xf4\xb9\x1b\x9e\xe2a/K\xd7b\xf2d\x03\xfba\x0e\xb4\x89\x16;0~V\xab\x95\xc3\x90\xd1\xee\xb7b\xfcp\x86As\xa3h\xf2$\x12\x9f\xa3\xa6i\xefl\xc6p~Ww\x95\xdcr\x17\xe0S\xd0\x8d\xee\xe1\x00\xe5A\xa1~\xceh\xf3(\x1cB\xba\x8e\xa8E7\rr>=:u\xecpz\xa2\x01L\x88\xb9\t\xe7\xec;\xef\xa1\xff\xdf%.9\xf4\x13\xcau\xa0\xb8H\x07`\xda\xe8T\xf3c\xb0\xf0\x17\xbc\xa5:\x8b\xb3\x9dFRM\xdd\ty:\xcd\xaa\x80~K:iy\xac=\xe5\xa2\xaca\xd6\xc7\xc87\xc4\x08\xad\x87\xe8h\xa3i\x89\xaa\xea\xb9\xf5\x10\xabsw\xf0\xae\xa0Q7\xb6\x11\x1b\xe9\x89\x94fU-\x96i+^\xba\xa2\x9e\xf1\xe2R\xe5y_\xb0;\xa7\xe8B\x0ef\xb9\xaf\xa8\xba\xfa\xd6\xf1\xb6ta{\xd3\xe4QtC\x8b\x92\xe9\xc6\xe0)\x90\xdfP\xb5K\xf2n|\xf9\xba\xa5-o\xban\xddN\x96\xc4\xcaC\x93\x96\xf3\xf9\xe9N\x16\xdf\x80\t\x05\xee\xf7\xa2\x94\xe0\x02\xd3k\x102\xbe\xb7W/G\xc5\x96\x9d\x8a\xe3\xa2^\xc7,\xd4\xf3|\xafH\n\x15ftV\xb0\xef\xc5\xaf\xef`\x00_S\x89d\x0cbSa\xb4\x9cN\xde\xaeIM#:F\xcc\x00\x01\x1e\xd7P,\n\x07\xcd\xed\x9f\xd1\x92\xc2\xae\xec\x9a\xe5\xd2v\xff\xb2\xe5\xe4-JN\x02\xae\xfa\xd4m\x82\x9eL0V\xd8C\xd1GL\xdc'
A packet that was sniffed with Python compiler:
[ Ethernet ]###
dst = 48:2c:a0:5f:bb:50
src = b8:81:98:86:ee:f3
type = 0x800
[ IP ]
version = 4
ihl = 5
tos = 0x0
len = 61
id = 30144
flags =
frag = 0
ttl = 128
proto = udp
chksum = 0xec5d
src = 192.168.43.127
dst = 192.168.43.194
\options \
[ UDP ]
sport = 63691
dport = domain
len = 41
chksum = 0xf1c7
[ DNS ]
id = 34891
qr = 0
opcode = QUERY
aa = 0
tc = 0
rd = 1
ra = 0
z = 0
ad = 0
cd = 0
rcode = ok
qdcount = 1
ancount = 0
nscount = 0
arcount = 0
\qd \
|###[ DNS Question Record ]###
| qname = 'docs.python.org.'
| qtype = A
| qclass = IN
an = None
ns = None
ar = None
I have initialized the script using Python.h class in c++, and I need the 'qname' field in the packet.
any solution will be appreciated.
Consider this simple python dns spoofer:
#!/usr/bin/python3
import socket
from scapy.all import *
port = 53
def handle(payload):
data = payload[0]
src_ip = payload[1][0]
src_port = payload[1][1]
print("-" * 10 + " Incoming " + "-" * 10)
a = DNS(data)
a.show2()
output = IP(dst=src_ip, chksum = 0)/ UDP(sport=53, dport=src_port) / DNS(id=a.id, qr=1, opcode=a.opcode, aa=1, tc=0, rd=1, ra=1, z=0, ad=0, cd=0, rcode=0, qdcount=1, ancount=1, nscount=0, arcount=0,qd=DNSQR(qname=a[DNS].qd.qname, qtype=a[DNS].qd.qtype, qclass=a[DNS].qd.qclass), an=DNSRR(rrname='cnn.com', rdata='192.168.1.100'), )
print("-" * 10 + " Output " + "-" * 10)
output.show2()
send(output)
if __name__ == "__main__":
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # create a socket object
s.bind(("", port))
while True:
payload = s.recvfrom(1024)
handle(payload)
I would run it from sudo (so I can bind to udp port 53):
$ sudo python3 -i ./dns_python.py
However my requests to it are timing out:
$ host cnn.com 127.0.0.1
;; connection timed out; no servers could be reached
I need help to figure out how to spoof successfully:
Some more details:
$ sudo python3 -i ./dns_python.py
---------- Incoming ----------
###[ DNS ]###
id = 59652
qr = 0
opcode = QUERY
aa = 0
tc = 0
rd = 1
ra = 0
z = 0
ad = 0
cd = 0
rcode = ok
qdcount = 1
ancount = 0
nscount = 0
arcount = 0
\qd \
|###[ DNS Question Record ]###
| qname = 'cnn.com.'
| qtype = A
| qclass = IN
an = None
ns = None
ar = None
---------- Output ----------
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 76
id = 1
flags =
frag = 0
ttl = 64
proto = udp
chksum = 0x0
src = 127.0.0.1
dst = 127.0.0.1
\options \
###[ UDP ]###
sport = domain
dport = 36774
len = 56
chksum = 0xb87f
###[ DNS ]###
id = 59652
qr = 1
opcode = QUERY
aa = 1
tc = 0
rd = 1
ra = 1
z = 0
ad = 0
cd = 0
rcode = ok
qdcount = 1
ancount = 1
nscount = 0
arcount = 0
\qd \
|###[ DNS Question Record ]###
| qname = 'cnn.com.'
| qtype = A
| qclass = IN
\an \
|###[ DNS Resource Record ]###
| rrname = 'cnn.com.'
| type = A
| rclass = IN
| ttl = 0
| rdlen = 4
| rdata = '192.168.1.100'
ns = None
ar = None
.
Sent 1 packets.
I see packets when I watch from a ngrep -d lo '' src or dst port 53 window. Any help would much appreciated!
Scapy does not work with 127.0.0.1 or on the loopback interface
http://scapy.readthedocs.io/en/latest/troubleshooting.html
The loopback interface is a very special interface. Packets going through it are not really assembled and disassembled. The kernel routes the packet to its destination while it is still stored an internal structure. What you see with tcpdump -i lo is only a fake to make you think everything is normal. The kernel is not aware of what Scapy is doing behind his back, so what you see on the loopback interface is also a fake. Except this one did not come from a local structure. Thus the kernel will never receive it.
In order to speak to local applications, you need to build your packets one layer upper, using a PF_INET/SOCK_RAW socket instead of a PF_PACKET/SOCK_RAW (or its equivalent on other systems than Linux):
I am using the following code to get the temperature of a PT100 (3-wire) and a PT1000 (2-wire) simultaneously on my raspberry.
According to https://cdn-learn.adafruit.com/downloads/pdf/adafruit-max31865-rtd-pt100-amplifier.pdf my wiring is correct.
from Max31865 import Max31865
maxGarraum = Max31865()
maxGarraum.initPt100_3WireSensor(26, True)
maxFleisch = Max31865()
maxFleisch.initPt1000_2WireSensor(24, True)
while True:
maxGarraum.getCurrentTemp()
time.sleep(1)
My Max31865.py looks like the following:
import time, math
import RPi.GPIO as GPIO
# import numpy
class Max31865():
def initPt1000_2WireSensor(self, iCsPin):
self.csPin = iCsPin
# Fleischsensor Pt1000 (2-wire)
self.registerCode = 0xA2
self.setupGPIO()
def initPt100_3WireSensor(self, iCsPin):
self.csPin = iCsPin
# Garraumsensor Pt100 (3-wire)
self.registerCode = 0xB2
self.setupGPIO()
def setupGPIO(self):
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(self.csPin, GPIO.OUT)
GPIO.setup(self.misoPin, GPIO.IN)
GPIO.setup(self.mosiPin, GPIO.OUT)
GPIO.setup(self.clkPin, GPIO.OUT)
GPIO.output(self.csPin, GPIO.HIGH)
GPIO.output(self.clkPin, GPIO.LOW)
GPIO.output(self.mosiPin, GPIO.LOW)
def getCurrentTemp(self):is
# b10000000 = 0x80
# 0x8x to specify 'write register value'
# 0xx0 to specify 'configuration register'
#
# 0b10110010 = 0xB2
# Config Register - https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
# ---------------
# bit 7: Vbias -> 1 (ON)
# bit 6: Conversion Mode -> 0 (MANUAL)
# bit 5: 1-shot ->1 (ON)
# bit 4: 3-wire select -> 1 (3 wire config) (0 for 2-/4-wire)
# bit 3-2: fault detection cycle -> 0 (none)
# bit 1: fault status clear -> 1 (clear any fault)
# bit 0: 50/60 Hz filter select -> 0 (60Hz)
#
# 0b11010010 or 0xD2 for continuous auto conversion
# at 60Hz (faster conversion)
# one shot
self.writeRegister(0, self.registerCode)
# conversion time is less than 100ms
time.sleep(.1) # give it 100ms for conversion
# read all registers
out = self.readRegisters(0, 8)
conf_reg = out[0]
#print("Config register byte: %x" % conf_reg)
[rtd_msb, rtd_lsb] = [out[1], out[2]]
rtd_ADC_Code = ((rtd_msb << 8) | rtd_lsb) >> 1
temp = self.calcTemperature(rtd_ADC_Code)
"""
# High fault threshold
[hft_msb, hft_lsb] = [out[3], out[4]]
hft = ((hft_msb << 8) | hft_lsb) >> 1
# Low fault threshold
[lft_msb, lft_lsb] = [out[5], out[6]]
lft = ((lft_msb << 8) | lft_lsb) >> 1
print ("High fault threshold: ", hft , " --- Low fault threshold: " , lft)
"""
status = out[7]
# 10 Mohm resistor is on breakout board to help
# detect cable faults
# bit 7: RTD High Threshold / cable fault open
# bit 6: RTD Low Threshold / cable fault short
# bit 5: REFIN- > 0.85 x VBias -> must be requested
# bit 4: REFIN- < 0.85 x VBias (FORCE- open) -> must be requested
# bit 3: RTDIN- < 0.85 x VBias (FORCE- open) -> must be requested
# bit 2: Overvoltage / undervoltage fault
# bits 1,0 don't care
# print "Status byte: %x" % status
if ((status & 0x80) == 1):
raise FaultError("High threshold limit (Cable fault/open)")
if ((status & 0x40) == 1):
raise FaultError("Low threshold limit (Cable fault/short)")
if ((status & 0x04) == 1):
raise FaultError("Overvoltage or Undervoltage Error")
return temp
def writeRegister(self, regNum, dataByte):
GPIO.output(self.csPin, GPIO.LOW)
# 0x8x to specify 'write register value'
addressByte = 0x80 | regNum;
# first byte is address byte
#print("Cs-Pin: ", self.csPin, "Addresse: ", addressByte)
self.sendByte(addressByte)
# the rest are data bytes
self.sendByte(dataByte)
GPIO.output(self.csPin, GPIO.HIGH)
def readRegisters(self, regNumStart, numRegisters):
out = []
GPIO.output(self.csPin, GPIO.LOW)
# 0x to specify 'read register value'
self.sendByte(regNumStart)
for byte in range(numRegisters):
data = self.recvByte()
out.append(data)
GPIO.output(self.csPin, GPIO.HIGH)
return out
def sendByte(self, byte):
for bit in range(8):
GPIO.output(self.clkPin, GPIO.HIGH)
if (byte & 0x80):
GPIO.output(self.mosiPin, GPIO.HIGH)
else:
GPIO.output(self.mosiPin, GPIO.LOW)
byte <<= 1
GPIO.output(self.clkPin, GPIO.LOW)
def recvByte(self):
byte = 0x00
for bit in range(8):
GPIO.output(self.clkPin, GPIO.HIGH)
byte <<= 1
if GPIO.input(self.misoPin):
byte |= 0x1
GPIO.output(self.clkPin, GPIO.LOW)
return byte
def calcTemperature(self, RTD_ADC_Code):
global temp
R_REF = 0.0 # Reference Resistor
Res0 = 0.0; # Resistance at 0 degC for 400ohm R_Ref
a = 0.0
b = 0.0
c = 0.0
if (self.registerCode == 0xA2):
############# PT1000 #############
R_REF = 4300.0 # Reference Resistor
Res0 = 1000.0; # Resistance at 0 degC for 430ohm R_Ref
a = .00381
b = -.000000602
# c = -4.18301e-12 # for -200 <= T <= 0 (degC)
c = -0.000000000006
# c = 0 # for 0 <= T <= 850 (degC)
else:
############# PT100 #############
R_REF = 430.0 # Reference Resistor
Res0 = 100.0; # Resistance at 0 degC for 430ohm R_Ref
a = .00390830
b = -.000000577500
# c = -4.18301e-12 # for -200 <= T <= 0 (degC)
c = -0.00000000000418301
# c = 0 # for 0 <= T <= 850 (degC)
Res_RTD = (RTD_ADC_Code * R_REF) / 32768.0 # PT1000 Resistance
#print("CS-Pin: " , self.csPin, " --- ADC-Value: ", RTD_ADC_Code , " --- Resistance: ", round(Res_RTD, 2) , " Ohms")
# Callendar-Van Dusen equation
# Res_RTD = Res0 * (1 + a*T + b*T**2 + c*(T-100)*T**3)
# Res_RTD = Res0 + a*Res0*T + b*Res0*T**2 # c = 0
# (c*Res0)T**4 - (c*Res0)*100*T**3
# + (b*Res0)*T**2 + (a*Res0)*T + (Res0 - Res_RTD) = 0
#
# quadratic formula:
# for 0 <= T <= 850 (degC)
temp = -(a * Res0) + math.sqrt(a * a * Res0 * Res0 - 4 * (b * Res0) * (Res0 - Res_RTD))
temp = round(temp / (2 * (b * Res0)), 2)
# removing numpy.roots will greatly speed things up
# temp_C_numpy = numpy.roots([c*Res0, -c*Res0*100, b*Res0, a*Res0, (Res0 - Res_RTD)])
# temp_C_numpy = abs(temp_C_numpy[-1])
# print "Solving Full Callendar-Van Dusen using numpy: %f" % temp_C_numpy
if (temp < 0): # use straight line approximation if less than 0
# Can also use python lib numpy to solve cubic
# Should never get here in this application
temp = (RTD_ADC_Code / 32) - 256
print ("CSPin " , self.csPin, " - ADC: ", RTD_ADC_Code , " - Resistance: ", round(Res_RTD, 2) , " Ohms - Temp: " , temp)
return temp
##############################################################################################################################
# Programmstart #
###############################################################################################################################
csPin = 0
misoPin = 21
mosiPin = 19
clkPin = 23
registerCode = 0
# BOARD:21,19,23
# BCM: 9,10,11
class FaultError(Exception):
pass
The problem is that I get no data for the PT100-rtd - only for the PT1000.
The wiring with my raspberry must be correct, because I also adapted my code to test the wiring with two PT1000-rtd and it works.
I think that my problem is somewhere at "getCurrentTemp(self)". Maybe at the readRegister(..) and writeRegister(..) with the "regNum" and "regNumStart".
Any idea?
It looks like you are trying to use the circuitPython code.
Look at this location for the latest version of this code.
Follow the instructions and ensure that you have all required
dependencies met on your platform.
Look here for their simple example of how to test.
Good Luck!
I wrote a simple WebSocket client. I used the code I found on SO, here: How can I send and receive WebSocket messages on the server side?.
I'm using Python 2.7 and my server is echo.websocket.org on 80 TCP port. Basically, I think that I have a problem with receiving messages. (Or maybe the sending is wrong too?)
At least I am sure that the handshake is all ok, since I receive a good handshake response:
HTTP/1.1 101 Web Socket Protocol Handshake
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Headers: x-websocket-extensions
Access-Control-Allow-Headers: x-websocket-version
Access-Control-Allow-Headers: x-websocket-protocol
Access-Control-Allow-Origin: http://example.com
Connection: Upgrade
Date: Tue, 02 May 2017 21:54:31 GMT
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Server: Kaazing Gateway
Upgrade: websocket
And my code:
#!/usr/bin/env python
import socket
def encode_text_msg_websocket(data):
bytesFormatted = []
bytesFormatted.append(129)
bytesRaw = data.encode()
bytesLength = len(bytesRaw)
if bytesLength <= 125:
bytesFormatted.append(bytesLength)
elif 126 <= bytesLength <= 65535:
bytesFormatted.append(126)
bytesFormatted.append((bytesLength >> 8) & 255)
bytesFormatted.append(bytesLength & 255)
else:
bytesFormatted.append(127)
bytesFormatted.append((bytesLength >> 56) & 255)
bytesFormatted.append((bytesLength >> 48) & 255)
bytesFormatted.append((bytesLength >> 40) & 255)
bytesFormatted.append((bytesLength >> 32) & 255)
bytesFormatted.append((bytesLength >> 24) & 255)
bytesFormatted.append((bytesLength >> 16) & 255)
bytesFormatted.append((bytesLength >> 8) & 255)
bytesFormatted.append(bytesLength & 255)
bytesFormatted = bytes(bytesFormatted)
bytesFormatted = bytesFormatted + bytesRaw
return bytesFormatted
def dencode_text_msg_websocket(stringStreamIn):
byteArray = [ord(character) for character in stringStreamIn]
datalength = byteArray[1] & 127
indexFirstMask = 2
if datalength == 126:
indexFirstMask = 4
elif datalength == 127:
indexFirstMask = 10
masks = [m for m in byteArray[indexFirstMask: indexFirstMask + 4]]
indexFirstDataByte = indexFirstMask + 4
decodedChars = []
i = indexFirstDataByte
j = 0
while i < len(byteArray):
decodedChars.append(chr(byteArray[i] ^ masks[j % 4]))
i += 1
j += 1
return ''.join(decodedChars)
# connect
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((socket.gethostbyname('echo.websocket.org'), 80))
# handshake
handshake = 'GET / HTTP/1.1\r\nHost: echo.websocket.org\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: gfhjgfhjfj\r\nOrigin: http://example.com\r\nSec-WebSocket-Protocol: echo\r\n' \
'Sec-WebSocket-Version: 13\r\n\r\n'
sock.send(handshake)
print sock.recv(1024)
# send test msg
msg = encode_text_msg_websocket('hello world!')
sock.sendall(msg)
# receive it back
response = dencode_text_msg_websocket(sock.recv(1024))
print '--%s--' % response
sock.close()
What is wrong here? It gets complicated after the handshake.
The dencode_text_msg_websocket method returns an empty string but it should return the same string I send to the server, which is hello world!.
I DO NOT WANT to use libraries (I know how to use them). The question is about achieving the same thing WITHOUT libraries, using only sockets.
I only want to send a message to echo.websocket.org server and receive a response, that's all. I do not want to modify the headers, just build the headers like they're used by this server. I checked how they should look like using Wireshark, and tried to build the same packets with Python.
For tests below, I used my browser:
Not masked data, from server to client:
Masked data, from client to server:
I have hacked your code into something that at least sends a reply and receives an answer, by changing the encoding to use chr() to insert byte strings rather than decimals to the header. The decoding I have left alone but the other answer here has a solution for that.
The real guts of this is detailed here https://www.rfc-editor.org/rfc/rfc6455.txt
which details exactly what it is that you have to do
#!/usr/bin/env python
import socket
def encode_text_msg_websocket(data):
bytesFormatted = []
bytesFormatted.append(chr(129))
bytesRaw = data.encode()
bytesLength = len(bytesRaw)
if bytesLength <= 125:
bytesFormatted.append(chr(bytesLength))
elif 126 <= bytesLength <= 65535:
bytesFormatted.append(chr(126))
bytesFormatted.append((chr(bytesLength >> 8)) & 255)
bytesFormatted.append(chr(bytesLength) & 255)
else:
bytesFormatted.append(chr(127))
bytesFormatted.append(chr((bytesLength >> 56)) & 255)
bytesFormatted.append(chr((bytesLength >> 48)) & 255)
bytesFormatted.append(chr((bytesLength >> 40)) & 255)
bytesFormatted.append(chr((bytesLength >> 32)) & 255)
bytesFormatted.append(chr((bytesLength >> 24)) & 255)
bytesFormatted.append(chr((bytesLength >> 16)) & 255)
bytesFormatted.append(chr((bytesLength >> 8)) & 255)
bytesFormatted.append(chr(bytesLength) & 255)
send_str = ""
for i in bytesFormatted:
send_str+=i
send_str += bytesRaw
return send_str
# connect
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5.0)
try:
sock.connect((socket.gethostbyname('ws.websocket.org'), 80))
except:
print "Connection failed"
handshake = '\
GET /echo HTTP/1.1\r\n\
Host: echo.websocket.org\r\n\
Upgrade: websocket\r\n\
Connection: Upgrade\r\n\
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n\
Origin: http://example.com\r\n\
WebSocket-Protocol: echo\r\n\
Sec-WebSocket-Version: 13\r\n\r\n\
'
sock.send(bytes(handshake))
data = sock.recv(1024).decode('UTF-8')
print data
# send test msg
msg = encode_text_msg_websocket('Now is the winter of our discontent, made glorious Summer by this son of York')
print "Sent: ",repr(msg)
sock.sendall(bytes(msg))
# receive it back
response = sock.recv(1024)
#decode not sorted so ignore the first 2 bytes
print "\nReceived: ", response[2:].decode()
sock.close()
Result:
HTTP/1.1 101 Web Socket Protocol Handshake
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Headers: x-websocket-extensions
Access-Control-Allow-Headers: x-websocket-version
Access-Control-Allow-Headers: x-websocket-protocol
Access-Control-Allow-Origin: http://example.com
Connection: Upgrade
Date: Mon, 08 May 2017 15:08:33 GMT
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Server: Kaazing Gateway
Upgrade: websocket
Sent: '\x81MNow is the winter of our discontent, made glorious Summer by this son of York'
Received: Now is the winter of our discontent, made glorious Summer by this son of York
I should note here, that this is going to be a pig to code without pulling in some extra libraries, as #gushitong has done.
Accoding to https://www.rfc-editor.org/rfc/rfc6455#section-5.1:
You should mask the client frames. (And the server frames is not masked at all.)
a client MUST mask all frames that it
sends to the server (see Section 5.3 for further details). (Note
that masking is done whether or not the WebSocket Protocol is running
over TLS.) The server MUST close the connection upon receiving a
frame that is not masked. In this case, a server MAY send a Close
frame with a status code of 1002 (protocol error) as defined in
Section 7.4.1. A server MUST NOT mask any frames that it sends to
the client. A client MUST close a connection if it detects a masked
frame。
This is a working version:
import os
import array
import six
import socket
import struct
OPCODE_TEXT = 0x1
try:
# If wsaccel is available we use compiled routines to mask data.
from wsaccel.xormask import XorMaskerSimple
def _mask(_m, _d):
return XorMaskerSimple(_m).process(_d)
except ImportError:
# wsaccel is not available, we rely on python implementations.
def _mask(_m, _d):
for i in range(len(_d)):
_d[i] ^= _m[i % 4]
if six.PY3:
return _d.tobytes()
else:
return _d.tostring()
def get_masked(data):
mask_key = os.urandom(4)
if data is None:
data = ""
bin_mask_key = mask_key
if isinstance(mask_key, six.text_type):
bin_mask_key = six.b(mask_key)
if isinstance(data, six.text_type):
data = six.b(data)
_m = array.array("B", bin_mask_key)
_d = array.array("B", data)
s = _mask(_m, _d)
if isinstance(mask_key, six.text_type):
mask_key = mask_key.encode('utf-8')
return mask_key + s
def ws_encode(data="", opcode=OPCODE_TEXT, mask=1):
if opcode == OPCODE_TEXT and isinstance(data, six.text_type):
data = data.encode('utf-8')
length = len(data)
fin, rsv1, rsv2, rsv3, opcode = 1, 0, 0, 0, opcode
frame_header = chr(fin << 7 | rsv1 << 6 | rsv2 << 5 | rsv3 << 4 | opcode)
if length < 0x7e:
frame_header += chr(mask << 7 | length)
frame_header = six.b(frame_header)
elif length < 1 << 16:
frame_header += chr(mask << 7 | 0x7e)
frame_header = six.b(frame_header)
frame_header += struct.pack("!H", length)
else:
frame_header += chr(mask << 7 | 0x7f)
frame_header = six.b(frame_header)
frame_header += struct.pack("!Q", length)
if not mask:
return frame_header + data
return frame_header + get_masked(data)
def ws_decode(data):
"""
ws frame decode.
:param data:
:return:
"""
_data = [ord(character) for character in data]
length = _data[1] & 127
index = 2
if length < 126:
index = 2
if length == 126:
index = 4
elif length == 127:
index = 10
return array.array('B', _data[index:]).tostring()
# connect
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((socket.gethostbyname('echo.websocket.org'), 80))
# handshake
handshake = 'GET / HTTP/1.1\r\nHost: echo.websocket.org\r\nUpgrade: websocket\r\nConnection: ' \
'Upgrade\r\nSec-WebSocket-Key: gfhjgfhjfj\r\nOrigin: http://example.com\r\nSec-WebSocket-Protocol: ' \
'echo\r\n' \
'Sec-WebSocket-Version: 13\r\n\r\n'
sock.send(handshake)
print(sock.recv(1024))
sock.sendall(ws_encode(data='Hello, China!', opcode=OPCODE_TEXT))
# receive it back
response = ws_decode(sock.recv(1024))
print('--%s--' % response)
sock.close()