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.