diff --git a/README.md b/README.md index 7f3fe0a..10a14ca 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # CasTor :beaver: -Tor HTTP proxy with balanced Tor instances. +Tor proxy with balanced Tor instances. ![Tor balance schema](docs/tor-balance.png) @@ -19,7 +19,7 @@ This command will start one Tor instance and HAProxy: docker-compose up ``` -The HTTP proxy will be running on port **8080**. +By default the proxy will be a SOCKS5 proxy running on port **8080**. ### Start multiple Tor instances @@ -31,12 +31,22 @@ For instance to start 5 Tor instances: docker-compose up --scale tor=5 ``` -### Run proxy on a different port +By default, 5 tor instances are started. This also can be tunned in [`docker-compose.yml`](docker-compose.yml) file by editing the `scale` parameter of tor service. -Proxy port can be set using the environement varaible `HTTP_PROXY_PORT`. You can specify it in the [`.env`](.env) file or dirrectly in the shell such as: +### Use HTTP CONNECT proxy + +Tor also provides an HTTP CONNECT proxy; you can use it by setting the environment variable `PROXY_MODE` to "http". This can be done by editing the [`.env`](.env) file or dirrectly in the shell such as: ```bash -export HTTP_PROXY_PORT=8080 +export PROXY_MODE="http" +``` + +### Run proxy on a different port + +Proxy port can be set using the environement varaible `PROXY_PORT`. You can specify it in the [`.env`](.env) file or dirrectly in the shell such as: + +```bash +export PROXY_PORT=8080 ``` ## Test the proxy @@ -48,8 +58,8 @@ Once the application is started, you can test your proxy with `curl`: $ curl https://ipinfo.io/ip A.B.C.D # => your current IP address -# test with the proxy -$ curl -x http://localhost:8080 https://ipinfo.io/ip +# test with the proxy (with the default proxy conf) +$ curl -x socks5://localhost:8080 https://ipinfo.io/ip W.X.Y.Z # => Tor exit node IP address ``` @@ -57,11 +67,11 @@ W.X.Y.Z # => Tor exit node IP address When you run the command `docker-compose up`, you start at least 3 services (more if you scaled up the number of Tor instances): **tor**, **conf-generator** and **haproxy**. -The first service started is **tor**, this service is running a Tor instance with a Tor HTTP Tunnel (mandatory to have an HTTP proxy rather than a sock proxy). +1. The first service started is **tor**, this service is running a Tor instance with a SOCKS5 proxy (and with a Tor HTTP Tunnel if you use the "http" mode). -The second service is **conf-generator**, this services runs a python script that does the following things: +2. The second service is **conf-generator**, this service runs a python script that does the following things: -1. get all the IP address of the Tor instances within the docker network (using the Docker API) -2. generate an HAProxy configuration file with the retrieved IPs + 1. get all the IP address of the Tor instances within the docker network (using the Docker API) + 2. generate an HAProxy configuration file with the retrieved IPs and the proxy mode -The final service is an HAProxy load balancer using the configuration file generated by **conf-generator**. +3. The final service is an HAProxy load balancer using the configuration file generated by **conf-generator**. diff --git a/conf-generator/gen_conf.py b/conf-generator/gen_conf.py index 7c65106..65a6b99 100644 --- a/conf-generator/gen_conf.py +++ b/conf-generator/gen_conf.py @@ -1,5 +1,6 @@ -from jinja2 import Template +import os import docker +from jinja2 import Template def get_tor_ips(): @@ -21,10 +22,22 @@ def get_tor_ips(): return ip_addrs +def resolve_proxy_mode(proxy_mode): + if proxy_mode == "http": + return "http", 9080 + return "tcp", 9050 + + if __name__ == "__main__": + proxy_mode = os.environ.get("PROXY_MODE") + print(proxy_mode) + proxy_type, tor_port = resolve_proxy_mode(proxy_mode) + tor_ips = get_tor_ips() + with open("haproxy.j2", "r") as file: - conf = Template(file.read()).render(tor_hosts=tor_ips) + conf = Template(file.read()).render(proxy_type=proxy_type, tor_port=tor_port, + tor_hosts=tor_ips) with open("/usr/local/etc/haproxy/haproxy.cfg", "w") as file: file.write(conf) diff --git a/conf-generator/haproxy.j2 b/conf-generator/haproxy.j2 index 31a7dae..cf5ee30 100644 --- a/conf-generator/haproxy.j2 +++ b/conf-generator/haproxy.j2 @@ -2,7 +2,7 @@ global log stdout format raw local0 info defaults - mode http + mode {{proxy_type}} timeout client 10s timeout connect 5s timeout server 10s @@ -10,16 +10,13 @@ defaults log global frontend loadbalancer - bind :80 - mode http + bind :8080 use_backend tors backend tors balance roundrobin - mode http - option forwardfor {%- for host in tor_hosts %} - server tor{{loop.index}} {{host}}:9080 check + server tor{{loop.index}} {{host}}:{{tor_port}} check {%- endfor %} diff --git a/docker-compose.yml b/docker-compose.yml index 2099cea..d258cdc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,33 +7,39 @@ services: dockerfile: Dockerfile networks: - net_tor + expose: + - 9050 + - 9080 + scale: 5 haproxy: image: haproxy:alpine restart: always depends_on: tor: - condition: service_healthy + condition: service_started haproxy-conf-generator: condition: service_completed_successfully ports: - - ${HTTP_PROXY_PORT}:80 + - ${PROXY_PORT}:8080 volumes: - haproxy_conf:/usr/local/etc/haproxy networks: - net_tor + env_file: ./.env haproxy-conf-generator: build: ./conf-generator command: python gen_conf.py depends_on: tor: - condition: service_healthy + condition: service_started volumes: - haproxy_conf:/usr/local/etc/haproxy - /var/run/docker.sock:/tmp/docker.sock networks: - net_tor + env_file: ./.env volumes: haproxy_conf: