├── .env
├── .github
├── ha-stats.png
└── workflows
│ ├── tor.yml
│ └── haconfig.yml
├── dashboard
├── postcss.config.js
├── tsconfig.json
├── src
│ ├── main.tsx
│ ├── lib
│ │ ├── utils.ts
│ │ └── api.ts
│ ├── components
│ │ ├── ui
│ │ │ ├── badge.tsx
│ │ │ ├── card.tsx
│ │ │ ├── button.tsx
│ │ │ ├── tabs.tsx
│ │ │ └── toast.tsx
│ │ ├── Diagnostics.tsx
│ │ ├── CircuitMonitor.tsx
│ │ ├── SystemOverview.tsx
│ │ └── NetworkTraffic.tsx
│ ├── types
│ │ └── index.ts
│ ├── index.css
│ └── App.tsx
├── .gitignore
├── vite.config.ts
├── index.html
├── dockerfile
├── eslint.config.js
├── tsconfig.node.json
├── tsconfig.app.json
├── public
│ └── vite.svg
├── package.json
├── tailwind.config.js
└── README.md
├── metrics
├── requirements.txt
├── dockerfile
└── app
│ └── main.py
├── env.example
├── haproxy
├── dockerfile
└── check-tor.sh
├── haconfig
├── dockerfile
├── haproxy.j2
└── gen_conf.py
├── get-relays.sh
├── tor
├── dockerfile
└── torrc
├── .gitignore
├── get-exits.py
├── speedtest.sh
├── loadtest.py
├── docker-compose.yml
└── README.md
/.env:
--------------------------------------------------------------------------------
1 | SOCKS=5
--------------------------------------------------------------------------------
/.github/ha-stats.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshhighet/multisocks/HEAD/.github/ha-stats.png
--------------------------------------------------------------------------------
/dashboard/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | '@tailwindcss/postcss': {},
4 | },
5 | }
--------------------------------------------------------------------------------
/metrics/requirements.txt:
--------------------------------------------------------------------------------
1 | stem
2 | geoip2
3 | fastapi>=0.115.0
4 | uvicorn[standard]>=0.30.0
5 | docker
6 | requests[socks]
--------------------------------------------------------------------------------
/env.example:
--------------------------------------------------------------------------------
1 | # multisocks
2 | # copy this file to .env and customize
3 |
4 | # number of Tor instances
5 | SOCKS=5
6 |
7 | # CORS
8 | HOSTNAME=localhost
9 |
--------------------------------------------------------------------------------
/dashboard/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | { "path": "./tsconfig.app.json" },
5 | { "path": "./tsconfig.node.json" }
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/haproxy/dockerfile:
--------------------------------------------------------------------------------
1 | FROM haproxy:alpine
2 | LABEL org.opencontainers.image.source https://github.com/joshhighet/multisocks/haproxy
3 | USER root
4 | RUN apk add --no-cache curl
5 | USER haproxy
--------------------------------------------------------------------------------
/haconfig/dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.13-alpine
2 | LABEL org.opencontainers.image.source https://github.com/joshhighet/multisocks/haconfig
3 | WORKDIR /usr/app/
4 | RUN pip install docker jinja2
5 | COPY haproxy.j2 /usr/app/haproxy.j2
6 | COPY gen_conf.py /usr/app/gen_conf.py
--------------------------------------------------------------------------------
/get-relays.sh:
--------------------------------------------------------------------------------
1 | for container in $(docker ps --filter "ancestor=multisocks-private-tor" --format "{{.ID}}"); do
2 | docker exec -u root $container \
3 | curl -s --socks5-hostname localhost:9050 \
4 | https://cloudflare.com/cdn-cgi/trace \
5 | | grep ip | sed 's/ip=//'
6 | done
--------------------------------------------------------------------------------
/dashboard/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import './index.css'
4 | import App from './App.tsx'
5 |
6 | createRoot(document.getElementById('root')!).render(
7 |
Connecting to Tor circuits
85 |102 | Failed to connect to the multisocks metrics service. 103 |
104 |105 | Make sure the metrics service is running on port 8000. 106 |
107 | 111 |No dashboard data received
124 |136 | {diagnostic.message} 137 |
138 |139 | {diagnostic.details} 140 |
141 || Backend | 259 |Status | 260 |Sessions | 261 |Bytes In | 262 |Bytes Out | 263 |Rate | 264 |
|---|---|---|---|---|---|
| {stat.svname} | 270 |
271 | |
275 | {stat.stot.toLocaleString()} | 276 |{formatBytes(stat.bin)} | 277 |{formatBytes(stat.bout)} | 278 |{stat.rate}/s | 279 |
No HAProxy statistics available
288 |All circuits
155 |Ready for traffic
166 |In progress
177 |Terminated
188 |294 | Host: {circuit.hostname} 295 |
296 |No circuits found
373 |374 | {selectedHost ? 'Try selecting a different host' : 'Circuits may be building or all hosts are offline'} 375 |
376 |92 | Healthy hosts • Click to view all 93 |
94 |107 | of {summary.totalCircuits} total 108 |
109 |122 | Data transferred 123 |
124 |137 | Response time 138 |
139 |Port 8080
161 |Load Balancer
175 |{healthyHosts.length} healthy
189 |{summary.activeCircuits} active
205 |