C언어로 소켓 프로그래밍을 해보자 1일차 - 네트워크 개요

2

Socket_C

목록 보기
1/2

1. OSI layer model

현대 사회에서 이질적인 시스템, 기기 간의 통신이 이루어지고 있는 것을 보면 '통신' 을 위한 어떠한 표준적인 약속이 정의되어 있음을 알 수 있다. 이 약속을 Protocol이라고 한다.

Protocol(프로토콜)은 이더넷 케이블에서 발생한 전압에서부터 웹 페이지에 JPEG 이미지가 어떻게 압축되었는 지까지 모든 것을 정의한다. 사실 이는 상상이 잘 안가긴한다. 왜냐하면 우리는 이더넷 케이블에서 발생한 전압과 JPEG 압축이 완전히 다른 것처럼 생각하기 때문이다. 즉, 이들은 훨씬 다른 추상화 수준에 있다고 느껴지기 때문이다.

웹 사이트를 프로그래밍 하는 경우 이더넷 케이블이나, WIFI 주파수에 대해 깊이 생각하고 싶지 않을 것이다. 마찬가지로 인터넷 라우터를 프로그래밍한느 경우 JPEG 이미지가 압축되는 방식에 대해서 전혀 걱정하고싶지 않을 것이다. 이러한 이유로 우리는 네트워크 계층을 여러 조각으로 나눈 것이다.

관심(concern) 수준에 따라 우리는 계층을 나눌 것이다. 그런 다음 각 계층은 그 위에 있는 계층에 대한 서비스를 제공하고 각 상위 계층은 작동 방식에 대한 걱정 없이 그 아래에 있는 계층에 의존할 수 있다. 즉, 아래 계층이 무슨 방식으로 작동하던지 간에 아래 계층에서 수행한 결과를 사용(의존)할 수 있다는 것이다.

이러한 네트워크 계층 시스템을 OSI 모델(Open Systems Interconnection model)이라고 한다. 1977년에 표준화되었으며 ISO 7498 규약으로 발생되었다.

현재 OSI 모델은 7계층으로 구성되어있다.

[사진1 OSI-7계층]

  1. Physical layer : 실제 세계에서 물리적 의사소통의 수준이다. 이 수준에서 우리는 이더넷 케이블의 전압 수준, 커넥터의 각 핀이 무엇을 위한 것인지, WI-FI의 무선 주파수, 광섬유를 통해 깜박이는 표시등과 같은 항목에 대한 사양을 가지고 있다.

  2. Data Link : 이 레벨을 물리 계층에 구축된다. 두 노드 간의 직접 통신을 위한 프로토콜을 다룬다. 노드 간의 직접 메시지 시작 및 종료(framing), 오류 감지 및 수정, 흐름 제어를 정의한다.

  3. Letwork layer : 서로 다른 네트워크의 노드 간에 데이터 시퀀스(패킷)를 전송하는 방법을 제공한다. 여러 중간 노드를 통해 전송하여 한 노드에서 다른 노드로(직접 물리적 연결없이) 패킷을 라우팅하는 방법을 제공한다.

  4. Transport layer : 호스트 간에 가변 길이 데이터를 안정적으로 전달하는 방법이 있다. 이러한 방법은 데이터 분할, 재결합, 데이터가 순서대로 도착하도록 하는 등의 작업을 처리한다. TCP(Transmission Control Protocol) 및 UDP(User Datagram Protocol)는 이 계층에 속한다.

  5. Session layer : communication을 설정, 체크포인트, 일시 중간, 재개 및 종료 하는 방법을 추가하여 전송 계충을 구축한다.

  6. Presentation layer : 어플리케이션에 대한 데이터 구조 및 표현이 정의되는 최하위 계층이다. 데이터 인코딩, 직렬화 및 암호화와 같은 문제가 여기에서 처리된다.

  7. Application layer : 사용자가 인터페이스하는 어플리케이션(ex, 웹 브라우저 및 이메일 클라이언트)이 여기에 존재합니다. 이러한 응용 프로그램은 6개의 하위 계층에서 제공하는 서비스를 사용한다.

[사진2- abstracted]

OSI모델에서 웹 브라우저와 같은 어플리케이션은 Application layer에 존재한다.

데이터 또는 데이터 청크(data chunk)는 OSI 계층에 따라 종종 다른 이름으로 참조된다. 계층 2인 Data link에서는 프레임이라고 한다. 이는 계층 2에서 Framing을 담당하기 때문이다. 계층 3인 Network layer에서는 패킷이라고 한다. 반면 계층 4인 Transport layer에서는 TCP이면 세그먼트, UDP이면 데이터 그램이라고 한다.

2. TCP/IP 계층 모델

TCP/IP 프로토콜은 오늘날 가장 일반적인 네트워크 통신 모델이다. TCP/IP참조 모델은 7개 레이어가 아닌, 4개의 레이어로 이루어져 OSI모델과는 약간 다르다.

[사진3 - TCP/IP모델]

TCP/IP 모델과 OSI모델 계층은 정확히 일치하지 않는다. 그러나 두 모델은 동일한 기능이 수행된다. 단지 다르게만 나뉠 뿐이다.

TCP/IP 참조 모델은 TCP/IP 프로토콜이 이미 일반적으로 사용된 후에 개발되었다. 여전히 계층적이지만 덜 경직된 모델을 구독한다는 점에서 OSI모델과는 다르다. 이러한 이유로 OSI모델은 때때로 네트워킹 문제를 이해하고 추론하는 데 더 적합하지만 TCP/IP 모델은 오늘날 일반적으로 네트워킹이 구현되는 방식에 대한 보다 현실적인 관점을 반영한다.

