Python How can I send an ICMP packet without spoofing? - python

I am trying to send an ICMP packet in python using scapy using my Debian VPS but I am not trying to spoof the IP or anything, but since my server doesn't spoof it won't send it anyways, but I cannot figure out any other way to create an ICMP packet and send it. How can I do this?

Build an IP and an ICMP layer, like this:
from scapy.layers.inet import IP, ICMP
DESTINATION = "192.168.111.4"
packet = IP(dst=DESTINATION, ttl=20) / ICMP()
# print(packet)

Related

How to create http packet in Scapy

I have tried and tested scapy to create TCP packets and UDP packets.
Investigated the packet using tcpdump also.
I created the packet with one source IP and one destination IP.
My purpose was to test suricata with the content in the rule as my packet payload.
Suricata could trigger alerts easily in these scenarios.
But when the turn came to create http packets with the payload, it failed.
Please tell me how to create an http packet using scapy.
The packet should contain any string as data. {In TCP I used Raw(load=data)}

Scapy ICMP echo request (Ping) is not replied while a Ping from the command line gets replies

I am using the command line of Windows 10 to ping a device that is not on my LAN. I am using a VPN connection to communicate with that device. The device responds to all the ping requests that I send from the command line.
But when I send the ICMP echo requests with scapy, I don't get any response. The only difference between the command line ping and the scapy ping is that the latter doesn't fill the Identifier and Sequence fields of the ICMP packet (the default value is probably 0 in both fields).
This is my python code:
from scapy.all import IP, ICMP, sr1
reply = sr1(IP(dst=dst_ip)/ICMP())
I have tried both ping requests with the windows firewall off.
What could be wrong? How can I get response with the scapy ping?
Scapy may be picking the wrong interface/route.
What I would do is run sr1 with the iface parameter and provide an explicit interface name. Scapy has the get_if_list() function to list your network interfaces but on Windows this could be different. Seeing that you are using Windows you may have to use the 'meaningful name' ie 'Network Connection 1'. Here is a useful link just in case: Python netifaces and scapy: Getting meaningful Interface-names and full IP-Adresses-/Netmask-Information

How to send packets in scapy from a specific socket?

I am trying to send some packet through scapy by creating a socket. I want to send the packets through the socket which I created. How can I accomplish this
here is some code which I tried
pkt = "\x00\x1c\x7fb\xb5\xfd\x00PV\xb8\x08\x9f\x08\x00E\x00\x000/t\x00\x00\x80\x11\x00\x00\n\xe7\xa0\xc6\n\xe7\x922\xd2\xb4\x05\xdc\x00\x1cH\xf4\t\x8d\x01\x00\x01\x01\x00\x10\xff\xff\xfe\xd4\x00\x00\x00\x00\xb2\x1a=\x0f"
Socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Socket.bind(('',udp_sport))
S = Socket.connect_ex(("10.146.144.51",1803))
Socket.settimeout(10)
sendp(pkt,socket=S)
I have seen in scapy library that there is an option to use Socket in sendp. How can I use this to send? Please help.
You can use a StreamSocket as a wrapper for your socket. See https://scapy.readthedocs.io/en/latest/layers/tcp.html?highlight=streamsocket#using-the-kernel-s-tcp-stack
In your case:
ss=StreamSocket(s,Raw)
ss.send(...)
Note: in your example, you are using sendp(). This means a layer 2 packet. This won't work with the layer 3 socket that you have created: make sure the packet you are sending is L3.

Finding source IP address in Python

I am trying to find source IP address of the received packet using python 3, but without success. Does anyone has an idea how to do that? I want to reply to multicast message with unicast message to the sender and also make a list of senders IP addresses.
Thank you
are you trying to sniff a packet? or is the packet already captured by python? if you want to sniff the packet, read the information, create a new packet and send it to the sender, you can use scapy

Unable to send UDP packets to local port with python, fails checksum according to WireShark

I've been pulling my hair out over this one. I'm trying to write a SOCKS5 server in Python to tunnel UDP traffic. I bind to a port, and receive data fine. I then parse the SOCKS5 UDP header (not the typical UDP header), and forward the datagram to the requested endpoint.
All is good. I then listen for a response from the endpoint (resending if timeout), and get a response. Great!
Here is where I'm losing my mind-
I get the datagram back from the endpoint. I re-encapsulate the returned datagram according to the SOCKS5 RFC, which is the same UDP header as before, except I have now changed the destination address and port to the original caller. I use:
sock_client = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock_client.sendto(packed_datagram, (self.client_ip, self.client_port))
to send the datagram back to client. The client never receives the reply! Ever!
Looking at WireShark, it says this: Header checksum: 0x0000 [incorrect, should be 0xcd1f (may be caused by "IP checksum offload"?)]
Shouldn't the python socket implementation, with socket.DGRAM set, automatically pack my data correctly in a UDP header and calculate the appropriate checksum? Why is it being set to 0x0000? I checked the payload in hex, the checksum is indeed set wrong. What the heck is going on?
The checksum calculation is done by the drivers in the operating system. In may cases, the calculation is done by the network card itself. IIRC, Wireshark grabs local packets just before they are handed off to the network stack. It's common to checksum errors for all locally generated packets.
I was not following two pieces of the SOCKS5 spec accurately.
A UDP association terminates when the TCP connection that the UDP
ASSOCIATE request arrived on terminates.
I was terminating the TCP socket immediately after completing UDP relay handshake. TCP must stay open until the back-and-forth is finished.
When a UDP relay server receives a reply datagram from a remote
host, it MUST encapsulate that datagram using the above UDP request
header, and any authentication-method-dependent encapsulation.
I was using the client's IP and port as the values in the datagram. It needs to be the remote server's IP and port, essentially the UDP header encapsulation is a clone of what the client passed in.
With these two issues solved, the SOCKS5 server works as anticipated.
If I understand your part of code correctly you create a new socket to send the data back to the client. Thus this will be a new socket with a random source IP, e.g. from the view of the client you have the following packet flow:
client_ip:client_port -> socks5_ip:socks_port
client_ip:client_port <- socks5_ip:random_port
The client has probably a connected socket to the socks5 server and thus expects replies coming from socks5_ip:socks_port, not the random_port.
So you should not create a new socket to the client but instead reply using the existing socket where you received the data from the client.
turn off tx-checksumming using the linux command:
ethtool -K eth0 tx off
OR use this function to calculate the checksum
def checksum(data):
s = 0
n = len(data) % 2
for i in range(0, len(data)-n, 2):
s+= ord(data[i]) + (ord(data[i+1]) << 8)
if n:
s+= ord(data[i+1])
while (s >> 16):
s = (s & 0xFFFF) + (s >> 16)
s = ~s & 0xffff
return s
Where the data is the pseudo header

Categories