Craft an IP in IP example with scapy - python

I am trying to send an IP in IP packet with scapy but I seem to be missing or misunderstanding something. Here is my attempt:
from scapy.all import *
payload = "HelloWorld"
inner = IP(dst="192.168.1.2")
inner.add_payload(payload)
outer = IP(dst="192.168.1.2")
send(outer/inner)
I watched for the packet with wireshark on the destination and it showed that the packet was malformed:
Expert Info (Error/Protocol): IPv6 Hop-by-Hop extension header must
appear immediately after IPv6 header
the destination then sends an ICMP packet back with type 3 (destination unreachable) and code 2 (Protocol unreachable).
I have tried setting several protocols on the outer and inner packets (protocol 4 IPv4 encapsulation feels right) but so far they all send back a "protocol unreachable" ICMP packet.
If it makes a difference my intent is to have the inner packet get sent to a different destination than the outer packet. I just thought I should make the simplest possible example to get started. Once I figure out why I am getting a protocol unreachable message I will change the inner packets destination IP.
Suggestions?

If you want to send an IP in IP packet (Outer IP header, Inner IP header, IP payload), e.g.:
from scapy.all import *
payload = "TEST"
send(IP(dst="192.168.1.2")/IP(dst="192.168.1.2")/UDP(dport=4444)/payload)

Related

Why is the Priority Code Point (PCP) not modified within an IP packet using Scapy?

I am trying to do an application to generate traffic that includes a priority field. To do this, I want to include the 802.1Q tag within the Ethernet Frame and modify its PCP field. I generate and send the packet as follows:
pkt = IP(dst = "172.24.100.61")/Dot1Q(prio = 7)
send(pkt, iface='eth0')
The problem is that when I capture the traffic with Wireshark and check the Ethernet header fields, the 802.1Q tag does not appear:
I understand that 802.1Q is related with Layer 2 of the TCP/IP stack and I am sending an IP packet but, why isn't the change reflected in Wireshark?
P.D: When I create an Ethernet frame and send it with the sendp instruction, the change is reflected, but I need to create an IP packet.
The layer Dot1Q is between the layer Ether and IP.
in you case, the send is adding the Ether layer for you and send it to the interface.
The following code work for me (meaning the wireshark doesn't complains).
from scapy.all import send
from scapy.layers.inet import IP
from scapy.layers.l2 import Dot1Q
pkt = Dot1Q(prio = 7) /IP(dst = "172.24.100.61")
send(pkt, iface='eth0')

How to send TCP packets through socks?

I have this code:
import socket
import socks
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4, "IP_SOCK", PORT_SOCK, True)
s = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target,port))
s.close()
print("Connection tested.")
It works, but the lenght of the packets is 0. I'd like to add a payload data, how can I do that?
For example, here I have this working code with scapy library:
import socket
import socks
from scapy.all import *
def send(src_ip, dst_ip, dst_port):
ip = IP(src=src_ip, dst=dst_ip)
src_port = random.randint(20, 65000)
transport = TCP(sport=src_port, dport=dst_port, flags="S")
send(ip/transport/b"mydata")
if __name__ == '__main__':
send('SRC_IP', 'DST_IP', DST_PORT)
And it send indeed the "mydata" payload. If I intercept it with tcpdump, I can see the lenght of data field and "mydata" in the syn packet.
I would like to send it through a sock or a http proxy, but I don't know how can I do it.
The fact is that I don't need to establish the connection, because I want to send packets even if the port is closed.
Some people continue to tell me that I can't use socks to send tcp packets. It's not true. SOCKS acts in layer 4, so it's perfectly doeable, the thing is that I don't know how to do it in Python since I'm new to it.
Some people continue to tell me that I can't use socks to send tcp packets. It's not true.
It is true even if you don't like it. A proxy (HTTP proxy or Socks proxy) is not a packet forwarder on the network level. It is instead a payload forwarder at the application level. If you want a packet forwarder you need a real VPN (with the focus on "N", i.e. network level) instead.
When using a Socks or HTTP proxy one needs to establish a TCP connection to the proxy first. Inside this TCP connection one then does some initial handshaking like authentication against the proxy and specification of the target one likes to reach. The proxy then connects to the target and once this is done there are two TCP connections: one between client and proxy and another between proxy and server. The proxy will then read on both of these connections and forward the data received to the peer, i.e. data received from the client will be forwarded to the server etc. The proxy might also modify data in transit.
Since the proxy only forwards the data at the application level there is no way to send crafted TCP packets trough the proxy. And since the proxy maintains two independent TCP connections and just forwards application level data even the incoming and outgoing packet sizes might be different, i.e. two incoming packets can be merged in one outgoing packet or might result in three etc. Since TCP is just byte stream packet sizes don't matter at the application level.
you can use sendall(); for example: s.sendall("GET / HTTP/1.1 ...")
For more details, see https://pypi.org/project/PySocks/ , where I obtained this example from, as well as https://docs.python.org/3/library/socket.html (socks mimics python's built in sockets)

