Skip to content

Защита от SSRF

SSRF (Server-Side Request Forgery, подделка серверных запросов) — атака, при которой злоумышленник использует сервер для отправки запросов во внутреннюю сеть. HTTPC включает защиту от SSRF по умолчанию.

Поведение по умолчанию

go
cfg := httpc.DefaultConfig()
// AllowPrivateIPs = false → по умолчанию блокируются все приватные IP

Блокируемые диапазоны IP по умолчанию:

ДиапазонCIDRОписание
IPv4 loopback127.0.0.0/8localhost
Класс A приватные10.0.0.0/8Внутренняя сеть
Класс B приватные172.16.0.0/12Внутренняя сеть
Класс C приватные192.168.0.0/16Внутренняя сеть
Link-local169.254.0.0/16Автоконфигурация
CGNAT100.64.0.0/10Carrier-grade NAT (включая метаданные Alibaba Cloud 100.100.100.200)
Класс E зарезервированные240.0.0.0/4Зарезервированные адреса
IPv6 loopback::1/128localhost
IPv6 уникальные локальныеfc00::/7Уникальные локальные адреса
IPv6 link-localfe80::/10Link-local

Выше приведены основные диапазоны. Полный список блокировки также включает 0.0.0.0/8, TEST-NET (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 и т. д.), префикс документации IPv6 2001:db8::/32 и NAT64 64:ff9b::/96. Подробности см. в исходном коде isPrivateOrReservedIP.

Исключения CIDR

В микросервисной среде может потребоваться доступ к внутренним сервисам:

go
cfg := httpc.DefaultConfig()
cfg.Security.SSRFExemptCIDRs = []string{
    "10.0.0.0/8",       // Внутренний VPC
    "100.64.0.0/10",    // Tailscale VPN
    "172.20.0.0/16",    // Kubernetes Service CIDR
}

WARNING

Исключения CIDR должны быть максимально точными. Избегайте использования слишком больших диапазонов (например, 0.0.0.0/0), так как это равносильно отключению защиты от SSRF.

Освобождение частных IP по запросу

Если нужно разрешить частные IP только для отдельных запросов (например, вызов endpoint проверки работоспособности на localhost), не обязательно глобально включать AllowPrivateIPs — можно использовать параметр запроса WithAllowPrivateIPs, который освобождает адреса только для этого вызова:

go
// Клиент по умолчанию блокирует частные IP; этот вызов освобождает их по запросу
result, err := httpc.Get("http://localhost:8080/health",
    httpc.WithAllowPrivateIPs(true),
)

WARNING

Включайте этот параметр только для URL, которые надёжны и не поступают от пользовательского ввода. Назначение защиты от SSRF — не дать злоумышленнику заставить ваш процесс обращаться к внутренним endpoint; отключение по запросу вновь открывает этот риск для данного вызова. Если весь клиент должен обращаться к внутренним службам, задайте Security.AllowPrivateIPs = true в Config.

Защита от перепривязки DNS

HTTPC использует модель "resolve-validate-dial" для предотвращения атак перепривязки DNS:

  1. Разрешение доменного имени в IP-адрес
  2. Проверка всех разрешённых IP на принадлежность к приватным адресам
  3. Прямое подключение к проверенному IP (а не повторное разрешение домена)
go
// Сценарий атаки:
// 1. Злоумышленник управляет DNS сервером evil.com
// 2. Первое разрешение возвращает публичный IP (проходит проверку)
// 3. При фактическом подключении DNS возвращает 127.0.0.1 (обходит проверку)
//
// Защита HTTPC: после проверки подключение происходит напрямую к проверенному IP без повторного разрешения

Проверка SSRF при перенаправлениях

Цели перенаправлений также проходят проверку SSRF:

go
// Предположим, запрос к public-api.com, сервер возвращает 302 с перенаправлением на http://169.254.169.254/
// HTTPC проверит IP цели перенаправления, блокируя доступ к службе метаданных

Белый список доменов перенаправлений

go
cfg := httpc.DefaultConfig()
cfg.Security.RedirectWhitelist = []string{
    "api.example.com",
    "auth.example.com",
    "*.cdn.example.com",  // Поддерживаются подстановочные символы
}

// Перенаправления на домены, не входящие в белый список, будут заблокированы

Защита метаданных облачных сред

Адреса служб метаданных на облачных платформах:

ПлатформаАдресОписание
AWS169.254.169.254Метаданные экземпляра
GCPmetadata.google.internalСлужба метаданных
Azure169.254.169.254Метаданные экземпляра
Alibaba Cloud100.100.100.200Служба метаданных

HTTPC по умолчанию блокирует доступ к метаданным AWS/Azure (адрес 169.254.169.254 находится в блокируемом диапазоне 169.254.0.0/16). Метаданные GCP (metadata.google.internal) блокируются через проверку разрешения DNS.

WARNING

Метаданные Alibaba Cloud (100.100.100.200) находятся в диапазоне CGNAT (100.64.0.0/10), который HTTPC блокирует по умолчанию, поэтому доступ к метаданным Alibaba Cloud блокируется по умолчанию. Если для VPN (например, Tailscale/WireGuard) или внутренней маршрутизации действительно требуется доступ к этому диапазону, его необходимо явно освободить через SSRFExemptCIDRs: []string{"100.64.0.0/10"} — после освобождения метаданные Alibaba Cloud в этом диапазоне также станут доступны, оценивайте риски соответствующим образом.

Полное отключение защиты от SSRF

Используйте только в тестовой среде:

go
// TestingConfig отключает защиту от SSRF
client, _ := httpc.New(httpc.TestingConfig())

// Или ручная настройка
cfg := httpc.DefaultConfig()
cfg.Security.AllowPrivateIPs = true

DANGER

Никогда не устанавливайте AllowPrivateIPs = true в продакшене.

Лучшие практики

  1. Используйте SecureConfig() как базовую конфигурацию безопасности
  2. Исключайте только необходимые диапазоны CIDR
  3. Настройте RedirectWhitelist для ограничения целей перенаправлений
  4. Регулярно проводите аудит конфигурации SSRFExemptCIDRs
  5. Используйте промежуточное ПО аудита для логирования всех запросов

Что дальше