전송 계층 멀티플렉싱·역다중화: 포트와 소켓으로 이해하기

반응형

한 컴퓨터에서는 브라우저, 메신저, SSH 클라이언트 같은 여러 프로세스가 동시에 네트워크를 쓴다. 전송 계층은 보내는 쪽에서 여러 애플리케이션의 데이터를 segment 또는 datagram으로 모으고, 받는 쪽에서 주소와 포트 정보를 보고 알맞은 소켓에 전달한다. 앞을 멀티플렉싱, 뒤를 역다중화(demultiplexing)라고 부른다.

여기서 말하는 멀티플렉싱은 주파수나 시간 슬롯으로 물리 채널을 나누는 방식과 층이 다르다. FDM·TDM·WDM은 네트워크 멀티플렉싱 방식에서 별도로 다룬다.

네트워크 계층과 전송 계층의 책임

단순화하면 IP는 패킷을 목적지 호스트까지 전달하고, TCP·UDP는 그 호스트 안의 통신 endpoint를 포트로 구분한다.

애플리케이션 A ─┐
애플리케이션 B ─┼─ 전송 계층 멀티플렉싱 ─ IP ─ 네트워크
애플리케이션 C ─┘

네트워크 ─ IP ─ 전송 계층 역다중화 ─┬─ 서버 소켓 X
                                      └─ 서버 소켓 Y

포트는 16비트 값이며 TCP와 UDP는 각각의 포트 공간을 사용한다. 같은 숫자 53이라도 TCP 53과 UDP 53은 별도 endpoint다. 포트 번호가 운영체제 전체에서 프로세스 하나를 영구적으로 식별하는 것도 아니다. 주소 체계, 전송 프로토콜, 로컬 주소, socket option과 프로세스 상태가 binding 가능 여부에 함께 영향을 준다.

멀티플렉싱은 보낼 때 무슨 일을 할까

애플리케이션이 소켓으로 bytes를 쓰면 전송 계층은 TCP header 또는 UDP header를 붙인다. header의 source port와 destination port 덕분에 여러 애플리케이션 흐름이 같은 호스트와 네트워크 인터페이스를 공유할 수 있다.

예를 들어 브라우저가 같은 웹 서버에 연결 두 개를 열면 운영체제가 서로 다른 임시 source port를 선택할 수 있다.

192.0.2.10:53001 → 198.51.100.20:443
192.0.2.10:53002 → 198.51.100.20:443

목적지 주소와 port는 같아도 source port가 달라 두 연결을 구분할 수 있다. 임시 포트 범위와 선택 방식은 운영체제 설정에 따라 다르다. “클라이언트 포트는 항상 49152 이상”처럼 고정 범위를 가정하지 말고 실제 시스템 값을 확인한다.

TCP 연결은 어떤 tuple로 구분할까

TCP의 connected endpoint는 보통 다음 4개 값의 조합으로 설명한다.

(source IP, source port, destination IP, destination port)

전송 프로토콜까지 포함해 network flow를 설명할 때는 5-tuple이라고 부른다.

(protocol, source IP, source port, destination IP, destination port)

서버는 0.0.0.0:443 또는 특정 로컬 주소의 :443에 listening socket을 둘 수 있다. 연결 요청이 들어오면 accept()는 listening socket과 별도로 connected socket을 만든다. 그래서 하나의 서버 포트가 여러 클라이언트 연결을 동시에 처리할 수 있다.

listening:  198.51.100.20:443

connected: 192.0.2.10:53001 ↔ 198.51.100.20:443
connected: 203.0.113.7:61120 ↔ 198.51.100.20:443

둘은 source IP 또는 source port가 달라 별도 연결이다. NAT가 경로에 있으면 외부에서 보이는 source 주소·port가 변환될 수 있으므로 클라이언트 로그와 서버 로그의 tuple이 그대로 일치하지 않을 수 있다.

UDP 역다중화는 왜 다르게 설명할까

UDP header에도 source port와 destination port가 있다. 들어온 datagram은 우선 목적지 로컬 주소·port와 binding 규칙에 맞는 소켓으로 전달된다. connect()를 호출한 UDP socket은 커널이 기본 상대 주소를 기억하고 수신 peer를 제한하는 등 더 구체적인 조건을 가질 수 있다.

같은 UDP port를 여러 소켓이 공유할 때의 분배는 SO_REUSEPORT 같은 option과 운영체제 구현에 따라 달라진다. 따라서 “UDP는 destination port 하나만 본다”는 문장은 개념 소개에는 편하지만 실제 socket 선택 규칙 전체를 설명하지는 못한다.

TCP와 달리 UDP는 각 datagram의 경계를 보존하며 연결 수립, 전달 보장, 순서 복구를 제공하지 않는다. source 주소와 port는 응답을 보낼 후보를 알려 주지만 상대 신원을 인증하지 않는다.

well-known port와 서비스 이름

RFC 6335는 IANA의 service name과 transport protocol port registry 관리 절차를 정의한다. 포트 범위는 다음처럼 구분된다.

범위 이름 의미
0–1023 System Ports 널리 알려진 시스템 서비스에 주로 할당
1024–49151 User Ports 등록된 사용자·애플리케이션 서비스에 사용
49152–65535 Dynamic/Private Ports 동적 선택 또는 사설 용도

등록된 번호는 상호운용을 위한 기본값이지 방화벽 허용이나 서비스 진위를 보장하지 않는다. HTTP 서버를 8080에 띄울 수 있고, 443을 연 프로세스가 반드시 안전한 HTTPS 서버라는 보장도 없다.

Linux에서 소켓과 tuple 확인하기

listening TCP socket을 본다.

ss -lntp

연결된 TCP socket과 프로세스 정보를 본다.

ss -ntp

UDP socket을 본다.

ss -lunp

권한이 부족하면 다른 사용자의 프로세스 정보가 보이지 않을 수 있다. 출력에서 다음을 구분한다.

  • Local Address:Port와 Peer Address:Port
  • LISTEN, ESTAB, TIME-WAIT 같은 TCP 상태
  • IPv4와 IPv6 binding
  • 예상한 프로세스가 포트를 소유하는지
  • backlog와 socket queue가 쌓이는지

컨테이너·Kubernetes 환경에서는 애플리케이션 process, Pod network namespace, Service·NAT, node 외부에서 보이는 tuple이 다를 수 있다. 어느 namespace에서 관측한 값인지 함께 기록한다.

자주 생기는 오해

포트 하나에는 연결 하나만 가능하다?

아니다. listening port 하나에서 다수 connected socket을 만들 수 있고, 각 연결은 tuple로 구분된다.

source port는 애플리케이션이 항상 직접 정한다?

아니다. 클라이언트가 bind()하지 않으면 운영체제가 사용 가능한 임시 port를 선택하는 경우가 일반적이다.

포트만 알면 프로세스를 알 수 있다?

로컬 시스템에서는 socket table과 process 정보를 연결해 확인할 수 있지만, 네트워크 패킷의 port 번호만으로 원격 process의 신원이나 권한을 증명할 수 없다.

멀티플렉싱이면 동시에 전송된다는 뜻이다?

전송 계층 멀티플렉싱은 여러 애플리케이션 흐름을 식별해 공유한다는 개념이다. 실제 동시성과 처리 순서는 TCP 연결, HTTP 버전, 스케줄러와 네트워크 상태에 따라 달라진다.

Python에서 listening socket과 connected socket을 직접 만들어 보려면 TCP·UDP 소켓 프로그래밍을 함께 보면 좋다.

참고 자료

반응형
KEEP READING
카테고리 전체 보기 →

댓글