4

Assuming I managed to be in the middle of the communication between a client and a server (let's say that I open up a hotspot and cause the client to connect to the server only through my machine).

How can I alter packets that my client sends and receives without interrupting my own communication with other services? There must be a way to route all of the packets the client both sends and is about to receive (before forwarding them to him) through my script.

I think that the correct direction of going about accomplishing this is with iptables but not sure exactly what arguments would fit to make this work. I already have the following simple script:

hotspotd start #a script that runs dnsmasq as both a DNS and DHCP server, configures and starts a hotspot
iptables -P FORWARD ACCEPT
iptables --append FORWARD --in-interface wlan0 -j ACCEPT
iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE 
#wlan0 is the interface on which the hotspot is.
#eth0 is the interface that is connected to the internet

Now, this perfectly works for a passive MITM - I can see everything that the client sends and receives. But now I want to step it up and redirect every message he sends and receives through me.

My eventual purpose is to get to a level where I could execute the following script:

from scapy.all import *
from scapy_http.http import *

def callback(pkt):
   #Process the packet here, see source and destination addresses, ports, data
   send(pkt)

sniff(filter='port 666', prn=callback) #Assuming all relevant packets are redirected to port 666

How do I accomplish redirecting every packet the client sends and is-about-to-receive?

Jon Snow
  • 41
  • 1
  • 2

1 Answers1

4

You can use NFQUEUE which has python bindings.

NFQUEUE is a userspace queue that is a valid iptables target. You can redirect some traffic to the NFQUQUE:

iptables -I INPUT -d 192.168.0.0/24 -j NFQUEUE --queue-num 1

Then access the packets from your code:

from netfilterqueue import NetfilterQueue

def print_and_accept(pkt):
    print(pkt)
    pkt.accept()

nfqueue = NetfilterQueue()
nfqueue.bind(1, print_and_accept)
try:
    nfqueue.run()
except KeyboardInterrupt:
    print('')

nfqueue.unbind()

Note the pkt.accept() call. This returns a verdict to the nfqueue, telling it that it should accept the packet - i.e. allow it to continue along its normal route in the kernel. To modify a packet, instead of accepting it, you'd need to copy it, return a drop verdict, and finally resend it with the included modifications.

Malt
  • 28,965
  • 9
  • 65
  • 105
  • Seems to work. But how do I recognize which packets are from the device and which are from my machine? – Jon Snow Oct 05 '16 at 13:13
  • You can use either iptables or your app for that. 1. Using IP tables you can filter packets by their source, and send only the relevant ones into the nfqueue (or send them to two separate NFQUEUES depending on the source). 2. Since your application receives the entire packet from the NFQUEUE, you can simply check the IP address of each packet you receive. – Malt Oct 05 '16 at 21:04
  • but isn't it determined in a later stage? I mean packets sourced from some local address I guess are okay and easy to determine but what about packets **destined** to that device IP address? They arrive as to my external IP, will such a feat work? – Jon Snow Oct 06 '16 at 06:57
  • @JonSnow I don't follow. If you know your IP address, you can look at the destination IP address of each packet and compare to yours. If the network interface is behind a NAT, both the IP of the interface and the IP in the packet would be private. – Malt Oct 06 '16 at 07:53
  • My machine functions as a hotspot for my MITM attack and is doing routing from interfaces (`wlan0` to `eth0` and vice versa). When a package is out I can sniff and see which packet is, e.g, from `10.0.0.2`. But when I get the response, I get the destination IP as my external IP, don't I? – Jon Snow Oct 06 '16 at 08:40
  • I don't know your network setup. If you're sniffing inside the NAT, you'll see private addresses. If you're sniffing outside the NAT, you'll see the external address. Either way, you can use IPTABLES/NFQUEUE to capture the packets and among other things, extract their IP addresses. – Malt Oct 06 '16 at 16:22
  • I mean, if I see the external addresses can I somehow change it and understand which device is it supposed to get to ? Which internal address? – Jon Snow Oct 09 '16 at 09:40