feat: add tor-proxy service for SSH and admin panel access via Tor
- Add tor-proxy/Dockerfile: Alpine + Tor with entrypoint - Add tor-proxy/entrypoint.sh: dynamic torrc generation with env var validation - Update docker-compose.yml: add tor-proxy service with shared tor_proxy_net network - Two Tor hidden services: SSH (port 22) and admin panel (port 80 -> 3001) - Update .env.example: add SSH_HOST_IP, SHOP_CONTAINER, ADMIN_PORT vars
This commit is contained in:
@@ -39,6 +39,14 @@ WG_ADDRESS=
|
|||||||
WG_DNS=
|
WG_DNS=
|
||||||
WG_ALLOWED_IPS=0.0.0.0/0,::/0
|
WG_ALLOWED_IPS=0.0.0.0/0,::/0
|
||||||
|
|
||||||
|
# --- Tor Proxy ---
|
||||||
|
# SSH backend: куда Tor перенаправляет SSH (по умолчанию хост-машина)
|
||||||
|
SSH_HOST_IP=host.docker.internal
|
||||||
|
# Имя контейнера магазина (для проброса админки через Tor)
|
||||||
|
SHOP_CONTAINER=telegram_shop_prod
|
||||||
|
# Порт админ-панели внутри контейнера магазина
|
||||||
|
ADMIN_PORT=3001
|
||||||
|
|
||||||
# --- Gitea API (для CI/CD и пайплайна) ---
|
# --- Gitea API (для CI/CD и пайплайна) ---
|
||||||
GITEA_API_URL=https://git.softuniq.eu/api/v1
|
GITEA_API_URL=https://git.softuniq.eu/api/v1
|
||||||
GITEA_TOKEN=
|
GITEA_TOKEN=
|
||||||
@@ -27,3 +27,40 @@ services:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 60s
|
start_period: 60s
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
- tor_proxy_net
|
||||||
|
|
||||||
|
tor-proxy:
|
||||||
|
build:
|
||||||
|
context: ./tor-proxy
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: tor-proxy
|
||||||
|
environment:
|
||||||
|
SSH_HOST_IP: ${SSH_HOST_IP:-host.docker.internal}
|
||||||
|
SHOP_CONTAINER: ${SHOP_CONTAINER:-telegram_shop_prod}
|
||||||
|
ADMIN_PORT: ${ADMIN_PORT:-3001}
|
||||||
|
volumes:
|
||||||
|
- tor_data:/var/lib/tor
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
- tor_proxy_net
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "test -s /var/lib/tor/ssh/hostname && test -s /var/lib/tor/admin/hostname"]
|
||||||
|
interval: 60s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 2
|
||||||
|
start_period: 120s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
tor_proxy_net:
|
||||||
|
name: tor_proxy_net
|
||||||
|
driver: bridge
|
||||||
|
attachable: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
tor_data:
|
||||||
|
name: tor_proxy_data
|
||||||
12
tor-proxy/Dockerfile
Normal file
12
tor-proxy/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
FROM alpine:3.18
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
tor \
|
||||||
|
bash
|
||||||
|
|
||||||
|
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
|
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 22 80
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||||
57
tor-proxy/entrypoint.sh
Normal file
57
tor-proxy/entrypoint.sh
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
validate_alnum() {
|
||||||
|
local val="$1"
|
||||||
|
local name="$2"
|
||||||
|
if ! echo "$val" | grep -qE '^[a-zA-Z0-9._-]+$'; then
|
||||||
|
echo "ERROR: $name contains invalid characters: $val"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if echo "$val" | grep -q $'\n'; then
|
||||||
|
echo "ERROR: $name contains newlines: $val"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_alnum "$SSH_HOST_IP" "SSH_HOST_IP"
|
||||||
|
validate_alnum "$SHOP_CONTAINER" "SHOP_CONTAINER"
|
||||||
|
if ! echo "$ADMIN_PORT" | grep -qE '^[0-9]+$'; then
|
||||||
|
echo "ERROR: ADMIN_PORT must be a number: $ADMIN_PORT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$SSH_HOST_IP" = "host.docker.internal" ]; then
|
||||||
|
if ! getent hosts host.docker.internal >/dev/null 2>&1; then
|
||||||
|
GATEWAY=$(ip route | grep default | awk '{print $3}')
|
||||||
|
if [ -n "$GATEWAY" ]; then
|
||||||
|
SSH_HOST_IP="$GATEWAY"
|
||||||
|
echo "host.docker.internal not resolvable, using gateway: $SSH_HOST_IP"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p /var/lib/tor/ssh /var/lib/tor/admin
|
||||||
|
chmod 700 /var/lib/tor/ssh /var/lib/tor/admin
|
||||||
|
|
||||||
|
cat > /etc/tor/torrc <<EOF
|
||||||
|
# Generated by entrypoint.sh at container start
|
||||||
|
RunAsDaemon 0
|
||||||
|
SocksPort 0
|
||||||
|
Log notice stdout
|
||||||
|
DataDirectory /var/lib/tor
|
||||||
|
|
||||||
|
# --- SSH hidden service (proxies to host SSH) ---
|
||||||
|
HiddenServiceDir /var/lib/tor/ssh/
|
||||||
|
HiddenServicePort 22 ${SSH_HOST_IP}:22
|
||||||
|
|
||||||
|
# --- Admin panel hidden service (proxies to shop container) ---
|
||||||
|
HiddenServiceDir /var/lib/tor/admin/
|
||||||
|
HiddenServicePort 80 ${SHOP_CONTAINER}:${ADMIN_PORT}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "torrc contents:"
|
||||||
|
cat /etc/tor/torrc
|
||||||
|
|
||||||
|
echo "Starting Tor..."
|
||||||
|
exec tor -f /etc/tor/torrc
|
||||||
Reference in New Issue
Block a user