TCP/IP 모델의 4개 계층은 다음과 같다.

  1. Network Access 계층: 이 계층에서 physical한 연결과 data framing이 발생한다. 이더넷 또는 WI-FI 패킷 전송은 레이어 1문제의 예이다.

  2. Internet 계층 : 이 계층은 패킷 주소를 지정하고 여러 상호 연결 네트워크를 통해 패킷을 라우팅하는 문제를 처리한다. 이 계층에서 IP주소가 정의된다.

  3. Host-to-Host 계층 : 호스트-호스트 계층은 TCP와 UDP의 두 가지 프로토콜을 제공하며 이에 대해서는 다음에 말한다. 이러한 프로토콜은 데이터 순서, 데이터의 분할, 네트워크 정체 및 오류 수정과 같은 문제를 해결한다.

  4. Process/Application 계층 : HTTP, SMTP, FTP와 같은 프로토콜이 구현되는 곳이다.

OSI든, TCP/IP 모델이든 관계없이 실제 프로토콜은 여러 수준에서 작동한다. 낮은 수준은 높은 수준의 데이터를 처리한다. 따라서 이러한 하위 수준 데이터 구조는 상위 수준의 데이터를 캡슐화해야 한다. 즉, 서로 다른 레이어 간에 데이터가 주고 받고, 전달되기 위해서는 데이터가 캡슐화되어야 한다는 것이다.

3. 데이터 캡슐화

OSI, TCP/IP 모델은 레이어를 나누어 추상화를 지원한다. 이러한 추상화의 장점은 응용 프로그램을 프로그래밍 할 때 가장 높은 수준의 프로토콜만 고려하면 된다는 것이다. 가령, 웹 브라우저는 HTTP, HTML, CSS 등 웹 사이트를 특별히 다루는 프로토콜만 구현하면 된다. TCP/IP 구현에 신경 쓸 필요가 없으며 이더넷, 또는 WIFI 패킷이 인코딩되는 방식을 이해할 필요도 없다. 이러한 직업을 위해 미리 만들어진 하위 계층 구현에 의존할 수 있다. 이러한 구현은 운영 제체에서 제공한다.

네트워크를 통해 통신할 때 데이터는 발신자의 계층을 통홰 아래로 처리되고, 수신자의 계층을 통해 다시 위로 처리되어야 한다. 가령, 웹 서버가 있는 경우 호스트 A, 웹 페이지를 수신자인 호스트 B로 전송하는 경우 다음과 같을 수 있다.

[사진 - data flow]

웹 페이지에는 몇 단락의 텍스트가 포함되어 있지만, 웹 서버는 텍스트만 보내면 끝나는 것이 아니다. 텍스트가 올바르게 렌더링 되려면 HTML 구조로 인코딩되어야 한다.

[사진 - html ,text]

html도 마찬가지이다. 웹 서버에서는 HTML을 보내기위한 프로토콜로 HTTP를 사용한다. HTML을 HTTP의 응답 헤더를 적용하여 전송하는 것이다.

[사진 - http, html]

HTTP는 TCP 세션의 일부로 전송된다. 이것은 웹서버에서 명시적으로 수행되지 않지만 운영 체제의 TCP/IP 스택에 의해 처리된다.

[사진 - TCP, HTTP]

TCP 패킷은 IP 패킷으로 라우팅된다.

[사진 - IP, TCP]

IP 패킷은 이더넷 패킷(또는 다른 프로토콜)의 유선을 통해 전송된다.

[사진 - Ethernet, ip]

네트워크 프로그래밍에 소켓 API를 사용할 때 하위 수준 문제가 자동으로 처리된다. 무대 뒤에서 무슨 일이 일어나는 지 아는 것은 여전히 유용하지만, 몰라도 상관은 없는 것이다.

Internet Protocol

수많은 프로토콜 중에서 가장 유명하고 많이 쓰이는 것이 바로, Internet Protocol이다. 오늘날에는 두 가지 버전으로 나뉘었다. 하나는 IPv4, 하나는 IPv6이다.

IPv4는 오늘날에 가장 많이 사용되며, 32-bit 주소체계를 사용한다. 이는, 2^32가지의 경우 말고는 커버할 수 없다. 그러나, 이 주소들은 처음에 효율적으로 사용되지 못했고, 현재 수많은 Internet Service Providers(ISPs)가 IPv4 주소들을 할당하기를 요구되고 있다.

IPv6는 IPv4의 부족한 ip개수를 보완하기위해 등장하였고, 1998년 Internet Engineering Task Force(IETF)에 의해 정립되었다. IPv6는 128-bit 주소 체계를 사용하기 때문에 약 3.4x10^38 개의 주소를 사용할 수 있다.

오늘날, 대부분의 데스크탑, 스마트폰 OS는 IPv4와 IPv6 모두를 지원하는데 이를 dual-stack configuration이라고 한다. 그러나, 수많은 어플리케이션, 서버들, 네트워크들은 아직도 IPv4만을 사용하는 곳이 많다. 이는 다양한 인터넷에 접속하기 위해서는 IPv4를 지원해야한다는 것을 의미하지만, 미래를 위해, 그리고 IPv4에서 IPv6로의 이향을 위해 IPv6도 지원해야한다.

주소란 무엇인가?

