크롤링을 막는 방법

Jerry·2025년 8월 4일

1단계: robots.txt 설정 (기본 권고)

User-agent: *
Disallow: /private/
  • 모든 크롤러(*)에 대해 /private/ 경로 접근 금지
  • 하지만 법적 강제성은 없음
    → 크롤러가 이 파일을 무시하면 막을 수 없습니다

2단계: User-Agent 확인 및 차단

String userAgent = request.getHeader("User-Agent");
if (userAgent != null && userAgent.contains("Jsoup")) {
    response.sendError(403, "Forbidden");
}
  • Jsoup, python-requests, curl, bot 등 키워드를 필터링
  • 예외적으로 정상 브라우저 User-Agent만 허용하는 정책 가능

3단계: IP 기반 접근 제한

  • 방문 횟수/속도 감지 후, 과도한 요청 IP를 차단
  • Geo-IP 차단도 가능 (해외 IP 차단 등)

예시

  • 10초에 20건 이상 → 임시 차단
  • Cloudflare, AWS WAF, Nginx rate limit 등 활용

4단계: 로그인/세션 기반 컨텐츠 보호

  • 민감한 정보는 로그인 후에만 제공
  • 세션 토큰 없으면 401 / 403 반환
  • JWT 또는 OAuth2 인증 강화

5단계: JavaScript 렌더링 사용 (동적 콘텐츠)

  • 데이터 로딩을 JavaScript로 수행 (예: Vue, React, Ajax)
  • 단순 HTML 파서로는 정보 접근 불가 (Jsoup이나 Python BeautifulSoup 차단 가능)

대가

  • SEO에 불리할 수 있음
  • 성능 오버헤드 증가

6단계: CAPTCHA 적용

  • 로그인, 댓글 등 민감 경로에 Google reCAPTCHA v2/v3 적용
  • 봇 자동화 요청을 완전히 차단할 수 있는 방법 중 하나

7단계: 동적 URL/의도적 난독화

  • 페이지마다 URL을 자주 바꾸거나, 데이터를 암호화
  • DOM 구조를 자주 바꿔서 크롤러가 구조를 예측하지 못하게 함

8단계: 방어 툴 or 서비스 사용

서비스설명
Cloudflare Bot Management자동화 탐지 및 방어
AWS WAFWeb ACL로 접근 제어
Imperva, Akamai상업용 보안 서비스

사람은 허용, 봇은 차단하려면?

  • 마우스 이벤트/스크롤 이벤트 감지
  • 헤더 정보, referrer, 쿠키 값 등을 기반으로 판단
  • 행위 분석 (Behavior Analysis) 도입

정리: 크롤링 방지 레벨별 전략

레벨방법특징
1단계robots.txt약한 제어 (권고 수준)
2단계User-Agent 차단단순 봇 차단
3단계IP 제한과도한 요청 방어
4단계인증 요구세션 없이 차단 가능
5단계JavaScript 렌더링파싱 어렵게 함
6단계CAPTCHA인간 인증
7단계구조 난독화파서 우회 어려움
8단계보안 서비스고도화된 종합 방어

Spring Boot에서 User-Agent/IP 필터 만드는 방법

목표

  • 의심스러운 User-Agent 차단 (예: Jsoup, curl, bot 등)
  • 요청자의 IP 기반으로 차단 or 로깅
  • 차단 시: 403 Forbidden 응답

방법 선택

방법설명사용 상황
Filter모든 요청 전처리빠르고 낮은 수준에서 처리
HandlerInterceptor컨트롤러 진입 직전에 처리Spring MVC와 더 친화적

UserAgent & IP 필터 구현 (Filter 방식)

package com.example.demo.filter;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@Component
public class RequestFilter implements Filter {

    // 차단할 User-Agent 키워드
    private final List<String> blockedAgents = Arrays.asList("jsoup", "curl", "python", "bot");

    // 차단할 IP 리스트 (예시용)
    private final List<String> blockedIps = Arrays.asList("192.168.0.100", "203.0.113.42");

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        String userAgent = req.getHeader("User-Agent");
        String ip = getClientIp(req);

        // User-Agent 검사
        if (userAgent != null) {
            for (String blocked : blockedAgents) {
                if (userAgent.toLowerCase().contains(blocked)) {
                    res.sendError(HttpServletResponse.SC_FORBIDDEN, "Blocked User-Agent");
                    return;
                }
            }
        }

