요청은 갔는데, 응답은 왜 안 올까?
스테이트풀·스테이트리스와 응답 트래픽

안녕하세요, JP-Hosting입니다.
“분명히 443번 포트를 허용했는데, 웹사이트가 열리지 않아요.”
서버를 운영하다 보면 한 번쯤 만나는 상황입니다. 이때는 요청이 서버에 도착하는지만 볼 것이 아니라, 응답이 클라이언트까지 돌아올 수 있는지도 확인해야 합니다. 방화벽이 연결을 기억하는지에 따라 필요한 정책도 달라집니다.

1. 요청은 443번으로, 응답은 어디로 갈까요?
TCP 기반 HTTPS 접속을 예로 들어 보겠습니다. 클라이언트가 임시 출발지 포트 50000번을 선택해 서버의 443번에 연결한다고 가정합니다. NAT가 없는 단순한 구간에서는 다음처럼 보입니다.
| 구분 | 출발지 | 목적지 |
|---|---|---|
| 요청 방향 | 클라이언트:50000 | 서버:443 |
| 응답 방향 | 서버:443 | 클라이언트:50000 |
응답의 출발지는 서버의 443번이지만, 목적지는 클라이언트의 50000번입니다. “HTTPS니까 양쪽 모두 목적지 443번만 허용하면 된다”는 생각은 여기서 어긋납니다.
50000은 설명용 예시입니다. 실제 임시 포트 범위는 운영체제와 설정에 따라 다르며, 중간에 NAT가 있으면 관찰하는 구간에 따라 주소나 포트가 변환되어 보일 수 있습니다. 이 글은 TCP 예시이며, UDP를 사용하는 HTTP/3는 별도로 구분해야 합니다.
인바운드·아웃바운드도 기준점에 따라 달라집니다. 클라이언트 쪽에서는 요청이 아웃바운드, 응답이 인바운드입니다. 서버 쪽에서는 요청이 인바운드, 응답이 아웃바운드입니다.
2. Stateless: 응답도 규칙에 맞아야 합니다
스테이트리스 방식은 앞서 허용한 요청을 연결 상태로 기억해 응답을 자동 판별하지 않습니다. 들어온 패킷이 현재 규칙에 맞는지 각각 확인합니다.
예를 들어 서버 측의 스테이트리스 필터에서 요청 방향의 목적지 TCP 443만 허용하고, 나가는 트래픽은 모두 차단했다면 어떨까요? 요청이 도착하더라도 클라이언트의 임시 포트로 돌아가는 응답은 차단될 수 있습니다.
따라서 요청과 응답이 각 방향의 허용 정책에 모두 포함되어야 합니다. 연결마다 규칙을 새로 만든다는 뜻은 아닙니다. 이미 설정된 규칙이 응답 트래픽을 허용한다면 추가 규칙은 필요하지 않습니다.
대표적인 예가 AWS의 Network ACL(NACL)입니다. 서브넷 경계에서 적용되는 스테이트리스 필터이므로, 요청 방향뿐 아니라 응답 방향의 규칙도 확인해야 합니다. 모든 제품에서 ‘ACL’이라는 이름만 보고 동작을 단정하지 말고 해당 기능의 문서를 확인하는 것이 정확합니다.
3. Stateful: 허용한 연결의 응답을 알아봅니다
스테이트풀 방식은 연결의 주소·포트·프로토콜과 상태 등을 추적해, 돌아온 패킷이 허용한 통신의 응답인지 판단합니다.
대표적으로 AWS의 보안 그룹(Security Group)은 스테이트풀 방식입니다. 허용된 인바운드 요청의 응답은 보안 그룹의 아웃바운드 규칙과 관계없이 나갈 수 있고, 허용된 아웃바운드 통신의 응답도 인바운드 규칙과 관계없이 들어올 수 있습니다.
다만 이는 그 보안 그룹에서 처리하는 응답 트래픽에 대한 설명입니다. 같은 경로의 NACL이나 운영체제 방화벽까지 자동으로 통과시키는 기능은 아닙니다. 외부에서 시작한 새로운 연결을 전부 허용한다는 뜻도 아닙니다.
| 비교 | Stateless | Stateful |
|---|---|---|
| 판단의 핵심 | 패킷별 규칙 | 규칙과 연결 상태 |
| 응답 트래픽 | 응답 방향도 허용 정책에 포함 | 추적 중인 허용 연결의 응답으로 판별 |
| AWS의 대표 예 | Network ACL | Security Group |
AWS에서 보안 그룹과 NACL은 적용 위치와 기능도 다릅니다. 단순히 둘 중 하나를 고르는 관계가 아니라, 함께 적용되는 구간에서는 두 계층을 모두 확인해야 합니다. 상태 추적 역시 시간 초과나 자원 한계, 비대칭 경로 등 운영 조건의 영향을 받을 수 있습니다.
4. NAT와 상태 추적은 같은 기능이 아닙니다
지난 NAT 글에서 다뤘듯이 NAT의 핵심은 주소나 포트를 변환하는 것입니다. 반면 스테이트풀 방화벽의 핵심은 연결 상태를 바탕으로 통과 여부를 판단하는 것입니다.
같은 장비에서 두 기능을 제공하고, 동적 NAT도 변환 상태를 관리할 수 있지만 역할은 구분해야 합니다. 포트 포워딩을 설정했다고 접근 정책까지 자동으로 허용되거나, 서버에서 서비스가 저절로 실행되는 것은 아닙니다.
실무에서는 “포트는 열었다”가 NAT 설정을 했다는 뜻인지, 방화벽 규칙을 허용했다는 뜻인지, 서버가 실제로 해당 포트에서 대기 중이라는 뜻인지부터 나누어 확인하면 문제를 훨씬 빠르게 좁힐 수 있습니다.
5. 접속이 안 될 때는 이 순서로 확인하세요
- 서비스가 실제로 대기 중인가요? 서버가 올바른 IP와 TCP 포트에서 접속을 받고 있는지, 운영체제 방화벽은 허용하는지 확인합니다. 로컬 주소에서만 대기하면 외부 접속을 받지 못할 수 있습니다.
- 어느 지점의 어떤 방향을 보고 있나요? 클라이언트·서버의 주소와 포트를 적고, 그 구간에서 요청과 응답이 각각 인바운드인지 아웃바운드인지 표시합니다. NAT가 있다면 변환 전후도 구분합니다.
- 중간의 필터와 왕복 경로는 정상인가요? 보안 그룹, NACL, 경계 방화벽 등 실제 경로에 있는 계층을 확인합니다. 스테이트리스 구간은 응답의 목적지 임시 포트도 정책에 포함되는지 점검합니다. 포트 범위는 실제 환경을 확인해 정합니다.
- 어디까지 통신했는지 증거를 확인했나요? 패킷 캡처와 로그로 TCP 연결 요청과 응답이 보이는지 확인합니다. 연결 후 TLS 오류나 HTTP 403 응답이 나온다면, 단순 포트 차단과는 다른 단계의 문제일 수 있습니다.
범위를 무작정 넓혀 허용하기보다는, 실제 출발지·목적지·프로토콜·포트와 차단 지점을 먼저 확인하는 것이 좋습니다.
요청의 목적지 포트와 응답의 목적지 포트는 다를 수 있습니다.
Stateless는 양방향 정책을, Stateful은 허용 연결의 상태 추적을 이해해야 합니다.
‘포트 하나를 열었다’는 것과 ‘왕복 통신이 완성됐다’는 것은 다른 이야기입니다.
참고 자료
이 글은 けんと@設計構築チャンネル(@yeiquer12)의 Stateful·Stateless 설명에서 주제를 참고해 JP-Hosting 독자를 위한 한국어 원고로 새롭게 구성했습니다. 기술 설명은 아래 공식 문서와 교차 확인했습니다. 표지와 비교 이미지는 이 글을 위해 새롭게 제작했습니다.