모든 Internet Protocol 트래픽은 주소로 라우팅된다. 즉, IPv4, IPv6 주소를 통해 상대방을 찾고, 패킷을 전송하고 수신한다는 것이다. 오늘날 가장 많이 사용되는 IPv4 주소는 32-bit로 쭉 나열하면 알아보기 어렵다. 그래서, 4개의 8-bit로 나누고 정수로 표현한다. 4개의 각 칸을 8-bit으로 설명하기 때문에 하나당 2^8개까지만 표현이 가능하다. 즉 0~255개만 표현이 가능하다.

예시는 다음과 같다.

  • 0.0.0.0
  • 127.0.0.1
  • 10.0.0.0
  • 172.16.0.5
  • 192.168.0.1
  • 255.255.255.255

127.0.0.1은 특별한 주소로 loopback 주소라고 한다. loopback이라는 이름처럼 자신(myself)에게 연결을 만드는 것이 특징이다. 운영체제는 이 주소를 단락시켜, 패킷이 네트워크에 들어가지 않고 시스템에서 로컬로 유지되도록 한다. 즉, 패킷을 127.0.0.1에 보내면 네트워크를 통해 다른 노드로 전송되는 것이 아닌, 다시 자신에게 돌아온다고 생각하면 된다.

IPv4는 프라이빗한 사용을 위해 일부 주소 범위를 남겨둔다. 만약 사용자가 IPv4를 route/NAT를 통해 사용한다면, 사용자는 다음 중 하나의 범위를 사용해야한다. 이것은 프라이빗한 용도로 사용하기위해 남겨둔 것이다.

  • 10.0.0.0 ~ 10.255.255.255
  • 172.16.0.0 ~ 172.31.255.255
  • 192.168.0.0 ~ 192.168.255.255

IP를 표현하는데 있어 한 가지 단축 표현이 있다. 이것을 Classless Inter-Domain Routing(CIDR) 표기라고 하는데, 우리는 위의 IP표현을 다음과 같이 쓸 수 있다.

  • 10.0.0.0/8
  • 172.16.0.0/12
  • 192.168.0.0/16

CIDR 표기법은 고정되는 IP값들을 일련의 숫자로 표현하는 것이다. 가령, 10.0.0.0/8이라는 것은 앞에 8개의 비트가 고정되었다는 것이다. 즉, 10부분은 고정되어서 바뀔 수 없는 부분이고, 10.X.X.X에서 X부분은 유동적이므로 사용가능하다는 것이다. 따라서, 10.0.0.0/8이면 2^24개 만큼의 ip를 만들 수 있다. 176.16.0.0/12는 앞에 12비트가 고정이라는 것이다.

- 172.16.0.0
이진수 변환 : 10101100 00010000 00000000 00000000
고정된 자리 : oooooooo ooooxxxx xxxxxxxx xxxxxxxx

고정된 자리에서 O는 고정되었다는 것을, X는 유동적이라는 것을 의미한다. 따라서 X로 표시된 부분이 10101100 0001까지이므로 0000 00000000 00000000부분은 값을 바꿀 수 있다. 그래서, 두번째 자리(00010000)가 31까지만 가능한 것이다.

IPv6 주소들은 128-bit로 길다. 이들은 4개의 그룹이 아니라 8개의 그룹으로 나눈다. 때문에 한 그룹당 16비트를 소화해야한다. 때문에 정수로 표현하기에는 2^16값은 너무 커 16진수로 표현한다. 즉, 정리하면 128-bit인 IPv6는 8개의 그룹으로 나눈 다음 각 그룹들의 값을 4개의 16진수로 표현한다는 이야기이다. 왜냐하면 16진수는 2^4이고, 128/8 = 16이기 때문이다.

  • 0000:0000:0000:0000:0000:0000:0000:0001
  • 2001:0db8:0000:0000:0000:ff00:0042:8329
  • fe80:0000:0000:0000:75f4:ac69:5fa7:67f9
  • ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

IPv6는 소문자로 표현한다. 이는 많은 컴퓨터 프로그래밍에서 16진수를 표현하는 방식과 다른 방식이다. IPv6도 loopback주소가 있는데 ::1이라고 한다. 이는 단축어 표현으로 앞의 0들을 모두 생략한 것을 의미한다.

IPv6는 크게 확장된 주소 범위 외에도 IPv4에 비해 많은 추가 기능을 도입한다는 점에서 유의미하다. IPv6주소에는 범위 및 수명과 같은 새로운 속성이 있으며 IPv6네트워크 인터페이스에는 여러 IPv6주소가 있는 것이 일반적이다. 또한, IPv6주소는 IPv4주소와 다르게 사용 및 관리된다.

Domain names

인터넷 프로토콜은 이름이 아니라, 오직 IP address를 통해서만 패킷을 전송할 수 있다. 따라서, 만약 특정 이름을 가진 웹사이트(example.com)에 접속하려고 한다면, 우리의 시스템은 웹사이트(example)를 호스팅하는 서버에서 example.com을 어떤 IP address로 맵핑하였는 지 확인해야한다.

도메인 이름 example.com만을 가지고, 어떤 IP address와 연결되었는 지 확인하는 작업을 해주는 것이 바로, DNS(Domain Name System)의 역할이다. DNS는 IP주소를 미리 알고 도메인 이름 서버에 연결한다. 우리가 DNS의 IP주소를 알 수 있는 것은 일반적으로 ISP에서 할당하기 때문이다.

도메인 공급자 서버들은 일반적으로 주소가 공개되어있다.

