설치¶
요구사항¶
- Java 21+
- Spring Boot 3.5+ (Spring 기반 모듈)
- Spring AI 모듈: Spring AI 1.0+
- Feign 모듈: Spring Cloud 2024.0+
모듈 선택¶
ssrf-guard 3.0+은 HTTP 클라이언트 경계로 분리되어 있습니다. 실제로 쓰는 모듈만 고르면 됩니다.
<dependency>
<groupId>kr.devslab</groupId>
<artifactId>ssrf-guard</artifactId>
<version>3.1.0</version>
</dependency>
메타 아티팩트가 -core, -httpclient5, -restclient를 끌어옵니다 — v2.0.0 전체 surface와 동등.
<dependency>
<groupId>kr.devslab</groupId>
<artifactId>ssrf-guard-resttemplate</artifactId>
<version>3.1.0</version>
</dependency>
RestTemplateBuilder에 동일한 ClientHttpRequestInterceptor + HttpComponentsClientHttpRequestFactory를 wiring. 둘 다 쓰면 -restclient도 추가.
<dependency>
<groupId>kr.devslab</groupId>
<artifactId>ssrf-guard-webclient</artifactId>
<version>3.1.0</version>
</dependency>
자동설정된 WebClient.Builder에 ExchangeFilterFunction 추가. Reactive — 정책 위반은 Mono.error(SsrfGuardException)으로 옴.
<dependency>
<groupId>kr.devslab</groupId>
<artifactId>ssrf-guard-feign</artifactId>
<version>3.1.0</version>
</dependency>
feign.RequestInterceptor 등록 — Spring Cloud OpenFeign이 모든 @FeignClient에 자동 적용.
<dependency>
<groupId>kr.devslab</groupId>
<artifactId>ssrf-guard-springai</artifactId>
<version>3.1.0</version>
</dependency>
모든 ToolCallback 빈을 URL 인자 검증으로 감쌈. LLM 에이전트가 URL을 받아 fetch하는 시나리오의 결정적인 새 SSRF 표면. v3.1+는 내부적으로 ssrf-guard-llm (프레임워크-중립 코어)에 위임 — public API 동일.
<dependency>
<groupId>kr.devslab</groupId>
<artifactId>ssrf-guard-langchain4j</artifactId>
<version>3.1.0</version>
</dependency>
Spring AI 탭과 동일한 위협 모델, 다른 프레임워크. 모든 ToolExecutor 빈을 wrap. LangChain4j 툴이 Spring 빈일 때 BeanPostProcessor가 자동 처리; 프로그래매틱/비-Spring 사용에는 SsrfGuardedToolExecutors.wrap(...) 헬퍼가 AiServices.builder(...).tools(Map<ToolSpecification, ToolExecutor>) 형태 지원.
<dependency>
<groupId>kr.devslab</groupId>
<artifactId>ssrf-guard-llm</artifactId>
<version>3.1.0</version>
</dependency>
프레임워크-중립 코어. 자체 툴 라우터 (MCP 서버, 내부 RPC dispatcher, 커스텀 에이전트 루프) 만든 경우 직접 사용:
최신 버전
3.1.0을 Maven Central 최신으로 교체.
v2.0.0에서 올라온다면
kr.devslab:ssrf-guard 좌표는 여전히 동작 — 메타 아티팩트가 -core, -httpclient5, -restclient를 끌어옴. 대부분 버전만 올리고 다시 빌드하면 끝. kr.devslab.ssrfguard.security.* 직접 import한 코드는 v3.0.0 changelog의 패키지 매핑 참고.
최소 설정¶
어떤 모듈이든 ssrf.guard.* 키는 동일:
ssrf:
guard:
enabled: true # 기본값 — false로 끄면 가드 비활성화
suffixes: # 최소한 이거 — 비어있으면 "모든 호스트 차단"
- api.partner.com
- example.org
화이트리스트 비워두면 fail-closed — 모든 외부 호출이 Host not allowed로 막힘. 의도된 동작입니다.
추가 하드닝 (기본값이 안전)¶
ssrf:
guard:
reject-ip-literal-hosts: true # 기본 — http://127.0.0.1, http://2130706433 등 차단
reject-user-info: true # 기본 — https://user:pass@host/... 차단
block-private-networks: true # 기본 — DNS 단계 사설/메타데이터 IP 필터
follow-redirects: true # 기본 — 매 hop 재검증
allowed-schemes: [https] # 기본 [http, https]보다 엄격
allowed-ports: [443] # 기본 [-1, 80, 443]보다 엄격
관찰성 (선택)¶
spring-boot-starter-actuator를 추가하면 Micrometer 메트릭이 무료:
ssrf_guard_blocked_total{reason="blocked_private_ip", scheme="http"} 42
ssrf_guard_allowed_total{scheme="https"} 13042
태그가 bounded (reason은 enum, scheme은 http/https) 라서 Prometheus / Datadog / CloudWatch에 문제 없이 적재됨.
설치 확인¶
Spring 모듈은 --debug 출력에 자동설정 이름이 보임:
matched: 라인이 최소 하나 보여야 정상. 의도적으로 차단되는 URL을 호출하면: