1. 사전 필요사항
    1. AWS CloudFront 설정
1. 메뉴
 - AWS 웹 콘솔 -> CloudFront -> 대상 CloudFront ID(도메인에 맵핑된) -> Behaviors -> 해당 Behaviors 선택 -> Edit

2.  Cache key and origin requests 영역 설정
 1) Cache policy and origin request policy (recommended) 선택
 2) Cache policy 를  CachingDisabled 로 설정
  - CloudFront를 동적 컨텐츠 전송 목적과 위치정보 헤더 값등 필요 헤더를 획득할 목적이기 때문에
  - 참고: https://aws.amazon.com/ko/cloudfront/dynamic-content/
  - 참고: https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html
 3) Origin request policy - optional 에 커스텀 policy추가해서 반영
  - 샘플) CloudFront에서 추가되는 헤더를 모두 선택한 경우

설정샘플(주의: 뒷단 was까지 Query Strings와 Cookies를 넘겨줘야하기 때문에 ALL로 설정)

  1. Java 샘플소스
/**
	 * 클라이언트 요청자의 IP를 가져옴(WAS 앞단에 로드밸런서 등이 존재할 수 있음을 감안한 메소드)
	 *  - AWS CloudFront -> ALB(LB) -> Nginx-> 톰캣을 사용하는 케이스를 감안한 메소드
	 *  - AWS CloudFront사용시 해당 헤더의 IP정보를 최우선으로 신뢰함(즉, IP를 얻어오는 순서에 의미가 있음)
	 *  - 주의: Spring webflux는 해당 메소드를 사용불가(대신 ServerWebExchange exchange.getRequest().getRemoteAddress().getAddress().getHostAddress() 같은 메소드를 사용해야함)
	 *
	 * @param request HttpServletRequest
	 * @return
	 */
	public static String getClientIp(HttpServletRequest request) {

		//참고 https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/using-cloudfront-headers.html#cloudfront-headers-viewer-location
		//참고 https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/WhatsNew.html
		final String awsCfAddress = request.getHeader("CloudFront-Viewer-Address"); //ex) 123.45.67.89:46532
		if (StringUtils.isNotBlank(awsCfAddress)) {
			log.trace("\nIP획득 출처: AWS CloudFront-Viewer-Address\n\t요청 http header => {}", HttpRequestUtil.getRequestHeaderToMap(request));
			return awsCfAddress.split(":")[0].trim(); //구분자 :
		}

		//프록시 레이어를 감안한 XFF값
		//TODO: XFF는 spoofed(속일 수 있음)가 가능하기 때문에 오른쪽부터 IP를 가져오도록 수정해야함. 이때 신뢰하는 프록시IP들은 제외하는 로직 작업도 필요 https://news.hada.io/topic?id=6098
		//https://en.wikipedia.org/wiki/X-Forwarded-For
		//https://blog.lael.be/post/8989
		final String xForwardedFor = request.getHeader("X-Forwarded-For"); //ex) 123.456.78.99,15.162.1.11
		if (StringUtils.isNotBlank(xForwardedFor)) {
			log.trace("\nIP획득 출처: X-Forwarded-For\n\t요청 http header => {}", HttpRequestUtil.getRequestHeaderToMap(request));
			return xForwardedFor.split(",")[0].trim(); //구분자 ,
		}

		final String realIp = request.getHeader("X-Real-IP"); //일반적으로는 인프라(프록시) 설정 들이 잘되어 있다면 다른 언어 및 프레임웤에서는 보안문제 때문에 Real IP가 XFF보다 우선순위 높음
		if (StringUtils.isNotBlank(realIp)) {
			log.trace("\nIP획득 출처: X-Real-IP\n\t요청 http header => {}", HttpRequestUtil.getRequestHeaderToMap(request));
			return realIp;
		}

		log.trace("\nIP획득 출처: request.getRemoteAddr\n\t요청 http header => {}", HttpRequestUtil.getRequestHeaderToMap(request));
		return request.getRemoteAddr();
	}

+ Recent posts