Tor Stem - To Russia With Love Connection Issues
Question: I am trying to get the [To Russia With Love
tutoial](https://stem.torproject.org/tutorials/to_russia_with_love.html) from
the Stem project working.

    
    
    from io import StringIO
    import socket
    import urllib3
    import time
    
    import socks  # SocksiPy module
    import stem.process
    
    from stem.util import term
    
    SOCKS_PORT = 9150
    
    # Set socks proxy and wrap the urllib module
    
    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', SOCKS_PORT)
    socket.socket = socks.socksocket
    
    # Perform DNS resolution through the socket
    
    def getaddrinfo(*args):
      return [(socket.AF_INET, socket.SOCK_STREAM, 6, '', (args[0], args[1]))]
    
    socket.getaddrinfo = getaddrinfo
    
    
    def query(url):
      """
      Uses urllib to fetch a site using SocksiPy for Tor over the SOCKS_PORT.
      """
    
      try:
        return urllib3.urlopen(url).read()
      except:
        return "Unable to reach %s" % url
    
    
    # Start an instance of Tor configured to only exit through Russia. This prints
    # Tor's bootstrap information as it starts. Note that this likely will not
    # work if you have another Tor instance running.
    
    def print_bootstrap_lines(line):
      if "Bootstrapped " in line:
        print (term.format(line, term.Color.BLUE))
    
    
    print (term.format("Starting Tor:\n", term.Attr.BOLD))
    
    tor_process = stem.process.launch_tor_with_config(
      tor_cmd = "C:\Tor Browser\Browser\TorBrowser\Tor\\tor.exe", config = {
        'SocksPort': str(SOCKS_PORT),
    #    'ExitNodes': '{ru}',
      }, 
      init_msg_handler = print_bootstrap_lines,
    )
    
    print (term.format("\nChecking our endpoint:\n", term.Attr.BOLD))
    print (term.format(query("https://www.atagar.com/echo.php"), term.Color.BLUE))
    
    tor_process.kill()  # stops tor
    

I have tweaked it a bit from the original to get it working with python 3.4
and I am also using pysocks instead of socksipy. I started with urllib instead
of urllib3 and I had the same issue. Currently I am getting:

    
    
    C:\Python>python program1.py
    ←[1mStarting Tor:
    ←[0m
    ←[34mFeb 28 21:59:45.000 [notice] Bootstrapped 0%: Starting←[0m
    ←[34mFeb 28 21:59:45.000 [notice] Bootstrapped 5%: Connecting to directory server←[0m
    ←[34mFeb 28 21:59:45.000 [notice] Bootstrapped 80%: Connecting to the Tor network←[0m
    ←[34mFeb 28 21:59:45.000 [notice] Bootstrapped 85%: Finishing handshake with first hop←[0m
    ←[34mFeb 28 21:59:46.000 [notice] Bootstrapped 90%: Establishing a Tor circuit←[0m
    ←[34mFeb 28 21:59:47.000 [notice] Bootstrapped 100%: Done←[0m
    ←[1m
    Checking our endpoint:
    ←[0m
    ←[34mUnable to reach https://www.atagar.com/echo.php←[0m
    

I have had similar code work outside of tor. I can connect my tor browser to
this site and I can browse to it with no problems. I have tried changing the
port numbers, but this is the one that is set up in Tor's proxy settings. One
thought I had is that this may be a timing issue. Is it possible that the code
is not waiting long enough to the site to respond?

Any help in getting this working would be greatly appreciated.


Answer: Here's a working version of [the stem
tutorial](https://stem.torproject.org/tutorials/to_russia_with_love.html) that
uses [`pysocks`](https://github.com/Anorov/PySocks) and its `sockshandler`
module to avoid monkey-patching the socket module:

    
    
    #!/usr/bin/env python
    """
    https://stem.torproject.org/tutorials/to_russia_with_love.html
    
    Usage:
      russian-tor-exit-node [<tor>] [--color] [--geoipfile=</path/to/file>]
      russian-tor-exit-node -h | --help
      russion-tor-exit-node --version
    
    Dependencies:
    
    - tor (packaged and standalone executables work)
    - pip install stem
    - pip install PySocks
    - pip install docopt
      : parse options
    - pip install colorama
      : cross-platform support for ANSI colors
    - [optional] sudo apt-get tor-geoipdb
      : if tor is bundled without geoip files; --geoipfile=/usr/share/tor/geoip
    """
    import sys
    from contextlib import closing
    
    import colorama  # $ pip install colorama
    import docopt  # $ pip install docopt
    import socks  # $ pip install PySocks
    import stem.process  # $ pip install stem
    from sockshandler import SocksiPyHandler  # see pysocks repository
    from stem.util import term
    
    try:
        import urllib2
    except ImportError: # Python 3
        import urllib.request as urllib2
    
    
    args = docopt.docopt(__doc__, version='0.2')
    colorama.init(strip=not (sys.stdout.isatty() or args['--color']))
    
    tor_cmd = args['<tor>'] or 'tor'
    socks_port = 7000
    config = dict(SocksPort=str(socks_port), ExitNodes='{ru}')
    if args['--geoipfile']:
        config.update(GeoIPFile=args['--geoipfile'], GeoIPv6File=args['--geoipfile']+'6')
    
    
    def query(url, opener=urllib2.build_opener(
            SocksiPyHandler(socks.PROXY_TYPE_SOCKS5, "localhost", socks_port))):
      try:
          with closing(opener.open(url)) as r:
              return r.read().decode('ascii')
      except EnvironmentError as e:
        return "Unable to reach %s: %s" % (url, e)
    
    # Start an instance of Tor configured to only exit through Russia. This prints
    # Tor's bootstrap information as it starts. Note that this likely will not
    # work if you have another Tor instance running.
    def print_bootstrap_lines(line):
      if "Bootstrapped " in line:
        print(term.format(line, term.Color.BLUE))
      else:
        print(line)
    
    print(term.format("Starting Tor:\n", term.Attr.BOLD))
    tor_process = stem.process.launch_tor_with_config(
        tor_cmd=tor_cmd,
        config=config,
        init_msg_handler=print_bootstrap_lines,
    )
    try:
        print(term.format("\nChecking our endpoint:\n", term.Attr.BOLD))
        print(term.format(query("https://icanhazip.com"), term.Color.BLUE))
    finally:
        if tor_process.poll() is None: # still running
            tor_process.terminate()  # stops tor
            tor_process.wait()
    

It works on both Python 2 and 3 on my Ubuntu machine.

`strace` shows data and dns requests are made via the tor proxy.

