Kushal Das

FOSS and life. Kushal Das talks here.

kushal76uaid62oup5774umh654scnu5dwzh4u2534qxhcbi4wbab3ad.onion

Using Python to access Onion network over SOCKS proxy

Tor provides a SOCKS proxy so that you can have any application using the same to connect the Onion network. The default port is 9050. The Tor Browser also provides the same service on port 9150. In this post, we will see how can we use the same SOCKS proxy to access the Internet.

Using Python requests module

I used pipenv to install the dependencies.

$ pipenv install
$ pipenv shell
$ pipenv install requests[socks]
Installing requests[socks]…
Collecting requests[socks]
  Using cached requests-2.18.4-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests[socks])
  Using cached chardet-3.0.4-py2.py3-none-any.whl
Collecting urllib3<1.23,>=1.21.1 (from requests[socks])
  Using cached urllib3-1.22-py2.py3-none-any.whl
Collecting idna<2.7,>=2.5 (from requests[socks])
  Using cached idna-2.6-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests[socks])
  Using cached certifi-2018.1.18-py2.py3-none-any.whl
Collecting PySocks!=1.5.7,>=1.5.6; extra == "socks" (from requests[socks])
  Using cached PySocks-1.6.8.tar.gz
Building wheels for collected packages: PySocks
  Running setup.py bdist_wheel for PySocks: started
  Running setup.py bdist_wheel for PySocks: finished with status 'done'
  Stored in directory: /home/kdas/.cache/pip/wheels/77/f0/00/52f304b7dddcca8fca05ad1226382134ad50ba6c1662d7539e
Successfully built PySocks
Installing collected packages: chardet, urllib3, idna, certifi, PySocks, requests
Successfully installed PySocks-1.6.8 certifi-2018.1.18 chardet-3.0.4 idna-2.6 requests-2.18.4 urllib3-1.22

Adding requests[socks] to Pipfile's [packages]…
Pipfile.lock (711973) out of date, updating to (dcbf91)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (dcbf91)!
Installing dependencies from Pipfile.lock (dcbf91)…
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 6/6 — 00:00:01

After this, writing the actual code is very simple, we will be doing a GET request to https://httpbin.org to find out our IP address.

import requests

def main():
    proxies = {
            'http': 'socks5h://127.0.0.1:9050',
            'https': 'socks5h://127.0.0.1:9050'
    }
    r = requests.get('https://httpbin.org/get', proxies=proxies)
    print(r.text)


if __name__ == '__main__':
    main()

If you see closely, you will find that I am using socks5h as the protocol, instead of socks5. The request documentation mentions that using socks5h will make sure that DNS resolution happens over the proxy instead of on the client side.

The output of the code looks like below:

$ python usesocks.py 
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.18.4"
  }, 
  "origin": "137.74.169.241", 
  "url": "https://httpbin.org/get"
}

$ python usesocks.py 
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.18.4"
  }, 
  "origin": "77.247.181.162", 
  "url": "https://httpbin.org/get"
}

Now, you can use the same code to access any standard webservice or access any Onion address.