Skip to content

jacksurfer/mazok-proxy

Repository files navigation

Mazok Proxy — SOCKS5 с динамическим выбором IP

Go Go Report Card License: MIT

Высокопроизводительный SOCKS5 прокси-сервер с динамическим выбором исходящего IP через username.

🇬🇧 English version

Зачем это нужно?

Проблема: В Kubernetes кластерах (DigitalOcean, AWS, GCP и др.) исходящий IP-адрес нод может меняться — при автоскейлинге, обновлении нод или пересоздании кластера. Если ваше приложение требует фиксированный исходящий IP, это становится проблемой.

Стандартные решения:

  • BYOIP (Bring Your Own IP) — дорого, долго настраивать, не все провайдеры поддерживают
  • NAT Gateway с Elastic IP — дополнительные расходы, single point of failure
  • Прокси-сервисы — ежемесячная плата, зависимость от третьих лиц

Моё решение:

  1. Арендовал выделенный сервер в OVH с блоком /24 (256 IP-адресов) за фиксированную цену
  2. Написал этот прокси, который позволяет выбирать исходящий IP через поле username
  3. Приложение в Kubernetes подключается к прокси и работает с нужным фиксированным IP

Результат: Независимо от того, какие IP получают ноды кластера, приложение всегда выходит в интернет с предсказуемого адреса. Бонус — 256 IP на выбор для разных задач.

Возможности

  • 🔀 Динамический выбор IP — исходящий IP задаётся через username
  • 🔒 TLS шифрование — защита трафика между клиентом и прокси
  • 🛡️ IP Whitelist — подключаемые провайдеры (DigitalOcean, расширяемо)
  • 💚 Health checks — эндпоинты /health, /ready, /stats для Kubernetes
  • Без внешних зависимостей — чистый Go, один бинарный файл
  • 🧪 Покрыт тестами — полное тестовое покрытие

Как это работает

Username = IP адрес (полный или последний октет)
Password = общий пароль

socks5://42:secret@proxy:1080       → исходящий IP: 54.11.11.42
socks5://54.11.11.99:secret@proxy:1080 → исходящий IP: 54.11.11.99

Прокси привязывает исходящие соединения к IP, указанному в поле username, позволяя маршрутизировать разные запросы через разные IP-адреса вашей подсети.

Быстрый старт

Скачать

Скачайте последнюю версию из Releases.

Сборка из исходников

git clone https://github.com/jacksurfer/mazok-proxy.git
cd mazok-proxy
go build -o mazok-proxy ./cmd/mazok-proxy/

Настройка

cp config.example.yaml config.yaml
# Отредактируйте config.yaml

Запуск

./mazok-proxy config.yaml

Конфигурация

server:
  listen: ":1080"
  tls:
    enabled: true
    cert: "/etc/mazok-proxy/cert.pem"
    key: "/etc/mazok-proxy/key.pem"

auth:
  # Username = исходящий IP (например, "42" или "54.11.11.42")
  password: "${PROXY_PASSWORD}"

outbound:
  # Ваша IP-подсеть
  subnet: "54.11.11.0/24"

whitelist:
  enabled: true
  digitalocean:
    enabled: true
    token: "${DO_API_TOKEN}"
    poll_interval: 60s
    tags: []
    kubernetes_clusters:
      - "my-cluster"
  additional:
    - "127.0.0.1"

health:
  enabled: true
  listen: ":8080"

timeouts:
  connect: 30s
  read_write: 60s
  idle: 300s

Поддерживаются переменные окружения: ${VAR_NAME}.

Провайдеры Whitelist

DigitalOcean

Автоматически получает IP-адреса из:

  • Droplets (опционально с фильтрацией по тегам)
  • Узлов Kubernetes кластеров
whitelist:
  digitalocean:
    enabled: true
    token: "${DO_API_TOKEN}"
    tags: ["web", "api"]  # Пусто = все дроплеты
    kubernetes_clusters:
      - "prod-cluster"

Добавление своих провайдеров

Реализуйте интерфейс Provider:

type Provider interface {
    Name() string
    FetchIPs(ctx context.Context) ([]string, error)
}

Смотрите internal/whitelist/providers/digitalocean/ как образец.

Примеры клиентов

curl

# Без TLS
curl -x socks5://42:password@proxy:1080 https://ifconfig.me

# С TLS (самоподписанный сертификат)
curl -x socks5://42:password@proxy:1080 --proxy-insecure https://ifconfig.me

Go

import "golang.org/x/net/proxy"

auth := &proxy.Auth{
    User:     "42",           // Исходящий IP
    Password: "your_password",
}

dialer, _ := proxy.SOCKS5("tcp", "proxy:1080", auth, proxy.Direct)

transport := &http.Transport{
    DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
        return dialer.Dial(network, addr)
    },
}

client := &http.Client{Transport: transport}

Полный пример с TLS в examples/client/.

API Reference

Endpoint Описание
GET /health Liveness probe (всегда 200)
GET /ready Readiness probe (проверяет загрузку whitelist)
GET /stats JSON статистика

Деплой

Systemd

sudo cp mazok-proxy /usr/local/bin/
sudo cp config.yaml /etc/mazok-proxy/
sudo cp mazok-proxy.service /etc/systemd/system/
sudo systemctl enable --now mazok-proxy

Docker

FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o mazok-proxy ./cmd/mazok-proxy/

FROM alpine:latest
COPY --from=builder /app/mazok-proxy /usr/local/bin/
ENTRYPOINT ["mazok-proxy"]

Безопасность

  • TLS шифрование — защищает трафик между клиентом и прокси
  • Аутентификация по паролю — совместимо с RFC 1929
  • IP Whitelist — ограничивает доступ известными IP
  • Валидация подсети — не позволяет использовать IP вне вашего диапазона
  • Минимальные привилегии — работает от непривилегированного пользователя с CAP_NET_RAW

Структура проекта

├── cmd/mazok-proxy/       # Точка входа
├── internal/
│   ├── config/             # Загрузка конфигурации
│   ├── dialer/             # Привязка исходящего IP
│   ├── health/             # HTTP сервер health check
│   ├── server/             # Реализация SOCKS5 протокола
│   └── whitelist/          # Управление IP whitelist
│       └── providers/
│           └── digitalocean/
├── examples/client/        # Пример Go клиента
└── config.example.yaml

Участие в разработке

  1. Форкните репозиторий
  2. Создайте feature branch
  3. Напишите тесты для новой функциональности
  4. Убедитесь, что все тесты проходят: go test ./...
  5. Создайте pull request

Лицензия

MIT License — смотрите файл LICENSE.

About

SOCKS5 Proxy with Dynamic IP Binding

Resources

License

Stars

Watchers

Forks

Packages

No packages published