IP 접근 제어는 많은 개발자들이 주의를 기울이지 않는 영역일 수 있이지만, 보안에서는 중요성 높은 요소 중 하나이다.
OSI 4계층(전송계층: Transport Layer)에서 사용되는 TCP와 UDP는 모두 OSI 3계층(네트워크계층)의 IP에 의존한다. 이는 IP가 네트워크 상에서 누군가를 특정 하기 위한 기본적인 식별자라는 뜻이다.
상위 레이어로 전파될 필요 없이 하위 계층에서 보안을 강화하는 것은 정보를 보호하는 데 중요한 요소이다. 레이어가 깊어진다는 것은, 버그 또는 취약점의 개수도 많아질 수 있다는 뜻이며, 복잡해지는 프로토콜을 분석하기 위한 비용이 많이 든다는 뜻이기도 하기 때문이다. IP를 기준으로 접근을 제한함으로써 간단하지만 강력한 보안을 구현할 수 있다.
많은 기업이 인트라넷(사내 망)을 구축하는 이유는 중요한 자산을 보호하기 위해서이다. 네트워크 계층인 IP를 통한 접근제어는 외부망에서 내부망으로의 불법 접근을 방지하는데 효과적이다. 기업은 VPN, 방화벽 등을 사용하여 다양한 IP 접근 제한을 구현하고 있다.
클라우드 컴퓨팅 시대인 요즘에는 AWS, GCP 등의 CSP 뿐만아니라 많은 SaaS 제품들이 기본적으로 IP 접근 제한 기능을 제공하고 있다.
네트워크에서 진짜 Client IP를 찾는 것은 현실적으로 어려운 문제이다. 현대의 네트워크는 다양한 프락시들로 구성되어있다. 웹 서버를 예로 들면, ALB 또는 NLB가 HA나 부하 분산을 위해 구성될 수 있으며, Circuit Breaker, 리버스 프락시 그리고 게이트웨이 등이 모두 네트워크 상에서 프락시 역할을 수행하고 있다. 이는 NAT 장비나 공유기도 해당되며, 이들은 네트워크에서 Client의 IP를 감추는 역할을 수행하고 있다.
Windows PC에서는 cmd에 ipconfig 명령어를 쳐서 내 PC의 IP 주소를 확인할 수 있다. MacOS에서는 terminal에 ifconfig를 치고 inet 주소를 찾아 해장 주소를 확인할 수 있다. 대부분의 경우 공유기를 사용하고 있기 때문에 192.168.X.X 주소 또는 172.X.X.X 주소를 확인할 수 있을 것이다. 그러나 이제 https://whatismyipaddress.com/ 와 같은 사이트에서 내 IP 주소를 확인해보면, 아까 보았던 IP 주소와 다른 주소가 나온다.
내부에서 보는 나의 IP 주소와 외부에서 보는 나의 IP 주소가 다르다는 뜻이며, 공유기가 내 진짜 IP 주소를 가리고 있다는 뜻이기도 하다. 실제로 공유기는 나의 내부 IP 주소를 감춤으로써 방화벽의 역할을 수행하기도 한다.
이러한 다양한 프락시와 네트워크 장비들 사이에서 진짜 Client IP를 식별하기 위해서 다음과 같은 기술들이 등장했다:
X-Forwarded-For 헤더는 HTTP 헤더이다. HTTP 패킷을 프락시하는 장비(흔히 L7 라고 부르는 것들)들이 X-Forwarded-For 헤더에 IP를 직접 추가해 줌으로써 최종 목적지에 있는 웹 서버는 해당 요청이 누구로부터, 그리고 어떤 장비들을 통해 왔는지 알 수 있다. 자세한 내용은 https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/X-Forwarded-For 에서 확인할 수 있다.
X-Forwarded-For: client, proxy1, proxy2
X-Forwarded-For은 HTTP 헤더이기 때문에 HTTP가 아닌 환경에서는 문제가 될 수 있다. HTTP 패킷이라고 하더라도 NLB와 같은 L4에서 동작하는 장비는 HTTP에 대해서 관여하지 않기 때문에 X-Forwarded-For 헤더를 붙여줄 수 없다.
이를 위해 Proxy Protocol을 사용할 수 있다. NLB가 요청을 전달하기 이전에 Client IP 정보를 먼저 보내주는 방법으로 Client IP를 알 수 있으며, 자세한 내용은 https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt 에서 확인할 수 있다.
위와 같은 기술들을 통해 전달된 Client IP를 신뢰하고 그대로 사용하는 것은 문제가 될 수 있다. IP Spoofing과 같은 더 복잡한 주제는 여기서 다루지 않겠지만, 다양한 프락시 및 네트워크 장비들이 통신 구간 사이에 위치해 있기 때문에, Client IP가 진짜 Client IP가 아닐 수 있다는 사실을 인지해야 한다.
먼저, 내 PC의 IP 주소로 등장한 192.168로 시작하는 사설 IP 대역에 대해 살펴보자. 해당 IP는 전 세계의 수 많은 사람들이 사용하는 사설 IP 대역 중 하나이다. IP 주소는 네트워크 상의 유일한 식별자라고 할지라도, 사설 IP는 여러 사용자가 동일한 대역의 IP를 가질 수 있어 실제로 클라이언트를 고유하게 식별하는데 한계가 있다. (이 부분은 인터넷에 집중된 내용이며, 기업에서는 네트워크 상의 구간 암호화를 포함하여 이러한 문제들을 해결하기 위해 VPN을 사용한다)
뿐만 아니라, X-Forwarded-For 헤더의 경우 언제든지 조작 및 변조가 가능하다. 중간에 멍청한 프락시 장비 하나를 두었다고 가정해보자. 해당 장비가 X-Forwarded-For 헤더를 변경하거나 제거한다면, 결과적으로 Client IP를 온전히 파악하는건 불가능하다.
경영부서만이 접근할 수 있는 서버가 있다고 가정해보자. 위와 같은 구성도에서 어떤 값을 사용할 수 있을까?
위 구성도에서는 3가지 장비가 있다.
결국 서버가 받게될 X-Forwarded-For 헤더는 다음과 같을 것이다.
X-Forwarded-For: 192.168.0.23, 10.1.1.73, 10.1.0.1, 10.100.0.73
관리자는 서버를 기준으로 몇 번째 hop까지를 신뢰할 것인지를 정의하고, 헤당 hop의 IP를 기준으로 접근 제어를 수행해야 한다. 위의 예제에서 경영부서만이 서버에 접근할 수 있도록 구성하기 위해서는, 3번째 hop(경영부서의 NAT 장비)의 IP 주소가 10.1.1.1이거나 4번째 hop(경영부서 임직원들의 PC 장비)의 IP 주소 대역이 10.1.1.0/24 인 경우를 조건으로 걸어 정책을 설정해야 한다.
관련하여 Envoy에서는 "xff_num_trusted_hops" 라는 기능을 제공하고 있는데, 관심이 있다면 찾아보면 좋을 것 같다. https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for
실제 사내의 네트워크 구성은 위에서 제공한 예제보다 훨씬 더 복잡하며 다양한 요소들이 상호작용한다. 이에 따라 많은 내용들을 함축하거나 배제하고 설명하였다.
중요한 점은 네트워크를 절대적으로 신뢰하면 안된다는 것이다. 네트워크는 누구나 변조가 가능하다는 점을 인지해라. 신뢰할 수 있는 네트워크 구성까지만을 신뢰하되, 해당 구성 또한 완벽하게 불변하다는 보장은 없다. 때문에 항상 지속적인 모니터링을 해야한다.
네트워크와 보안은 끊임없이 진화하고 변화하는게 사실이지만, IP와 같은 낮은 계층은 큰 변화가 없다. TCP/IP는 1983년에 표준으로 채택되었고, HTTP/1.1은 1997년에 등장한 이후 현재는 주로 HTTP/2가 사용되며, HTTP/3에 대한 논의가 이어지고 있다. 기본적인 네트워크 지식을 가지고 있다면 계속해서 활용할 수 있는 내용이기 때문에 미리 학습하는 것이 좋다.
IP 접근 제한, 방화벽, NLB, ALB 그리고 NGINX와 Envoy 등은 이미 많은 개발자들에게 익숙한 기술들이지만, 네트워크와 보안에 관해서는 이해가 부족한 사람들이 많다. 이 글은 그들을 위해 작성되었다.