DNS동작 방식은 굉장히 간단하다.

  1. 먼저 클라이언트가 서버로 요청을 보낼 때, 특정 도메인 example.com으로 보낸다면, 이 이름에 해당하는 IP 주소를 찾기위해 DNS에 물어봐야한다.
  2. 클라이언트는 해당 도메인에 맵핑된 IP address를 알기위해, ISP를 통해 DNS서버에 AAAA레코드를 전송한다. 만약 문제가 없다면 IPv6주소가 전달된다.
  3. 만약, AAAA레코드가 없다면 서버에 다시 쿼리하게되는데, 이때는 A레코드를 요청한다. 이 레코드가 있으면 서버에 대한 IPv4주소를 받게 된다.
  4. ISP는 DNS서버로부터 받은 IP주소를 클라이언트에 전송한다.
  5. 클라이언트는 해당 IP주소로 패킷을 전송하기위해 ISP로 전송하고 ISP가 패킷을 전송한다.

물론 DNS서버가 하나는 아닐 수 있다. DNS내부적으로 root 서버가 있을 수 있고, top-level domain 서버, second-level domain 서버, sub-level domain 서버 등이 있을 수 있다. 이들은 순차적으로 큰 대분류 순서로 root부터 top, second, sub로 해당 도메인에 대한 IP 주소를 유추해나간다.

shop.example.net.
이라고 한다면, .이 root .net이 top-level domain, .example이 second level domain, shop이 sub-level domain이다.

이는 빠른 응답을 위하여 가장 가까운 DNS server의 응답을 받고, 소속 순서로 IP addresss를 취득하기 위함이다.

이에 따라 DNS 기능을 나누면 다음과 같다.

  1. 서버 관리자가 획득한 도메인의 NS 레코드 정보를 접수 받는다.(도메인- ip주소 등록)
  2. 클라이언트가 요청한 도메인의 IP address를 클라이언트에 알려준다.

Internet routing

인터넷에서 서로 연결하려는 컴퓨터가 두 대라면 이들끼리 connection을 맺어주기만 하면된다.

그러나, 오늘날의 인터넷에는 수많은 컴퓨터, 기기들이 연결되어있다. 따라서 이들을 직접 connection을 맺어주기는 쉽지 않다.

그래서, 멀리 있는 특정 컴퓨터에 connection을 맺고 데이터를 전송하기위해서 우리는 라우터라는 것을 사용하게되었다.

데이터를 전송하려는 컴퓨터는 자신의 컴퓨터에 연결된 local router에게 데이터를 보내고, local router는 목적지가 어디냐에 따라 자신에게 연결된 라우터에 따라 데이터를 전송한다. 이렇게 각 라우터들은 데이터의 목적지에 따라 자신에게 연결된 라우터로 데이터를 전송하게되고, 마침내 목적지 컴퓨터에 데이터가 전송되고 connection을 맺게 되는 것이다.

그럼 얼마나 많은 라우터들을 거쳐서 데이터가 전송되는 것일까?? 다음의 명령어를 통해 우리는 중간에 걸치는 라우터들의 수를 알 수 있고, 몇 홉(라우터에서 라우터로 넘어가는 구간)을 거쳤는 지 알 수 있다.

  • window
tracert [ip 또는 domain]
  • unix
traceroute [ip 또는 domain]

다음의 명령어를 입력해서 특정 주소에 접근해보면, Request timed out메시지를 받는 라우터들이 있고, IP주로를 받은 라우터들이 있을 것이다. Request timed out메시지를 받은 것은, 문제의 시스템이 ICMP(internet control message protocol) 프로토콜 일부를 지원하지 않는다는 것을 의미한다.

즉, ICMP는 ip패킷을 처리할 때 발생되는 문제를 알려주는 프로토콜로, 이 중 일부를 지원하지 않는다는 것은 네트워크에 문제가 있던지, 아니면 일부러 해당 시스템에서 라우팅 ip를 알지 못하게 막은 것일 수도 있다.

Gateway

gateway는 router와 비슷한 기능을 하지만, 의미적으로 다르게 쓰이기도 하고 더 포괄적인 개념이다. gateway는 로컬 네트워크와 외부 네트워크를 잇는 하드웨어 또는 소프트웨어로 로컬 네트워크가 외부로 나가거나, 외부에서 내부로 패킷을 전송할 때 반드시 거쳐야한다.

gateway는 단순히 패킷을 전송, 전달하는 라우터와 달리 서로 다른 프로토콜 간의 변환을 해준다는 차이점이 있다. 즉, 이기종 간의 통신이 가능하게 해준다는 점이다. 때문에 gateway는 다양한 프로토콜을 지원하는 반면, router는 하나의 프로토콜만 지원한다는 점에서 차이가 있다.

정리하자면 gateway는 로컬 네트워크와 공중망 네트워크(외부)와의 엔드 포인트가되는 지점으로 서로 다른 프로토콜 간의 통신이 가능하도록 도와준다. 또한 라우터처럼 라우팅 기능도 한다. 일반적으로 로컬 네트워크에는 한 개의 게이트 웨이와 그 아래에 내부 네트워크를 라우팅하는 라우터들과 스위치로 이루어져있다고 생각하면된다. 그러나 점점 라우터가 발전함에 따라, 게이트웨이 처럼 이종간 프로토콜 변환도 가능해지고 기능도 다양해져 굳이 이들을 구별하지않아도 된다.

오히려, 요즘에는 gateway라는 말은 엔드 포인트 관점에서 많이들 언급한다. 대표적인 것이 AWS API gateway가 있다. 또한 백엔드 시스템을 만들 때 라우팅 작업을 할 것이다. 가령 example.com/home, example.com/user 라우터가 있다면, 게이트 웨이로 example.com/을 두어서 이 게이트 웨이에서 일련의 변환 작업(마샬링 또는 serialization 직렬화)를 거쳐 각 url인 /home 또는 /user에 데이터를 전송해줄 수 있다.