Setting source address when sending UDP multicast messages

How to set the source IP address for UDP multicast packages to something else than the interface IP?
I am trying to write a small router that selectively routes UDP SSDP packages from one network to another. The plan is to do it in python, although I am flexible on that.
It seems fairly easy to route SSDP NOTIFY messages: I receive them on one interface and decide which interface to re-broadcast them on. However the protocol for M-SEARCH messages require that the source IP is set to the original source of the message as any service that chooses to respond will respond with a unicast message to the source IP and port.
Example (heavily simplified):
Network A: 192.168.10.0/24
Network B: 192.168.11.0/24
My router application runs on a multihomed computer on 192.168.10.2 and 192.168.11.2.
A client on network A with IP 192.168.10.10 sends an M-SEARCH message:
Src IP/Port: 192.168.10.10 port 40000
Dst IP/Port: 239.255.255.250 port 1900
My "router application" on 192.168.10.2 receives the packet and would like to rebroadcast it on network B. However I cannot find any method in the socket API that allows me to set the source IP address. Only to pick the source interface.
Thus the rebroadcasted packet now looks like this:
Src IP/Port: 192.168.11.2 port xxxxx
Dst IP/Port: 239.255.255.250 port 1900
And now the receiving service is unable to unicast back to the client as the original IP and port are lost.
How to set the source IP address for UDP multicast packages to something else than the interface IP?
The only way I know of is to use a RAW socket and construct the IP headers manually. Note that use of RAW sockets is typically restricted to admin users on most platforms.
However I cannot find any method in the socket API that allows me to set the source IP address.
Because there isn't one.
And now the receiving service is unable to unicast back to the client as the original IP and port are lost.
Can't you just have your router remember the original source when it receives the M-SEARCH request, and when it receives the unicast reply then forward it to the original requester? That is how most routers usually work.

Netcat only receiving first UDP packet from Scapy and Python

I'm currently making a DNS tunnel in python using Scapy. I can send packets just fine (according to Wireshark). The problem is, when listening on Netcat on what I'm transmitting the dns packets to, I only receive the first packet.
I've heard that when binding, a UDP "connection" (for lack of better words) locks on a port, and drops all other packets from any other source port. However, I defined a source port, so I'm not sure what is going on.
def sendDns(incomingBytes):
print('sending packet data :\n' + incomingBytes.decode('utf-8'))
incomingBytes = base64.encodebytes(incomingBytes)
send(IP(dst=dnsServer)/UDP(dport=53, sport=12345)/DNS(qd=DNSQR(qname=incomingBytes)))

python / dpkt: Find out if packet is a tcp packet or a udp packet ,

I have a python scripts that captures the packets on the ethernet using dpkt, but how do i differentiate between which packets are tcp and which ones are for udp.
Eventually i would like to have a list of packets for each tcp connection that was established during the time interval.
my code is:
import dpkt
import pcapy
cap=pcap.open_live('eth0',100000,1,0)
(header,payload)=cap.next()
while header:
eth=dpkt.ethernet.Ethernet(str(payload))
ip=eth.data
tcp=ip.data
# i need to know whether it is a tcp or a udp packet here!!!
(header,payload)=cap.next()
IP header contains field protocol. dpkt should allow you to obtain this value and using it you can guess what is on top of IP. Here is a list of valid protocols numbers http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml.
UDP is equal to 17 while TCP is 6.
Edit:
I have checked this issue and as I mentioned dpkg provide p properties to access protocol field of IP. So you can check agains it. But it also automatically parse packet and set data property to instance of class that represent upper protocol like UDP or TCP. So you can check type of data property and you recognize this protocol.
from dpkt.ip import IP, IP_PROTO_UDP
from dpkt.udp import UDP
ip = IP('E\x00\x00"\x00\x00\x00\x00#\x11r\xc0\x01\x02\x03\x04\x01\x02\x03\x04\x00o\x00\xde\x00\x0e\xbf5foobar')
#if ip.p == IP_PROTO_UDP: # checking for protocol field in ip header
if type(ip.data) == UDP : # checking of type of data that was recognized by dpkg
udp = ip.data
print udp.sport
else:
print "Not UDP"
A python script that captures the packets on the ethernet adapter eth0 using dpkt, and differentiates between TCP and UDP packets of the IP.
import dpkt
import pcapy
cap=pcapy.open_live('eth0',100000,1,0)
(header,payload)=cap.next()
while header:
eth=dpkt.ethernet.Ethernet(str(payload))
# Check whether IP packets: to consider only IP packets
if eth.type!=dpkt.ethernet.ETH_TYPE_IP:
continue
# Skip if it is not an IP packet
ip=eth.data
if ip.p==dpkt.ip.IP_PROTO_TCP: # Check for TCP packets
TCP=ip.data
# ADD TCP packets Analysis code here
elif ip.p==dpkt.ip.IP_PROTO_UDP: # Check for UDP packets
UDP=ip.data
# UDP packets Analysis code here
(header,payload)=cap.next()

Categories

Resources