Some projects require tunneling through a proxy system to connect to, monitor or probe a specific resource. If you are programming with Python sockets you will come to find the standard library’s socket class does not support sending data piped through a SOCKS5 server. Depending on your specifications, here are two ways to overcome the default behavior.
For this, have these Python packages installed on your system globally or in your project environment.
Just install with pip.
pip install pysocks requests urllib3
Monkeypatching the socket
This allows you to have the same control over the socket like you normally would in Python. A benefit if you are tasked to fuzz a service with custom payloads, or are using a non standard protocol over the socket layer.
To patch the socket :
- Set the proxy you want to use with the socks method setdefaultproxy.
- Patch the socket module to use the Pysocks implementation of the socketsocket class.
- Override the create_connection method.
import socks
import socket
def create_connection(address, timeout=None, source_address=None):
sock = socks.socksocket()
sock.connect(address)
return sock
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050)
# patch the socket module
socket.socket = socks.socksocket
socket.create_connection = create_connection
import urllib3
try:
s = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("bot.whatismyipaddress.com", 80))
message = b'GET / HTTP/1.0\r\n\r\n'
s.sendall(message)
reply = s.recv(4069)
print(reply)
except Exception as e:
print(e)
If your SOCKS5 proxy address is returned when you run the script, you have successfully patched the module.
Request library
Request library is less granularity over your socket data. One advantage is it does support SSL out of the box. A benefit if you don’t want to implement yourself in the patch. The Request library allows you to do this with minimal lines of code. Just set your proxy details in a dictionary and supply as a parameter to your requests.get method.
import requests
proxies = {
'http': 'socks5h://127.0.0.1:9050',
'https': 'socks5h://127.0.0.1:9050'
}
data = requests.get("http://bot.whatismyipaddress.com",proxies=proxies).text
print(data)
Using the Request’s API, you can print out the return body with the .text method.
If you were having issues connecting your Python code to a SOCKS5 server, this should help you with your project requirements.