Altering packets on the fly with scapy as a MITM
<p>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).</p>

<p>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.</p>

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

<pre><code>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
</code></pre>

<p>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.</p>

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

<pre><code>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
</code></pre>

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

<p>You can use <a href="http://www.netfilter.org/projects/libnetfilter_queue/doxygen/" rel="nofollow">NFQUEUE</a> which has <a href="https://pypi.python.org/pypi/NetfilterQueue" rel="nofollow">python bindings</a>.</p>

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

<p><code>iptables -I INPUT -d 192.168.0.0/24 -j NFQUEUE --queue-num 1</code></p>

<p>Then access the packets from your code:</p>

<pre><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()
</code></pre>

<p>Note the <code>pkt.accept()</code> call. This returns a <a href="http://www.netfilter.org/projects/libnetfilter_queue/doxygen/group__Queue.html#gae36aee5b74d0c88d2f8530e356f68b79" rel="nofollow">verdict</a> 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 <code>accept</code>ing it, you'd need to copy it, return a <code>drop</code> verdict, and finally resend it with the included modifications.</p>

python linux iptables scapy man-in-the-middle