BASIC의 개발 노트
The Internet network layer 본문
Internet network layer는 host, router 모두 network layer 기능을 구현하고 있어야 한다.
다양한 routing protocols, IP protocol, ICMP protocol 등이 존재한다.
IP datagram format
<----------------------------------------------------------32bits--------------------------------------------------------->
-----------------------------------------------------------------------------------------------------------------------------
version | header length(기본 20바이트 + options에 따라 늘어남) | type of service | length(total datagram length)
-----------------------------------------------------------------------------------------------------------------------------
16-bit identifier | flgs | fragment offset -> 이 라인은 datagram을 쪼개고 다시 합치는데 사용
-----------------------------------------------------------------------------------------------------------------------------
time to live(router를 거쳐갈 때 마다 1씩 감소) | upper layer(UDP에서 보냈는지 TCP에서 보냈는지) | header checksum
-----------------------------------------------------------------------------------------------------------------------------
32 bit source IP address
-----------------------------------------------------------------------------------------------------------------------------
32 bit destination IP address
-----------------------------------------------------------------------------------------------------------------------------
options (if any)
-----------------------------------------------------------------------------------------------------------------------------
data (variable length typically a TCP or UDP segment)
-----------------------------------------------------------------------------------------------------------------------------
IP fragmentation(단편화, 분할)
IP fragmentation이 왜 필요한가?
각각의 link별로 MTU(link level 별 최대 보낼 수 있는 size)가 정의 되어 있는데
서로 다른 link의 type은 서로 다른 MTU 값을 갖게 된다.
어떤 link를 통해 packet이 전달 됐을 때 A 링크의 MTU와 B 링크의 MTU가 다르면 문제가 발생할 수 있다.
따라서 만약 large IP datagram이 들어올 경우 여러 개의 datagram으로 자른다.
link type 별로 MTU가 다르기 때문에 쪼갤 수 밖에 없다.
이후 datagram을 쪼갰기 때문에 다시 합쳐야 하는데 final destination에서만 reassemble을 한다.
만약에 합쳐놨는데 다음 link의 MTU가 작아서 또 쪼개는 것은 비효율적인 작업이기 때문에 마지막에 합친다.
이렇게 쪼개고 합칠 수 있도록 16-bit identifier, flgs, offset 같은 정보들을 header에 포함시켜서 보내는 것이다.
예제:
length = 4000, ID = x, fragflag = 0, offset = 0
4000byte datagram, MTU = 1500 bytes -> 쪼개야 한다. (MTU가 더 작아서 다 보낼 수 없다.)
----------------------------------------------------------
header가 20바이트 라고 가정하면, data는 3980 바이트가 된다.
따라서 쪼개보면
length = 1500, ID = x, fragflag = 1, offset = 0, data = 1480 (0번 바이트 ~ 1479번 바이트)
length = 1500, ID = x, fragflag = 1, offset = 185, data = 1480 (1480 바이트 ~ 2959 바이트)
length = 1040, ID = x, fragflag = 0, offset = 370, data = 1020 (2960 바이트 ~ 3979 바이트)
data의 합 = 3980 바이트, header size = 20 바이트 -> total length = 4000 byte 가 된다.
ID는 쪼갰으면 똑같은 값을 갖도록 하고, fragflag는 마지막 쪼개진 패킷이라면 0이 되고 그렇지 않으면 1이다.
offset은 data에 들어간 byte의 첫 번째 바이트의 번호를 붙여둔 것이다.
그렇다면 0번 offset, 1480번, 2960번이 되어야 하는데 그렇지 않다.
그 이유는 offset을 표현할 때는 나누기 8을 한 값을 쓴다. (나누기 8을 하면 offset을 표시하는데 3bit를 줄일 수 있다.)
따라서 0, 1480/8, 2960/8 해서 결과적으로 offset에는 각각 0, 185, 370이 각각 적히게 된다.
이렇게 잘라진 data fragment는 또 다시 잘라질 수 있다.
하지만 결국 최종적으로는 다 합쳐서 처리를 하게 된다.
IP Addressing
우선 IP Address는 기본적으로 32비트이다.
IP Address는 8비트(1바이트)씩 끊어서 10진수로 표현하고 각 바이트 사이는 .(점)으로 구분한다.
그리고 IP Address는 host나 router의 interface에 각각 IP 주소가 부여된다.
여기서 interface라는 것은 host나 router와 physical link를 연결해주는 device 이다. (ex: LAN 카드)
또한 라우터는 여러 개의 interface를 가지고 있을 수 있는데 이 경우 각각의 interface 마다 IP Address를 가지게 된다.
특히 요즘은 WiFi, Ethernet interface를 같이 가지고 있는 경우가 많다. (스마트폰의 경우 WiFi와 LTE)
이렇게 각각의 interface 별로 IP Address가 반드시 존재해야한다.
host와 router 사이에 스위치가 있는 경우가 많다.
스위치를 사용하면 여러 개의 host가 하나의 라우터에 연결 될 수 있다.
또 어떤 경우에는 무선 WiFi interface(공유기)를 사용해서 여러 host를 하나의 라우터의 interface에 연결하기도 한다.
중요한 것은 각각의 host가 router에 연결이 가능하다는 것이다.
Subnets
Subnet이란 interface들의 집합을 말한다.
같은 subnet part를 가지는 device를 모아놓은 것을 하나의 subnet이라고 한다.
subnet part가 같은 interface들은 물리적으로 서로 도달이 가능하다.
즉 subnet은 router가 없어도 서로 packet이 전달될 수 있는 interface들의 집합이다.
IP Address를 subnet part와 host part로 분리하고, 앞에서부터 3바이트(8비트)가 subnet part가 된다.
즉 앞 3바이트(24비트)가 같은 경우 같은 subnet part를 갖는다고 볼 수 있다.
Subnet을 표현할 때는 대표적인 IP Address를 하나 써주는데 보통 마지막이 0이 되도록 적고
/(슬래시) subnet part의 비트 수를 적어준다. -> ex: 223.1.3.0/24
여기서 /24를 subnet mask라고 부른다.
subnet part의 길이를 앞에서 24비트라고 했지만 이는 보통 많이 사용하는 길이이고 사실 길이가 다양하다.
CIDR(Classless InterDomain Routing)은 subnet portion이 임의의 길이를 가지도록 하는 방식이다.
과거에는 class가 존재했었고, subnet part의 길이가 고정이 되어있었다. (8, 16, 24비트 중 하나)
그리고 8비트, 16비트, 24비트를 각각 class로 구분했다.
만약 24비트 짜리를 사용하면 host part에는 남은 비트가 8비트가 되고, 이 비트가 IP Address의 개수를 의미한다.
지금은 임의의 숫자가 가능하도록 8, 16, 24비트와 같은 구분이 사라졌다.
게다가 과거와 달리 임의의 길이를 가지고도록 했기 때문에 IP를 사두고 놀고 있는 IP Address가 별로 없어졌다.
하지만 그래도 IP 주소가 부족해서 IPv4는 현재 대부분 할당이 된 상태이다.
DHCP(Dynamic Host Configuration Protocol)
그렇다면 Host는 어떻게 IP 주소를 얻게 될까?
수작업으로 할 수도 있지만 DHCP를 이용해서 자동으로 할 수도 있다.
DHCP는 IP주소를 Network Server로부터 자동으로 얻을 수 있게 한다.
우리가 흔히 와이파이를 연결할 때 이 기능이 사용된다.
얻어온 IP는 무한히 소유를 할 수 없기 때문에 사용하는 동안 반복적으로 renew를 해주어야한다. (자동)
이렇게 되다보니 Address를 재사용이 가능하다.
DHCP 과정
1. host가 Network에 join을 하면 "DHCP discover" 라는 메세지를 보낸다. (optional)
DHCP discover 메세지는 Broadcast로 같은 subnet 안에 있는 모든 node가 이 메세지를 받게 된다.
DHCP server가 아니면 해당 메세지를 무시할 것이다.
(Host는 아직 IP Address가 없기 때문에 Broadcast를 할 수 밖에 없다.)
안에 포함되는 내용 중에 transaction ID는 DCHP server가 누구로부터 메세지를 받았는지 확인하기 위한 Field이다.
이 외에 src(0.0.0.0, 68), dest(255.255.255.255, 67) 등이 있다.
2. DHCP server는 "DHCP offer" 라는 메세지를 보낸다. (optional)
필드로는 src, dest, transaction, lifetime(사용 가능 시간) 등이 포함된다.
이 DHCP offer 메세지 안에 사용할 수 있는 IP Address가 적혀있다.
3. host는 특정한 IP Address를 요청하는 "DHCP request" 메세지를 보낸다.
기존필드 + yiaddrr에 사용하려는 IP를 적어서 메세지를 보낸다.
4. DHCP server에서 메세지를 받고 "DHCP ack" 를 보내준다.
이 시점에서 IP Address 사용이 가능하다.
또한 DHCP를 통해서 IP Address 외 추가적인 정보를 얻게 되는데,
우선 first-hop router의 IP Address가 있다.
외부로 뭔가 패킷을 보내기 위해선 router에게 패킷을 보내야하기 때문에 알아야한다.
또한 DNS Server의 이름과 IP Address, network mask 정보도 같이 알려준다.
DHCP server는 subnet part의 IP Address는 어떻게 얻게 될까?
ISP에서 관리하는 Address Block이 있는데, 이들 중 일부를 여러 기관에 나눠주는 것이다.
그러면 또 ISP는 이렇게 큰 Address Block을 어디서 얻었을까?
ICANN이라고 하는 미국의 기관에서 Address를 나눠주고 DNS를 관리도 한다.
현재는 다 나눠주고 더 이상 남은 IPv4가 없다.
NAT(Network Address Translation)
Address가 이미 다 분배가 됐다고 했지만 이 모든 Address가 다 사용되고 있지는 않다.
그러나 새로 사업을 하거나 Address Space가 필요한 사람들은 더 이상 할당을 받지 못하는데
이런 문제(IP Address 부족 문제)를 해결하기 위해서 NAT가 도입됐다.
ISP로부터 여러 개의 IP 주소를 구매할 필요없이 모든 device에 대해서 IP Address 1개만 구매하면 된다.
이 1개의 IP Address로 집에 있는 예를 들면 10개의 컴퓨터를 연결하겠다는 것이다.
또한 만약 local network의 IP Address를 바꾸고 싶다면 밖에 알릴 필요가 없이 그냥 바꾸면 된다.
ISP 자체를 한꺼번에 바꿀 수 있다.
구매해온 IP Address를 철회하고 다른 IP Address를 받아와도 local network에 있는 IP Address를 바꿀 필요가 없다.
그리고 밖에서 내부에 있는 host로 패킷 자체를 보낼 수 없기 때문에 보안이 강화되는 측면이 있다.
안 쪽에서 먼저 시작해야지만 패킷을 보낼 수 있다.
▶ 구현
내부에서 서로 패킷을 보내는 것은 처리할 필요가 없다.
내부에서 외부로 나가는 패킷만 처리하면 되는데, 나가는 datagram에 대해서 NAT IP Address와 새로운 port로 바꾼다.
바꾼 IP와 Port를 source로 해서 보낸다. 받을 때도 이 주소 값을 destination으로 받는다.
router는 이렇게 IP와 Port를 치환하는 작업을 해줘야한다.
또한 치환한 내용을 NAT translation table을 만들어서 기억을 해야한다.
그래야 외부에서 reply가 왔을 때 정상적으로 내부 host로 보낼 수 있다.
새로운 datagram이 안으로 들어올 때도 이 table을 검색해서 거기에 있는 IP와 Port에 대한 mapping을 찾아서
원래의 IP와 Port로 바꿔서 그 쪽으로 보내주게 된다.
정리하면 NAT는 IP, Port 치환 -> 기록 -> datagram이 왔을 때 원래 IP, Port로 바꿔서 보내는 작업을 해준다.
또한 같은 local network에서는 port number로 구별해서 사용한다. (최대 약 6만 5천 개의 host 커버 가능)
▶ 문제점
- router가 network layer의 정보만 살펴봐야하는데, transport layer 정보까지 살펴본다.
즉 계층형 구조를 훼손할 수 있다는 문제가 논의될 수 있다.
- IP Address 부족은 IPv6를 사용하면 해결될 문제이기 때문에 굳이 이렇게 할 필요는 없다.
- end-to-end argument를 어기게 된다. (밖에서 안으로 직접적인 통신이 안된다.)
NAT traversal 문제 -> 외부에서 접속을 하려고 할 때 어떻게 해야하는가에 대한 문제
특히 P2P application에서는 NAT 내부에 있는 host를 고려해야하기 때문에 코드가 복잡해진다.
여담으로 NAT를 잘 처리해서 성공한 프로그램으로 Skype가 있다.
IPv6
32bit Address의 space가 곧 바닥이 나기 때문에 도입이 됐다.
새로운 IP version을 만드는 김에 추가적인 작업을 해보려는 노력이 있다.
- header format을 단순화 해서 packet을 처리하는 속도를 높이자.
- QoS도 처리할 수 있도록 바꿔보자.
IPv6는 fixed-length 40byte header이고, fragmentation이 허용되지 않는다. (MTU 크기가 안맞을 때 쪼개던 작업)
맨 처음 보낼 때 부터 모든 링크를 다 통과할만큼 작은 datagram을 만든다.
IPv6는 source address가 128bit로 늘어났다. 즉 2의 128승개 만큼의 여유가 있다.
또한 priority를 도입해서 우선순위를 명시적으로 설정할 수 있다.
그리고 flow label을 표시할 수 있는 필드가 생겼다. flow는 연관 있는 datagram을 모아놓은 것을 말한다.
마지막으로 upper layer protocol이 TCP인지 UDP인지 확인가능한 next header field가 있다.
IPv6는 header length가 고정되어있기 때문에 data length의 길이만 알면 된다.
그 길이에 대한 field가 payload length이다.
IPv4와 비교해서 무엇이 달라졌는가?
checksum field가 사라졌다.
IPv6에는 TTL이 있기 때문에 매번 TTL이 바뀔 때 마다 checksum을 다시 계산해야하는데
이 과정은 시간이 많이 걸리기 때문에 없애버렸다.
어차피 transport layer에서도 checksum field가 있기 때문에 그곳에서 bit error를 확인하면 된다.
굳이 IP Address field에서 할 필요가 없다고 판단했다.
ICMPv6 (ICMP 새로운 버전) -> 큰 사이즈의 datagram이 올 경우 발생시킬 새로운 error 메세지를 추가한다.
그 이전에는 사이즈가 크면 쪼개서 보냈기 때문에 이에 대한 에러 메세지가 없었다.
IPv4에서 IPv6로 동시에 모든 router들을 upgrade 하는 것은 불가능하다.
그러면 IPv4와 IPv6가 섞여있는 환경에서 둘 사이에 패킷을 어떻게 주고 받을 수 있는지에 대한 문제가 생긴다.
이 문제에 대한 해결방법으로 tunneling을 사용한다.
IPv6의 datagram이 IPv4의 data 부분 안에 포함이 되서 가도록 한다.
Tunneling
A B C D E F
A에서 F까지 패킷이 전송되며 C와 D만 IPv4를 사용하고 나머지는 IPv6를 사용할 때
A에서 IPv6에 대한 패킷을 만들고 C까지 전송하면 C에서는 IPv6를 확인하면 drop을 시킨다.
따라서 별도의 처리가 필요하다.
그것은 IPv6를 이해할 수 있는 router들 끼리 tunnel을 만들어준다. (A->B->tunnel->E->F)
tunnel은 가상의 링크라고 생각하면 된다.
tunnel은 각자가 알아서 만들어야한다.
'Computer Network' 카테고리의 다른 글
| Network layer - introduction (0) | 2021.06.12 |
|---|