RemoteIpValve로 실제 클라이언트 IP 복원하기
Nginx나 Apache를 앞단에 두면 Tomcat이 보는 접속 IP가 전부 프록시 주소(127.0.0.1 등)로 찍힙니다. 액세스 로그나 애플리케이션에서 실제 클라이언트 IP가 필요할 때 RemoteIpValve를 쓰면 됩니다. mod_remoteip를 Tomcat으로 옮긴 밸브로, 프록시가 넘긴 X-Forwarded-For 헤더를 오른쪽에서 왼쪽으로 훑어 request.getRemoteAddr() 값을 실제 클라이언트로 바꿔줍니다. 보통 Engine 레벨에 둡니다. 대상은 Tomcat 9 기준이고, 아래 값은 공식 Configuration Reference의 default를 확인한 것입니다.
server.xml의 Engine 하위에 밸브를 추가합니다. AccessLogValve보다 먼저 선언해야 로그에도 실제 IP가 남습니다.
<Engine name="Catalina" defaultHost="localhost">
<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="127\.0\.0\.1" />
...
</Engine>기본값만 알면 대부분 속성은 생략해도 됩니다. remoteIpHeader 기본값이 x-forwarded-for, protocolHeader 기본값이 X-Forwarded-Proto라서, 프록시에서 HTTPS를 종단하고 이 헤더만 제대로 넘기면 별도 지정 없이도 request.isSecure()와 scheme이 맞습니다. 문서에는 "To disable this feature set the value to the empty string"이라고 적혀 있어, 이 프로토콜 판별을 끄고 싶을 때만 protocolHeader=""로 비웁니다. HTTPS로 간주하는 값은 protocolHeaderHttpsValue(기본 https)로 판정합니다.
주의할 점은 internalProxies 기본 정규식이 10/8, 172.16-31, 192.168/16, 127/8, 169.254/16, 100.64/10(shared), IPv6 loopback/link-local 등 사설 대역만 신뢰한다는 점입니다. 프록시가 이 대역 밖 공인 IP면 그 주소를 믿지 않아 IP가 안 바뀌니, 그때는 internalProxies 정규식에 프록시 IP를 넣거나 trustedProxies에 추가합니다(trustedProxies는 기본값이 없어 지정 전까지 아무 프록시도 신뢰하지 않습니다). 당연히 프록시에서 proxy_set_header X-Forwarded-For가 실제로 전달되고 있어야 합니다.
🔗 https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html
로그인 후 답글을 남길 수 있습니다.