user2458048
user2458048

Reputation: 114

How to create a simple and secure Socks5 proxy in python?

Few days back I was wanting to build a proxy that could allow me to securely and anonymously connect to websites and servers. At first it seemed like a pretty easy idea, I would create an HTTP proxy that uses SSL between the client and the proxy, It would then create a SSL connection with what ever website/server the client requested and then forward that information to and from the client and server. I spent about a day researching and writing code that would do just that. But I then realized that someone could compromise the proxy and use the session key that the proxy had to decrypt and read the data being sent to and from the server.

After a little more research it seem that a socks proxy is what I needed. However there is not much documentation on a python version of a socks proxy(Mostly just how to connect to one). I was able to find The PySocks Module and read the Socks.py file. It looks great for creating a client but I don't see how I could use it to make a proxy.

I was wondering if anyone had a simple example of a socks5 proxy or if someone could point me to some material that could help me begin learning and building one?

Upvotes: 3

Views: 8255

Answers (2)

user14490111
user14490111

Reputation: 21

You create a python server to listen on a port and listen on IP 127.0.0.1. When you connect to your server you send: "www.facebook.com:80". No URL path nor http scheme. If the connect fails you send a failure message which may look something like "number Unable to connect to host." where number is an specific code that signifies a failed connection attempt. Upon success of a connection you send "200 Connection established". Then data is sent and received as normal. You do not want to use an http proxy because it accepts only website traffic.

You may want to use a framework for the proxy server because it should handle multiple connections.

I've read an ebook on asyncio named O'Reilly "Using Asyncio In Python 2020" multiple times and re-read it every now and again to try to grasp multiple connections. I have also just started to search for solutions using Flask because I want my proxy server to run along side a webserver.

Upvotes: 2

Dan
Dan

Reputation: 4663

I recommend using requesocks along with stem (assumes Tor). The official stem library is provided by Tor. Here's a simplified example based on a scraper that I wrote which also uses fake_useragent so you look like a browser:

import requesocks

from fake_useragent import UserAgent
from stem import Signal
from stem.control import Controller


class Proxy(object):
    def __init__(self, 
                 socks_port=9050,
                 tor_control_port=9051,
                 tor_connection_password='password')

        self._socks_port = int(socks_port)
        self._tor_control_port = int(tor_control_port)
        self._tor_connection_password = tor_connection_password
        self._user_agent = UserAgent()
        self._session = None
        self._update_session()

    def _update_session(self):
        self._session = requesocks.session()

        # port 9050 is the default SOCKS port
        self._session.proxies = {
            'http':  'socks5://127.0.0.1:{}'.format(self._socks_port),
            'https': 'socks5://127.0.0.1:{}'.format(self._socks_port),
        }

    def _renew_tor_connection(self):
        with Controller.from_port(port=self._tor_control_port) as controller:
            controller.authenticate(password=self._tor_connection_password)
            controller.signal(Signal.NEWNYM)

    def _sample_get_response(self, url):
        if not self._session:
            self._update_session()

        # generate random user agent string for every request
        headers = {
            'User-Agent': self._user_agent.random,
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Language': 'en-us,en;q=0.5',
        }  # adjust as desired

        response = self._session.get(url, verify=False, headers=headers)
        return response

You must have the Tor service running before executing this script and you must also modify your torrc file to enable the control port (9051).

Tor puts the torrc file in /usr/local/etc/tor/torrc if you compiled Tor from source, and /etc/tor/torrc or /etc/torrc if you installed a pre-built package. If you installed Tor Browser, look for Browser/TorBrowser/Data/Tor/torrc inside your Tor Browser directory (On Mac OS X, you must right-click or command-click on the Tor Browser icon and select "Show Package Contents" before the Tor Browser directories become visible).

Once you've found your torrc file, you need to uncomment the corresponding lines:

ControlPort 9051
## If you enable the controlport, be sure to enable one of these
## authentication methods, to prevent attackers from accessing it.
HashedControlPassword 16:05834BCEDD478D1060F1D7E2CE98E9C13075E8D3061D702F63BCD674DE

Please note that the HashedControlPassword above is for the password "password". If you want to set a different password (recommended), replace the HashedControlPassword in the torrc file by noting the output from tor --hash-password "<new_password>" where <new_password> is the password that you want to set.

Once you've changed your torrc file, you will need to restart tor for the changes to take effect (note that you actually only need to send Tor a HUP signal, not actually restart it). To restart it:

sudo service tor restart

I hope this helps and at least gets you started for what you were looking for.

Upvotes: 1

Related Questions