Note that there are some explanatory texts on larger screens.

plurals
  1. POPython/iptables: Capturing all UDP packets and their original destination
    primarykey
    data
    text
    <p>I am trying to write an <code>iptables</code> rule that will redirect all outgoing UDP packets to a local socket, but I also need the destination information. I started out with</p> <pre><code>sudo iptables -t nat -A sshuttle-12300 -j RETURN --dest 127.0.0.0/8 -p udp sudo iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 0.0.0.0/0 -p udp --to-ports 15000 </code></pre> <p>And that's great, now I can get all outgoing UDP packets by using a socket on port 15000.</p> <p>Now, I need the destination information (target host and port number) so a simple UDP socket isn't enough; need a raw socket so that it gets the full IP header.</p> <p>However, as it turns out, the packets received seem to be addressed for <code>localhost:15000</code>. This makes sense because that's where the socket is, but that's not what I want; I want the host/port before the packet was redirected by <code>iptables</code>.</p> <p>Googling led to <a href="https://stackoverflow.com/questions/5615579/how-to-get-original-destination-port-of-redirected-udp-message">this question</a>, with the answer suggesting two approaches: <code>TPROXY</code> and <code>SO_ORIGINAL_DST</code>, recommending the former, so that's what I tried to go with.</p> <p>Added the <code>iptables</code> rule for <code>TPROXY</code>:</p> <pre><code>sudo iptables -t mangle -A PREROUTING -j TPROXY --dest 0.0.0.0/0 -p udp --on-port 15000 </code></pre> <p>Reading from <a href="http://www.mjmwired.net/kernel/Documentation/networking/tproxy.txt" rel="nofollow noreferrer">tproxy.txt</a>, we need to create a listening socket with the <code>IP_TRANSPARENT</code> option (this is done as root):</p> <pre><code>from socket import * s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP) # The IP_TRANSPARENT option isn't defined in the socket module. # Took the value (19) from the patch in http://bugs.python.org/issue12809 s.setsockopt(SOL_IP, 19, 1) s.bind(('0.0.0.0', 15000)) s.recv(4096) # Will hang until it receives a packet </code></pre> <p>Alright, now let's write another script to generate a test packet to see if anything happens:</p> <pre><code>from socket import * s = socket(AF_INET, SOCK_DGRAM) s.connect(('192.168.1.1', 9001)) s.send('hello') </code></pre> <p>But then nothing happens on the receiving side. The <code>recv</code> call seems to hang, not receiving any data.</p> <p>So, the overall question is either:</p> <ul> <li>Is there something wrong in the code to receive the data from the <code>TPROXY</code> rule?</li> </ul> <p>or</p> <ul> <li>Is there another way to achieve this (redirect all outgoing UDP packets to a local socket with a way to get the destination information)?</li> </ul> <p><strong>Edit</strong>: I should insist that I'd like to <strong>redirect</strong> (therefore intercept) the packets, not just inspect them as they go through.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload