ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Nginx 실제 client ip 값 조회
    Web/Nginx 2022. 7. 21. 20:12

    안녕하세요.

    실제 접속한 client의 ip를 조회하는 방법을 정리하려 합니다.

     

    스펙

    Nginx + spring boot 

     

    문제점

    클라이언트가 웹에 접속시 IP를 알아내야 함. 하지만 Nginx의 proxy를 통해 웹에 접속하기 때문에 Nginx에 설정을 추가해야 합니다.

     

    해결방법 (1,3번 진행)

     

    1. nginx default.conf 수정 아래 두줄 설정 추가

    proxy_set_header Host "domain.com";  # proxy_pass의 도메인과 동일한것 적기
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    server {
      
      ...
      
      location / {
        proxy_set_header Host "domain.com";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass https://domain.com;
    
      }
      
    }

     

    2. Spring에서 Header값 출력 test

     

    1번을 완료 후 spring boot에서 X-Forwarded-Ford의 값이 Null이라 스프링에 접속시 나오는 헤더값을 전부 출력해 보았습니다.

    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
    Enumeration<String> headerNames = request.getHeaderNames();
    
    if (headerNames != null) {
        while (headerNames.hasMoreElements()) {
            String name = (String) headerNames.nextElement();
            String value = request.getHeader(name);
            log.info("Header ::: " + name + " : " + value);
        }
    }

    결과>

    Header ::: host : domain.com
    Header ::: x-request-id : 48a8a18ad91d985aacd6d70369982532
    Header ::: x-real-ip : nginx ip
    Header ::: accept-language : ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
    Header ::: x-forwarded-host : domain.com
    Header ::: x-forwarded-port : 443
    Header ::: x-forwarded-proto : https
    Header ::: x-forwarded-scheme : https
    Header ::: x-scheme : https
    Header ::: x-original-forwarded-for : 123.456.789 <-- 실제 클라이언트 ip
    Header ::: content-length : 49
    Header ::: sec-ch-ua : ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"
    Header ::: accept : application/json
    Header ::: content-type : application/json
    Header ::: authorization : Basic 토큰값
    Header ::: sec-ch-ua-mobile : ?0
    Header ::: user-agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
    Header ::: sec-ch-ua-platform : "Windows"
    Header ::: origin : domain-api.net
    Header ::: sec-fetch-site : same-origin
    Header ::: sec-fetch-mode : cors
    Header ::: sec-fetch-dest : empty
    Header ::: referer : domain-api.net
    Header ::: accept-encoding : gzip, deflate, br

    내가 찾던 실제 클라이언트의 IP는 Header의 x-original-forwarded-for에 있었습니다.

     

    X-Forwarded-Ford의 값이 Null이었던 이유?

    저는 nginx의 설정에 X-Forwarded-For를 추가했는데 스프링에선 x-original-forwarded-for로 받습니다.

    스프링에 없는 X-Forwarded-For값만 찾고있었으니 당연 null이 나올 수밖에요.

     

    3. spring boot client ip 조회 메소드 전문

    public String getClientIp() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String ip = request.getHeader("x-original-forwarded-for");
        log.info("ip : " + ip);
        
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            log.info("Proxy-Client-IP : " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            log.info("WL-Proxy-Client-IP : " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            log.info("HTTP_CLIENT_IP : " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            log.info("HTTP_X_FORWARDED_FOR : " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr()
                        .toLowerCase();
        }
        
        return ip;
    }

     

    2번은 해결방안을 찾는 과정이라 실제 적용시엔 1,3번만 진행하시면 됩니다.

     

    도움되셨다면 광고 클릭 해주시겠습니까 ?

    애드센스 100달러가 되어야 출금 가능한데, 이 속도라면 개발자 은퇴할때쯤 출금이 가능할것 같습니다.

     

    적용시 어려움 있으시다면 댓글주세요. ( 단, 오타로 인한 에러 질문 안받음 )

    반응형

    'Web > Nginx' 카테고리의 다른 글

    [Nginx] 401 cors에러 해결법  (0) 2022.12.01
    [Nginx] CORS 설정 및 테스트  (0) 2022.11.07
    [Nginx] 이미지 경로 설정  (0) 2022.08.19

    댓글

Designed by Tistory.