Search code examples
pythonsocketsnetwork-programmingudptor

Sending UDP requests through Tor (SOCKS5) with Python


So I have a python script that needs to send a packet to my server 'x.x.x.x'. I've been able to successfully initialise Tor through Python by setting up the SOCKS5 proxy, but upon trying to send a packet to my server I get the error:

Traceback (most recent call last):
File "test.py", line 18, in <module>
sock.sendto(bytes, ("x.x.x.x", 6000))
File "/usr/local/lib/python2.7/dist-packages/socks.py", line 338, in sendto
self.bind(("", 0))
File "/usr/local/lib/python2.7/dist-packages/socks.py", line 325, in bind
_, relay = self._SOCKS5_request(self._proxyconn, UDP_ASSOCIATE, dst)
File "/usr/local/lib/python2.7/dist-packages/socks.py", line 494, in _SOCKS5_request
raise SOCKS5Error("{0:#04x}: {1}".format(status, error))
socks.SOCKS5Error: 0x07: Command not supported, or protocol error

From what I've seen, socket/SOCKS5 doesn't support connectionless UDP, so I attempted connecting to the port and then sending the packet once connected. I still get the same error as seen above, output can be seen below.

Traceback (most recent call last):
File "test.py", line 18, in <module>
sock.connect(("x.x.x.x", 6000))
File "/usr/local/lib/python2.7/dist-packages/socks.py", line 698, in connect
self.bind(("", 0))
File "/usr/local/lib/python2.7/dist-packages/socks.py", line 325, in bind
_, relay = self._SOCKS5_request(self._proxyconn, UDP_ASSOCIATE, dst)
File "/usr/local/lib/python2.7/dist-packages/socks.py", line 494, in _SOCKS5_request
raise SOCKS5Error("{0:#04x}: {1}".format(status, error))
socks.SOCKS5Error: 0x07: Command not supported, or protocol error

Seeing as a UDP connection does not work either, I would prefer to stay connectionless as this makes my intended use simpler as the port is not necessarily active/open at any given time. The script I'm using to attempt to send the packet can be seen below. I've added but commented out the connectionless and connection methods I was using. Ignore all the extra imports at the top, these are for use later in the script development.

import socks
import socket
import requests
from TorCtl import TorCtl
import urllib2
import random
import math
import time

socks.setdefaultproxy(proxy_type=socks.PROXY_TYPE_SOCKS5, addr="127.0.0.1", port=9050)

socket.socket = socks.socksocket

print requests.get("http://icanhazip.com").text

sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
bytes=random._urandom(1024)

# UDP CONNECTION METHOD
#sock.connect(("x.x.x.x", 6000))
#sock.send(bytes)

# UDP CONNECTIONLESS METHOD
#sock.sendto(bytes, ("x.x.x.x", 6000))

Which brings me to my question - is there any way to send UDP packets via a connectionless method through a SOCKS5 proxy in python?

UPDATE

I originally had SocksiPy installed instead of PySocks, so I've replaced the modules and removed the monkeypatch in the original script. But now, I'm instead getting 'Broken Pipe' errors, as seen below.

Traceback (most recent call last):
File "test.py", line 19, in <module>
s.sendto(bytes, ("x.x.x.x", 6000))
File "/usr/local/lib/python2.7/dist-packages/socks.py", line 336, in sendto
return _BaseSocket.sendto(self, bytes, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/socks.py", line 223, in <lambda>
return lambda self, *pos, **kw: self._savedmethods[name](*pos, **kw)
socket.error: [Errno 32] Broken pipe

I've double checked to make sure Tor is actually working and the proxy is up, which it is as I can receive HTTP requests and responses through the Tor proxy - the responses to sites like http://icanhazip.com/ return a different IP that my actual IP, which suggests that Tor is indeed functioning. I also figured that removing the monkeypatch might make it work with better compatibility, seeing as with the new PySocks module on the OLD script it still fails with the original errors seen above.

The new script:

import socks
import socket
import random
import math

s = socks.socksocket()
s.set_proxy(socks.SOCKS5, "localhost", 9050)

bytes=random._urandom(1024)

# UDP CONNECTION METHOD
#sock.connect(("x.x.x.x", 6000))
#sock.send(bytes)

# UDP CONNECTIONLESS METHOD
#s.sendto(bytes, ("x.x.x.x", 6000))

The errors I'm describing above are with the connectionless method - using the connection method seems to possibly work, however it hangs when connecting to the port (which is the be expected, as the port isn't open).


Solution

  • As @gwyn pointed out, Tor only supports TCP streams, as specified on their website. Using UDP over Tor will not work, only TCP connections.