Local networks and address translation, NAT

회사나 가정에서 Local Area Networks(LANs)를 갖는 것은 매우 흔한일이다. 위에서도 말했듯이 LANs에는 고정적으로 사용되는 IPv4 범위가 있는데 다음과 같다.

  • 10.0.0.0 ~ 10.255.255.255
  • 172.16.0.0 ~ 172.31.255.255
  • 192.168.0.0 ~ 192.168.255.255

local 네트워크를 통해 만들어진 패킷이 외부로 전송될 때는 NAT을 거쳐야만 한다. NAT는 라우터에서 구현된 것으로 local address와 공인 IP, PORT를 맵핑시켜주는 기능을 한다. 조금 더 기술하면 다음과 같다.

NAT(Network Address Translation)

NAT는 local IP를 public IP변경에 필요한 주소 변환 서비스이다. 라우터, 공유기 등의 장비를 사용하여 다수의 사설 IP를 하나의 공인 IP 주소로 변환하되, 같은 공인 IP를 같은 것들에 대해서 포트번호로 이들을 나누는 기술이다.

즉, NAT는 다수의 주소 변환 정보에 대해 IP주소와 Port번호로 구성된 NAT Forwarding Table을 보관하고 있고 이에 맞게 주소 변환 서비스를 제공한다.

다음과 같은 NAT Table이 있다고 하자
| local | local-to-public | destination |
|---|---|---|
| 192.168.1.1:9688 | 101.89.101.12:8801 | 68.1.31.1:23 |
| 192.168.1.1:1253 | 101.89.101.12:5123 | 68.1.31.1:23 |
| 192.168.1.1:1025 | 101.89.101.12:102 | 68.1.31.1:23 |

NAT table은 다음과 같은 특징을 갖는다.

  1. local 네트워크의 IP와 포트 번호에 대한 정보가 있다.
  2. 외부로 나갈 때 local IP는 public IP가 동일하게 맵핑되지만 포트 번호는 다르다.
  3. 목적지 주소의 public IP와 port번호는 동일하다.

즉, NAT는 외부에서 내 local 디바이스에 정보를 보낼 때 public IP로 변환시켜주며 자세한 IP구분은 port로 해주겠다는 것이다.

작동 방식은 다음과 같다.

  1. local IP 192.168.1.1:9688이 local 망 외부에 있는 public IP 68.1.31.1:23에 데이터를 보려고한다. 이 때 패킷의 출발지 주소와 목적지 주소는 다음과 같다. [192.168.1.1:9688, 68.1.31.1:23]
  2. 라우터는 NAT 테이블에 따라 local IP 192.168.1.1:9688를 공인 IP 101.89.101.12로 바꾼다. 단, 포트번호로 구분하기위해 8801을 붙여준다. 이 때 패킷의 출발지 주소와 목적지 주소는 다음과 같다. [101.89.101.12:8801, 68.1.31.1:23]
  3. 패킷이 목적지 68.1.31.1:23에 도착하고 응답 패킷을 보내는데 이때, 출발지 주소가 local IP의 공인 IP 주소이므로 이를 목적지 주소로 하여 보낸다. 출발지 주소와 목적지 주소는 다음과 같다. [68.1.31.1:23, 101.89.101.12:8801]
  4. 응답 패킷이 라우터에 도착하고 라우터는 NAT TABLE에 따라 어떤 local IP에 해당 패킷을 전송할 지 결정한다. 이 때 사용되는 것이 바로 포트번호이다. 포트번호가 8801이므로 맵핑된 local IP주소는 192.168.1.1:9688이 된다. 이 때 응답 패킷의 출발지 주소와 목적지 주소는 다음과 같다. [68.1.31.1:23, 192.168.1.1:9688]
  5. 192.168.1.1:9688 IP를 가진 local 기기는 응답을 받고 완료한다.

추가적으로 NAT는 오류 검출도 한다. 패킷의 checksum도 업데이트하는데, 그렇지 않으면 패킷이 오류를 포함한 것으로 감지하고 다음 라우터에서 폐기된다.

그럼 NAT를 왜 사용하는가??

  1. public IP를 절약하는 장점이 있다.
  2. local IP를 외부에 노출되지 않는 장점이 있다. 즉, 보안상의 장점이 있다.

두 번째 목적지 중요하다. 내부에서 사설 IP를 사용하는 것은 외부에서 개인 PC나 인터넷 장비로 직접적인 접근을 하지 못하는 이유도 포함한다. NAT 장비는 방화벽 형태일 수도 있고, router일 수도 있다.
참조 : https://brunch.co.kr/@sangjinkang/61

그런데, 라우터가 메시지를 local로 전달 할 수 있는지 또는 전달해야 하는지 여부를 어떻게 알 수 있을까?? 이것은 넷마스크, 서브넷 마스크 또는 CIDR을 사용하여 수행한다.

Subnet and CIDR

Subnet이란, IP 주소를 나누어서 하나의 네트워크를 여러 개의 서브 네트워크로 나누는 것을 말한다. 이전에 A,B,C 클래스로 서브넷을 나누었었다. 그러나 이는 효율적이지 못하다. 각 기업이 필요로하는 호스트 수의 상황이 다를 수 있으므로 유연하게 서브넷을 설정할 수 있어야 한다.

