
저는 프로젝트에서 포트포워딩 관련 문제를 만나고 관련 발표를 진행한 경험이 있습니다!
포트포워딩, 그랬구나
해당 발표의 후속글로 해당 글을 준비하였습니다 👍
궁금한 거 있으면 댓글 남겨 주세요!
개발을 하다 보면 포트 포워딩이라는 용어를 종종 접하게 됩니다. 특히 서버 개발자에게 인프라를 구성하며 포트를 분리하는 일은 필수적입니다. 서버를 외부와 연결하거나 특정 네트워크 설정이 필요할 때 이 기술을 사용하게 될 수도 있습니다. 하지만 막상 포트 포워딩을 시도하면 개념이 낯설고 복잡하게 느껴질 수 있습니다. 매우 low level의 지식이니 부담감이 들기도 합니다. 저 역시 “방끗” 프로젝트를 진행하며 포트 포워딩을 경험했고, 그 과정에서 학습의 필요성을 느끼고 진행하였습니다.
이 글에서는 프로젝트를 진행하며 얻은 경험과 그 과정에서 궁금했던 점들을 공유하고자 합니다. 포트 포워딩의 개념을 간단히 설명하고, 이를 효과적으로 설정하는 방법을 실용적인 예시와 함께 살펴보겠습니다.
포트 포워딩(Port Forwarding) 은 직역하면 “포트를 전달하다”라는 의미를 담고 있습니다. 좀 더 자세한 의미를 살펴 보자면, 하나의 IP 주소와 포트 번호 결합의 통신 요청을 다른 곳으로 넘겨 주는 네트워크 주소 변환의 응용이라고 정의할 수 있습니다. 다양한 Level에서 해당 개념을 볼 수 있겠지만 오늘은 서버 개발자의 측면에서 포트 포워딩을 다뤄 보도록 하겠습니다.
포트 포워딩은 서버 개발자가 원격 네트워크 또는 로컬 네트워크에서 서비스에 접근하기 위해 사용되는 중요한 기법입니다. 특정 포트로 들어오는 트래픽을 다른 포트나 호스트로 전달함으로써 외부 클라이언트가 올바른 서버에 연결되도록 합니다. 서버 개발자들은 방화벽, NAT(Network Address Translation) 등의 네트워크 장비를 통과할 때 클라이언트의 요청이 특정 서버로 도달할 수 있도록 포트 포워딩을 구성합니다. 이를 활용하여 네트워크 구조에 구애받지 않고 애플리케이션과 서비스를 안정적으로 제공할 수 있습니다.
포트 포워딩이 필요한 예로는 여러 가지 상황이 존재합니다. 예를 들어 가정용 네트워크에서 NAS(Network Attached Storage) 서버를 외부에서 접근할 때, 사무실 내 IP 카메라에 외부에서 접속할 때, 게임 서버를 열어 다른 사용자들이 접속할 수 있도록 할 때, VPN 서버를 구성할 때 등이 있습니다. 특히 클라우드 서버에서는 인바운드 규칙과 더불어 포트 포워딩이 클라이언트와 서버 간의 통신을 원활하게 합니다.
AWS EC2 인스턴스에서 보안 그룹-Security Group은 특정 인바운드 및 아웃바운드 트래픽을 허용하는 일종의 가상 방화벽 역할을 합니다. 인바운드 규칙은 서버로 들어오는 요청을 필터링하며, 이를 활용하여 서버가 공격으로부터 보호받을 수 있습니다.
인바운드 보안 설정은 서버가 외부와 통신하는 방식을 제어하여 보안을 강화하는 데 중요한 역할을 합니다. 불필요한 포트를 차단하고 신뢰할 수 있는 IP만 접근을 허용함으로써 해커의 침입 경로를 줄이고 무단 접근을 방지할 수 있습니다.
일반적으로 웹 서비스에 사용되는 80(HTTP)과 443(HTTPS) 포트를 열어 외부 사용자가 웹사이트에 접근할 수 있도록 하며, 원격 관리 시에는 SSH의 22 포트를 특정 IP에만 허용하여 관리의 안전성을 높입니다. 또한, 이러한 설정을 사용하면 어떤 IP에서 어떤 요청이 들어오는지 모니터링할 수 있어 이상 징후를 조기에 탐지하고 대응할 수 있으며, 필요 없는 트래픽을 차단함으로써 네트워크 성능을 최적화할 수 있습니다. 결과적으로 인바운드 보안 설정은 서버와 네트워크의 안전을 보장하고 관리 효율성을 높이는 필수적인 단계입니다.
위와 같은 보안을 고려하여, 저의 인프라 구성에서는 인바운드 보안 설정으로 그림과 같이 80 포트, 443 포트, 특정 IP에 대한 22 포트를 허용해 준 상태입니다. 이러한 인바운드 보안 설정으로 spring 서버가 설정되어 있는 8080 포트로 요청을 전달해 주기 위해서는 포트 포워딩이 필요합니다.
포트 포워딩을 하기 위해서는 대표적으로 OSI 7계층에서 동작하는 Nginx와 OSI 3계층과 4계층에 걸쳐 동작하는 iptable을 활용하는 방법이 있습니다. 아래 단락에서 좀 더 상세히 해당 방법들을 알아 보도록 하겠습니다.
iptable은 규칙 집합을 정의할 수 있는 일반 방화벽 소프트웨어입니다. 해당 소프트웨어는 리눅스 커널의 네트워크 스텍에 내장된 프레임 워크인 netfilter의 기능을 활용하는 인터페이스로 동작합니다. iptable는 네트워크 패킷을 필터링하고 포트나 IP 주소를 변경하는 데 활용됩니다. 포트 포워딩을 설정하기 위해서는 다음과 같은 명령어를 사용할 수 있습니다.
iptables -t nat -A PREROUTING -p tcp --dport {타켓 포트} -j REDIRECT --to-port {대상 포트}
이 명령어는 외부에서 들어오는 트래픽을 특정 포트로 리다이렉트 시키는 역할을 합니다. 해당 명령어는 iptable을 활용하여 nat 테이블을 지정합니다. ‘-A’ 명령어는 규칙을 append한다는 의미로 사용하고 있습니다. 만약, ‘-D’를 사용할 경우, 규칙을 delete할 수 있습니다. PREROUTING 규칙은 패킷이 라우팅 되기 전, 패킷이 목적지에 도달하기 전에 뒤에 나오는 규칙을 적용할 수 있습니다. 뒤에 나오는 명령어는, TCP 프로토콜로 들어오는 패킷에 대하여 Destination인 dport가 타겟 포트가 맞다면 패킷을 대상 포트로 리다이렉트하라는 명령어입니다. iptables -h 명령어를 사용한다면 옵션에 대한 설명을 좀 더 자세히 볼 수 있습니다.
iptable은 여러 테이블과 체인으로 구성되며, 각 테이블과 체인에는 패킷을 처리하는 규칙이 존재합니다. FILTER 테이블, NAT 테이블, MANGLE 테이블, RAW 테이블 등이 있습니다. 우리가 사용하는 NAT 테이블은 네트워크 주소 변환을 처리하는 테이블입니다. 주로 패킷의 출발지 또는 목적지 IP 주소를 변환합니다. 여기에는 패킷이 라우팅 되기 전에 처리하는 PREROUTING 체인, 패킷이 라우팅된 후에 처리하는 POSTROUTING 체인, 로컬에서 생성된 패킷을 대상으로 처리하는 OUTPUT 체인이 있습니다.
반복적으로 등장하는 NAT 키워드에 대해 좀 더 살펴보겠습니다. NAT - Network Address Translation은 네트워크에서 패킷의 출발지 또는 목적지 IP 주소를 변환하는 기술입니다. 주로 사설 네트워크와 공용 네트워크 사이의 통신을 가능하게 하기 위해 사용됩니다. 사설 네트워크의 기기들이 인터넷에 접근할 때, NAT는 사설 IP 주소를 공인 IP 주소로 변환해줍니다. 이 과정을 거쳐 사설 네트워크 내부의 IP 주소들이 외부에 노출되지 않으며, IP 주소의 부족 문제도 해결할 수 있습니다. NAT는 라우터와 같은 네트워크 장비에서 동작하며, 공용 네트워크로 나가는 패킷은 NAT를 거치면서 IP 주소가 변환됩니다. 반대로, 외부 네트워크에서 들어오는 패킷도 NAT를 거쳐 내부 IP 주소로 변환됩니다.
NAT는 주로 두 가지 방식으로 작동합니다. 첫 번째는 Static NAT로, 이 방식에서는 특정 사설 IP 주소가 항상 같은 공인 IP 주소로 매핑됩니다. 주로 서버와 같이 고정된 IP 주소가 필요한 경우에 사용됩니다. 예를 들어, 기업의 웹 서버가 항상 외부에서 접근 가능한 203.0.113.1이라는 공인 IP 주소를 필요로 할 때, Static NAT를 사용하여 해당 서버의 사설 IP 주소인 192.168.1.10을 항상 같은 공인 IP 주소에 매핑할 수 있습니다. 이러한 방식은 신뢰할 수 있는 외부 접근을 보장하는 데 유리하지만, 할당된 공인 IP 주소를 비효율적으로 사용할 수 있는 단점이 있습니다.
두 번째는 Dynamic NAT로, 이 경우 NAT 장비는 내부 사설 IP 주소를 사용 가능한 공인 IP 주소 풀에서 동적으로 할당합니다. 이를 이용해 하나의 공인 IP 주소가 여러 사설 IP 주소와 공유될 수 있습니다. 예를 들어, 회사의 직원들이 사내 네트워크에서 인터넷에 접근할 때, NAT 장비는 각각의 직원 기기의 사설 IP 주소를 공인 IP 주소 203.0.113.2, 203.0.113.3 등으로 변환하여 인터넷에 연결합니다. 이러한 동적 할당은 네트워크의 유연성을 높이고, IP 주소의 효율적인 사용을 가능하게 합니다. 그러나, 이 방식은 공인 IP 주소가 부족한 경우에 사용될 수 있으며, 특정 연결이 항상 같은 공인 IP 주소를 필요로 할 때는 적합하지 않을 수 있습니다.
또한, NAT의 확장 개념으로 PAT - Port Address Translation가 있습니다. PAT는 여러 내부 사설 IP 주소가 단일 공인 IP 주소로 변환되면서, 각 연결을 식별하기 위해 포트 번호를 추가로 사용하는 방식입니다. 예를 들어, 내부 네트워크의 여러 장치가 모두 공인 IP 주소 203.0.113.1을 사용하여 인터넷에 접속한다고 가정할 때, NAT 장비는 각 장치의 요청을 관리하기 위해 요청마다 다른 포트 번호를 할당합니다. 이를 이용하여, 단일 공인 IP 주소를 통해 수많은 클라이언트가 동시에 인터넷에 접근할 수 있으며, 이는 IP 주소의 효율적인 활용을 더욱 극대화합니다.
NAT의 이러한 다양한 작동 방식은 네트워크의 요구사항과 구성에 따라 적절히 선택될 수 있으며, 서버 개발자는 이를 이해함으로써 더 효과적인 네트워크 설계 및 관리가 가능합니다.
Nginx는 웹 서버 소프트웨어로, 고성능과 효율성 때문에 널리 사용됩니다. 웹 서버 소프트웨어는 클라이언트(브라우저)로부터 HTTP 요청을 받아 HTML 페이지, 이미지, 비디오, 파일 등의 자원을 전달하는 역할을 합니다. 일반적으로 웹 서버는 정적 콘텐츠를 제공하며, 사용자의 요청에 따라 동적 콘텐츠를 제공하는 애플리케이션 서버와 협력할 수 있습니다.
Nginx는 특히 높은 동시 접속을 효율적으로 처리하는 비동기 이벤트 기반 아키텍처를 채택해 빠른 응답 속도와 적은 리소스 소비로 유명합니다. 이를 사용하여 트래픽이 많은 웹 사이트에서도 빠르고 안정적으로 콘텐츠를 제공할 수 있습니다.
포트 포워딩 설정으로 외부 요청을 내부 포트로 전달하여, Nginx는 리버스 프록시로서 동작하면서 네트워크 트래픽을 관리하는 로드 밸런싱의 역할을 수행할 수 있고 내부 애플리케이션 서버의 요청 처리를 보조할 수 있습니다. Nginx에서 포트 포워딩을 적용하기 위해서는 nginx.conf 파일에 리버스 프록시 설정을 추가해야 합니다. 예를 들어, 외부에서 80번 포트로 들어오는 요청을 내부의 8080번 포트로 전달하려면 다음과 같은 설정을 추가할 수 있습니다:
이 설정으로 Nginx는 클라이언트의 요청을 내부 서버의 8080번 포트로 전달하여 처리합니다.
Nginx의 포트 포워딩은 리버스 프록시를 이용하여 외부 클라이언트가 직접 내부 서버에 접근하지 않도록 중계해주는 방식입니다. 리버스 프록시 - Reverse Proxy란 클라이언트의 요청을 받아 실제 서버로 전달하고, 서버로부터 받은 응답을 다시 클라이언트로 전달하는 서버입니다. 클라이언트와 서버 간의 중개자로서 동작합니다. 이를 바탕으로 클라이언트는 실제로 응답을 제공하는 서버의 존재를 알지 못한 채, 리버스 프록시를 서버로 인식하게 됩니다. 따라서 클라이언트는 Nginx에 요청을 보내고, Nginx는 그 요청을 내부 서버로 전달한 후, 내부 서버의 응답을 다시 클라이언트에게 반환합니다. 이 방식은 서버 구조를 숨기고, 트래픽을 효율적으로 분산시키는 데 유용합니다.
리버스 프록시의 가장 큰 장점 중 하나는 보안 강화입니다. 리버스 프록시는 클라이언트와 내부 서버 간의 직접적인 연결을 차단하여, 내부 서버의 IP 주소와 구성을 숨길 수 있습니다. 이것을 이용하여 외부의 공격으로부터 내부 서버를 보호할 수 있으며, DDOS(Distributed Denial of Service) 공격 같은 보안 위협을 완화할 수 있습니다. 또한 Nginx는 다수의 내부 서버 간에 클라이언트의 요청을 분산시키는 로드 밸런싱 기능을 제공합니다. 이 기능은 서버의 부하를 고르게 분산시키고, 고가용성을 유지할 수 있습니다. 즉, 서버가 과부하에 걸리지 않도록 지원하여 애플리케이션의 성능과 안정성을 향상시킵니다.
리버스 프록시는 정적 콘텐츠를 캐싱하여 반복적인 요청에 대해 내부 서버에 대한 직접적인 요청을 줄일 수 있습니다. 이것은 응답 시간을 줄이고, 서버의 부하를 감소시키며, 클라이언트에게 더 빠른 응답을 제공합니다. 또한 SSL/TLS 암호화를 처리하여 내부 서버가 암호화된 트래픽을 직접 처리하지 않도록 할 수 있습니다. 이로 인해 내부 서버의 성능을 향상시키고, 관리의 복잡성을 줄일 수 있습니다.
이와 같은 이유로, Nginx의 리버스 프록시 기능은 서버 개발자에게 필수적인 도구가 되어 주며, 네트워크 및 애플리케이션 성능을 극대화하는 데 기여합니다. 다양한 사용 사례에서 리버스 프록시는 대규모 웹 애플리케이션에서 여러 대의 백엔드 서버를 운영하면서 클라이언트의 요청을 효율적으로 관리할 수 있도록 돕고, 마이크로서비스 아키텍처에서는 서비스 간의 통신을 간소화하며 보안을 강화하는 데 활용될 수 있습니다.
| iptables | Nginx |
|---|---|
| 장점 | 장점 |
| 고성능 | 설정 간편성 |
iptables는 리눅스 커널 수준에서 작동하므로, 네트워크 트래픽을 효율적으로 처리할 수 있으며, 성능 오버헤드가 적고 대규모 트래픽 처리에 적합합니다. 패킷을 빠르게 필터링하고, 최소한의 지연으로 패킷을 전달할 수 있어 성능이 뛰어납니다. | Nginx는 간단한 설정 파일로 쉽게 포트 포워딩과 리버스 프록시를 설정할 수 있으며, HTTP/HTTPS 기반의 트래픽 처리에 최적화되어 있습니다. 설정 예제가 명확하게 문서화되어 있어, 사용자 친화적인 인터페이스를 제공합니다. |
| 유연성 | 애플리케이션 레벨 기능 |
| 복잡한 라우팅 규칙을 설정할 수 있으며, 특정 네트워크 인터페이스나 IP 기반의 세밀한 제어가 가능하여 네트워크 전반에 대한 정책 관리를 강화할 수 있습니다. 다양한 규칙을 조합하여 특정 요구사항에 맞춰 세밀한 네트워크 관리가 가능합니다. | SSL/TLS 암호화 처리, 로드 밸런싱, 캐싱 기능 등을 제공하여 웹 애플리케이션의 성능과 보안을 향상시킬 수 있습니다. 이러한 기능들은 트래픽의 신뢰성과 속도를 높이는 데 기여하며, 사용자의 요구에 맞춘 다양한 설정을 지원합니다. |
| 보안 강화 | 로드 밸런싱 |
| 방화벽 기능으로 외부에서 들어오는 트래픽을 필터링하여 내부 네트워크를 보호할 수 있습니다. 특정 IP 주소나 포트를 차단하여 악의적인 접근을 차단하고, 보안 규칙을 세분화하여 더욱 강력한 방어 체계를 구축할 수 있습니다. | 여러 서버로 트래픽을 분산시켜 고가용성을 보장하고 서버 부하를 줄이는 데 유리합니다. 이를 이용해해 단일 서버의 과부하를 방지하고, 장애 발생 시에도 다른 서버가 요청을 처리하여 서비스 연속성을 유지할 수 있습니다. |
| 단점 | 단점 |
| 설정 복잡성 | 성능 한계 |
| 네트워크 지식이 필요하며, 설정이 복잡하고 관리하기 어려울 수 있습니다. 잘못된 설정은 네트워크에 문제를 일으킬 수 있으며, 특히 복잡한 환경에서는 오류가 발생하기 쉬워 관리에 어려움을 겪을 수 있습니다. | Nginx는 애플리케이션 레벨에서 동작하므로 iptables보다 성능 오버헤드가 발생할 수 있으며, 대규모 네트워크 트래픽 처리에 적합하지 않을 수 있습니다. 이로 인해 대량의 동시 연결 처리 시 성능 저하가 발생할 수 있습니다. |
| 애플리케이션 레벨 기능 부족 | 프로토콜 제한 |
iptables는 주로 네트워크 레벨에서 작동하므로 SSL 처리나 로드 밸런싱 같은 고급 애플리케이션 기능을 제공하지 않습니다. 따라서, 애플리케이션의 복잡한 요구를 충족시키기 위해서는 추가적인 도구나 설정이 필요할 수 있습니다. | 주로 HTTP/HTTPS 트래픽에 초점을 맞추고 있어 다른 프로토콜(UDP, ICMP 등) 지원이 제한적입니다. 따라서, 다양한 프로토콜을 활용해야 하는 경우에는 대체 솔루션을 고려해야 할 수 있습니다. |
저의 경우, 두 방식 중 Nginx를 사용하여 포트 포워딩을 할 것이라고 결정하였습니다. 사유는 다음과 같습니다.
명령어 설정에서의 오류 가능성 감소
포트 포워딩을 명령어 기반으로 설정할 경우, 특히 iptables와 같이 세밀한 옵션과 플래그를 사용하는 터미널 명령어는 실수를 초래할 가능성이 큽니다. 예를 들어, 옵션의 입력 실수는 예상치 못한 결과를 초래하고 디버깅을 어렵게 할 수 있습니다. 실제로 포트 포워딩을 설정하는 과정에서 여러 번 디버깅에 어려움을 겪었고, 이러한 경험으로 안정적이고 명확하게 설정을 유지할 수 있는 Nginx로 전환하게 되었습니다.
관리 포인트의 효율성
iptable을 사용하는 경우, 서버 내부에서 기본적으로 사용할 수 있는 포트 포워딩 기능을 제공하기 때문에 추가적인 소프트웨어 도입 없이 설정할 수 있습니다. 그러나 Nginx는 이미 로드 밸런싱과 같은 기능을 위한 선택지로 도입된 상태였기에, 두 가지 방식의 포트 포워딩 방식을 병행하는 것은 관리 포인트를 불필요하게 늘리는 일이 되었습니다. Nginx로 포트 포워딩과 관련된 설정을 일원화함으로써 운영 부담을 줄이고, 모든 포워딩 설정을 Nginx 설정 파일에서 쉽게 관리할 수 있게 되었습니다.
설정 보존 및 유지 관리의 간편성
EC2와 같은 환경에서 서버를 중지하고 재시작할 때 iptables의 설정은 일시적으로 사라지기 때문에, 매번 동일한 명령어를 반복적으로 입력해야 하는 불편함이 있습니다. 반면, Nginx는 설정 파일(nginx.conf)에 포워딩 관련 설정이 영구적으로 저장됩니다. 서버 재부팅 시에도 Nginx 서비스만 다시 시작하면 이전 설정이 그대로 유지되기 때문에 보다 간편한 설정 복원이 가능합니다.