Skip to content

a scaling framework for tor traffic balancing 🧦 🧅 ⚖️

Notifications You must be signed in to change notification settings

nerdlabs/multisocks

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

multisocks

multisocks is a tool for running frameworks such as spiders or scanners against infrastructure (onion services) on the tor network

it is a tcp load balanced SOCKS5 proxy that can speed up other tools by spawning up to 4095 tor circuits of which inbound requests can be distributed across

it can significantly cut-down load times for correctly scaled applications by doing the following

  • creating a very large number of tor circuits
  • surfacing a single-ingress SOCKS5 proxy
  • adequately load-balance backend connections
  • performing health-checks against each backend tor circuit
  • serving a load balancer monitoring dashboard

multisocks is a fork/derivative of the excellent Iglesys347/castor

multisocks exposes a SOCKS5 proxy on :8080 and a statistics report on :1337 by default.

flowchart TB
    sclient[proxy client :8080]<-->front
    stat{{stats :1337}}-..->front
    front[haproxy]
    style stat stroke-width:2px,color:#fff,stroke-dasharray: 5 5
    style sclient stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
    subgraph scaler[x scaled instances]
        subgraph tor1 [tor]
        ctrl[controlport]
        sock[socksport]
        end
        subgraph tor2 [tor]
        ctrl2[controlport]
        sock2[socksport]
        end
        subgraph tor3 [tor]
        ctrl3[controlport]
        sock3[socksport]
        end
    end
    front<-->sock
    front-. healthcheck .-> ctrl
    front<-->sock2
    front-. healthcheck .-> ctrl2
    front<-->sock3
    front-. healthcheck .-> ctrl3
Loading

configuration

if you do not define a number of Tor instances (ref backends) - it will default to 5. on 2x2 (cpu/memory) machine this can comfortably run 50 circuits.

avoid defining more than 4095 backends - this is a haproxy limitation. to work around this, create a secondary backend group - do so referencing backend tors within haproxy.j2 and update the configuration template haproxy.j2 accordingly.

set the number of tor instances to be created by altering SOCKS within .env

reference services.tor.deploy.replicas within docker-compose.yml

runtime

git clone https://github.com/joshhighet/multisocks
# add --detach at the end of the below command detatch the command from your existing session
docker compose --file multisocks/docker-compose.yml up

stats & obserability

to view the status of haproxy, navigate to your-multisocks-host:1337 in a browser. you should see the number of backends as defined in .env along with other useful metrics

haproxy stats, example

to fetch state of each circuit you could leverage something similar to the below

watch -n 5 "curl -s 'http://localhost:1337/;csv' \
| awk -F ',' '{print \$2 \" - \" \$18}' \
| grep -v 'status\|FRONT\|BACK'"

debugging

to trail logs, leverage docker compose logs

cd multisocks
docker compose logs --timestamps --follow

to enter a shell in a running container, use docker exec.

to view your container names use docker ps - replace multisocks-haproxy accordingly

docker exec -it -u root multisocks-haproxy ash

testing

this is a short script to check multisocks is running correctly.

it assumes multisocks is running locally and makes ten requests to Cloudflare, returning the requested IP for each request

for i in {1..10}; do
    curl -sLx socks5://localhost:8080 cloudflare.com/cdn-cgi/trace | grep ip\=
done

to test against hsdir resolutions, simply replace the cloudflare URL with an onion service

to find some online onion services, go browse around or use the below for starters

curl -sL ransomwhat.telemetry.ltd/groups \
| jq -r '.[].locations[] | select(.available==true) | .slug' \
| head -n 10

notes

the current health-check implementation leaves much room for improvement. it uses netcat to send an authenticated telnet command getinfo circuit-status. an alternate could be to use stem, with something like the below

import stem.control
def is_circuit_built():
    with stem.control.Controller.from_port(port=9051) as controller:
        controller.authenticate()
        circs = controller.get_circuits()
        for circ in circs:
            if circ.status == 'BUILT':
                return True
        return False

About

a scaling framework for tor traffic balancing 🧦 🧅 ⚖️

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 39.4%
  • Shell 36.5%
  • Jinja 24.1%