가령, 어떤 통신사에서 클래스 C로 IP를 나누어 A 회사에게 제공하였다고 하자. 그러면 클래스 C는 255.255.255.0이므로 호스트 수는 총 256개가 될 것이다. 그런데, A라는 회사는 host(ip개수)를 10개만 쓴다. A회사에게 클래스 C로 IP를 주면 나머지 246개의 IP는 사용하지 않은 IP가 된다. 이는 비효율적이다. 딱 맞게 호스트 수 10개를 커버할 만큼의 IP를 주고, 나머지 IP는 다른 회사에게 파는 것이 효율적이다.

이걸 가능하게 하는 것이 Subnetting(서브넷팅)이다. 서브넷팅은 IP 주소를 가지고, subnet부분과 호스트 부분을 나누는 것을 의미한다.

[Network prefix | Host Number]
IP가 위와 같이 분리된다는 것이다. 즉, 서브넷팅은 IP를 가지고 내부적으로 서브 네트워크(서브넷)을 만드는 것이다. 가령 클래스 C의 경우는 255.255.255.0이기 때문에 xxx.xxx.xxx.ooo x부분은 네트워크 prefix 로 서브넷 부분이고, o부분은 host number로 각 PC들이 가지는 IP가 되겠다.

위의 문제 상황은 호스트 IP를 너무 많이 차지하여 발생하는 문제인 것이다. 따라서, 다음과 같이 바꿔주면 된다.

XXXXXXXX XXXXXXXX XXXXXXXX XXXXOOOO X는 고정된 ip부분으로 서브넷 부분이다. O는 호스트로 사용하는 ip부분이다. 이렇게 두면, 호스트 개수로 16개를 사용할 수 있다. 그러므로 총 10개를 사용할 수 있는 상황을 커버할 수 있다.

그런데, 클래스 A, B, C가 아니면 어떻게 해야할까? 어디서부터 어디까지가 Network prefix이고, Host number인지 알 수 있을까??

이를 해결하기 위하여 서브넷 마스크를 도입한 것이다. 즉, 서브넷 부분(network prefix)가 어디까지인지 알려주고, 나머지는 호스트 ip로 사용할 수 있다는 것을 알려주기 위해 도입된 것이다.

서브넷 마스크의 작동 방법은 다음과 같다.

1. 서브넷 마스크는 서브넷에 해당하는 부분은 모두 1로 써준다. 단 1은 연속적으로 써주지 도중에 끊기질 않는다.
2. 입력받은 IP를 서브넷 마스크와 비트 단위로 ```and``` 연산한다.
3. 결과로 나온 비트가 바로 서브넷 부분으로 즉, network prefix(id)이다.
4. 서브넷 부분이 현재 라우터가 서비스하고 있는 서브넷 부분이라면 해당 패킷을 가져오고 아니면 던진다.

즉, 서브넷 마스크는 입력으로 들어온 IP 주소와 and 연산을 하여 어느 부분이 네트워크 prefix에 해당하는 지 알려주기 위해 사용하는 것이다.

예시를 들어보자

서브넷 주소 : 10.32.192.0
서브넷 마스크: 255.255.255.0
입력받은 IP: 10.32.192.34

이 두 개의 값을 서로 비트 단위로 AND 연산해보자

11111111 11111111 11111111 00000000 (서브넷 마스크)
00001010 00100000 11000000 00100010 (입력받은 IP)

00001010 00100000 11000000 00000000 (and 연산 결과)

==> 10.32.192.0이 된다. 즉, 네트워크 prefix는 10.32.192.0으로 호스트, 10.32.192.1, 10.32.192.34 ... 등은 같은 서브넷 네트워크(10.32.192.0)에 있다는 것이다. 따라서, 해당 패킷을 서브넷에 포워드 시켜줄 수 있다. 만약, 다르다면, 가령 10.129.192.0, 10.32.123.12 등이라면 실패하고 던진다.

한가지 주의해야할 것은 위의 경우 호스트 수가 0~255이므로 256개 같지만, 맨 처음 호스트는 서브넷 구분을 위해, 맨 마지막은 브로드 캐스트를 위해 사용되므로 실제로 사용 가능한 호스트 개수는 254개가 맞다.

따라서, 위에서 예시로 든 서브넷 부분도 호스트는 16개가 아니라 14개를 수용할 수 있는 것이 맞다.

서브넷 마스크를 일일히 쓰기 귀찮으므로 우리는 ip옆에 CIDR을 사용한다. 이 표기법은 IP/서브넷 마스크에서 1의 개수 가 된다. 위의 경우는 10.32.192.34/24가 된다.

그럼 10.32.192.34/26은 어떻게 되는가??

11111111 11111111 11111111 11000000 (서브넷 마스크)
00001010 00100000 11000000 00100010 (입력받은 IP)

00001010 00100000 11000000 00000000 (and 연산 결과)

가 된다. 서브넷 마스크의 1의 개수가 26개가 되었고, AND연산 결과 값이 10.32.192.0으로 같지만, 한 가지 알아두어야 할 것이 있다.

지금까지 호스트 수는 알겠는데, 그럼 서브넷 수는 얼마나 나뉘게되는 지 어떻게 아냐는 것이다?? 위의 경우에는 2^2 = 4개이다.

11111111 11111111 11111111 11000000
11111111 11111111 11111111 10000000
11111111 11111111 11111111 01000000
11111111 11111111 11111111 00000000

다음의 4가지 서브넷이 있는 것이다. 따라서 각 서브넷마다 호스트 수는 2^6-2= 62이다. -2를 해준 이유는 아까도 설명했듯이 맨 처음은 서브넷 마스크를 위해, 맨 마지막은 브로드 캐스팅를 위해 나눈 것이다.

그런데, 궁금한 것이 있다. 왜 앞부분 11111111 11111111 11111111은 서브넷 경우의 수로 안쳐주냐는 것이다.