        // IP 검사
        if (blockedIps.contains(ip)) {
            res.sendError(HttpServletResponse.SC_FORBIDDEN, "Blocked IP");
            return;
        }

        // 계속 처리
        chain.doFilter(request, response);
    }

    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            return ip.split(",")[0];
        }
        return request.getRemoteAddr();
    }
}
조건결과
User-Agent: Jsoup/1.15403 Forbidden
IP: 203.0.113.42403 Forbidden
정상 브라우저통과 (200 OK)

테스트

# 차단 시도
curl -H "User-Agent: Jsoup/1.15" http://localhost:8080
# 결과: HTTP/1.1 403 Forbidden

# 허용 시도
curl -H "User-Agent: Mozilla/5.0" http://localhost:8080
# 결과: 정상 응답

  • IP 차단을 동적으로 하고 싶다면
    • DB나 Redis에 저장된 블랙리스트에서 IP 조회
    • 차단 횟수를 기록해서 자동 차단 (RateLimiter, Redis 카운터 등)

Cloudflare, WAF 설정 예시

전제: 사이트가 Cloudflare로 DNS 설정되어 있어야 함 (CNAME, A, Proxy Enabled (orange cloud))

WAF 기능 개요 (Cloudflare 기준)

기능설명
Managed RulesOWASP Top 10 공격 자동 차단 (SQLi, XSS 등)
Custom RulesIP, User-Agent, Path 등 조건 지정 차단
Rate Limiting요청 속도 제한
Bot Management정교한 봇 탐지 및 CAPTCHA 처리
Geo Blocking국가 단위 IP 차단 가능

Custom WAF Rule 설정 예시

목표

  • Jsoup, curl, Python 등 User-Agent 차단
  • /api/secret/* 같은 민감 경로 접근 제한

Cloudflare Dashboard > Security > WAF > Custom Rules > Create Rule

설정 예시 1: User-Agent 차단

항목
Rule nameBlock Jsoup and curl
When incoming requests match...
(http.user_agent contains "jsoup") or
(http.user_agent contains "curl") or
(http.user_agent contains "python")
Then...Block

설정 예시 2: 특정 경로 접근 차단 (봇 의심 포함)

항목
Rule nameProtect sensitive API
Expression
(http.request.uri.path contains "/api/secret") and 
(not cf.client.bot)
Then...Managed Challenge or Block

Rate Limiting 설정 예시

목표

/login 엔드포인트에 1분에 5회 이상 접근 시 차단

Cloudflare Dashboard → Security → Rate Limiting → Create Rule

항목
Rule nameLogin Brute Force Protection
Request URL*yourdomain.com/login*
MethodPOST
Threshold5 requests per 1 minute
ActionChallenge or Block

Geo IP 차단 (국가별)

특정 국가에서만 허용하거나 차단

not ip.geoip.country in {"KR" "JP" "US"}

→ 위 외 국가에서 접근 시 차단

Bot Management 설정

Bot Score (1~100): 낮을수록 비정상 트래픽

예: 봇 점수 낮고 로그인 시도 시 차단

(http.request.uri.path contains "/login") and 
(cf.bot_management.score < 30)

항목설명
cf.client.botCloudflare가 알려진 봇(Googlebot 등)인지 여부
cf.threat_scoreIP 신뢰도 점수 기반 필터링
ip.src in $bad_ips사용자 정의 IP 리스트 활용
http.referer / uri.query리퍼러 및 쿼리 파라미터 기반 제한 가능

예시 정리

목적Cloudflare WAF 규칙
Jsoup 차단http.user_agent contains "jsoup"
API 보호uri.path contains "/api" and not cf.client.bot
국가 제한not ip.geoip.country in {"KR"}
로그인 속도 제한Rate Limiting + POST + /login
자동화 차단cf.bot_management.score < 30

기타 설정 권장

  • Bot Fight Mode: 클라우드플레어 무료 플랜에서도 제공
  • Security Level: High: 악성 IP 차단 강화
  • JavaScript Challenge: 봇에게는 난해한 미니 JS 퍼즐 요구

정리

항목용도
WAF Rule사용자 정의 필터, 크롤링/SQLi 등 방어
Rate Limit특정 경로/속도 제한
Bot Management봇 탐지 후 자동 처리
Geo IP Rule국가 단위 차단
Managed RulesOWASP 공격 사전 방어
profile
Backend engineer

0개의 댓글