7

Using normal sockets I can stream a list of numbers (updated every second) from a server to a client. This works perfectly fine. Now I want to do the same using Tor. Using Socksipy I am able to make HTTP requests to a web page (using this code). So from that starting point, I tried to build a piece of code that connects to a remote socket through Tor like this:

import socket
import socks
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050, True)
#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s = socket.socket = socks.socksocket
s.connect(('<the ip address here>', 46956))
s.sendall('Hello world')
print(s.recv(1024))

If I uncomment line 4 and comment out line 5 it all works fine, but running it like this results in an error saying: TypeError: unbound method connect() must be called with socksocket instance as first argument (got tuple instance instead).

So my question: What am I doing wrong here? How can I connect to this remote socket through Tor?

Also two other questions:

  1. Is there no better way of doing this? By using stem.socket for example?
  2. How would I be able to build the public socket that I want to connect to, using a Tor hidden service?

Any information or hints are welcome.

hubbtwea
  • 411
  • 2
  • 5
  • 6

2 Answers2

3

This works for me:

import socket
import socks

socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050, True)
s = socks.socksocket()
s.connect(('anguilla.debian.or.at', 1234))
s.sendall('Hello world')
print(s.recv(1024))

So, that's just initializing s differently, via s = socks.socksocket().

With socks, connect() also takes a hostname. This should enable you to connect to a hidden service, as in:

socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050, True)
s = socks.socksocket()
s.connect(('3g2upl4pq6kufc4m.onion', 80))

message = 'GET / HTTP/1.0\r\n\r\n'
s.sendall(message)

reply = s.recv(4069)
print reply
weasel - Peter Palfrader
  • 5,158
  • 1
  • 24
  • 39
3

You're almost there, you're replacing socket.socket with socks.socket, so far so good.

However upon assignment of variable s, you're not properly instantiating the replacement class, and therefore later during the connect call, your code results in the unbound method type error.

In your original code, s gets assigned a class instance, and in your updated code, a class method, it's in the difference of socket.socket(...) vs sock.socket, see?

Try this instead:

socket.socket = socks.socksocket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Because you don't actually want to replace socket.socket (a module level class) with a class instance (it might be needed later or be relied upon within 3rd party libraries you're not even aware of).

As for your other two questions, I'm not familiar with stem.socket at all, sorry. With regard to building the public (listening) part of your socket, you do no such thing, you use the tor distribution to tie in your "existing" server to the tor network. Unless ofcourse you don't want your software to be dependent on the official tor distribution, and build it into your code on your own (to my knowledge, no python implementation or library of/for the tor protocol exists, let alone the hidden service implementation, but don't quote me on this). It's not that technically complex a protocol, but if you go that route you need to read a lot of rfc's in order to stay compatible with the rest of the network, version interopability etc.

-- Kind regards, Yuka

Yuka
  • 231
  • 1
  • 6