Sending scapy IP packet with no interface IP error - python

I'm currently trying to send an IP packet to an interface using the send(pkt, iface="eth0") function and I'm getting the error:
WARNING: Mac address to reach destination not found. Using broadcast
The interface I am trying to send out on doesn't have an IP address, and thats the way I would prefer it. And if it makes a difference, the interface is a bridge (created with brctl)
There is an ARP entry for the host that is in the IP packet however it seems scapy isn't doing the lookup required to get the MAC from the ARP table...
Thoughts?!

I would say this is normal, since making a valid ARP request requires an IP address (and Scapy maintains its own ARP table, independent from the OS one).
You can set the destination address yourself: srp(Ether(dst="[MAC address]")/[...]). If you need to get the MAC address first, create and send an ARP request the same way.
To query Scapy's ARP table, access the element conf.netcache.arp_cache, which is a Scapy-specific dict subclass (called CacheInstance).
For example, to add an entry for your host (and then use sr([...]) instead of srp(Ether(dst="[MAC address])/[...])), use:
conf.netcache.arp_cache['[IP address]'] = '[MAC address]'

The default dst address (MAC address) of an Ethernet frame in scapy is broadcast. This warning is generated whenever you send an Ethernet frame to the broadcast address (ff:ff:ff:ff:ff:ff), as far as I'm concerned. You can see this by creating the packet like this:
Ether()/IP() or Ether()/ARP()
instead of just IP() or ARP().

Related

python baserequesthandler client address is real established ip?

i have a question for you
I'm using the udp socket server using baserequesthandler on python
I want to protect the server against spoofing - source address changes.
Does client_address is the actual ip address of established to server ?
If not, how do I get the actual address?
Authenticate the packets so that you know that every message in session X from source address Y is from the same client.
By establishing a shared session key which is then used along with a sequence number to produce a hash of the packet keyed by the (sequence, session_key) pair. Which is then included in every packet. This can be done in both directions protecting both the client and server.
When you receive a packet you use its source address and the session number to look up the session, then you compute HMAC((sequence, session_key), packet) and check if the MAC field in the message matches. If it doesn't discard the message.
This might not be a correct protocol but it is close enough to demonstrate the principle.

generating a spoofed UDP packet in python

how can i create a spoofed UDP packet using python sockets,without using scapy library.
i have created the socket like this
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.sendto(bytes('', "utf-8"), ('192.168.1.9', 7043))# 192.168.1.9dest 7043 dest port
This is one of the first results for google searches like "spoofing udp packet python" so I am going to expand #Cukic0d's answer using scapy.
Using the scapy CLI tool (some Linux distributions package it separately to the scapy Python library ):
pkt = IP(dst="1.1.1.1")/UDP(sport=13338, dport=13337)/"fm12abcd"
send(pkt)
This sends a UDP Packet to the IP 1.1.1.1 with the source port 13338, destination port 13337 and the content fm12abcd.
If you need to a certain interface for some reason (like sending over a VPN that isn't your default route) you can use send(pkt, iface='tun0') to specify it.
One difference to #Cukic0d's answer is that this solution is more flexible by sending a layer 3 packet with send instead of a layer 2 packet with sendp. So it isn't necessary to prepend the correct Ethernet header with Ether() which can cause issues in some scenarios, e.g.:
WARNING: Could not get the source MAC: Unsupported address family (-2) for interface [tun0]
WARNING: Mac address to reach destination not found. Using broadcast.
I think you mean changing the source and destination addresses from the IP layer (on which the UDP layer is based).
To do so, you will need to use raw sockets. (SOCK_RAW), meaning that you have to build everything starting from the Ethernet layer to the UDP layer.
Honestly, without scapy, that’s a lot of hard work. If you wanted to use scapy, it would take 2 lines:
pkt = Ether()/IP(src=“...”, dst=“...”)/UDP()/...
sendp(pkt)
I really advice you to use scapy. The code itself is quite small so I don’t see a reason not to use it. It’s defiantly the easiest in python

Find LAN router IP address with Scapy?

I am attempting to find my router's IP address with Scapy.
I am running a distro of Linux and fully understand that I could use system calls or subprocess to get to the routing tables and find the gateway. However, I am trying to do this without system calls.
I imagine there is a way to do there is a way to do this with Scapy, does anyone know?
FTR, see https://scapy.readthedocs.io/en/latest/routing.html
Get router IP address
>>> gw = conf.route.route("0.0.0.0")[2]
>>> gw
'10.0.0.1'
I used the knowledge that if i send a packet to a distant IP adress with ttl = 0, I will get an ICMP packet from the first router i pass(my default gateway), all i'll need to do later is get the IP from that packet
from scapy.all import *
p = sr1(IP(dst="www.slashdot.org", ttl = 0)/ICMP()/"XXXXXXXXXXX")
print p.src

Sending traffic from multiple source IPs Scapy

I am trying to send some traffic via python using scapy (on Ubuntu). I am using a range of source IPs (10.0.0.32/29). Everything seems to be working (at least I see the traffic in wireshark and it reaches my firewall) but I am having a problem completing the TCP handshake using the IP addresses that aren't the main IP of the eth0 adapter. Does anyone know if this is possible to do:
Source:
from scapy.all import *
import random
sp=random.randint(1024,65535)
ip=IP(src="10.0.0.234/29",dst="www.google.com")
SYN=TCP(sport=sp, dport=80,flags="S",seq=10)
SYNACK=sr1(ip/SYN)
my_ack=SYNACK.seq+1
ACK=TCP(sport=sp,dport=80,flags="A",seq=11,ack=my_ack)
send(ip/ACK)
payload="SEND TCP"
PUSH=TCP(sport=sp,dport=80,flags="PA",seq=11,ack=my_ack)
send(ip/PUSH/payload)
Because you are behind a NAT/router, you should check it allows you to use the full range of IPs. If it is running DHCP protocol, your eth0 will typically recieve a unique IP adress that will be the only routed in your private network.
Furthermore, you must ensure your kernel knows what IPs are attributed to it, else it will drop response packets. If you want to use the full range of IP, you have two choices :
Create virtual devices with virtual mac adresses, each requesting an IP through DHCP.
Configure your router so it statically routes the full IP table to your host, and alias each IP you intend to use
Once you have done that, there is no reason you wouldn't be able to syn/ack from your multiple source IPs. From distant server point of view, there wouldn't be any difference between what you are trying to do and several machines in a local network requesting a page at the same time.

Python dhcp client

I'm trying to learn how to directly (no libraries) send DHCP request from python on multi-homed machine (multiple interfaces).
I've looked at pydhcplib, but still do not get it.
This code send DHCP packet on specific interface (eth3 in my case - no IP assigned), but it sends with eth0 IP address. How to change my src IP to 0.0.0.0?
dhcp-message is truncated in this example
LOCAL_PORT=68
SERVER_PORT=67
LOCAL_IP="0.0.0.0"
BCAST_IP="255.255.255.255"
LISTEN_DEV="eth3"
MSG_SIZE=2048
Conn=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Conn.settimeout(5)
Conn.setsockopt(socket.SOL_SOCKET,IN.SO_BINDTODEVICE,LISTEN_DEV+'\0')
Conn.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
Conn.bind((LOCAL_IP, LOCAL_PORT))
# Create DHCP-Discovery
msg="010106003f7d1664......"
Conn.sendto(msg.decode("hex"),(BCAST_IP,SERVER_PORT))
received = Conn.recv(MSG_SIZE)
Conn.close()
I assume you already know about the Advanced Interprocess Communication Tutorial.
Spoiler Alert: If you want to jump straight to the bottom line, have a look at the DHCP Query recipe.
Edit:
The special value INADDR_ANY (0.0.0.0, or the empty string '' in a python socket) is not an IP address.
"When an address is specified as INADDR_ANY (a manifest constant
defined in < netinet/in.h >), the system interprets the address as 'any
valid address'."
From RFC 2131:
In the case of a client using DHCP for initial configuration
(before the client's TCP/IP software has been completely
configured), DHCP requires creative use of the client's TCP/IP
software and liberal interpretation of RFC 1122. The TCP/IP
software SHOULD accept and forward to the IP layer any IP packets
delivered to the client's hardware address before the IP address is
configured; DHCP servers and BOOTP relay agents may not be able to
deliver DHCP messages to clients that cannot accept hardware
unicast datagrams before the TCP/IP software is configured.
Presumably you're running this program on a system where the ethernet interfaces have already been configured and have valid IP addresses. I'm not sure why you'd want the source IP address to be 0.0.0.0, but perhaps you could set the interface IP to 0.0.0.0 with ifconfig to get the effect you want.
Or you could use a RAW socket and build the IP and UDP headers yourself to contain anything.

Categories