답은 간단하다. 우리가 클래스 C라는 것을 가정하고 서브넷을 나누었기 때문이다. 즉, 앞 부분 11111111 11111111 11111111은 고정이 되고, 다른 네트워크 주체가 결정해준다고 생각하면 된다. 클래스 C인 상태에서 우리가 건드릴 수 있는 것은 2비트 밖에 없기 때문에 서브넷이 4개 밖에 안생긴 것이다.

따라서, 서브넷은 총 4가지로 10.32.192.0 , 10.32.192.128, 10.32.192.68, 10.32.192.192가 된다. 이 서브넷 중, 자신이 속한 서브넷은 위에서 10.32.192.0으로 가정하였으므로, 라우팅이 가능하다.

그럼 만약 클래스 B에 10.32.192.34/26이면 어떻게되는가??

11111111 11111111 1111111 11000000

빨간색으로 표시한 부분이 서브넷을 나눌 수 있는 개수가 된다. 즉, 2^10개이므로 1024개가 된다. 어떤 곳은 실제적으로 쓸 수 있는 서브넷 개수도 -2를 해야한다고 하는데, 대부분 안하니까 빼지말도록 하자

그럼 서브넷이 무엇에 좋은가?? 한다면, 사실 IP할당을 효율적으로 할 수 있다는 장점 말고도 좋은 점이 굉장히 많다.

  1. 서브넷을 나누어 IP할당을 효율적으로 할 수 있다.
  2. 서브넷을 나누었기 때문에 특정 주소로 트래픽이 쏠리는 현상을 막을 수 있다. 트래픽 감소 효과가 있다.
  3. 서브넷을 나누어 관리하면 관리하기가 편하다.

가장 큰 장점은 네트워크 성능 최적화이다. 서브넷을 나누면, 같은 서브넷 IP(네트워크 prefix)를 가진 IP끼리는 통신할 때 멀리안가도 된다.

가령, 내가 삼성 아파트 102호에 사는데, 1022호 친구를 만나기위해서 그냥 엘리베이터만타면 된다. 굳이 아파트 밖으로 나갈 필요가 없다.

이것이 가능한 이유는 서브넷 마스크를 통해 서브넷을 확인할 수 있기 때문이다. 라우터가 서브넷을 확인하고 패킷을 전송하는 호스트와 동일한 호스트라면 굳이 게이트웨이를 통해 패킷을 전송시킬 필요가 없이 내부 라우터들 끼리로 처리가 가능하다는 것이다.

만약, 서브넷 마스크가 다르다면 게이트를 웨이를 통해 외부로 나가야한다. 이는 아파트를 나가 다른 아파트로 나가야 하는 상황일 것이다.

서브넷이 없다면 삼성 아파트 102호에 살아도 같은 1022호에 친구가 있다는 사실만 알고 여기저기 물어보고 다녀야 한다. 즉, 아파트를 나가서 여기저기 수소문해야 자신의 아파트에 있다는 것을 알게된다. 이 처럼 서브넷은 네트워크 성능 향상에 아주 좋은 기능을 한다.

https://www.tutorialspoint.com/ipv4/ipv4_subnetting.htm
https://engkimbs.tistory.com/622

Multicast, Broadcast and anycast

어떤 디바이스가 다른 디바이스에게 패킷을 전송할 때, 어떤 방식으로 보내냐에 따라 Multicast, Broadcast, anycast 등이 결정된다.

  1. unicast: 한 디바이스가 다른 한 디바이스에게 패킷을 라우팅한다. (one -> one)
  2. Broadcast: 한 디바이스가 모든 디바이스에게 동시에 패킷을 전송한다. 일반적으로 subnet에 있는 모든 receiver에게 패킷을 전송하기위해 사용한다. (one -> all)
  3. Multicast: Broadcast가 한 네트워크에 속한 모든 호스트에 패킷을 전송하는 것이라면, Multicast는 전체는 아니고, 그렇다고 하나는 아닌 여러개의 호스트에게 패킷을 전송하는 것이다. 가령, 어떤 전체 네트워크에서 어떤 그룹이 있다면 해당 그룹에게만 보내는 것이다. (one -> many)
  4. Anycast: 패킷이 누군가에게 전송될 뿐이지, 누군가는 중요하지 않는 경우이다. 가령, 같은 기능을 하는 서버가 여러 대일 때, 우리는 어떤 기능에 대한 요청을 굳이 하나를 딱 선택해서 요청할 필요가 없다. 서버 중 누구라도 요청을 처리하면 되므로 아무나를 선택해서 전송하면 된다. 단, 오해하지 말아야하는 것이 여러 호스트에게 패킷을 전송한다는 것이 아닌, 여러 개 중 아무나 한 개에 패킷을 전송한다는 것이다. (one -> any)

