Skip to content

SSRF 방어

SSRF(Server-Side Request Forgery, 서버 측 요청 위조) 는 공격자가 서버를 이용해 내부 네트워크에 요청을 보내는 공격 방식입니다. HTTPC 은 기본적으로 SSRF 방어가 활성화되어 있습니다.

기본 동작

go
cfg := httpc.DefaultConfig()
// AllowPrivateIPs = false → 기본적으로 모든 사설 IP 차단

기본 차단 IP 범위:

범위CIDR설명
IPv4 루프백127.0.0.0/8localhost
A 클래스 사설10.0.0.0/8내부망
B 클래스 사설172.16.0.0/12내부망
C 클래스 사설192.168.0.0/16내부망
링크 로컬169.254.0.0/16자동 설정
CGNAT100.64.0.0/10통신사급 NAT (알리바바 클라우드 메타데이터 100.100.100.200 포함)
E 클래스 예약240.0.0.0/4예약 주소
IPv6 루프백::1/128localhost
IPv6 로컬fc00::/7고유 로컬 주소
IPv6 링크fe80::/10링크 로컬

위 표는 주요 범위입니다. 전체 차단 목록에는 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 를 허용하면 되는 경우 (예: localhost 헬스 체크 엔드포인트 호출) 에는 전역으로 AllowPrivateIPs를 켤 필요 없이 WithAllowPrivateIPs 요청 옵션으로 해당 요청에만 허용할 수 있습니다:

go
// 기본 클라이언트는 사설 IP 를 차단; 이 호출은 요청별로 허용
result, err := httpc.Get("http://localhost:8080/health",
    httpc.WithAllowPrivateIPs(true),
)

WARNING

이 옵션은 신뢰할 수 있고 사용자 입력이 아닌 URL 에만 활성화하세요. SSRF 방어의 목적은 공격자가 귀하의 프로세스를 유도해 내부망 엔드포인트에 접근하는 것을 막는 것이며, 요청별로 비활성화하면 해당 호출에 이 위험이 다시 발생합니다. 클라이언트 전체가 내부 서비스에 접근해야 한다면 Config 에서 Security.AllowPrivateIPs = true를 설정하세요.

DNS 리바인딩 방어

HTTPC 은 "해석 - 검증 - 직접 연결" 모드로 DNS 리바인딩 공격을 방지합니다:

  1. 도메인을 IP 주소로 해석
  2. 해석된 모든 IP 가 사설 주소인지 검증
  3. 검증된 IP 에 직접 연결 (도메인을 다시 해석하지 않음)
go
// 공격 시나리오:
// 1. 공격자가 evil.com 의 DNS 를 제어
// 2. 첫 번째 해석에서 공인 IP 반환 (검증 통과)
// 3. 실제 연결 시 DNS 가 127.0.0.1 반환 (검증 우회)
//
// HTTPC 방어: 검증 후 검증된 IP 로 직접 연결, 재해석하지 않음

리다이렉트 SSRF 검사

리다이렉트 대상도 SSRF 검증을 거칩니다:

go
// public-api.com 에 요청했는데 서버가 http://169.254.169.254/로 302 리다이렉트 반환
// 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인스턴스 메타데이터
알리바바 클라우드100.100.100.200메타데이터 서비스

HTTPC 은 기본적으로 AWS/Azure 메타데이터 접근을 차단합니다 (169.254.169.254169.254.0.0/16 차단 목록에 포함). GCP 메타데이터 (metadata.google.internal) 는 DNS 해석 검증으로 차단됩니다.

WARNING

알리바바 클라우드 메타데이터 (100.100.100.200) 는 CGNAT 범위 (100.64.0.0/10) 에 위치하며, HTTPC 은 기본적으로 이 범위를 차단하므로 알리바바 클라우드 메타데이터 접근이 기본적으로 차단됩니다. Tailscale/WireGuard 등 VPN 이나 내부 라우팅으로 인해 이 범위에 접근해야 하는 경우, SSRFExemptCIDRs: []string{"100.64.0.0/10"}로 명시적으로 면제해야 합니다 — 면제 시 해당 범위의 알리바바 클라우드 메타데이터도 접근 가능해지므로 위험을 평가하세요.

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. 감사 미들웨어로 모든 요청 기록

다음 단계