scapy sniffed udp packets can not be received after sending to another host

Viewed 583

I am trying to send udp packets sniffed by scapy to another host. The host address is reachable through my default gateway.

In the host I listen to the destination port 10000 by tcpdump, but the packets are not received.

My code is this:

from scapy.all import *

class Des:
    def __init__(self, port):
        self.port = port

def send_packets(port):
    des = Des(port)
    def get_pack(packet):
        pkt = packet.copy()
        pkt['IP'].dst= "192.168.20.111" # address of the destination host
        pkt['IP'].src = "192.168.12.111" # address of my system
        pkt['UDP'].dport = des.port
        pkt['Ethernet'].dst = dst_mac
        pkt['Ethernet'].src = src_mac
        send(pkt)
    return get_pack

sniff(filter = 'udp and port 50000', prn = send_packets(10000))

If I send the packets to another host 192.168.12.112 in my network the problem still exists. In this scenario if I replace the send line with the following line, these packets will be received in the destination!

send(IP(dst='192.168.12.112')/UDP(dport=10000))

While replacing it with the following line, results in no receiving packets in host 192.168.20.111.

send(IP(dst='192.168.20.111')/UDP(dport=10000))

I searched for the problem but found no result. The firewall in the both side is disabled and scapy has the routing path as the following output.

>>> conf.route
Network         Netmask         Gateway         Iface           Output IP
0.0.0.0         0.0.0.0         192.168.12.1    vr0             192.168.12.111
192.168.12.0    255.255.255.0   0.0.0.0         vr0             192.168.12.111 

Furthermore, tcpdump on my output interface shows that when using

send(IP(dst='ANY_DST)/UDP(dport=ANY_PORT))

the packets are going out, but when I send the sniffed packets, they don't!

Where did I go wrong? May the problem be with the changed packets? They are RTP packets containing payload.

I am very new to python and scapy. Any help can be a light to move in the right direction. Thanks for your time.

My OS is FreeBSD9.2 and i am using python 2.7 and scapy (2.2.0).

1 Answers

if I replace the send line with the following line, these packets will be received in the destination!

send(IP(dst='192.168.12.112')/UDP(dport=10000))

After debugging the code and checking the source of scapy, I found the reason of the above problem. When I call send(pkt), From class L3dnetSocket following function is called.

        def send(self, x):
            iff,a,gw  = x.route()
            # Rest of the code is ignored here

Here object x is of class Packet and its route function always returns None for gateway! So the packet will be send in layer 2.

    def route(self):
        return (None,None,None)

While when I call send(IP(dst='192.168.12.112')/UDP(dport=10000)), type of object x is class IP that it's route function returns the correct gateway.

    def route(self):
        dst = self.dst
        if isinstance(dst,Gen):
            dst = iter(dst).next()
        return conf.route.route(dst)

Finally, I changed my code as the following and it works correctly :)

def send_packet(port):
    des = Des(port)
    def get_pack(packet):
        udp = UDP()
        udp.sport = packet[UDP].sport
        udp.dport = des.port
        udp.len = packet[UDP].len

        ip = IP()
        ip.version = packet[IP].version
        ip.tos = packet[IP].tos
        ip.len = packet[IP].len
        ip.id = packet[IP].id
        ip.flags = packet[IP].flags
        ip.frag = packet[IP].frag
        ip.ttl = packet[IP].ttl
        ip.proto = packet[IP].proto
        ip.dst = '192.168.12.112'

        payload = packet[Raw].load

        pkt = ip/udp/payload
        pkt = pkt.__class__(bytes(pkt))

        send(pkt)

    return get_pack

Furthermore, the reason that the packets were not received in my reachable networks, was from my network :)

Related