그럼 ``AnycastUnicast의 차이가 모호할 수도 있는데, 둘 다 결국은 one -> one이라는 것은 같다. 그러나, Unicast는 원래 전송하려는 대상자가 한 명이었던 것이고, Anycast는 원래 전송하려는 대상자는 여러 명인데 그 중 한 명에게 패킷을 전송하는 것이다. 그래서 Unicastone to one, Anycastone to any```인 것이다.

https://www.baeldung.com/cs/multicast-vs-broadcast-anycast-unicast

참조하면 좋은 사이트가 있다.

IPv4와 저수준 네트워크는 local broadcast addressing을 지원한다. IPv4는 또한, 옵셔날하게 multicasting도 지원한다. IPv6는 IPv4의 multicasting에 추가 기능을 제공하면서 멀티 캐스팅 지원을 의무화한다. 단, IPv6은 broadcast를 고려하지않는다. 단지, IPv6의 multicasting 기능으로 broadcasting과 같이 에뮬레이트할 수는 있다.

Port numbers

ip와 port의 관계를 전화기에 비유하자면, 전화번호는 IP와 같다. 그런데 이런 경험있을 것이다. 공공기관에 전화하면, 바로 전화가 되는 것이 아니라 ARS로 무슨 이유로 전화했는 지 묻고, 전화가 돌려진다. 이런 경우들은 같은 전화번호를 쓰지만 내선이 다른 경우들이다. 포트는 이 내선에 속한다.

일반적으로, IP 주소는 패킷이 어떤 시스템(컴퓨터 등)에 라우팅될 것인가를 결정한다면, 포트 숫자는 이 시스템의 어떤 어플리케이션에 패킷을 라우팅할 지 결정하는 것이다.

가령, 우리는 컴퓨터로 웹 브라우저를 띄우고, 이메일 어플리케이션을 사용하고, zoom같은 화상 회의 시스템도 사용한다. 컴퓨터가 UDP, TCP 통신으로 어떤 데이터를 받았다면, 우리의 OS는 목적지 port를 확인하고, 해당 port를 가진 어플리케이션에 패킷을 전송한다.

port 숫자는 0~65535으로 unsigned int 16bit로 이루어져 있다. 일부 어플리케이션 단 프로토콜은 약속된 포트로 통신을 해야하므로, 전용 포트를 가지고 있어야 한다.

가령, 파일을 전송하는 FTP 프로토콜은 20, 21 port를 전용으로 사용해야한다.

Port Number		Protocol	
20, 21	        TCP	File Transfer Protocol (FTP)	
22	            TCP	Secure Shell (SSH)
23	            TCP	Telnet	
25	            TCP	Simple Mail Transfer Protocol (SMTP)
53	            UDP	Domain Name System (DNS)
80	            TCP	Hypertext Transfer Protocol (HTTP)	
110	            TCP	Post Office Protocol, Version 3 (POP3)	
143	            TCP	Internet Message Access Protocol (IMAP)	
194	            TCP	Internet Relay Chat (IRC)	
443	            TCP	HTTP over TLS/SSL (HTTPS)	
993	            TCP	IMAP over TLS/SSL (IMAPS)	
995	            TCP	POP3 over TLS/SSL (POP3S)

정리하면 다음과 같다. 해당 포트들은 IANA(Internet Assigned Numbers Authority)에 의해 할당된 것들이다. 이들은 특정 프로토콜이 어떤 포트를 써야할 지 정하고 이에 대한 책임을 진다.

이러한 포트들을 official port라고 하는데, unofficial port는 사용자가 직접 프로토콜을 만들고, 사용하는데 있어 마음 껏 사용해도된다. 즉, 어플리케이션에서 포트를 서로 충돌만 내지 않으면 얼마든지 포트를 사용해도 된다는 것이다.

sockets

소켓은 시스템 간의 통신을 위한 하나의 end-point이다. end-point가 무엇이냐면, 통신을 하기위한 마지막 부분이라고 생각하면된다. 소켓은 위의 IP, port와는 다른 또 다른 네트워크 정보는 아니다. 이는 어플리케이션에서 네트워크를 건너 데이터를 보내고 받기위해 소프트웨어적으로 만들어진 추상화일 뿐이다.

즉, 네트워크 통신을 하는 방법들을 추상화하여 사용자에게 제공된 것이 소켓이다. 따라서 모든 네트워크 통신은 소켓을 기반으로 이루어진다. 단지 이 소켓 사용을 추상화하여 다른 프로토콜로 덮어서 잘 보이지 않은 것일 뿐이다.

소켓은 5가지 요소들로 유니크하게 구성된다.

  1. Local IP 주소
  2. Local Port
  3. Remote IP address (목적지 주소)
  4. Remote port (목적지 포트)
  5. Protocol (UDP, TCP)

이 5개의 요소는 매우 중요하다. OS 시스템이 이 정보들을 토대로 어떤 패킷이 어떤 어플리케이션이 책임을 지고있고, 라우팅되어야할 지 결정하기 때문이다.

가령, 두 개의 웹 브라우저를 사용하여 같은 페이지(www.example.com)에 port 8080으로 접속했다고하자, 이 경우, local IP주소, Remote IP address, Remote port, Protocol은 모두 같다. 하나 다른게 있는데, 바로 Local port이다.

웹 브라우저의 창을 두 개 띄우고, example.com:8080에 접속할 때 우리는 로컬 local port를 따로 설정해놓고 접속하지 않는다. 이는 OS에서 local port를 결정해주기 때문이다. 이 때문에 local port임시 포트( ephemeral port )라고도 한다. 이 포트는 OS에 따라 다르게 설정된다.

또한, 소켓의 5가지 요소는 NAT을 구성할 때도 매우 중요하다. 가령, private network에서 같은 외부 소스에 접근하려는 많은 시스템들이 존재한다. private network는 자신들 네트워크의 특정 IP, 특정 Port에 대해서는 외부에서 전달된 패킷을 호스트에 전달할지, 말지, 또는 패킷에 보안적 요소를 추가해서 전달할 지 등을 결정해야한다. 이를 위해 NAT를 사용한다. NAT는 5개의 요소를 모두 저장한 다음 각 connection(연결)을 구분한다. 그리고, 패킷이 private network로 들어왔을 때 해당 connection에 어떻게 패킷을 전달할 지 결정한다.

0개의 댓글