Reputation: 8079
I have the following script which uses SocksiPY
and Tor:
from TorCtl import TorCtl
import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050)
socket.socket = socks.socksocket
import urllib2
import sqlite3
from BeautifulSoup import BeautifulSoup
def newId():
conn = TorCtl.connect(controlAddr="127.0.0.1", controlPort=9051, passphrase="123")
TorCtl.Connection.send_signal(conn, "NEWNYM")
newId()
print(urllib2.urlopen("http://www.ifconfig.me/ip").read())
This code should change Tor identity but it waits for some time and gives the following error:
tuple index out of range
Traceback (most recent call last):
File "template.py", line 16, in <module>
newId()
File "template.py", line 14, in newId
TorCtl.Connection.send_signal(conn, "NEWNYM")
TypeError: unbound method send_signal() must be called with Connection instance as first argument (got NoneType instance instead)
But above script is divided into 2 separate scripts:
import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050)
socket.socket = socks.socksocket
import urllib2
import sqlite3
from BeautifulSoup import BeautifulSoup
print(urllib2.urlopen("http://www.ifconfig.me/ip").read())
AND:
from TorCtl import TorCtl
def newId():
conn = TorCtl.connect(controlAddr="127.0.0.1", controlPort=9051, passphrase="123")
TorCtl.Connection.send_signal(conn, "NEWNYM")
newId()
When second script is called then first is called it is ok. Can anyone explain what is the problem and how to fix?
Upvotes: 5
Views: 3642
Reputation: 116
Anonymous explained very well this socket overwrite, answer is almost perfect except you have to close the control socket. It is safer because of the TorCtl event loop, but I have to look deeper in the TorCtl code to understand this event loop.
To summarize your code becomes:
from TorCtl import TorCtl
import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050)
import urllib2
import sqlite3
from BeautifulSoup import BeautifulSoup
__originalSocket = socket.socket
def newId():
''' Clean circuit switcher
Restores socket to original system value.
Calls TOR control socket and closes it
Replaces system socket with socksified socket
'''
socket.socket = __originalSocket
conn = TorCtl.connect(controlAddr="127.0.0.1", controlPort=9051, passphrase="123")
TorCtl.Connection.send_signal(conn, "NEWNYM")
conn.close()
socket.socket = socks.socksocket
newId()
print(urllib2.urlopen("http://www.ifconfig.me/ip").read())
Upvotes: 5
Reputation: 50329
The connection to the control port fails, and conn
is assigned the value which Python sockets uses to indicate failure (which is apparently of type NoneType
).
The reason is that in the statement socket.socket = socks.socksocket
, apparently you're replacing the default socket object or class with one which transparently proxies everything through Tor, which that makes the program try to proxy your control port connection.
The solution is to only perform socket.socket = socks.socksocket
after you've opened the control connection (and keep that connection around if you need it later) or save the original socket.socket
value so you can switch between values as needed.
Upvotes: 2