|
|
원래는 IPv6 의 헤더를 중심으로 실제 프로토콜의 특징에 대한
자세한 내용에 대한 글을 쓰고자 했으나,
그러기 위해서는 기본적인 IPv6 테스트 환경의 구축이 먼저 되어야
겠다고 판단되어서 "환경구축" 에 관한 내용을 먼저 다루게 되었다.
이 환경구축은 나중에 IPv6 소켓프로그래밍의 테스트를 위해서도
반드시 필요한 내용임으로 알아두고 넘어가도록 하자.
이글은 리눅스 Kernel 2.4.x 에서의 IPv6 환경구축과 테스트에 관한
내용을 다룰것이다.
IPv6 는 주소를 위해서 128 bit 를 사용한다. 이것을 계산해보면
(bc 와 같은 어플리케이션을 사용하도록 한다)
2^128 - 1: 340282366920938463463374607431768211455 |
그런데 위의 값은 인터넷주소로 사용하기에는 너무길고 너무 외우기
힘들다. 그래서 인터넷 주소를 16 진수로 변경한다음 4자리씩(16 bit씩)
끊어서 계산을 하게 된다.
각각의 자리를 끊을때는 IPv4의 "." 과달리 ":" 을 사용한다.
2^128 - 1: 0xffffffffffffffffffffffffffffffff 2^128 - 1: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff |
이렇게 변경해도 무려 32크기의 자릿수를 가지지만 어쨋든 10진수
표현에 비해서는 나름대로 관리하기가 좀더 쉽게 되었다.
즉 IPv6 의 인터넷주소는 다음과 같은 방식으로 표시될수 있을것이다.
3ffe:ffff:0100:f101:0210:a4ff:fee3:9566 |
또한 각각의 블럭에서 가장앞자리에 오는 '0' 은 생략해서
표시 할수도 있는데, 이렇게 함으로써 좀더 짧은 주소값을
가질수 있다 - 당연히 외우기도 좀더 쉬워진다 -
3ffe:ffff:100:f101:210:a4ff:fee3:9566 |
만약에 한블럭 전체가 0이라면 이 블럭들은 생략될수도 있다.
3ffe:ffff:100:f101:0:0:0:1 ==> 3ffe:ffff:100:f101::1 |
우리가 IPv4 주소를 사용할때 루프백 주소를 위해서 "127.0.0.1" 이
할당되어 있다는 것을 잘알고 있을것이다.
IPv6 의 경우에는 "0000:0000:0000:0000:0000:0000:0000:0001" 이
루프백주소로 할당되는데, 위의 주소표시 규칙을 사용해서
다음과 같이 간단하게 표시할수 있다.
0000:0000:0000:0000:0000:0000:0000:0001 ==> ::1 |
최근의 2.4.x 버젼대의 커널을 포함한 대부분의 리눅스 배포판은
IPv6 를 기본적으로 지원하도록 되어있다. 다만 일반적인 경우에
있어서는 IPv6 를 사용하는 경우가 거의 없음으로, IPv6 가
비활성화된 상태로 운영될 뿐이다.
현재 커널이 IPv6 가 활성화된 상태로 운용되고 있는지 확인해보고
싶다면 다음 파일들이 존재하는 지 확인해 보면된다.
[root@localhost net]# ls *6* if_inet6 ip6_flowlabel raw6 snmp6 tcp6 igmp6 ipv6_route rt6_stats sockstat6 udp6 |
만약 위의 파일들이 없다면, 현재 커널은 IPv6 가 비활성화된
상태로 운영되고 있음을 뜻한다.
이럴경우 IPv6 를 활성화 시켜줘야 하는데, 간단하게 ipv6 모듈을
적재함으로써 IPv6 기능을 활성화 시켜줄수 있다.
[root@localhost net]# modprobe ipv6 [root@localhost net]# lsmod Module Size Used by Tainted: P ipv6 140416 -1 sb 7968 0 (autoclean) sb_lib 34624 0 (autoclean) [sb] ... |
modprobe 를 이용해서 ipv6 모듈을 올리고 lsmod 를 통해서
모듈이 성공적으로 적재되었음을 확인하라. 만약
ipv6 모듈이 없어서 모듈적재에 실패했다면,
자신의 커널버젼과 동일한 커널쏘쓰를 얻어서 ipv6 모듈을
컴파일 시킨후 적재해야 할것이다. 자신의 커널 버젼은
uname(1) 를 통해서 확인할수 있다.
[root@localhost net]# uname -a Linux localhost 2.4.13-1hl #1 2001. 11. 04. (일) 04:04:58 KST i686 unknown |
커널모듈컴파일 관련된 내용은 이문서에서는 언급하지 않을것이다.
커널 컴파일 관련된 내용은 kldp,
tldp 등에서 제공하는 문서를
참고하기 바란다.
IPv6 는 근본적으로 IPv4 와 다르다. 그러므로 당연히
IPv6 를 지원할수 있는 네트워크도구들이 준비되어 있어야지만
효과적인 IPv6 지원 환경을 구축할수 있다.
이번장에서는 가장 기본적으로 사용되는 필수 네트웍도구들이
Ipv6 를 지원하는지에 대해서 알아보고 이들 도구를 이용한
네트웍 환경설정 방법과 네트웍환경 테스트등의 방법에 대해서
알아보도록 하겠다.
우선은 우리가 사용하고 있는 ifconfig 가 IPv6 를
지원하는지 확인해 보도록 하자.
[root@localhost net]# ifconfig --help 2>& 1| grep inet6 unix (UNIX Domain) inet (DARPA Internet) inet6 (IPv6) |
다행히도 IPv6 를 지원하고 있음을 알수 있다. - 사실
ifconfig 와 같은 기본적인 네트웍도구들은 대부분 IPv4와 IPv6
모두의 환경을 지원하도록 프로그래밍 되어있다. -
ipv6 모듈을 성공적으로 올렸다면 ifconfig 를 통해서 정말로
ipv6 주소가 할당되어 있는지 한번 확인을 해보도록 하자.
|
[root@localhost net]# ifconfig eth0 Link encap:Ethernet HWaddr 00:50:BF:2C:7B:B2 inet addr:210.205.210.230 Bcast:210.205.210.255 Mask:255.255.255.0 inet6 addr: fe80::250:bfff:fe2c:7bb2/10 Scope:Link UP BROADCAST NOTRAILERS RUNNING MTU:1500 Metric:1 RX packets:9337 errors:0 dropped:0 overruns:0 frame:0 TX packets:7470 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 RX bytes:9858614 (9.4 Mb) TX bytes:805387 (786.5 Kb)
lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) |
이더넷 장치와 루프백장치 부분의 "inet6 addr" 부분을 눈여겨
보기 바란다. 성공적으로 ipv6 주소가 할당되어 있음을 알수 있을
것이다. 먼저 루프백을 위해서 "::1" 이 성공적으로 할당되어
있음을 알수 있다. 그런데 한가지 이상한점이 있다.
우리는 분명히 IPv6 의 주소 지정을 위한 어떠한 작업을
한일이 없음에도
eth0 의 주소가 "fe80::250:bfff:fe2c:7bb2" 로 할당되어 있다는
점이다.
IPv6(1)-개요의 문서를 읽어보았다면, IPv6의 특징중에서
인터넷 주소의 자동할당 이라는 기능이 있다는 것을
알고 있을것이다. IPv6 는 수동으로 일일이 주소를 지정해
주어야 하는 IPv4와 달리 주변의 네트웍 환경을 파악해서
능동적으로 자신의 주소를 할당받을수 있도록 설계되어 있다.
위의 주소도 IPv6 의 이러한 기능으로 인하여 자동할당된
주소이다.
fe80::250:bfff:fe2c:7bb2 == fe80:0000:0000:0000:0250:bfff:fe2c:7bb2 |
그렇다면 ifconfig 를 이용해서
자동으로 부여되는 IPv6 대신에 수동으로 IPv6 의 주소를
할당하고 결과를 확인해 보도록 하자
[root@localhost net]# ifconfig eth0 inet6 add 3ffe:ffff:0:f101::1/64 [root@localhost net]# ifconfig eth0 | grep inet6 inet6 addr: 3ffe:ffff:0:f101::1/64 Scope:Global inet6 addr: fe80::250:bfff:fe2c:7bb2/10 Scope:Link |
성공적으로 추가되었음을 알수 있다. 필요없는 주소에 대한
삭제는 add 대신 del 을 이용하면 된다.
[root@localhost net]# ifconfig eth0 inet6 del 3ffe:ffff:0:f101::1/64 [root@localhost net]# ifconfig eth0 | grep inet6 inet6 addr: fe80::250:bfff:fe2c:7bb2/10 Scope:Link |
보통 네트워크 테스트를 하기위해서 가장 자주.. 그리고 가장
유용하게 사용하는 도구는 뭐니뭐니 해도 ping 일것이다.
이 ping 는 ICMP 를 사용하는 것으로 ICMP 가 비록 IP와
동일한 레이어에서 사용되는 프로토콜이긴 하지만, 라우팅을
위해서 IP 를 사용하게 된다. 우리가 IPv4 환경에서 사용하는
ping 은 당연히 IPv4 에 최적화된것으로 IPv6 환경에서는
사용할수 없도록 되어있다. 다행히(당연히) IPv6 환경에서
네트웍환경을 테스트 할수있는 "ping6" 라는 ICMP 체크
프로그램이 존재한다. 참고로 IPv6 에서는 ICMP 프로토콜을
사용하지 않고 IPv6에 최적화된 ICMP6 프로토콜을 사용한다.
[root@localhost net]# ping6 Usage: ping6 [-LRUdfnqrvV] [-c count] [-i interval] [-w wait] [-p pattern] [-s packetsize] [-t ttl] [-I interface address] [-T timestamp option] [-F flow label] [-P traffic class] host |
그렇다면 루프백과 eth0 장치로 직접 ping6를 이용해서 체크를
해보도록 하자.
[root@localhost net]# ping6 ::1 PING ::1(::1) from ::1 : 56 data bytes 64 bytes from ::1: icmp_seq=0 hops=64 time=65 usec 64 bytes from ::1: icmp_seq=1 hops=64 time=53 usec
[root@localhost net]# ping6 -I eth0 fe80::250:bfff:fe2c:7bb2 PING fe80::250:bfff:fe2c:7bb2(fe80::250:bfff:fe2c:7bb2) from ::1 eth0: 56 data bytes 64 bytes from fe80::250:bfff:fe2c:7bb2: icmp_seq=0 hops=64 time=65 usec 64 bytes from fe80::250:bfff:fe2c:7bb2: icmp_seq=1 hops=64 time=60 usec |
route 는 IP 라우팅 테이블을 편집하기 위해서 사용하는
네트워크관리 툴이며, 다른 기본적인 네트워크관련 툴들과
마찬가지로 IPv4 와 IPv6 모두를 지원한다. 기본적으로
아무런 옵션이 없이 route 명령을 사용하게 될경우
IPv4 를 기준으로 라우팅 테이블 내용을 보여준다.
[root@localhost root]# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 210.205.210.0 * 255.255.255.0 U 0 0 0 eth0 127.0.0.0 * 255.0.0.0 U 0 0 0 lo default 210.205.210.1 0.0.0.0 UG 0 0 0 eth0 |
위의 라우팅 테이블은 두루넷의 DHCP 서비스에 의해서
자동으로 IP가 할당된 Linux 시스템에서의 라우팅 테이블
결과이다. 루프백 주소인 127.0.0.0 과 LAN 주소인 210.205.210.0
을 제외한 모든 패킷은 디폴트 게이트웨이인 210.205.210.1 로
보내지도록 라우팅 설정되어 있음을 알수 있다.
그럼 이제 IPv6 라우팅 테이블 설정내용을 알아보도록 하자.
[root@localhost root]# route -A inet6 Kernel IPv6 routing table Destination Next Hop Flags Metric Ref Use Iface ::1/128 :: U 0 0 0 lo fe80::250:bfff:fe2c:7bb2/128 :: U 0 0 0 lo fe80::/10 :: UA 256 0 0 eth0 ff00::/8 :: UA 256 0 0 eth0 ::/0 :: UDA 256 0 0 eth0 |
::1 은 루프백주소라는걸 이미 알고 있을것이다.
fe80::/10은 link-local 을 위한 라우트 인터페이스이며,
ff00::/8 은 멀티캐스트(multicast) 를 위한 라우트 인터페이스
이다. 마지막 ::/0 은 자동으로 설정된 디폴트 라우트 주소값이다.
만약에 새로운 게이트웨이를 추가하고자 한다면 다음과 같이
하면 될것이다.
[root@localhost root]# route -A inet6 add 2000::/3 gw 3ffe:ffff:0:f101::1 [root@localhost root]# route -A inet6 Kernel IPv6 routing table Destination Next Hop Flags Metric Ref Use Iface ::1/128 :: U 0 0 0 lo 2000::/3 3ffe:ffff:0:f101::1 UG 1 1 0 eth0 .... |
위의 라우팅 주소들에 대한 자세한 이해는 IPv6 에 대한
좀더 깊은 지식을 필요로 한다. - IPv6 하에서의
서브넷팅과 cast(Anycast, multicast, unicast) 와 같은 -
여기에서는 이런식으로 사용이 가능하다는것만을
알아두는 것으로 하고, 자세한 내용은 다음 문서에서 다루도록
하겠다.
tcpdump 는 네트워크 트래픽을 덤프하기 위한 어플리케이션으로
네트웍 문제검색과 해결, 테스트를 위한 매우 중요한 도구로 libpcap의 응용으로 유명하다.
또한 패킷수준에서 데이타를 확인 할수 있음으로, 학습용으로도
자주 사용된다. tcpdump 의 경우 기본적으로 ipv6 패킷을 검색할수
있도록 되어있다.
그럼 ping6 를 통해서 ICMP 패킷을 발생시키고, tcpdump 를 통해서
이 패킷을 덤프받아보도록 하겠다. 우선 제대로된 테스트를
위해서 2대의 linux 시스템을 준비해서 각각 ipv6 운용환경을
활성화 시켰다.
+--------------------------+ ICMP6 +--------------------------+ | LB 1 | -------> | LB 1 | +--------------------------+ +--------------------------+ | fe80::2e0:29ff:fe5d:5c89 | <------- | fe80::2d0:b7ff:fe89:2e17 | +--------------------------+ +--------------------------+ |
테스트는 LB1 에서 LB2 로 ping6 를 이용해서
ICMP6 요청을 보내고, 이 과정을 tcpdump 로 확인하는
방식으로 이루어진다.
[root@localhost /root]# ping6 -I eth0 fe80::2d0:b7ff:fe89:2e17 PING fe80::2d0:b7ff:fe89:2e17(fe80::2d0:b7ff:fe89:2e17) from fe80::2e0:29ff:fe5d:5c89 eth0: 56 data bytes Warning: time of day goes back, taking countermeasures. 64 bytes from fe80::2d0:b7ff:fe89:2e17: icmp_seq=0 hops=64 time=850 usec 64 bytes from fe80::2d0:b7ff:fe89:2e17: icmp_seq=1 hops=64 time=503 usec .... |
[root@localhost /home]# tcpdump ipv6 Kernel filter, protocol ALL, TURBO mode (575 frames), datagram packet socket tcpdump: listening on all devices 13:17:07.769057 eth0 > 0:0:0:0:0:0 0:e0:29:5d:5c:89 ipv6 86: 13:17:07.769057 eth0 < 0:d0:b7:89:2e:17 0:0:0:0:0:1 ipv6 86: ... |
이상 간단하게 리눅스 OS 에서의 IPv6 환경을 구축하는 방법과
이 환경을 제어하고 테스트하기 위한 몇가지 IPv6 기반 네트웍
어플리케이션을 사용하는 방법에 대해서 알아보았다.
이 내용들은 실제 IPv6 의 프로토콜 레벨에서의 학습과
프로그래밍을 위한 Socket Layer 에서의 프로그래밍 테스트를 위한
기본환경을 구축하는데에 이용할수 있을것이다.
:::

TCP/IP 소개
지금의 인터넷이 있게한 프로토콜이다. 이들에 대한 자세한 내용은 TCP/IP 미니사이트 문서를 읽어보기 바란다.
이 문서는 유닉스 환경에서 TCP/IP를 관리하기 위해서 중요하게 사용되는 툴들을 설명한다.
netstat
네트워크 연결상태를 알려준다. 이 프로그램을 통해서 알 수 있는 정보는 다음과 같다.
- 네트워크 연결 상태
- 유닉스 도메인 소켓 연결 상태
- 네트워크연결에 사용된 프로세스 - 리눅스 에서만 가능 -
netstat를 통해서 얻을 수 있는 가장 중요한 정보는 1번이 될 것이다. netstat를 사용하면 현재 네트워크에 연결이 되어있는 상태뿐만 아니라, TIME_WAIT와 SYN_RECV 상태까지도 얻어올 수 있다.
TIME_WAIT를 이해하기 위해서는 소켓의
종료 상태에 대해서 알고 있어야 한다. TIME_WAIT 상태는 소켓이 연결을 종료하는 과정에서 거치는 과정인데 마지막 ACK
신호를 보내지 못하는 경우가 있다. 이 경우 ACK를 재전송하기 위해서 기다리는데, 이를 TIME_WAIT 상태라고 한다.
이것은 2MSL(maximum segment life time)이라고 불리운다. 서버에서 데이터를 모두 다 보내면 연결을 닫기 위해서 close()
함수를 호출하게 된다. 그리고 서버는 ACK신호를 보내고 TIME_WAIT 상태에 들어간다. 클라이언트로 부터 ACK에 대한
응답이 있어야지만 연결이 완전히 종료가 된다. 만약 상대편 클라이언트가 ACK에 대한 응답을 보내지 않고 종료되어 버렸다면,
서버는 2MSL 시간만큼을 기다리게 된다.
TIME_WAIT는 하는 일은 없지만, 클라이언트로 부터의 종료메시지를 기다리는 상태가 되므로 다른 연결을 받아들이지 못하게
된다. 이는 TIME_WAIT 상태가 지나치게 많아지게 될 경우, 그만큼의 연결을 유지해야 하므로 서버프로그램에 문제가 생길 수
있다.
만약 다수의 SYN_RECV 가 있다면, DOS
공격을 의심할 수 있을 것이다. SYN_RECV는 클라이언트가 마지막 3번째 패킷을 서버에게 보내지 않음으로써, 불완전한 연결이
유지되게 된다. 반쪽자리 연결이라고 볼 수 있는데, 이러한 연결을 다수 생성해서 서비스가 거부되도록 공격하는 경우가 종종
발생한다.
# netstat -na : grep 80 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN tcp 0 0 218.234.19.87:80 122.152.181.156:11962 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:47119 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:3429 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:8208 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:59406 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.155:40277 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.155:35498 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:29028 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:55652 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:42340 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:16741 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.155:26965 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:33807 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:50873 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:38586 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:25274 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.155:48810 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.155:1366 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.155:9899 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:64185 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.155:18432 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.155:31744 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.156:20495 SYN_RECV tcp 0 0 218.234.19.87:80 122.152.181.155:57343 SYN_RECV tcp 567 0 218.234.19.87:36126 121.185.96.43:80 CLOSE_WAIT tcp 0 0 218.234.19.87:22 222.119.23.60:2801 ESTABLISHED tcp 0 0 218.234.19.87:37489 121.185.96.48:80 ESTABLISHED tcp 0 0 218.234.19.87:80 222.231.42.193:34267 TIME_WAIT tcp 0 0 218.234.19.87:80 66.249.73.50:63782 ESTABLISHED tcp 0 0 218.234.19.87:80 210.116.196.225:39776 FIN_WAIT2 tcp 0 0 218.234.19.87:80 74.6.27.107:44671 TIME_WAIT tcp 0 18981 218.234.19.87:80 141.85.90.195:2982 FIN_WAIT1
이 서버는 SYN_RECV 상태의 연결이 지나치게 많다. DOS공격이 의심되는 상황이다. :::

sub-networking 을 이해하려면 우선 IP 번호가 어떻게 만들어지고
관리되어지는지 알고 있어야 한다.
이러한 IP 번호에 대해서는 TCP/IP 개요(2) 에서 간단하게 알아본적이
있는데 이번장에서는 IP 번호에 대해 좀더 자세한 내용을 알아보도록
할것이다.
이 문서는 IPv4 를 기준으로 설명할것이다.
간혹 혼동할수도 있는데 있는데 IP 번호는 hosts 에 부여되는 것이
아닌, Interfaces(랜카드 혹은 이더넷 카드로 불리워지는)에 부여
되는 것이다. 모든 랜카드는 랜카드 고유의 번호(Ethernet Address) 를 가지고
있으며, 이 이더넷 번호에 IP 번호를 매핑시키는 방식으로 각각의 이더넷에
IP 번호를 부여하게 된다.
이렇게 호스트 기반이 아닌 Interfaces 기반으로 IP 가 부여됨으로,
우리는 하나의 호스트라 할지라고 Interfaces 의 수만충분하다면 여러개의 IP를
가질수 있도록 할수있다 - 물론 하나의 Interfaces 에 여러개의 IP 번호를
부여해줄수도 있겠지만, 이는 일반적인 방법이라고는 할수 없다 -.
보통 우리가 사용하는 호스트(PC)의 경우는 단지 하나의 인터페이스 만으로도
네트웍과 연결해서 대부분의 작업을 하는데 무리가 없겠지만,
라우터 같은경우에는 인접하고 있는 많은 라우터들중 원하는 라우터와 선별적으로
통신을 해야 함으로 당연히 여러개의 인터페이스를 가져야만하고,
각각의 인터페이스에 하나의 IP를 할당해서 사용하게 될것이다.
+------------+ | ROUTER A | | | | eth0<--|---------------> ROUTER B | eth1<--|---------------> ROUTER C | eth2<--|---------------> ROUTER D +------------+
|
아직까지 가장널리 사용되고 있는 IPv4 버젼의 경우 IP 어드레스를 위해서
32bit 주소체계를 나누며, 이것을 다시 8bit 씩 4개 자리로 나누어서
관리한다. 그리고 각각의 자리는 "."을 이용해서 구분한다. 그래서
192.168.182.145 와 같이 표시한다.
그러므로 이론상 0.0.0.0 에서부터 255.255.255.255 까지의
주소할당이 가능할것이다. 대략적으로 계산을 해보면 4294967296 개 만큼의
인터페이스에 IP 주소를 할당해 줄수 있다.
언뜻 생각하기에 40억이란 숫자는 터무니 없이 큰숫자로 보일수도 있으며,
이정도의 숫자라면 모든 PC의 Interface 에 IP 번호를 할당하는데, 문제가 없을
것으로 생각될수도 있지만, 안타깝게도 벌써 부터 인터페이스에 부여할 IP 번호
부족사태가 벌어지고 있다. 이유는 단지 PC 만이 인터넷에 연결되는게 아니기
때문이다. 조만간 냉장고, 세탁기, PDA, 공장자동화기기, 장난감 등 OS를
가질수 있는 모든 소형기기에까지 분명히 인터넷에 연결될것이기 때문이다.
어쨋든간에 우리는 IP 번호를 이용해서 각 인터페이스를 인터넷에서 유일한 것으로
만들어줄수 있다(사실 IP번호가 부족하고 그나마 각나라에 균등하게 분배된것이
아님으로 IP 번호 부족해결을 위한 다른 방법들 - 사설망 구성과 같은 - 을 사용
하지만 이 문제는 논외로 하겠다).
또한 IP 번호는 관리상의 이유로 클래스(Class)로 나누어서 관리되어지고 있다.
다음장에서 이 클래스에 대해서 알아보도록 하겠다.
IP 는 크게 3개의 클래스로 나뉜다.
Class 로 IP를 다시 나누는 이유는 몇번말했듯이 관리상의 목적이 가장크다고
할수 있다. 보통의 국가에서도 중앙정부에서 모든 행정을 관리하게 되면
너무 크고 복잡해짐으로 이걸 여러개의 부서로 나누고 다시 부서는 여러개의
과로 나누어서 관리하는데, 마찬가지로 IP 어드래스 역시
하나의 대규모의 IP 어드레스를 가지고 관리하는것보다는 여러개의 적은 개수의
대규모/중간규모의 네트워크로 나누어서 관리하는게 훨씬 편하기 때문이다.
이렇게 해서 IP 어드레스는 A, B, C 클래스로 나누어서 관리하게 된다.
나누는 방법은 간단하다. 위에서 IP 어드래스는 8bit 씩 4개의 영역으로 나뉘어서
계산한다고 했었는데, 이 영역은 다시 네트웍영역과 호스트 영역으로 나뉜다.
네트웍영역은 Internic 등의 기관에서 할당해준 고정된 IP 영역이며,
호스트 영역은 자신이 관리 가능한 IP 영역이 된다.
또한 최상위(네트웍영역)의 3bit 를 이용해서 클래스를 구분한다.
즉 1번째 bit 가 0이라면 A 클래스 2번째 bit 가 0 이라면 B 클래스
3번째 비트가 0 이라면 C 클래스 이런식으로 나누는 것이다.
01234567012345670123456701234567
+- NET 영역 +- HOST 영역 | | |======|-----------------------| +------+-------+-------+-------+ |0 | | | | A Class +------+-------+-------+-------+
|==============|---------------| +------+-------+-------+-------+ |10 | | | | B Class +------+-------+-------+-------+
|======================|-------| +------+-------+-------+-------+ |110 | | | | C Class +------+-------+-------+-------+ |
위의 그림을 가지고 계산 하면 각각의 클래스가 관리할수 있는 IP 영역이
대강 계산이 될것이다.
A 클래스에 포함된 IP 를 할당받았다면 나머지 24bit 가 호스트영역이 되고
호스트영역은 자신이 관리 가능한 IP 라고 했음으로 결국 2^24 개 만큼의
IP 를 관리할수 있게 된다.
먼저 A 클래스를 보면 최상위 1개 비트가 이미 예약이 되어 있음으로
실제 IP를 만드는데에는 7개 비트를 사용가능할것이다. 고로 2^7 하면
128 이된다. 그러므로 관리 가능한 IP 범위는 0 - 127 이 될것이다.
그러나 0은 사용할수가 없으며 마찬가지로 127 은 루프백 어드레스로
사용하기 위해서 예약되어 있음으로 사용할수 없다. 그러므로
A 클래스의 IP 영역은 1 - 126 이 될것이다. 또한 A 클래스에 포함된
각각의 IP의 경우 관리할수 있는 호스트의 범위는 2^24 이 될것이다.
이것의 크기는 약 17000000 정도의 상당히 큰크기이므로, 국가등에 부여한다.
B 클래스를 보면 최상위 2개 비트가 예약되어 있음으로 관리 가능한
아이피 범위는 2^6(64) 가 될것이다. 그러므로 A 클래스가 사용하고 있는
1 - 126 이후로 사용이 가능함으로 128 에서 부터 191(128 + 64) 이 될것이다.
(흠... 외 128+64 는 192 인데 191 이 되었는지는 설명할 필요가 없겠죠?)
그리고 관리 가능한 호스트는 2^16 개가 될것이다. 지역정부 혹은 꽤 큰규모의
대학교등에 할당해준다.
나머지 192 - 254 까지는 C 클래스가 되며 관리가능한 아이피의 범위는
2^8 개가 될것이다.
표 1. 클래스의 IP 할당범위 | 네트웍 클래스 | 관리영역 | 관리 IP 갯수 | | A | 1-126 | 2^32 | | B | 128-191 | 2^16 | | C | 192-254 | 2^8 |
우리는 보통 여러가지 이유로 사설망등을 구성한다. 이러한 사설망에 포함된
컴퓨터들역시 IP 를 가지고 있어야만 서로 통신이 가능할것이다.
이론적으로 봤을때는 사설망에 포함된 컴퓨터들이라면 어차피 내부에서만
서로를 구분해줄수 있으면 됨으로 어떠한 아이피라도 사용이 가능할것이다.
그러나 이렇게 되면 외부 Internet 에 연결된 컴퓨터들과의 IP 가 서로
겹치는 문제가 발생할것이다. 이러한 문제는 발생하면 안될것이다.
이러한 문제를 해결하기 위해서 각 클래스 별로 사설망을 위한 IP 를 별도로
준비해두고 있다. 이들 주소는 오직 사설망구성을 위해서만 사용할수 있으며,
Internet 에 연결된 컴퓨터(인터페이스)는 이들 IP 주소 영역내에 있는
IP 번호는 가질수가 없다.
표 2. 사설망용으로 예약된 IP | IP 클래스 | 예약된 주소 | | A | 10.0.0.0 | | B | 172.16.0.0 | | C | 192.168.0.0 |
1
서브넷이 사전적 의미는 특정 지역에서 관리되는 IP 영역을 몇개의 영역으로
나누어서 관리하는걸 말한다.
우리는 이미 앞장에서 IP 영역자체를 관리하기 위한 클래스에 대해서
알아보았다. 그런데 왜 다시 여기에 subnetwork 를 제공하게 되는걸까.
이러한 경우를 한번 생각해 보도록 하자. C 클래스 IP영역을 할당받아서
사용하고 있는데, 이중 하나의 호스트가 지나치게 많은 트래픽을 차지해서
다른 같은 영역의 호스트까지 이에 대한 영향을 심각하게 받을 것이다.
이러한 사이트를 관리하는건 상당히 고달플 것이다. 이럴경우 동일한 C클래스에
있는 호스트들이라 할지라도 관리상의 목적으로 서로 나누어서 관리하게
되면 (트래픽을 유발하는것과 그렇지 않은것을 나누는 식으로) 훨씬
관리가 편할것이다. 어쨋든 커다란 하나의 호스트영역을 관리하는 것 보다는
목적에 따라서 나누어서 관리하는게 여러모로 편할것이다.
이밖에도 몇가지 아래와 같은 이유들 때문에 호스트영역을 몇개의 영역으로
나누는 subnetworking 을 한다.
LAN 으로 구성할때 때때로 호스트들이 꽤 넓은 범위에 흩어져
있을수 있다. 그런데 이때 LAN으로 확장할수 있는 길이에는 한계가
있음으로 지역별로 네트웍을 다르게 구성해야 한다. 이럴때
subnetworking 으로 가까운 지역의 호스트끼러 서로 묶어서 관리할수
있다.
이러한 구성은 ISP 업체에서는 각각의 호스트가
지역적으로 넓게 퍼져 있을수 있음으로 매우 일반적으로
사용한다.
네트웍 트래픽이 너무 높아서 통신속도의 저하를 가져올때,
여러개의 서브네트웍으로 분리함으로써 통신속도를 높일수 있다.
보안이 필요한 호스트와 그렇지 않은 호스트 그룹으로 나누고자
할때, 예를 들어 인터넷 서비스를 해야하는 호스트들은 외부로
노출되어도 되지만 R&D 같은경우에는 중요한 기술적인 내용들을
보호해야함으로 별도로 관리되어야 할것이다.
다음과 같은 경우를 가정해 보자
210.211.231.001 .002 .003 +--------+ +--------+ +--------+ | Host 1 | | Host 2 | | Host 3 | Internet Service +--------+ +--------+ +--------+ ----------------------------------- | | +--------+ Internet ----->| Router | 210.211.231.000 +--------+ | | ----------------------------------- +--------+ +--------+ +--------+ | Host 1 | | Host 2 | | Host 3 | R&D +--------+ +--------+ +--------+ 210.211.231.129 .130 .131
|
위의 IP 번호를 보면 위의 구성도는 C 클래스에 기초하고 있음을 알수 있다.
Router 은 인터넷으로 연결되어 있으며 모든 패킷을 받아들인다.
라우터는 3개의 인터페이스를 가지고 있다. 하나는 Internet 에 연결된것이며,
나머지 2개는 자신이 관리하는 subnet 로 연결된 인터페이스이다.
위의 그림을 보면 하나의 C 클래스 어드레스를 2개로 분리한걸
볼수있다. 이유는 Internet Service 를 위한 호스트들과 R&D 를 위한 호스트를
서로 분리시키기 위해서이다. 이들이 하나의 네트웍상에 존재한다면,
보안문제, 트래픽문제등이 생길수 있을것이기 때문이다.
그런데 궁금한게 있다. Router 는 그렇다면 어떻게 목적지 IP 를 검사하여서
이걸 원하는 인터페이스로 보낼수 있을까 ? 답은 네트마스트(net mask) 와
서브넷마스트(subnet mask)에 있다.
net mask 는 인터넷 상에서 서브넷이 필요로 하지 않는 경우 사용되는
마스크로 어떤 비트들이 NET 영역이며, 어떤 부분이 HOST 영역인지를
계산(해석)하기 위해서 사용된다.
그러므로 각각의 클래스에 대한 넷마스크는 다음과 같이 정의될것이다.
표 3. Net Mask | 클래스 | 넷마스트 | 비트 | | A | 255.0.0.0 | 11111111.00000000.00000000.00000000 | | B | 255.255.0.0 | 11111111.11111111.00000000.00000000 | | C | 255.255.255.0 | 11111111.11111111.11111111.00000000 |
서브넷 마스크는 단지 위의 넷 마스크에서 8bit 더 확장한경우로써,
어떠한 서브넷으로 전달되어야하는지를 해석하기 위한 목적으로 사용된다.
예를들어 B 클래스 IP에 대한 서브넷 마스크는
(11111111.11111111.11111111.00000000) 이 될것이다.
서브넷 마스크는 가장마지막의 8bit 의 비트들을 조작함으로써 만들어주게
된다.
위에서 발했듯이 서브넷의 구성은 서브넷마스크의 비트를 어떻게
조작해주느냐로 결정할수 있다.
즉 11111111.11111111.11111111.10000000(255.255.128) 로
서브넷 마스크 비트를 확장시켰다면 2^1(2) 개의 서브네트웍을 구성할수
있을것이다.
예를 들어서 C 클래스 영역을 가지며 Network address가 203.211.5.0 일때
subnetmask 를 255.255.255.128 로 했다면, 각각 사용가능한 host address 의
범위가 203.211.5.1 ~ 203.211.5.128, 203.211.5.129 ~ 203.211.5.254 인
2개의 서브네트웍을 구성할수 있을것이다.
2 개의 서브네트웍으로 구성되었다고 가정을 할때 이것을 라우팅하기 위해서
라우팅 테이블은 대충 다음과 같이 구성되어야 할것이다.
203.211.5.1/127 255.255.255.0 eth0 203.211.5.128/254 255.255.255.128 eth1 |
정말로 IP 가 자기가 가야할 서브넷을 향해서 올바로 해석되는지 알아보도록
하겠다. 만약 203.211.5.121 이 도착했다면 이것은 다음과 같이 계산
될것이다.
11001011.11010011.00000101.01111001 IP (203.211.5.121) 11111111.11111111.11111111.00000000 subnet mask 255.255.255.254 ----------------------------------------------------------------- 11001011.11010011.00000101.01111001 |
만약 203.211.5.138 이라면
11001011.11010011.00000101.10001010 IP (203.211.5.138) 11111111.11111111.11111111.10000000 subnet mask 255.255.255.254 ----------------------------------------------------------------- 11001011.11010011.00000101.10001010 |
제대로 해석되고 있는것을 볼수 있을것이다.
4개의 서브네트웍으로 구성하고 싶다면 11111111.11111111.11111111.11000000
으로 해주면 될것이다.
4개의 서브네트웍으로 구성하기로 했다면 범위는 다음과 같을것이다.
203.211.5.1/63 255.255.255.0 eth0 203.211.5.64/127 255.255.255.64 eth1 203.211.5.128/191 255.255.255.128 eth2 203.211.5.192/254 255.255.255.192 eth3 |
다음은 203.211.5.121 이 어떻게 계산될수 있는지를
보여준다.
11001011.11010011.00000101.01111001 IP (203.211.5.121) 11111111.11111111.11111111.01000000 subnet mask 255.255.255.64 ----------------------------------------------------------------- 11001011.11010011.00000101.01111001 |
다음은 203.211.5.145 가 계산되는 방법을 보여준다.
11001011.11010011.00000101.10010001 IP (203.211.5.145) 11111111.11111111.11111111.10000000 subnet mask 255.255.255.128 ----------------------------------------------------------------- 11001011.11010011.00000101.10010001 |
모든 경우에 대해서 제대로 계산되고 있음을 알수 있다.
보통 서브넷을 나눌때는 4의 배수로 가지고 가는게 일반적이다.
아무래도 계산하기가 좀더 수월하기 때문이다.
보면 알겟지만 서브넷계산하는게 꽤 혼동스럽기 때문이다. (컴퓨터입장에서
봤을때는 별 문제가 없겠지만) 이 문서는 수정될 수 있습니다. 최신문서는 Joinc Wiki를 확인하세요.
:::

TCP 자세히 보기
| 고친 과정 |
| 고침 0.8 |
2004년 5월 12일 |
|
| Contro Bits 내용보강, sequence number 내용 보강, 이미지 수정 |
1. 소개
우리는 IP 자세히보기 를 통해서 IP 프로토콜을 헤더차원에서 살펴보았다. 이번 문서에서는 TCP 프로토콜을 헤더차원에서 살펴보도록 할것이다.
2. TCP (Transmission Control Protocol)
2.1. TCP 란
TCP 개념에 대해선 이미 몇개의 문서를 통해서 다루어지긴 했지만 확인차원에서 다시한번 다루어 보도록 하겠다.
TCP 는 기본적으로 IP 와 함께 사용되며, 그런이유로 TCP/IP 라고 불리워진다. IP는 호스트 사이의 데이타 교환을 목적으로 만들어진 프로토콜인데, 기본적으로 IP는 오로지 데이타 교환을 위한 임무만을 수행한다. 즉 네트웍상에서 발생할수 있는 데이타 누락, 패킷의 순서 뒤바뀜 등의 데이타 교정과 관련된 기능을 가지고 있지를 않다.
그래서 만들어 진개 TCP 프로토콜이다. IP 프로토콜의 상위 레벨 프로토콜로써, IP가 제공하지 못하는 기능즉, 데이타 누락검사 패킷순서 뒤바뀜 등 데이타 교정과 관련된 기능을 제공한다.
+---+----+-------------+ |IPH|TCPH|Internet Data| +---+----+-------------+
IPH : IP Header TCPH : TCP Header Internet Data : 교환하고자하는 데이타 | 이러한 TCP 의 기능상 특징으로 인하여 흔히 TCP 프로토콜을 "신뢰성있는 프로토콜" 이라고한다. TCP 는 이러한 신뢰성 있는 데이타 전송을 위한 방법으로 서버와 클라이언트간에 연결을 설정한다. 이러한 연결을 만드는 특성으로 TCP 프로토콜은 "연결지향 프로토콜" 이라고 말한다.
TCP 는 이러한 연결을 설정시 위에서의 그림에서와 같은 "전 이중 통신 선로"를 개설한다. 하나는 읽기 전용의 선로이며, 다른 하나는 쓰기 전용의 선로로써, 각각의 전용선로를 이용함으로 써 읽기와 쓰기를 동시에 할수 있게 된다. 이것은 Unix 에서 IPC 목적으로 pipe 를 생성할때, 읽기와 쓰기전용의 파이프를 동시에 생성하는것과 동일한 원리이다.
TCP 헤더에는 위의 TCP 의 특성을 충족시켜주기 위한 여러가지 기능을 가지는 필드들로 구성되어 있다. 우리는 다음장에서 TCP 헤더의 이러한 필드들을 분석함으로써, 어떻게 TCP 가 서버 클라이언트간 연결을 만들고, 신뢰성 있도록 데이타를 전달하는지 알아보게 될것이다.
2.2. TCP 헤더 구조
TCP 는 다음과 같은 헤더 구조를 가진다. 두 호스트 사이에 전송되는 TCP 데이타 단위를 세그먼트라고 부른다. 그러므로 TCP 세그먼트는 TCP 헤더 + DATA 가 될것이다. 다음은 TCP 세그먼트의 구조이다.
2.2.1. SOURCE PORT/DESTINATION PORT
source port 는 메시지를 보내는 측에서 통신을 위해 사용하는 port 번호이며, destination port 는 목적지, 즉 메시지를 받는측의 통신 port 번호이다.
여기에 있는 port 번호와 더불어 IP 헤더에 있는 source/destination address 를 이용하면 유일하게 식별되는 통신연결을 만들수 있게 된다.
아마도 IP 의 출발지/목적지 주소와 TCP 헤더의 출발지/목적지 포트 번호가 어플리케이션간 통신을 위한 가장 핵심이라고 할수 있을것이다. 다른 정보들은 통신을 원할하도록 도와주기 위해서 부가적으로 존재하는 것이라고 볼수 있다.
이들 포트번호의 크기는 16bit 크기를 가진다. 그러므로 대략 65536 만큼의 포트를 가질수 있을것이다.
2.2.2. SEQUENCE NUMBER
TCP 세그먼트안의 데이터의 송신 바이트 흐름의 위치를 가리킨다. 다른 호스트로 전달되는 패킷은 여러개의 서로 다른 경로를 거치면서 전달되다 보니 패킷의 순서가 뒤바뀔 수 있다. 이를 수신측에서는 재 조립해야할 필요가 있는데, Sequence Number 를 이용해서 조립하게 된다.
2.2.3. ACK
acknowledgment number 라고 말한다. 다음에 받을것으로 예상되는 데이타 옥텟의 순서번호를 나타낸다.
2.2.4. HLEN
TCP 세그먼트의 길이를 정의한다.
2.2.5. RESERVED
현재는 사용하지 않지만, 나중을 위해서 예약된 필드이다.
2.2.6. (Control)CODE BITS
세그먼트의 용도와 내용을 결정하기 위해서 사용된다. URG, ACK, PSH, RST, SYN, FIN 6개의 비트가 정의되어 있다. TCP는 이러한 비트를 이용해서 패킷의 내용이 어떤 목적으로 전달될 것인지를 설정할 수 있다. 이들 비트중 SYN, ACK, RST를 주목할 필요가 있다.
SYN은 TCP연결을 만들 때, 양 호스간 sequence numbers의 동기화를 이루기 위한 목적으로 사용된다. ACK는 원격 호스트의 sequence number에 대한 응답을 위한 목적으로 사용된다. 즉 데이터를 잘 받았다는 걸 알려주기 위한 목적으로 사용되는데, 원격호스트의 sequence number의 번호에 +1을 해줘서 다시 전달하는 방법을 이용한다. SYN 비트는 특히 세번 악수 기법(three-way handshake)를 위해서 사용된다.
RST 비트가 설정되어 있을 경우 받은 호스트는 즉시 연결을 끊어 버리고 FIN 비트가 설정되어 있을 경우 여러가지 테스트를 거쳐서 연결을 끊게 된다. 일반적인 정상종료를 원한다면 FIN 비트를 설정해서 사용하게 된다. 이들 비트에 대한 자세한 내용은 2.3.3절를 참고하기 바란다.
2.2.7. OPTION & PADDING
옵션은 말그대로 옵션이다. TCP 헤더의 정보를 좀더 확장시키고자 할때 사용한다. PADDING 은 32bit 크기를 채우기 위해서 사용된다.
2.2.8. CHECKSUM
TCP 세그먼트 데이타는 중간에 훼손될수 있으며, 변조될수도 있다. 그러므로 이를 체크할수 있는 장치가 필요하다. CHECKSUM 을 만드는 방법(알고리즘)은 기회가 되면 별도로 설명하도록 하겠다.
2.3. 실제 통신상에서 TCP 패킷의 내용을 살펴보자
위에서 각 TCP 필드에 대한 설명을 해보았지만, 솔직히 위의 정보만을 가지고는 뭐가 뭔지 도대체 알수가 없을 것이다. 그래서 이번에는 실제 TCP/IP 통신이 어떻게 이루어지는지에 대해서 알아보고 이러한 통신이 이루어지도록 어떻게 TCP/IP 패킷(세그먼트)가 전송되어지는지 알아보도록 하겠다.
2.3.1. 테스트 프로그램 준비
셈플로 알아보는 소켓프로그램 에서 제작한 적이 있는 우편번호 서버/클라이언트 프로그램을 이용해서 테스트 하도록 할것이다. 서버 프로그램의 이름은 zipcode 이며 클라이언트 프로그램의 이름은 zipcode_cl 이다.
이와 더불어 tcp/ip 패킷분석을 위해서 tcpdump 를 사용할것이니 준비해놓기 바란다. (아마도 기본 설치되어 있겠지만)
2.3.2. 테스트 방법
테스트를 가장 효과적으로 수행하기 위해서는 서버와 클라이언트가 별도의 네트웍에 묶여 있는게 가장 좋겠지만, 여의치 않을경우 하나의 서버에 서버와 클라이언트를 두고 테스트를 해도 관계 없다.
여기에서의 테스트는 서버와 클라이언트가 별도의 네트웍환경에 묶여있는 것을 기준하여 이루어질것이다.
Server 은 Port 번호 4445 로 연결하도록 할것이다.
2.3.3. 서버와 클라이언트간의 연결
TCP 는 기본적으로 연결지향의 프로토콜이라고 했다. 이말은 처음 통신을 하기 전에 서로를 연결하는 전용의 통신선로를 개설한다라는 말이 된다. 이는 우리가 전화를 할때
홍길동 : "여보세요 아무개 씨 맞습니까 ?" 아무개 : "내 아무개 입니다." 홍길동 : "아그러세요 저는 홍길동 입니다" ... .... 이런 저런 대화들 .... ... | 실제 대화를 하기 위해서 서로간에 확인절차를 거치는 것과 마찬가지다.
TCP 도 통신선로를 만들기 위해서 처음에 이러한 확인 절차를 거친다. 우리가 보통 전화상에서 서로의 확인 작업을 위해서 3번 통화가 이루어지는 것처럼 TCP 상에서도 3번의 데이타 전송이 일어난다.
client server ① Send SYN seq=x ---------------------------> Receive SYN segment | ② | Recevie SYN+ACK segment <-------------------------- Send SYN seq=y, ACK x+1 | | ③ send ACK y+1 --------------------------> Receive ACK segment | 그런 이유로 흔히 위의 과정을 "3 way Hand Shaking" 또는 "3번 악수기법" 이라고 한다. 최초에 클라이언트가 seq 번호 x 를 보내면 server 에서는 이 x 에 1 을 더해서 ACK 로 보낸다. 이때 자신의 seq 번호 y 도 포함해서 보낸다. 그러면 클라이언트에서는 server 부터 넘어온 패킷의 ACK가 자신의 seq 번호와 일치하는지 확인하고, 확인이 되면 server 의 seq 번호인 y 에 1을 더해서 ACK로 보낸다. server 에서는 client 가 보낸 ACK 의 번호와 자신의 seq 번호가 일치하는지 확인해서 일치하면 연결이 제대로 되었다는것을 인증하고 데이타 통신에 들어가게 된다.
그럼 tcpdump 를 이용해서 어떻게 위의 3번 악수기법 이 이루어지는 지 확인해 보도록 하겠다. 우선 tcpdump 를 다음과 같은 옵션으로 띄우도록 한다.
[root@localhost test]# tcpdump -x tcp 4445 Kernel filter, protocol ALL, TURBO mode (575 frames), datagram packet socket tcpdump: listening on all devices ... | 그다음에 zipcode_cl 을 이용해서 서버에 접근해보자 그러면 아래와 같은 패킷 dump 화면이 뜰것이다. ----- 1, ----- 2 는 구분하기 쉽도록 필자가 추가시킨 문자이다.
13:42:47.952336 eth0 > localhost.2310 > 211.234.96.141.4445: S 2850317194:2850317194(0) win 5840 <mss 1460,sackOK,timestamp 10265185 0,nop,wscale 0> (DF) 4500 003c c1eb 4000 4006 1f2e c0a8 6482 ----- 1 d3ea 608d 0906 115d a9e4 638a 0000 0000 a002 16d0 0cc5 0000 0204 05b4 0402 080a 009c a261 0000 0000 0103 0300 13:42:48.202336 eth0 < 211.234.96.141.4445 > localhost.2310: S 2213490312:2213490312(0) ack 2850317195 win 5792 < mss 1460,sackOK,timestamp 2310931230 10265185,nop,wscale 0> (DF) 4500 003c 0000 4000 3806 e919 d3ea 608d ----- 2 c0a8 6482 115d 0906 83ef 2e88 a9e4 638b a012 16a0 cd8f 0000 0204 05b4 0402 080a 89be 031e 009c a261 0103 0300 13:42:48.202336 eth0 > localhost.2310 > 211.234.96.141.4445: . 1:1(0) ack 1 win 5840 <nop,nop,timestamp 10265210 2310931230> (DF) 4500 0034 c1ec 4000 4006 1f35 c0a8 6482 ----- 3 d3ea 608d 0906 115d a9e4 638b 83ef 2e89 8010 16d0 fc0b 0000 0101 080a 009c a27a 89be 031e | 3번 악수 기법을 위해서 3번의 패킷이 오고 갔음을 알수 있다. 언뜻 봤을때 절대 이해할수 없을것 같은 숫자로 된 정보들을 뿌려주는데 원리만 알면 간단하게 분석할수 있다. 위의 숫자로 된 정보들이 바로 TCP/IP 세그먼트의 정보를 16 진수로 나타낸 것이다. 4자리씩 구분되어 있는데, 이 4자리의 크기는 16 비트크기를 가진다(하나의 숫자는 4비트이다. 이 정보만 알고 있다면 위의 패킷정보에서 IP 영역과 TCP 영역을 분리해 낼수 있다.
IP 헤더의 크기는 유동적이긴 하지만 기본적으로 5 * (32 bit) 의 크기를 갖는다. 그러므로 ----- 1 번 패킷을 높고 보자면 IP 헤더는 다음과 같을 것이다.
4500 003c c1eb 4000 4006 1f2e c0a8 6482 d3ea 608d | 정말 IP 헤더 정보가 맞는지 확인해보자. IP 헤더의 첫번째 4bit 는 IP의 버젼을 나타낸다. 위에서 보면 '4' 로 되어 있음으로 이 TCP/IP 패킷은 IPv4 를 이용하고 있음을 알수 있다. c0a8 6482 는 source IP, d3ea 608d 는 destination IP 이다.
이제 ---- 1 번 패킷에서 TCP 헤더 정보를 분석해 보도록 하자. 분석한 데이타는 tcpdump 헤더와 비교하면서 계산하도록 하자. TCP 헤더데이타는 0906 부터이다. TCP 의 처음 16bit 는 SOURCE PORT 다음 16bit 는 DESTINATION PORT 를 나타낸다. 0906 을 계산해 보면(진수변환 되는 계산기로) 2310 이며 115d 를 계산해보면 4445 이다. 정확하게 일치하고 있음을 알수 있다. 클라이언트측의 PORT 번호는 서버측 포트 번호와는 달리 임의의 번호로 할당된다.
우리는 ---- 1 번 패킷에서 a9e4 638a 가 시퀀스 넘버임을 유추해낼수 있을것이다. 이것을 계산해 보면 2850317194 임을 알수 있다. ACK는 0000 0000 이다. ACK 는 0000 0000 즉 0 으로 초기화 되어있는데 반해서, 시퀀스 넘버는 0으로 초기화 되어 있지 않다. 실지로 ACK 는 새로운 연결이 이루어질때 마다 0 으로 초기화 되는데 비해 시퀀스 넘버는 새로운 연결이 생길때 마다 임의의 번호로 새로 만들어진다.
Header Length 는 4bit 크기를 가지므로 a002 에서 'a' 임을 알수 있다. 해서 Header Length 는 10(a) 임을 계산할수 있는데, 이때 Length 의 단위는 워드(32 bit) 이다. 그러므로 헤더는 0906 에서 0300 까지의 데이타임을 유추해 낼수 있다.
0906 115d a9e4 638a 0000 0000 a002 16d0 0cc5 0000 0204 05b4 0402 080a 009c a261 0000 0000 0103 0300 | 즉 최초 세번 악수 기법을 통한 세션 연결시에 오고 가는 3개의 패킷 데이타는 단지 TCP/IP 헤더정보만을 포함하고 있으며, 그외의 아무런 다른 정보도 포함하고 있지 않음을 알수 있다.
2.3.3.1. 패킷 분석을 통해서 알아보는 3번 악수 기법 - 연결
이전에 ---- 1 패킷을 분석함으로써, 우리는 dump 된 패킷을 분석하는 기본적인 기법을 배웠다. 이 방법들을 토대로 정말로 3번 악수 기법이 제대로 이루어 지는지 한번 확인해 보도록 하겠다.
3번 악수 기법을 보면 알겠지만 가장 핵심이 되는 키워드는 SEQ 번호와 ACK 번호 그리고 패킷의 타입을 나타내는 CODE BITS 이다. 이 세가지 필드의 의 계산만 잘하면 TCP 연결이 어떻게 이루어지는지 이해가 가능할것이다. 그럼 ---- 1, ---- 2, ---- 3의 dump 패킷을 분석해서 3번 악수 기법의 흐름을 알아보도록 하자.
- ---- 1
-
클라이언트는 자신의 SEQ 를 a9e4 638a (2850317194)로 만들고 . ACK 를 0000 0000 (0) 으로 만들어서 ---- 1 패킷을 서버측 측에 보낸다.
- ---- 2
-
서버는 클라이언트로 부터 ---- 1 패킷을 받는다. SEQ 는 a9e4 638a 인데, 여기에 +1 (a9e4 638b) 를 해서 ACK 를 만든다. 그리고 자신의 SEQ 를 83ef 2e88 로 세팅해서 ---- 2 패킷을 만들고 만들어진 패킷을 다시 클라이언트로 보낸다.
CODE BITS 를 보면 값이 02 임을 알수 있다. 2 는 2진수로 10 CODE BITS 의 세팅은 00 00 10 으로 되어있음을 알수 있다. 5번째 BIT 는 SYN 비트 임으로 이 패킷은 최초 연결을 시도하기 위한 패킷임을 알수 있다.
CODE BITS 를 보면 값이 12 임을 알수 있다. 이것을 2진수로 변경 시켜 보면 10 00 10 이다 그러므로 URG 와 SYN 비트가 세팅되어 있음을 알수 있다.
- ---- 3
-
클라이언트는 서버로 부터 ---- 2 패킷을 받는다. ---- 2 패킷에서 넘어온 ACK 를 확인해 본다. 최초에 클라이언트가 서버측으로 보낸 SEQ 에 +1 된 값이므로 올바른 데이타임을 확인할수 있다. 이제 ---- 2 에서 넘어온 ACK 를 자신의 SEQ 로 설정하고, ---- 2 에서 넘어온 SEQ (83ef 2e88)에 +1 을 해서 ---- 3 패킷을 만들고 이것을 서버로 보낸다.
CODE BITS 를 보면 값이 10 이다. 2진수로 10 00 00 임으로 URG 가 세팅되어 있음을 알수 있다. 이상 꽤 복잡한것 같지만 곰곰히 생각해 보면 별거 아니란걸 알수 있을것이다.
2.3.3.2. 패킷 분석을 통해서 알아보는 연결 종료
연결과는 좀 다르다. 완전한 종료를 위해서는 아래와 같이 4 번의 패킷 교환이 일어난다.
client server ① Send SYN seq=x ---------------------------> Receive FIN segment | ② | Recevie segment <-------------------------- Send ACK x+1
① Receive FIN + ACK segment <-------------------------- Send FIN seq=y, ACK x+1 | | ② Send ACK y + 1 --------------------------> Receive ACK segment | 완전한 연결종료를 위해서 위의 zipcode 어플리케이션 대신에 telnet(port 23) 을 이용해서 테스트 하기로 했다. 테스트 방법은 telnet 로 해당 서버에 연결한 연결한 다음 login 프롬프트가 떨어지면 (CTRL + ]) 키를 이용해서 telnet> 프롬프트를 부르고 여기에 quit 를 입력해서 연결을 종료시키는 방법이다.
[root@coco test]# telnet 192.168.100.190 Trying 192.168.100.190... Connected to 192.168.100.190. Escape character is '^]'.
SunOS 5.8
login: // 여기에서 CTRL+] 입력 telnet> quit | 이 과정을 tcpdump 로 패킷 덤프 받은 데이타 내용은 다음과 같다.
17:03:01.412336 eth0 > localhost.2437 > develop.telnet: F 110:110(0) ack 89 win 5840 <nop,nop,timestamp 11466531 71617405> (DF) 4500 0034 980c 4000 4006 5826 c0a8 6482 ---- 1 c0a8 64be 0985 0017 9d14 6d27 1f57 e476 8011 16d0 3621 0000 0101 080a 00ae f723 0444 cb7d 17:03:01.412336 eth0 < develop.telnet > localhost.2437: . 89:89(0) ack 111 win 10136 <nop,nop,timestamp 71618004 11466531> (DF) 4500 0034 23c2 4000 ff06 0d70 c0a8 64be ---- 2 c0a8 6482 0017 0985 1f57 e476 9d14 6d28 8010 2798 2302 0000 0101 080a 0444 cdd4 00ae f723
17:03:01.412336 eth0 < develop.telnet > localhost.2437: F 89:89(0) ack 111 win 10136 <nop,nop,timestamp 71618005 11466531> (DF) 4500 0034 23c3 4000 ff06 0d6f c0a8 64be ---- 3 c0a8 6482 0017 0985 1f57 e476 9d14 6d28 8011 2798 2300 0000 0101 080a 0444 cdd5 00ae f723 17:03:01.412336 eth0 > localhost.2437 > develop.telnet: . 111:111(0) ack 90 win 5840 <nop,nop,timestamp 11466531 71618005< (DF) 4500 0034 0000 4000 ff06 3132 c0a8 6482 ---- 4 c0a8 64be 0985 0017 9d14 6d28 1f57 e477 8010 16d0 33c8 0000 0101 080a 00ae f723 0444 cdd5 | 패킷 분석방법은 위에서 모두 설명했으니 굳이 다시 설명하진 않겠다. 주의 해서 볼점은 CODE BITS 부분이다. ---- 1 번을 보면 CODE BITS 가 11 로 설정되어 있음을 볼수 있다. 이를 2진수로 변환하면 10 00 01 이다. FIN 비트 가 세팅되어 있음을 알수 있다.
2.3.3.3. 실 데이타 전송
실 데이타를 전송할때는 연결/종료 와 같은 3번 악수 기법에 의한 복잡한 (뭐 그리 복잡하지도 않지만) 그러한 패킷 교환은 없다. 단지 한쪽에서 데이타를 보내면 받은쪽에서는 데이타를 잘 받았다라는 패킷만을 보내게 된다.
이제 실제 데이타가 전송될때의 TCP/IP 패킷의 분석을 해보도록 하자. 여기에서는 다시 zipcode 의 서버/클라이언트가 사용될것이다. zipcode_cl 을 이용해서 서버여 연결하고 "지역이름 입력 : " 프롬프트가 떨어지면 a 를 입력해보도록 하자.
[root@s210-205-210-195 test]# ./zipcode_cl 4445 지역이름 입력 : a 지역이름 입력 : | 다음은 위의 결과 를 tcpdump 를 이용해서 dump 뜬 결과 이다.
23:32:49.951938 s210-205-210-195.thrunet.ne.kr.33638 > 211.234.96.141.4445: P 1:256(255) ack 1 win 5840 <nop,nop,timestamp 26681991 2314595836> (DF) 4500 0133 484f 4000 4006 176d d2cd d2c3 ---- 1 d3ea 608d 8366 115d 5b9e 5641 872e f2e8 8018 16d0 19eb 0000 0101 080a 0197 2287 89f5 edfc 6100 0000 5066 0140 0100 0000 dc81 0408 9460 0140 0f53 8e07 0f53 8e07 70f7 23:32:49.967321 211.234.96.141.4445 > s210-205-210-195.thrunet.ne.kr.33638: . ack 256 win 6432 <nop,nop,timestamp 2314596983 26681991> (DF) 4500 0034 1f16 4000 3806 49a5 d3ea 608d ---- 2 d2cd d2c3 115d 8366 872e f2e8 5b9e 5740 8010 1920 214f 0000 0101 080a 89f5 f277 0197 2287 23:32:49.971577 211.234.96.141.4445 > s210-205-210-195.thrunet.ne.kr.33638: P 1:256(255) ack 256 win 6432 <nop,nop,timestamp 2314596983 26681991> (DF) 4500 0133 1f17 4000 3806 48a5 d3ea 608d ---- 3 d2cd d2c3 115d 8366 872e f2e8 5b9e 5740 8018 1920 07d6 0000 0101 080a 89f5 f277 0197 2287 656e 6400 7365 6e64 2065 6e64 0a00 0000 0000 0000 0000 001c 9e04 0800 0000 23:32:49.971653 s210-205-210-195.thrunet.ne.kr.33638 > 211.234.96.141.4445: . ack 256 win 6432 <nop,nop,timestamp 26681993 2314596983> (DF) 4500 0034 4850 4000 4006 186b d2cd d2c3 ---- 4 d3ea 608d 8366 115d 5b9e 5740 872e f3e7 8010 1920 204e 0000 0101 080a 0197 2289 89f5 f277 | ---- 1 에서 실제 데이타를 보내고 있으며 여기에서는 서버측으로 'a' 를 보내게 될것이다. 실제 'a' 를 보내는지 확인을 해보자. IP 헤더의 크기는 (5*32) 로 고정되어 있을것이다. 문제는 TCP 헤더의 크기인데, 8018 에서 8 이 헤더의 크기를 나타냄을 알수 있다. 단위는 워드 이므로 계산을 해보면(8 * 32) 8366 에서 부터 edfc 까지가 TCP 헤더 임을 알수 있다. 그러므로 우리가 보내고자 하는 데이타는 6100 에서 부터가 될것이다. 61 은 'a' 라는걸 알수 있다. - 61 은 10 진수 97 을 나타내며 ASCII 코드를 보면 97 은 'a' 를 나타낸다.
서버에서 데이타를 받았다면 서버는 이에 대한 응답 메시지(저 메시지 잘 받았습니다) 를 클라이언트측에 보내야 할것이다. ---- 2 패킷이 바로 응답 메시지가 된다. ---- 2 패킷의 CODE BITS 를 보면 10 으로 세팅되어 있는데, 이것을 2진수로 변경하면 01 00 00 이 된다. 2번째 비트가 켜져 있는데 2번째 비트는 ACK 를 나타낸다. 그러므로 이 패킷은 응답용 패킷이라는 걸 알수 있다. 그렇다면 --- 2 패킷을 받은 클라이언트는 이게 과연 ----2 패킷이 ---- 1 에 대한 응답 메시지인지를 확인해야 하는데 이는 SEQ 번호와 ACK 번호를 계산함으로써 알나 낼수 있을것이다.
---- 3 번 데이타는 서버측에서 클라이언트로 보내는 패킷의 dump 내용이다. 클라이언트로 보내는 데이타는 "send end" 임을 알아낼수 있을 것이다. ---- 4 번 데이타는 이에 대한 응답으로 클라이언트에서 서버측으로 보내는 패킷 dump 내용이다.
3. 결론
이상 TCP 헤더에 대한 비교적 상세한 내용을 다루었다. 이러한 내용들은 나중에 다루게될 RAW 소켓등 낮은 수준에서의 네트웍 프로그래밍을 원한다면 알아두어야할 내용이다. 또한 네트웍 관련 문제해결을 하는데 많은 도움을 줄것이다.
이 문서에서 이해되지 않는 내용등이 있다면 댓글을 달아주길 바란다. 그러면 최대한 공부를 해서라도 답변을 해주도록 하겠다.
관련문서 CheckSum 알고리즘을 응용한 코드, 네트워크프로그래밍, TCP/IP 미니사이트이 문서는 수정될 수 있습니다. 최신문서는 Joinc Wiki에서 확인하세요. :::

| 교정 과정 |
|---|
| 교정 0.8 | 2003년 3월 19일 23시 |
| | 이미지추가 |
우리는 그동안 몇번의 기사를 통해서 IP에 대해서 이미 알아보았다.
이번에는 IP에 대한 좀더 자세한 내용을 알아보도록 하겠다.
이문서는 여러분이 TCP/IP 에 대한 기본적인 이해를 하고 있다고 가정할것이다.
이 문서를 읽기전에
TCP/IP 개요,
TCP/IP 개요(2),
TCP/IP 개요(3)
에 대한 문서를 먼저 읽어서 TCP/IP 에 대한 어느 정도의 이해를 해놓길 바란다.
IP 는 인터넷으로 연결된 호스트 사이에 bit 데이터 (인터넷 데이타 그램)의 교환을
가능하도록 하기 위해 만들어진 프로토콜이다. IP는 인터넷 환경에서 host 간 데이타
그램의 교환을 목적으로 하므로 host-to-host 프로토콜이라고 불리우기도 한다.
IP는 addressing(주소지정) 과 데이타 그램의 단편화를 통해서 데이타 그램을
교환한다. 일단 보내고자 하는 크기의 데이타가 있다면, IP는 이 데이타를
한꺼번에 보내지 않고, 여러개의 조그만 데이타 그램으로 단편화 (fragmentation) 작업을
수행하게 된다. 그리고 이러한 단편화된 데이타 앞에 목적지로 찾아갈수 있도록 하기 위한
여러가지 정보 들을 채워 넣게 된다 (이것을 IP Header 이라고 한다).
위의 그림을 보면 하나의 Internet Data 를 보내기 위해서 3개의 조그만
데이타로 쪼개고 이앞에 IP Header 을 붙였음을 알수 있다.
IP 프로토콜은 다음과 같은 몇가지 특징을 가지고 있다.
- 비신뢰성(unreliable)
IP 는 데이타 그램이 목적지로 전달될 것이라는 것을 보증하지 않는다.
IP 데이타 그램은 목적지로 가는 도중 여러가지 원인에 의해서 손실될수도
있는데, IP 헤더에는 이러한 손실을 복구하기 위한 어떠한 장치도 마련되어
있지 않다. 대신에 TCP 에 이러한 데이타 손실을 복구하기 위한 장치를 마련한다.
- 비연결지향성(connectionless)
호스트와 호스트간에 데이타 그램을 전달하기 위하여서 세션을
개설하지 않는다. 모든 데이타 그램은 각각 독립적으로
전달되게 된다. 받는 호스트에서는 해당 데이타 그램간의 연관성에 대해서
전혀 알지 못한다. 만약 A와 B 데이타가 호스트로 전달되고,
A가 첫번째 데이타 B가 두번째 데이타라고 한다면, 받은측에서는
어느 데이타가 첫번째 데이타인지 알지 못한다. 또한 B데이타가 A데이타
보다 먼저 전달될수도 있는데, IP는 이를 교정할수 있는 장치를
가지지 않는다.
이번장에서는 IP 프로토콜의 헤더 포맷에 대해서 알아보도록하겠다.
- Version: 4bits
IP 포맷의 버젼을 나타낸다. 현재는 주로 IPv4 가 가장 널리 쓰이며,
차세대 포맷으로 IPv6 가 제안되어서 조금씩 사용범위가 늘어나고 있는 추세이다.
- IHL(Internet Header Length): 4bits
IP 헤더의 길이다. 보통은 32bit 크기를 가지는 5개의 열로 이루어진다.
나마지 하나의 열은(Options, Padding)는 옵션사항이다.
- Type of Service: 8 bits
인터넷에는 다양한 종류의 데이타 그램이 돌아다닌다. 이중 어떤것은
상대적으로 중요한 데이터 그램이라서 데이타 전송에 있어서 다른
데이타 그램보다 전송에 있어서 우선순위를 두어야 하는 그런경우가 있을것이다.
이럴때 Type of Service 를 이용함으로써, 데이타 그램의 전송에 대한 우선순위
등을 제어할수 있다. 간단한 형태의 QOS(Quality of service) 라고 볼수 있다.
- Total Length: 16 bits
IP 헤더와 실제 데이타의 크기를 모두 합친 크기이다.
- Identification: 16 bits
보내고자 하는 데이타 그램에 단편화(fragmentation)가 일어났을경우
단편화된 각 데이타 그램을 구분할수 있는 일련의 번호이다.
이 값을 이용해서 이 데이타 그램이 어떤 데이타 그램에서 단편화 된것인지를
알수 있다.
- Flags: 3bits
데이타 그램의 단편화에 대한 정보를 알려주기 위해서 사용된다.
첫번째 비트는 예비로 사용되며, 0으로 세팅된다.
두번째 비트와 세번째 비트는 단편화된 데이타그램의 정보를 세팅하기
위해서 사용된다. 두번째 비트가 0으로 세팅되었을경우 단편화된 데이타임을
의미하며, 1일경우 단편화 되지 않은 데이타를 의미한다. 3번째 비트가 0일경우
마지막 단편화 데이타 임을 나타내며, 1일경우에는 단편화된 데이타가
더 있다는것 나타낸다.
표 1. Flags 세팅 | 0 | 예비 : 반드시 0 | | 1 | (DF) 0 = 단편화되었음, 1 = 단편화되지 않았음 | | 2 | (MF) 0 = 마지막 단편화 데이타, 1 = 단편화 데이타 더 있음 |
0 1 2 +---+---+---+ | | D | M | | 0 | F | F | +---+---+---+ |
- Fragment Offset: 13bits
데이타그램에 대한 단편화가 일어났을경우 현재 데이타 그램이 원래 데이타 그램의
몇번째 위치부터 단편화가 이루어 졌는지를 나타낸다.
- Time To Live: 8bits
TTL 이라고 불리우는 값으로 데이타 그램이 살아있을 시간을 지정한다.
시간 이라고 해서 1시간 2시간 하는 시간이 아닌, 몇개의 라우터를 이동할수 있는지를
명시함으로써 데이타 그램의 생존기간을 명시한다. IP 데이타 그램이 라우터를 경유하게
되면 라우터는 TTL 필드를 조사해서 TTL의 값에 1을 빼준다. 만약 TTL 에 16의 값이
세팅되어 있다면 16번째 라우터를 지날때 TTL 값은 0이 될것이며, 라우터는 이 데이타
그램을 전달하지 않고 drop 시켜버린다. TTL 값을 명시하는 이유는 데이타 그램이
라우터 상에서 무한 순환 하는 사태가 발생할수 있기 때문이다.
- Header Checksum: 16bits
Header 정보는 고정된게 아니고 필요에 따라 바뀌게 된다(TTL 과 같은정보).
그러므로 헤더를 체크할수 있는 장치를 필요로 한다.
- Source Address: 32bits
데이타그램을 보내는 측의 IP 주소이다.
- Destination Address: 32bits
데이타그램을 받는측의 IP 주소이다.
- Options: 크기변화
프로그램의 특성에 의해서 특정한 기능을 추가하기 위해서 사용된다.
이 필드는 필수적인 것이 아니다. 데이타 그램에 보안기능을 추가하거나,
QOS 와 같은 기능, 혹은 라우팅관련된 부가적인 여러 기능을 추가하기 위해서
사용된다.
- Padding: 크기변화
특별한 사용용도는 없다. 단지 32bit 크기를 맞추기 위해서 사용되며, 0으로 세팅된다.
IP 데이타 그램의 목적지까지의 경로 배정은 Destination Address 필드에 세팅되어
있는 IP 주소를 통하여서 이루어진다. 일단 데이타 그램이 보내질 목적지가 LAN 상에
존재하면, 데이타 그램은 곧바로 해당 목적지 호스트로 보내어진다. 그렇지 않을경우
데이타 그램은 설정되어 있는 default gateway(router) 로 보내어진다. 이것은
router 의 ip routing table 에 의해서 목적지까지 경우되어서 최종 호스트로
도착하게 된다. 여기에 대한 내용들은 이미 다른 기사에서 자세히 언급되어 있음으로
이정도에서 끝내도록 하겠다.
위에서 IP 헤더 필드를 설명하면서 "데이타 단편화" 에 대한 언급을 했었다.
이번장에서는 이러한 데이타 단편화가 일어나는 원인과 어떻게 단편화된 데이타를
재조합 할수 있는지에 대해서 알아보도록 하겠다.
2.4.1절. MTU(Maximum Transmission Unit) MTU 란 다음 호스트에 한번에 보낼수 있는 데이타 그램의 크기이다.
어쨋든 데이타를 한번에 몽땅 보낼수는 없으므로 호스트에서는
이것을 적당한 크기로 잘라내야 할것이다. 그런데 이 적당한 크기라는게
말그대로 적당한 크기로 망에 따라서 약간씩 그 크기가 다르며, 각 망에서
통신하기에 가장 최적화된 크기의 MTU를 가지고 있다. MTU 사이즈는
헤더를 제외한 data 만의 크기이다.
이러한 MTU 사이즈는 여러번의 테스트를 걸쳐서 각망에 최적화된다라고 생각되는
실험적인 크기로 정해진다. 우리가 보통 사용하는 이더넷 망의 경우 1500,
ATM 망의 경우 9600 의 사이즈를 가지며, SLIP 의 경우 576 의 크기를 가진다. 또한
이 값은 망 상태에 따라서 네트웍 관리자에 의해서 임의로 조정될수 있다.
[root@localhost root]# ifconfig eth0 Link encap:Ethernet HWaddr 00:50:BF:2C:7B:B2 inet addr:192.168.0.4 Bcast:192.168.0.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:355481 errors:1 dropped:0 overruns:0 frame:0 TX packets:360573 errors:0 dropped:0 overruns:0 carrier:0 collisions:5023 RX bytes:369176288 (352.0 Mb) TX bytes:33374363 (31.8 Mb)
lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:68 errors:0 dropped:0 overruns:0 frame:0 TX packets:68 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 RX bytes:3400 (3.3 Kb) TX bytes:3400 (3.3 Kb) |
이러한 MTU 의 크기는 ifconfig 를 통해서 확인 가능하며, 변경도 가능하다. 위의 ifconfig 정보는
필자의 리눅스박스에서 측정한 크기이다. 필자의 리눅스 박스는 보통의 이더넷카드를 이용하므로
MTU 1500 으로 세팅되어 있다.
인터넷은 다양한 환경을 가지는 망으로 서로 연결되어 있음으로, 데이타 그램이 목적지로
이동하는 동안 다양한 MTU 크기를 가지는 망을 통과하게 된다. 만약 1500 의 MTU 크기를 가지는
호스트에서 만들어진 데이타 그램이 576 MTU 크기를 가지는 SLIP 를 통과하게 되면 어떻게 될까 ?
1500 의 크기로는 576 크기를 통과할수 없음으로, 576 크기에 맞도록 데이타가 단편화 되게 된다.
IPH : IP Header +-----+------------------------+ | IPH | 1500 | +-----+------------------------+ +-----+-----+ +-----+-----+ +-----+-----+ | IPH | 576 | | IPH | 576 | | IPH | 348 | +-----+-----+ +-----+-----+ +-----+-----+ |
위의 그림처럼 1500 데이타는 2개의 576크기를 가지는 데이타 그램과 348 크기를 가지는 데이타
그램으로 단편화 되게 될것이다. 또한 이 데이타 그램은 단편화 된다고 하더라도, IP 데이타 그램의
특성을 가져야 함으로 각각 IP 헤더를 가지는 완전한 IP 데이타 그램의 형태가 될것이다.
이렇게 단편화 되어서 전송되는 데이타 그램의 경우 목적지에 서로 다른 순서로 도달할수가 있을것이다.
그러므로 단편화 작업을 수행할때, 각각의 단편화된 데이타 그램이 원래의 데이타그램의 어떤 위치에서
단편화 되었는지등의 정보를 넣어둠으로써 최종도착지점에서 단편화된 데이타를
다시 조립할수 있도록 만들어줘야 할것이다. 이러한 작업은
커널의 IP를 담당하는 모듈에서 자동적으로 수행하며, IP 테이블의 Flags 와 Fragment Offset
필드를 수정함으로써 단편화 정보를 유지하게 된다. 여기에는 현재의 데이타 그램의 단편화가 되어있는지
단편화가 되어 있다면, 어떤 데이타그램에서 단편화 된것인지,
몇번째 단편화 데이타 인지, 마지막 단편화 데이타 인지, 원래 데이타 그램에서
offset 은 어느정도가 되는지등의 정보가 들어가게 된다. 최종적으로 목적지에서는
데이타 그램의 Identification 과 Flag, Fragment Offset 을 이용해서 단편화된 데이타를
재조립하게 될것이다.
다음은 IP 헤더의 가장간단한 예로 단편화가 일어나지 않은 데이타 그램의 IP 헤더의 형태이다.
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Ver= 4 |IHL= 5 |Type of Service| Total Length = 168 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification = 111 |Flg=0| Fragment Offset = 0 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time = 123 | Protocol = 1 | header checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | source address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | destination address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+ |
데이타 그램의 총 크기는 168bit 이고, 이중 헤더의 크기가 160bit 데이타의 크기가 8bit 임을
알수 있다. IPv4 버전이며, 단편화가 일어나지 않았(Flg=0)음을 알수 있다.
이번에는 좀더 복잡한 예로, 단편화가 일어난 데이타 그램의 경우이다. MTU 사이즈는 2048 이며,
보내고자 하는데이타의 크기는 2500 이라고 가정하겠다.
이것은 첫번째 데이타 그램이다.
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Ver= 4 |IHL= 5 |Type of Service| Total Length = 2208 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification = 112 |Flg=1| Fragment Offset = 0 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time = 119 | Protocol = 6 | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | source address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | destination address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
데이타 그램의 총크기는 2048 + (32*5) = 2208 이 될것이다.
데이타 그램의 단편화가 이루어졌음으로 Flg = 1 이 세팅된다.
그리고 단편화된 데이타 중 첫번째 데이타 그램이므로 Fragment Offset 는 0이
될것이다.
다음은 두번째 데이타 그램이다.
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Ver= 4 |IHL= 5 |Type of Service| Total Length = 612 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification = 112 |Flg=0| Fragment Offset = 2048 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time = 119 | Protocol = 6 | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | source address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | destination address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
Identification 이 112 임을 주목하라. 마지막 단편화 데이타 이므로
(더이상 단편화된 데이타가 없음) Flg 가 0으로 세팅되어있다.
이 데이타 그램의 Total Length 는 (32 * 5) + (2500 - 2048) = 612
가 될것이다. 그리고 이 단편화된 데이타 그램이 원래 데이타 그램에서
단편화된 위치는 2048 이 될것임으로 Fragment Offset 는 2048 이
될것이다.
이상 IP 프로토콜에 대한 좀더 자세한 내용들을 알아보았습니다.
이러한 내용들에 대한 좀더 자세한 내용을 원한다면
RFC791 와
W. Richard Stevens 의 TCP/IP Illustrated Volume 1 을 참고하기 바랍니다.
이 문서는 수정될 수 있습니다. 최신 문서는 Joinc Wiki를 참고해 주세요. :::

복습
TCI/IP 소개 1, TCP/IP 소개 2 2개의 문서에서 부족하게 나마 TCP/IP에 대한 대략적인 내용들과, TCP/IP의 계층 구조 그리고, 각각의 계층 구조를 이루는 TCP, IP, ARP, UDP
와 같은 프로토콜에 대해서 간단하게 살펴보았다. 지금까지의 내용을 도표로 좀더 익목요연하게 그려보자면 아래와 같이 그려볼수
있을것이다. 아래의 그림은 그동안 의 내용을 정리한것으로, 몇개 새로운 프로토콜들이 나오는데, 거기에 대한 설명도 하도록
하겠다.
application +------------------------------------------------------------------------+ | +--------------+ +--------------+ +--------------+ +--------------+ | | | User | | User | | User | | User | | | | application | | application | | application | | application | | | +--------------+ +--------------+ +--------------+ +--------------+ | +----------|---------------|--------|--------|---------------------------+ | | | | | +------|--------|--------|------+ | | +---------+ | +---------+ | transport | | | TCP | | | UDP | | | | +---------+ | +---------+ | | +---------------|---------------+ | | +-----|------------------------|-----------------------------+ | +---------+ +---------+ +---------+ | network | | ICMP |<----------->| IP |<---------->| IGMP | | | +---------+ +---------+ +---------+ | +------------------------------|-----------------------------+ | | +------------------------------|-----------------------------+ | +---------+ +---------+ +---------+ | link | | ARP |<----------->| HardWare|<---------->| RARP | | | +---------+ +---------+ +---------+ | +------------------------------------------------------------+
User application 은 telnet, ftp, web browser 와 같은 사용자 응용프로그램으로 각 어플리케이션 프로토콜을 사용한다. transport 계층의 TCP/UDP는 앞장에서 언급했음으로 다시 설명하진 않겠다. transport 계층 아래로 network 계층이 존재하며, 여기에는 IP, IGMP, ICMP 와 같은 프로토콜이 사용된다. 그림에서 보면 IP 프로토콜은 바로 application 계층과 통신이 가능한데, raw socket이란 도구를 통해서 transport 계층을 거치지 않고 곧바로 IP 계층과 통신할수 있다. raw socket 는 우리말로 생소켓 날소켓 이라고도 불리운다.
ICMP 는 Internet Control Message
Protocol 혹은 인터넷 제어 메시지 프로토콜 이라고 불리운다. 호스트서버와 인터넷 게이트웨이 사이에서 메시지를 제어하고
어떤 에러가 발생했는지 알려주는 프로토콜이다. 위의 그림에서 처럼 network 레이어에서 작동을 하지만 User
application 에 의해서 직접처리된다. ICMP 를 이용한 가장 대표적인 응용프로그램은 ping 이라는 프로그램으로,
서버상태를 확인하기 위해서 매우 자주 사용한다.
IGMP는 멀티캐스팅을 위해서 사용되는 프로토콜로써, 다수의 다른 컴퓨터에게 컨텐츠를 보낼수 있도록 하는 프로토콜이다. 최근들어 멀티미디어 데이타 그중 스트리밍 데이타를 전송하기 위해서 자주 응용되는 프로토콜이다.
기존의 방식은 보통 유니케스트 방식으로 서버와 클라이언트가 1:1 로 데이타를 전송하는 방식이였는데, 이는 동일한 스트리밍
데이타를 모든 유저에 대해서 복사해서 전송해야 했음으로, CPU자원과 네트웍자원을 과도하게 소모하는 단점을 가지고 있다. 이를
해결하기 위한 방법으로 멀티캐스팅 이라는 메시지를 전달하는 다른 방법이 나오게 되었다. 멀티캐스팅을 사용하게 되면 서버측에서는
단지 하나의 스트리밍 정보만을 보내게 되고, 라우터 측에서 수신받아야될 클라이언트 에게 스트리밍 데이타를 복사해서 전달하게
된다. 그러므로 서버측 부하가 분산되어서 처리된다. 물론 일반적인 라우터가 아닌 멀티캐스트를 지원하는 라우터를
사용해야 한다. IGMP는 이러한 라우터에 메시지를 송신받을 그룹에 대한 정보를 전송시켜준다. IGMP 는 Interget
Group Management Protocol 의 줄임말 이며 인터넷 그룹 관리 프로토콜이라고 불리운다.
ARP는 이전에 논의된적이 있으니 넘어가고 RARP에 대해서만 설명하도록 하겠다. RARP 는 ARP의 반대되는 일을한다.
ARP가 IP주소를 물리적인 네트워크 주소로 변환시켰다면 RARP는 물리적인 네트워크 주소를 IP 주소로 변환하는 작업을 한다.
보통의 운영체로 운영되는 시스템이라면 부팅시에 이더넷 카드에 IP 번호를 부여해 줄수 있을것이다. 그러나 하드디스크를 가지않은
전용단말기와 같은 기기의 경우 부팅시 이더넷 카드에 IP를 부여해줄수가 없을것이다. 그렇다고 메모리에 IP를 넣어 버리는 방법도
이동성이 크게 떨어지기 때문에 그리 적당하지 않다. 이럴경우 RARP 를 이용 주변의 네트웍환경을 파악하여 자신의 네트워크
주소에 IP주소를 자동적으로 할당할수 있다.
Encapsulation
user application에서 만들어진 유저 데이타는 각각의 계층(TCP/IP 4)을 거치면서 각 계층에 필요한 정보를 유저
데이타에 덧붙이게 된다. 이러한 과정이 내용물을 캡슐에 담는것과 비슷하다고 해서, Encapsulation 이라고 불리우게
된다.
AH : Application Header TCPH : TCP Header IPH : IP Header EtherH : Ethernet Header EtherT : Ethernet Trailer +-----------+ | user data | +-----------+ ↓ ↓ +------+-----------+ +-------------+ | AH | user data | | application | +------+-----------+ +-------------+ ↓ ↓ ↓ +------+------------------+ +-------------+ | TCPH | application data | | TCP | +------+------------------+ +-------------+ ↓ ↓ ↓ +------+------+------------------+ +-------------+ | IPH | TCPH | application data | | IP | +------+------+------------------+ +-------------+ ↓ ↓ ↓ +--------+------+------+------------------+--------+ +-------------+ | EtherH | IPH | TCPH | application data | EtherT | | Ethernet | +--------+------+------+------------------+--------+ +-------------+
위의 그림에서 처럼 최초 user data 가 만들어지면 user data 를 원하는 호스트까지 보내기 위해서 각 계층을
거치면서 필요한 정보를 데이타의 앞에 붙이게 된다. 그리고 마지막으로 Thernet Trailer 를 데이타의 뒤에 붙여줌으로써
데이타를 완전히 캡술화 하게 된다. 각 헤더에는 각 계층간 통신을 위해서 필요로하는 데이타들이 들어가게 된다.
LAN 과 인터넷 상에서의 패킷은 위와 같은 구조로 캡슐화 되어서 이동하게 된다.
Demultiplexing
인터넷 통신의 최종목적은 user data 를 전달하기 위한것이며, 여기에 TCP/IP 를 각계층별로 나누어서 데이타를 캡슐화
하는 등의 온갖 부산을 떠는것은 user data가 원하는 곳으로 전송되도록 하기위한 부가적인 작업들이다. 그러므로 일단 각종
프로토콜 헤더로 캡슐화된 데이타가 도착을 하게되면, 데이타를 받은 호스트에서는 user data 를 추출해 내는 일을 하게
되는데, 이를 Demultiplexing 라고 한다.
캡슐화된 데이타그램이 호스트에 도착하게 되면, 각 계층은 자신의 계층에서 처리해야될 헤더를 분석해서 상위 계층으로 넘기게 되며, 이때 자신이 처리했던 헤더를 데이타 그램에서 제거하게 된다. 이런식으로
최종적으로는 모든 헤더와 trailer 이 제거된 user data 가 전달되게 된다.
즉 최초 데이타 그램이 Ethernet 에 도착하게 되면, 이더넷은 Ethernet header 와 Ethernet
trailer 를 떼어내고 IP 계층(Network 계층) 으로 보내게 된다. 그럼 IP 계층에서는 IP header 를
떼어내고 다시 TCP 계층으로 보내게 되고, TCP 계층은 여기에서 다시 TCP header 를 떼어낸 다음 상위 계층인
어플리케이션 으로 보내게 되고, 어플리케이션에서는 다시 어플리케이션 헤더를 떼어내고, user data 를 받아보게 된다.
port
위와 같이 Demultiplexing 를 통해서 인터넷 데이타 그램은 application 까지 도착된다. 그런데 이러한
어플리케이션의 종류는 매우 다양하게 존재한다. ftp, mail, telnet, ssh, web 이처럼 다양한종류의 데이타가
하나의 서버에 도착하게 된다. 그렇다면 해당 어플리케이션은 이러한 다양한 데이타중에서 자신에게 도착하는 데이타라는걸 어떤
방식으로 구분할수 있을까 ?
이러한 문제를 해결하기 위해서 운영체제는 port 번호라는 것을 이용한다. 즉 각각의 서비스에 대해서 port 번호를
할당하여서, 특정 서비스는 특정 port 를 통해서만 통신 가능하도록 하는 것이다. 이를테면 금융서비스는 은행창구 에서, 민원
서비스는 동사무소에서, 볍률서비스는 법원에서 와 같은 원리이다.
이러한 port 번호는 16 비트 크기의 정수로 주어지며, 자주 사용되는 표준 인터넷 서비스에 대해서는 그 번호가 미리 할당(약속)되어져 있다. 즉 ftp는 21번, ssh 는 22, telnet 는 23, smtp(mail)
은 25, http 는 80 으로 약속되어져 있다. /etc/services 에 보면 이러한 약속되어진 port 번호와 해당
port 번호에 할당된 서비스에 대해 알아볼수 있다. 보통 1 - 1023 까지는 미리 할당된 서비스를 위한 port 번호이며,
그 이상은 어플리케이션 서비스를 위해 할당되거나, 혹은 그때그때 임시로 할당되는 포트번호들이다. 이건 어띠까지나 약속으로 강제로
규정된것이 아니므로 여러가지 사정에 의해서 다른 포트번호를 사용할수도 있다.
http 를 위한 포트를 80 대신 8080 으로 사용하는게 그 예이다. 하지만 열린 인터넷 상에서 서비스를 하기 원한다면 약속된 port 를 사용하는게 좋을것이다.
다중연결서버 만들기 의 zipcode_poll.c 예제를 이용해서 실제 어떤 방식으로 포트가 할당되어지는지 알아보도록 하겠다. 우선 zipcode_poll 을 다음과 같이 실행하도록 하자.
[root@localhost source]# ./zipcode_poll 5002
이제 Unix 의 netstate 도구를 이용해서 현재 네트웍 상황을 알아보도록 하자.
[root@localhost source]# netstate -na Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:5002 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
5002번 port 가 Listen 즉 연결대기 상태에 놓여있음을 알수 있다. 그다음 telnet 를 이용해서 5002 번 포트로 연결하고
[root@localhost source]# telnet 127.0.0.1 5002 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'.
netstat 를 이용해서 네트웍 상태가 어떻게 변했는지 알아보도록 하자.
[root@localhost root]# netstat -na Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:5002 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:5002 127.0.0.1:38214 ESTABLISHED
127.0.0.1 의 38214 포트를 통해서 5002 포트로 접근했음을 알수 있다.
다시 telnet 를 이용해서 5002 번포트로 연결을 하나 더만든 후 네트웍 상황을 보면
[root@localhost root]# netstat -na Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:5002 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:5002 127.0.0.1:38214 ESTABLISHED tcp 0 0 127.0.0.1:5002 127.0.0.1:38215 ESTABLISHED
이번엔 새로운 연결을 위해서 38215 번 포트를 이용하고 있음을 알수 있다.
(이러한 클라이언트측의 포트넘버는 OS에 의해서 자동적으로 부여된다.)
이렇듯 port 넘버를 이용해서 특정서버와의 독립적인 통신선로를 유지할수 있게
된다.
+-----------------+ +-----------------+ application | Server Host | | Client Host | | +-------------+ | | +-------------+ | | | telnet |-----------------| 38214 telnet|----- telnet | | 23 |---------+ | +-------------+ | | +-------------+ | | | +-------------+ | | +-------------+ | +-------| 38215 telnet|----- telnet | | http (23) |-------+ | +-------------+ | | +-------------+ | | | +-------------+ | +-----------------+ +---------| 38217 http |----- Mozilla | +-------------+ | +-----------------+
서버 호스트에서는 지정된 포트번호로 써비스를 하고, 클라이언트 호스트에서는 os 에서 할당한 임의의 포트번호를 이용해서 독립적인 통신을 함을 알수 있다. 이 문서는 수정될 수 있습니다. 최신 문서는 Joinc Wiki에서 확인하세요. :::

IP Address 관리 체계
원래 이것은 이전의 문서에서 다루었어야 하는데, 빼먹었음으로 먼저 IP 주소 관리 체계에 대해서 언급하고 넘어가겠다.
모든 인터넷에
연결되어 있는 인터페이스(이더넷 카드 같은)은 고유의 IP주소를 가지고 있어야만한다. IP주소는 32bit 크기를 가지는데
8bit 씩 끊어서 4자리로 나누게 되고, 각 자리는 "." 으로 구분되게 된다. 210.211.194.2 과 같이 표시되게
된다. 32bit 의 크기를 가지므로 2^32 만큼의 인터페이스에 고유한 주소를 부여할수 있게 된다.
매우 큰수라고 생각할지도 모르지만, - 밥통까지 인터넷에 연결되는 요즘 - 현재 모든 인터페이스에 고유한 주소를 부여하기에는 매우 부족한 숫자이다. 이를 해결하기 위해서 128bit 주소체계를 가지는 IPv6 버젼이 이미 나와있다. 지금은 과도기로써 IPv4 와 IPv6 가 혼용되어서 쓰이고 있으며 점차적으로 IPv6 로 넘어갈것으로 생각된다.
IP 주소는 관리상의 목적으로 그룹을 지어서 관리하고 있는데, 이를 class 라고 불리우며, A, B, C 3개의 클래스로 나누어서 관리한다. (D, E 클래스는 Multicast 용이므로 넘어가도록 한다.)
각각의 클래스는 관리(할당)가능한 IP 주소의 범위가 정해져 있다.
|
Class
|
관리 범위
|
|
A
|
0.0.0.0 ~ 127.255.255.255
|
|
B
|
128.0.0.0 ~ 191.255.255.255
|
|
C
|
192.0.0.0 ~ 223.255.255.255
|
예를 들어 IP가 210.205.210.101 이라면 이 IP는 C
클래스에 포함되어 있는 주소이다. A는 hostid 로 24bit 를 허용하고, B는 16, C 는 8bit 를 허용한다. 이를
계산해보면, A 클래스는 16777216개, B 는 65025개, C 는 256개의 IP를 관리할 수 있음을 알 수 있다.
TCP/IP 계층에 따른 데이타 전송
지난번 기사인 TCP/IP 개요 에서 우리는 TCP/IP 계층에서 데이타 전송이 어떻게 일어나는지, 계층간 통신이 어떻게 일어나는지 알아보았다. 이번에는 거기에 대해서 좀더 자세히 알아보도록 하겠다. 이번장의 설명은 아래의 그림을 설명하는데 많은 양을 할애할 것이다.
+----------+ HTTP Protocol +----------+ | Browser | <- - - - - - - - - - - - - - - - - - - - - -> | Server | +----------+ +----------+ ↓↑ ↓↑ +----------+ TCP protocol +----------+ | TCP | <- - - - - - - - - - - - - - - - - - - - - -> | TCP | +----------+ +----------+ ↓↑ ROUTER ↓↑ +----------+ IPP +------------------------+ IPP +----------+ | IP | <- - - - -|- - - -> IP <- - - - - | - - - -> | IP | +----------+ | | | +----------+ ↓↑ | +----+----+ | ↓↑ +----------+ ETP | | | | TRP +----------+ | Etnernet | <- - - - -|->Ethernet Token ring<-| - - - -> |Token ring| +----------+ +------------------------+ +----------+ ↓↑ | | ↓↑ ↓↑ | | ↓↑ =============================== ============================== Ethernet Token ring
ETP : Ethernet Protocol TRP : Token ring Protocol
위의 그림은 TCP/IP 개요 에서 다룬적 있는 TCP/IP 4계층에 의한 데이타 전송을 좀더 WAN 환경에서 넓게 조명한 그림이다.
각각의 컴퓨터즉 웹을 서비스하는 http 서버와, 이를 브라우징 하기 원하는 클라이언트 서버가 먼거리를 두고 떨어져 있을경우에는
위와 같은 전형적인 경로를 통해서 데이타 통신이 이루어지게 된다. 이 둘간에는 상당한 거리가 존재하며, 거미줄 처럼 연결된
internet 망을 가로질러야 하므로, 이들 중간중간에 데이타의 흐름을 원하는 곳까지 전달시켜주기 위한 어떠한 장치가 필요할
것이다.
Router
이것은 실생활에서의 우편전송 시스템과 비슷한데, 보통 국가에서 국가간에 우편을 전송할때 우편을 작성한 사람과 받는 사람간에
곧바로 우편을 전송하지 않고, 중간에 몇개의 단계를 거치듯이(우체통에 넣고, 지역 우체국국으로 가서 분류되고 표시된 국가로
보내지면, 다시 지방 우체국으로, 최종적으로 우편받을사람에게), 인터넷상에서의 데이타 통신역시 이러한 단계를 가지도록 자동화 시스템(autonomous
system)이라 불리는 다수의 소규모 네트웍장치로 연결되어 진다. 이렇게 함으로써, 데이타를 보낼때 이동경로에 관해서는
신경쓰지 않아도 된다는 장점을 가지게 된다. 이동경로는 위의 소규모 네트웍 장치가 알아서 설정한다.
이러한 장치를 Router(경로 배정기) 라고 한다. 라우터는 IP 패킷헤더까지를 분석해서(TCP/Application Protocol 은 무시한다) 이 패킷이 제대로 전달되기 위해서는 어디로 보내야 하는지를 알아내서, 해당 Interface 로 메시지를 전달하게 된다.
당연히 Router 은 메시지의 경로배정을 위한 경로를 저장하고 있어야 한다. 이것을 Routing Table 이라고 하며,
패킷이 들어오면 Router 은 IP헤더를 분석후 Routing Table 을 비교하여 적당한 Interface 로 메시지를
보내게 된다.
라우터는 이러한 Routing Table 의 데이타를 구성하기 위해서 주변에 있는 라우터들의 정보를 가지고 있어야 할것이다. 그러기 위해서 RIP라는 프로토콜을 사용한다. RIP 는 Routing Information Protocol 의 약자다. RIP 를 이용해서 라우터는 최신의 Routing 경로정보를 가지는 Routing Table 을 유지할수 있게 된다.
어떻게 이더넷은 IP 주소로 다른 이더넷의 주소를 찾아갈수 있는가.
일단 이렇게 해서 맛보기나마 Router 에 대해서 알아보았다. 그런데 Ethernet 드라이버까지 보내진 메시지는 어떻게 Router 혹은 주변의 다른 Eternet 드라이버까지 보내어지게 될까 ?
보통 메시지를 목적지 까지 보내기 위해서 우리는 IP 주소를 사용하게 되는데, 문제는 Eternet 카드와 IP주소는 별로
연관성이 없다는 것이다. Eternet 카드가 공장에서 만들어지면서 IP주소가 부여될리는 만무하기 때문이다.
Ethernet 카드에 IP주소를 맵핑 시켜주기 위해서 ARP라
는 프로토콜을 사용한다. ARP는 (Address Resolution Rrotocol)이라고 불리우는데, Eternet 카드로
메시지가 전달되어서 바깥으로 나가기 전에 tnernet 카드는 IP 어드레스에 일치하는 Eternet 카드를 찾기 위해서 ARP
프로토콜을 주위의 모든 Eternet 카드로 뿌리게 된다(보통 이것을 "broadcasting 한다" 라고 표현한다).
ARP 를 받은 호스트는 자신의 IP와 비교하고, 만약 맞다면 ARP 를 보낸 호스트로 ARP reply(즉 나 존재합니다)를
되돌려주고, 이것 받은 쪽에서는 ARP reply 를 보낸 호스트의 이더넷 카드주소를 알아내게 된다. 그런데 문제가 하나 있다.
세상에는 그야말로 엄청난 양의 이더넷 카드가 존재할것이다(아마 수십억 이상). 그럼 IP와 이더넷 카드를 맵핑 시키기 위해서
수천억의 모든 이더넷 카드에 ARP를 보내야 할것인가 ?
물론 그럴필요가 없다. 바로 Router 가 있기 때문이다. ARP는 LAN
상에서만 작동하는 프로토콜로써, LAN에 묶여있는 이더넷 사이에서만 유효한 프로토콜이다. 만약 하나의 호스트가 IP와 이더넷카드
이름을 맵핑 시키기 위해서 ARP 를 보내었는데, ARP reply 가 없다면, 찾고자하는 IP는 LAN 상에 있는 이더넷카드가
아닌 외부에 있는(internet 등으로 연결된)다른 이더넷카드라는것을 유추할수 있을것이다. 그러면 이 메시지는 Router 로
보내지고 (중간에 Gateway 가존재한다) Router 은 IP수준에서 최종 Router 을 찾아내고, 최종 Router 은
이 메시지를 다시 해당 IP를 포함하고 있는 LAN의 Gateway 로 보내고, GateWay 에서는 목적지 IP로 메시지를
보내게 된다. 즉 자신의 영역만 책임지면 된다.
그리고 ARP는 기본적으로 Ethernet 프로토콜이다. 즉 IP수준까지를 다루는 Router 을 넘을수가 없도록 되어 있다.
Router 을 넘어서 다른 라우터로 전송되기 위해서는 IP수준이상의 프로토콜을 지원받는 패킷이여야만 가능하다.
ARP의 의해 IP주소와 Ethernet 주소가 맵핑 되면, 이것은 cache 에 임시 저장된다. 그래서 동일한 IP를 다시
찾게되면, ARP 패킷을 날리지 않고, cache 에 저장된 내용을 찾게 된다. arp 명령을 이용해서 현재 cache 에
저장된 내용을 볼수 있다.
[root@localhost /root]# arp -a ? (192.168.100.1) at 00:40:3F:22:05:03 [ether] on eth0 </pre> </td></tr> </table> 이더넷 주소는 00:40:3F:22:05:03 이며, 흔히 MAC 어드레스라고 불리운다. 자신의 이더넷카드의 주소를 알고 싶다면 ifconfig 를 사용하면 된다. <table width=100%> <tr><td bgcolor=E0E0E0> <pre> [root@localhost /root]# [root@localhost /root]# ifconfig -a eth0 Link encap:Ethernet HWaddr 00:E0:29:5D:5C:89 inet addr:192.168.100.130 Bcast:192.168.100.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6584356 errors:24 dropped:0 overruns:0 frame:0 TX packets:1040157 errors:1 dropped:0 overruns:0 carrier:2 collisions:18331 txqueuelen:100 Interrupt:9 Base address:0xbf00
lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:31974078 errors:0 dropped:0 overruns:0 frame:0 TX packets:31974078 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0
위의 것은 필자의 리눅스 박스에서의 결과이다. 00:E0:29:5D:5C:89 가 이더넷 주소임을 알수 있다.
Gateway
위에서 Gateway 에 대한 얘기를 했는데, Gateway 란 LAN 으로 묶인 호스트들이 외부로 나가기 위한 통로 호스트
이다. 모든 호스트들은 Gateway 를 통해서만 외부의 다른 호스트에 접근이 가능하도록 되어 있다. Gateway 는 자신의
서브네트웍의 통로가 된다.
+--------+ +--------| Router |-----------+ | +--------+ | | | A | B | +---------+ +---------+ | GateWay | | GateWay | +---------+ +---------+ | | +------+------+ +------+------+ | | | | | | +---+ +---+ +---+ +---+ +---+ +---+ | 1 | | 2 | | 3 | | 1 | | 2 | | 3 | +---+ +---+ +---+ +---+ +---+ +---+
A 의 1와 2는 서로 메시지 교환이 가능하다. 이것은 ARP 프로토콜을 통해서 IP어드레스를 이더넷주소로 맵핑함으로 가능하다고
위에서 얘기를 했을것이다. 그러나 A의 1과 B 의 1은 위의 그림에서 보듯이 GateWay 를 통하지 않고는 메시지 교환이
가능하지 않음을 알수 있다.
Token ring
위의 그림은 매우 전형적인 네트웍구성을 보여주지만, TCP/IP 계층간 통신을 묘사한 그림에나와 있는 token ring 이 빠져 있다. 그럼 토큰링이 무엇인지 알아보도록 하겠다.
token ring 은 근거리 통신망을 나타내는 네트웍 연결 구조를 말한다. 이름에서 생각할수 있듯이 token ring 은 링형식으로 연결되어 있는 네트웍 연결 구조를 가지며, 각 연결호스트들은 서로들간에 메시지 교환을
위해서 token 을 포함하는 프레임을 교환함으로써, 메시지 충돌을 망지하면서 원하는 곳의 호스트로 메시지를 보낼수 있도록 한다. 각 호스트들은 router 가 될수도 있고 일반 호스트 컴퓨터가 될수도 있다.
아래에 token ring 작동의 원리를 간단히 설명하였다.
- 비어있는 정보 프레임이 링을 따라 끊임없이 순환한다.
- 만약에 호스트에 다른 목적지 호스트에 보내야할 데이타가 도착하면, 자신에게 그 프레임이 도착했을때, 빈프레임 속에
토큰을 삽입하고, 거기에 메시지와 목적지 호스트 주소를 삽입한다. 토큰은 0과 1의 비트값이며, 토큰을 삽입한다는 것은 0의
값을 1로 바꾼다는 뜻이다.
- 이 프레임은 링을 따라 선회하며, 각 호스트들에 의해 검사된다. 이 프레임이 목적지 호스트에 도착하면, 목적지 호스트는 이를 감지하고 프레임내의 toekn 을 다시 0으로 변경하고, 메시지를 가져오게 된다.
- 이 프레임이 다시 최초 메시지를 전송한 호스트로 되돌아오면, 호스트는 토큰이 0으로 변경되어 있음을 감지하고, 메시지가
제대로 송신되었다고 판단한다. 만약 토큰이 1이라면 수신한 호스트가 없다라는 의미가 될것이다. 토큰이 0으로 변경되어 있다면
호스트는 프레임으로부터 메시지를 제거하게 된다.
- 이런식으로 해서 프레임은 비어있는 상태로 순환하게 되며, 프레임이 비어있다는 건 메시지를 보낼수 있는 상태라는걸 의미한다.
위에서 사용한 프레임은 아래와 같은 패킷의 구조이다.
+------------+---------+----------------+------------+------------+ | flag | address | Data | frame num | flag | | (01111110) | | (0-4096 bytes) | | (01111110) | +------------+---------+----------------+------------+------------+
필자의 집은 리눅스 박스를 게이트웨이로 하는 홈네트워킹 환경이 구축되어 있는데(광케이블 사용) 필자집의 홈네트워킹 환경을 예로 들어서 ARP에 대해 더 자세히 알아보겠다.
+----------------+ | Gateway | | 210.205.210.1 | +----------------+ | ARP | | eth0 +----------------+ | 210.205.210.101| | Linux1 | | 192.168.0.1 | | Gateway | +----------------+ | eth1 ARP | ------------------------------------ | | | eth0 | eth0 +--------------+ +--------------+ | Linux2 | | Window | | 192.168.0.4 | | 192.168.0.20 | +--------------+ +--------------+
위는 필자의 홈네트웍 환경을 그림으로 나타낸것이다. Linux1 은 게이트 웨이로써 2개의 이더넷 카드를 가지며, eth0 은
디폴트 게이트 웨이인 210.205.210.1 과의 연결을 위해서 그리고 eth1 은 내부 LAN 연결을 위해서 사용된다.
eth0 인터페이스의 IP 는 DHCP 프로토콜에 의해서 210.205.210.101 로 자동 할당되었다. 아래는 Linux1 에서 arp 를 통해서 cache 에 남아 있는 arp 정보를 확인해본것이다.
[root@dream.com /root]$ arp Address HWtype HWaddress Flags Mask Iface 192.168.0.4 ether 00:50:BF:5E:F8:0E C eth1 210.205.210.1 ether 00:01:64:F2:1C:54 C eth0
내부 네트웍인 192.168.0.4 는 빈번하게 외부 네트웍과의 연결이 일어나므로 Linux1을 통과하게 되고 그런 이유로
arp cache 에 값이 남아 있음을 알수 있다. 210.205.210.1 은 210.205.210.0 주소를 관리하는
게이트웨이이며 Linux1 에서 외부로 빠져나가기 위해서는 반드시 210.205.210.1 을 거쳐야 함으로 계속적으로
cache 에 arp 정보를 유지하고 있음을 알수 있다.
여기에서 ping 을 이용해서 192.168.0.20 으로 패킷을 날리고 나서 arp 정보를 확인해보면 아래와 같이 arp cache 정보가 갱신되어 있음을 알수 있다.
[root@dream.com /root]$ arp Address HWtype HWaddress Flags Mask Iface 192.168.0.4 ether 00:50:BF:2C:7B:B2 C eth1 192.168.0.20 ether 00:50:BF:5E:F8:0E C eth1 210.205.210.1 ether 00:01:64:F2:1C:54 C eth0
arp cache 에 192.168.0.20 이 추가되었음을 알수 있다. 이제 www.joinc.co.kr 로 ping 을 날리면 www.joinc.co.kr 의 이더넷카드의 IP정보와 이더넷 주소가 arp 에 남게 될까?
답은 아니오 이다. 위에서 설명했듯이, arp 는 이더넷 프로토콜이므로 절대로 게이트웨이인 210.205.210.1 을 넘을수
없기 때문이다. www.joinc.co.kr 로 가는 패킷은 default gateway 인 210.205.210.1 로
보내지게 되고 라우터가 라우팅테이블 자료를 참조해서 www.joinc.co.kr 까지 패킷을 보내게 되는 것이다.
이제 Linux2 의 arp 정보를 알아보겠다.
[root@linux2 /root]$ arp Address HWtype HWaddress Flags Mask Iface 192.168.0.1 ether 52:54:05:FF:00:73 C eth0
게이트웨이와는 자주 통신을 해야 하니 arp 캐쉬에 정보가 남아 있을것이다. 이제 192.168.0.20 으로 ping 를
때리고 나서 arp 정보를 보면 192.168.0.20 의 이더넷주소 정보가 arp 캐쉬에 들어가 있음을 볼수 있을것이다.
[root@linux2 /root]$ arp Address HWtype HWaddress Flags Mask Iface 192.168.0.1 ether 52:54:05:FF:00:73 C eth0 192.168.0.20 ether 00:50:BF:5E:F8:0E C eth0
여기에서 최상위의 router 인 210.205.210.1 로 ping 을 보내면 arp 캐쉬에 들어가게 될까?
당연히 아니오 이다. 왜냐면 192.168.0.4 의 기본 게이트웨이인 192.168.0.1 바깥으로 넘어갈수 있는
Protocol 은 IP 프로토콜 이상이 되어야 하기 때문인데, arp 는 이더넷 프로토콜이므로 결코 바깥으로 나갈수 없게 되는
것이다.
어떻게 router 는 라우팅 테이블을 유지하는가
router 는 이웃하는 라우터가 단지 하나 일수도 있지만, 대부분의 경우, 여러개의 라우터와 이웃하고 있다. 그렇다면 router 는 router 에게 들어온 메시지의 경로에 맞는 라우터로 선택해서 내보내야 할것이다.
라우터는 이러한 지도를 갖는 routing table
이란걸 유지하고 있다고 앞에서 언급했었다. routing table에 유지되는 정보는 간단하다. 첫번째 필드에 목적지 어드레스를
가지고, 두번째 필드에 데이터그램이 라우팅될 인터페이스의 이름을 가지고, 세번째 옵션 필드로 네트워크를 통해 다음 스탭으로
데이타그램을 운반할 다른 머신의 어드레스를 가진다.
router 는 데이터그램의 IP의 헤더를 분석하여 목적지의 주소를 알아내고, 이 주소와 일치하는 필드를 routing
table 에서 검색하고, 라우팅될 인터페이스로 데이터그램을 보내게 된다. 유닉스 상에서 route 명령을 이용해서
routing table의 대략적인 모습을 볼수 있다. 아래는 필자의 리눅스 박스의 route 테이블의 내용이다.
[root@localhost /root]# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.100.0 * 255.255.255.0 U 0 0 0 eth0 127.0.0.0 * 255.0.0.0 U 0 0 0 lo default 192.168.100.1 0.0.0.0 UG 0 0 0 eth0
위의 경우는 LAN 에 Gateway 를 통해 묶여 있는 가장간단한 형태의 라우팅 테이블이다. 즉 LAN(192.168.100.0)으로 향하는 데이타그램과 loop back(127.0.0.0)으로 향하는 데이타그램을 제외한 모든 데이타 그램은 192.168.100.1 로 라우팅 되어라고 설정되어 있다.
그런데 이러한 routing table 은 어떻게 만들어지는것일까. routing table 유지를 위해서 "다이나믹 라우팅 프로토콜" 이라는 것들이 존재한다. 그중에서 가장 많이 사용하는것이 RIP(Routing Information Protocol) 이다.
RIP 는 중간정도의 네트워크 등에서 흔히 사용되는데, 라우터간 RIP를 계속적으로 교환함으로써, 라우팅 테이블을 유지하게 된다.
왜 RIP를 계속교환하는가? 초기 router 를 부팅시킬대 한번만 RIP를 교환해서 라우팅 테이블을 만들어 놓으면 되는가
아닌가? 안타깝게도, 우리가 알고 있는 네트웍은 완전한것이 아니다. 케이블이라면 선이 단절될수도 있고, 라우터가 다운 될수도
있으며, 새로운 라우터가 추가될수도 있을것이다. 그러므로 라우터 정보는 실행중에 동적으로 변화가 될수 있어야 할것이다. 아래의
예를 보자.
192.168.1.0 / 192.168.2.0 / 255.255.255.0 255.255.255.0 | +-------+ +-------+ | | | |ppp0 / ppp0 | | | eth0 |----| A |---------/----------| B |----| eth0 | | | / | | | | +-------+ +-------+ | |ppp1 ppp1| | | | | | | | +-------+ | | ppp0| |ppp1 | +---------| C |----------+ | | +-------+ | eth0 | --------- 192.168.3.0 / 255.255.255.0
A,B,C 는 라우터이며, Class C IP 네크워크를 지원한다. 라우터 A 의 라우팅 테이블은 분명히 아래와 같을 것이다.
# route add -net 192.168.1.0 netmask 255.255.255.0 eth0 # route add -net 192.168.2.0 netmask 255.255.255.0 ppp0 # route add -net 192.168.3.0 netmask 255.255.255.0 ppp1
그런데 A 와 B 사이의 케이블이 단절되어서, 네트웍 연결이 끊어졌다면 A에서는 B로 어떻게 메시지를 보낼까. 케이블이 연결되기
전까지는 절대 보낼수 없는 것일까 ? 그렇지 않다 C 는 여전히 B 와 연결되어 있고, A 와도 연결되어 있음으로 A ->
C -> B 의 과정을 통해서 패킷이 전달될수 있을것이다. 그러므로 라우팅 경로를 조정하여서 B 로 갈패킷을 C 로 보내면
될것이다.그러면 C에서는 알아서 B로 패킷을 보낼것이다. 다시 공사를 통해서 A 와 B 사이의 네트웍이 살아났다면, 어떻게 될까
? 여전히 A -> C -> B 의 경로를 가지게 되는건 대단히 비효율적이 될것이다. 이럴경우 다시 라우팅 테이블을
갱신해해서 곧바로 B로 가도록 해야할것이다.
RIP은 이처럼 동적으로 변화하는 경로를 그때그때 배정하기 위해서 필요한 프로토콜이다.
RIP의 중요 특징은 다음과 같다.
- 당연한 얘기지만 다양한 경로의 루틴이 있을때에만 필요하다.
- 네트웍변화에 적응하여 자동으로 라우팅 테이블을 변경한다.
- 중간 사이즈의 네트워크에 적합하다.
커다란 네트워크를 다루기 위해서는 OSFP(Open Short test Path Protocol)를 많이 사용한다. 이 문서는 수정될 수 있습니다. 최신 문서는 Joinc wiki에서 확인하세요. :::

TCP/IP 란
TCP/IP 가 나타난 이유는 컴퓨터간 "통신"을 위해서 이다. 통신을 얘기할때 빠지지 않는것이 통신의 역사인데 - 언어, 북,
연기, 전화.. 이런식으로 발전을 해왔다. 여기에서 발전을 하게된 계기는 새로운 도구의 발견(혹은 발명)이 결정적인 역할을 하고
있음을 알 수 있다.
TCP/IP 는 가장최근에 발명된 컴퓨터와 컴퓨터간의 지역네트워크(LAN) 혹은 광역네트워크(WAN)에서 원할한 통신을 가능하도록 하기 위한 "통신규약(Protocol)" 으로 정의할 수 있다. 최초 미국방성에서 구축한 ARANET 라는 프로토콜에서 시작되었으며, 후에 미국방위통신청(DAC-Defense Communication Agency)에서 컴퓨터간 통신을 위해서 TCP/IP를 사용하도록 한것이 그 시초가 되었다.
TCP/IP가 인기를 구가하게 된건 인터넷의 등장이 그 결정적인 역활을 했으며, 가장 인기있는 인터넷 서비스인 WWW,
EMAIL, TELNET, FTP 등 대부분이 TCP/IP 기반에서 만들어져있다. 인터넷으로 연결된 수많은 컴퓨터와 통신을
위해서 TCP/IP를 선택한 이유는 그 개방성에 있는데, 즉 하드웨어, 운영체제, 접속매체에 관계없이 동작할수 있다는점때문에,
인터넷 통신을 위한 핵심으로 선택되었다. 현재는 수천만대의 컴퓨터가 인터넷을 통하여 거미줄처럼 연결되어 있다.
TCP/IP 란 이름에서 알수 있듯이, TCP/IP 는 TCP + IP 의 2개의 프로토콜로 이루어져 있는데, 통상 IP 프로토콜 위에 TCP 프로토콜이 놓이게 되므로 TCP/IP 라고 부르게 되었다.
- IP - node(단말기)와 node 간의 데이타 패킷을 전송하기 위해서는 각 node 에 주소를 필요로 하는데(우편번호
같은) IP는 4바이트로 이루어진 주소번호를 사용하여서 각각의 node 를 구분하고, 목적지를 찾아가게 된다. 우리는 이를 IP 번호라고 하며, "192.168.100.100" 와 같은 점박이 3형제 형식으로 사용하게 된다. IP 는 Internet Protocol 의 줄임말이다. 숫자로된 인터넷주소를 위어서 원하는 컴퓨터를 식별하는건, 그리 쉽지 않기 때문에, IP주소를 인간이 식별하기 쉬운 Domain 네임으로 변환시켜주는 Name 서비스가 존재한다. 아무래도 www.yahoo.co.kr 이 211.234,109.2 이런것 보다는 외기가 수월할것이다.
- TCP - 서버와 클라이언트간에 데이타를 신뢰성있게 전달하기 위해 만들어진 프로토콜이다. 데이타는 네트웍선로를 통해
전달되는 과정에서 손실되거나 순서가 뒤바뀌어서 전달될수 있는데, TCP는 손실을 검색해내서, 이를 교정하고 순서를 재조합할수
있도록 해준다. Transmission Control Protocol 의 줄임말이다. 데이타를 전송하기 전에 데이타전송을 위한 연결을 만듦으로 연결지향 프로토콜 이라고 한다.
LAN 과 WAN 그리고 TCP/IP
흔히 LAN 은 Local Area Network 의 줄임말로 우리나라 말로 풀어쓰자면 지역내트웍(근거리 통신망) 이며 WAN 은 Wide Area Network 의 줄임말로 광역네트웍(원거리 통신망) 으로 해석할수 있을것이다.
즉 LAN 은 지역적으로 가까운 컴퓨터가 서로 연결(Network)된 상태를 말하며 WAN은 지역적으로 멀리떨어진 컴퓨터가 서로 연결 된 상태를 말한다.
다음의 그림은 이러한 LAN과 WAN의 구성을 보여주는 가장 단적인 그림이다.
+-------+ +-------+ +-------+ +-------+ +-------+ +-------+ | HOST1 | | HOST2 | | HOST3 | | HOST1 | | HOST2 | | HOST3 | +-------+ +-------+ +-------+ +-------+ +-------+ +-------+ | | | | | | | | | | | | =============================== =============================== LAN (Korea) | | LAN (Japan) | | +--------+ +--------+ | Router |---------| Router | +--------+ +--------+
HOST 와 HOST 그리고 HOST 와 Router 는 다양한 종류와 다양한 품질을 가지는 네트웍연결 회선으로 연결될수
있다(광케이블, 구리선, 인공위성등...). 통화품질이 다르다는 것은 데이타를 보내는중 데이타 손상이 일어날수도 있으며,
데이타의 순서가 뒤바뀔수도 있다는걸 의미한다.
데이타의 순서가 뒤바뀔수 있는 이유는, 패킷이 전달되는데 하나의 고정된 전달 경로만을 이용하지 않고 임의의 경로를 사용하기
때문인데, 위에서 말했듯이 각경로를 구성하는 회선의 품질이 다르므로, 먼저 보내어진 패킷이라도 나중에 보내어진 패킷보다 더
느리게 도착할수 있기 때문이다.(구리선으로 전달되는 패킷은 인공위성이나 광케이블로 전달된 패킷보다 아무래도 느리게 움직일
것이다.)
TCP/IP는 이러한 연결된 상태에서 서로 올바른 통신을 하도록 도와준다. 정확히 말하자면 TCP가 올바른 통신을 하도록 도와주는 기능을 가지고 있으며, IP는 이러한 기능없이 오로지 TCP 패킷을 전송하는 일만을 한다.
올바른 통신을 위해 TCP가 가지고 있는 기능은
- 패킷이 빠졌을경우, 재전송을 요청하는 기능
- 패킷에 일련번호를 줌으로써, 패킷의 순서를 재조하하는 기능
이다.
UDP와 TCP
위에서 데이타를 전송하기 위한 TCP 프로토콜에 대해서 설명했는데, TCP외에 UDP 라는 프로토콜 존재한다. 데이타를 전송한다는 점에서 TCP, UDP 모두 비슷하지만 특성에 있어서 약간의 차이가 있다. UDP 는 User Datagram Protocol 의 줄임말이다.
- TCP - 연결지향이며, 자체적으로 오류를 처리하며, 네트웍 전송중 순서가 뒤바뀐 메시지를 교정시켜주는 기능을 가지고 있다. 연결지향이란말은 데이타를 전송하는 측과 데이타를 전송받는 측에서 전용의 데이타 전송 선로(Session)을 만든다는 의미이다. 데이타의 신뢰도가 중요하다고 판단될때 주로 사용된다.
- UDP - 비연결지향이며, 오류를 처리하거나 순서를 재조합시켜주는 기능을 가지고 있지않다. 단순히 데이타를 받거나, 던져주기만 하는 프로토콜이다. UDP는 특히 실시간 멀티미디어 정보를 처리하기 위해서 주로 사용한다.
TCP를 실시간 멀티미디어 정보를 처리하는데, 사용할경우 TCP의 오류정정 특성상 메시지가 도착하지 않거나 할경우 다음 메시지를
받지 않고, 메시지 재전송을 요구하므로, 실시간으로 전송하기에는 그리 적당하지 않기 때문이다. 반면 UDP를 사용하면 중간에
패킷이 소실되더라도 개의치 않고 다음 패킷을 받아들이므로 실시간으로 메시지 처리가 가능하다.
물론 약간의 데이타 손실로 인한, 멀티미디어 데이타의 질이 떨어질수도 있으나, 화질이나 음질에 약간의 손상이 있더라도 계속적으로
서비스가 되는게 훨씬더 유리할것이다. 전화를 하는데, 약간 잡음이 섞인다고 해서, 잡은 정정하기 위해서 서로 통화를 못하는
사태가 발생하면 안되는것과 같은 이치이다.
여기에서는 주로 TCP 에 대해서 다룰것이며, UDP는 필요할경우 약간식 부연설명하도록 하겠다.
어떻게 TCP/IP 를 이용해서 컴퓨터간 데이타 통신이 가능한가 ?
지금까지 TCP/IP 그리고 UDP에 대한 개괄적인 내용을 살펴봤는데, 해결되지 않은 문제가 있다. 그렇다면, 각 컴퓨터간을 연결해주는 이더넷 카드를 통해서 어떻게 TCP/IP 메시지가 전달되는 것일까 ?
이것을 이해하기 위해서는 OSI 7 계층에 대한 이해가 필요하다. OSI 는 각종 시스템간의 연결을 위하여 ISO 에서 제안한 모델로써, OSI(Open System Interconnection Reference Model)에서 유추할수 있듯이, 시스템에 상관없이 서로의 시스템이 연결될수 있도록 만들어주는 모델이다.
OSI 는 아래와 같이 7개의 계층으로 되어 있다.
+---------------------+ | Application Layer | +---------------------+ | Presentation Layer | +---------------------+ | Session Layer | +---------------------+ | Transport Layer | +---------------------+ | Network Layer | +---------------------+ | Data Link Layer | +---------------------+ | Physical Layer | +---------------------+
컴퓨터와 컴퓨터사이의 데이타전송을 위해서는 위의 7개의 계층을 "직-간접적" 으로 거쳐서 전송이 되게 된다.
위와 같이 7개의 계층으로 나눈 이유는, 각 계층에 대한 캡술화와 은닉이 가능하기 때문이다. 캡슐화, 은닉에 대해서는 아마도
C++ 을 공부해 본적이 있다면 많이 들어본 개념일건데, 예를들어 서비스 개발자는 Application Layer 와
Prsentation Layer 만 신경쓰면 되며, 실지 어플리케이션 개발자는 Session Layer 와 Transport
Layer 정도만 신경쓰면 될것이다. Network Layer 계층 아래로는 거의 신경쓸 필요가 없을것이다. 마찬가지로
하드웨어를 만드는 사람은 Physical Layer 만 신경쓰면 되며, 그위의 계층에 대해서는 신경쓸필요가 없을것이다.(물론
개발자가 Application Layer 와 Presentation Layer 까지 몽땅 신경써서 개발하는 경우도 있지만 -
사실은 거의 대부분이겠지만)
OSI를 이렇듯 계층별로 나눔으로써, 각 계층에서 필요한 부분만을 개발자들이 신경쓰게 되고 통신서비스 개발시간을 줄일수 있도록 도와준다.
OSI 7 계층과 TCP/IP 4계층
TCP/IP 계층은 OSI 7계층을 더 단순화 시켜서 4개의 계층(Layer)로 만들어서 사용한다.
OSI 7 계층 TCP/IP 4 계층 +---------------------+ +---------------------+ | Application Layer | | Application Layer | +---------------------+ | | | Presentation Layer | | | +---------------------+ +---------------------+ | Session Layer | | Transport Layer | +---------------------+ | | | Transport Layer | | | +---------------------+ +---------------------+ | Network Layer | | Internet Layer | +---------------------+ | | | Data Link Layer | | | +---------------------+ +---------------------+ | Physical Layer | | Physical Layer | +---------------------+ +---------------------+
- Application Layer
이 계층은 네트웍을 사용하는 응용프로그램(FTP, Telnet, SMTP) 등으로 이루어지며, OSI 계층의 Aplication Layer 와 Presentation Layer 를 모두 포함한다.
- Transport Layer
계층의 이름에서 알수 있듯이, 도착을 원하는 시스템까지 데이타를 전송하기 위한 일을 하는 게층이다. OSI 모델의 Session
Layer 과 Transport Layer 를 포함하고 있으며, 각각의 시스템을 연결하고, TCP 프로토콜을 이용하여 데이타를
전송한다.
- Internet Layer
데이타를 정의하고 데이타의 경로를 배정하는일(라우팅)을 담당한다. 데이타를 정확히 라우팅 하기 위해서 IP프로토콜을 사용한다. OSI 의 Network Layer 과 Data Link Layer 를 포함한다.
- Physical Layer
물리적 계층 즉 이더넷 카드와 같은 하드웨어를 말한다.
TCP/IP 4계층에 의한 데이타 전송
그럼 실제로 TCP/IP 4계층을 이용해서 어떻게 데이타가 전송되는지 알아보도록 하자. 아래는 이러한 계층 통신의 가장 단적인
모습을 보여주는 그림인데, 현재 가장 많이 사용하는 인터넷 서비스중 하나인 WWW 을 예를 들어 그림을 그려 보았다.
+----------+ HTTP Protocol +----------+ | Browser | <- - - - - - - - - - - - - -> | Server | Application Layer +----------+ +----------+ ↓↑ ↓↑ +----------+ TCP protocol +----------+ | TCP | <- - - - - - - - - - - - - -> | TCP | Transport Layer +----------+ +----------+ ↓↑ ↓↑ +----------+ IP protocol +----------+ | IP | <- - - - - - - - - - - - - -> | IP | Internet Layer +----------+ +----------+ ↓↑ ↓↑ +----------+ Ethernet Protocol +----------+ | Etnernet | <- - - - - - - - - - - - - -> | Etnernet | Physical Layer +----------+ +----------+ ↓↑ ↓↑ ========================================================= TCP/IP 패킷 INTERNET
WWW (World Wide Web)은 더이상 설멍이 필요없는 유명한 서비스로써, HTTP (HyperText Transfor Protocol)이라는 프로토콜을 이용한다.
위의 그림을 설명해 보자면, 일단 사용자는 Mozilla 나 IE 같은 브라우저를 사용하여서 www.joinc.co.kr 같은
URL 입력을 통해서 웹페이지를 요청하게 될것이다.(www.joinc.co.kr 은 인간이 인식할수 있는 도메인명이고 Name
서비스를 이용하여 이것을 다시 IP 주소체계로 바꾸는 작업을 브라우저 내부적으로 하게 될것이다.)
그럼 사용자의 요청(문자 메시지가 될것이다)은 인터넷상에서 전달되기 용이한 패킷으로 만들기 위해서 TCP 패킷으로 만들어지게 된다.
이것은 다시 인터넷 상에서 원하는 주소로 이동할수 있도록 하기 위해서 IP 패킷으로 다시 만들어 지고(IP 패킷에는 자신의
주소와, 도착해야될 상대방의 주소정보가 들어있을것이다) 이것은 이더넷 카드로 보내어져서 Internet 으로 나가게 된다.
Internet 상에서는 원하는 주소로 TCP/IP 패킷을 보내기 위한 여러가지 장치들이 존재하는데(라우터, 토큰링 같은),
이들 장치를 통해서, www.joinc.co.kr 의 이더넷카드로 TCP/IP 패킷이 전달되게 된다. 그럼 이더넷 카드는
TCP/IP 패킷을 바로 윗 계층(Internet Layer)으로 보내는데, 여기에서는 IP 패킷을 분석해서, 이 패킷이 어디에서 왔으며, 그 도착지가 어디인지를 판단하게 된다.(물론 이는 IP주소 기반으로 판단한다)
그리하여 목적지가 자신이면 이것을 다시 Transport Layer 로 보내고, TCP 프로토콜을 사용하여, 메시지가 누락된게
있으면 다시 요청하고, 순서를 재조합하는등 통신 메시지를 검사해서 이것을 다시 Application Layer 에게 보낸다
Application Layer 에서는 웹서버(IIS, Apache 같은)가 통신메시지를 HTTP 프로토콜에 준하여, 검사를
하여서 사용자가 요청한 웹페이지를 읽어들여서, Transport 계층으로 보내게 된다. 웹페이지를 브라우저까지 전송하는 과정은
위의 정반대의 과정을 순차적으로 거치게 된다.
최종적으로 웹브라우저는 웹페이지를 받아서(text) 역시 HTTP 프로토콜에 준하여, 렌더링 작업을 거친후 화면에 뿌려주게 된다.
위의 그림에서 보면 알겠지만 각각의 계층은 각각의 계층만을 상관하고 있음을 알수 있다. 즉 Application Layer 에
위치하는 브라우저와 webserver 는 HTTP 프로토콜에 의해서 자신의 계층끼리만 통신을 하고, Transport Layer
은 역시 TCP 프로토콜에 의해서 Transport Layer 끼리 통시을 함을 알수 있을것이다. 말그대로 계층적 구조를
가지며, 각 계층은 대응되는 상대편의 계층에 대해서만 상관한다.
연결지향 이란 무엇인가 ?
TCP는 UDP와 달리 연결지향이라고 배웠었다. 그렇다면 연결지향이란 무엇을 의미하는것일까 ? 우리는 바로 위에서 TCP/IP
에 의해서 데이타가 어떻게 전송되어지는지를 알아봤는데, 데이타가 전송되기전에, Browser 와 Server 간의 연결을
성립하는 과정이 데이타를 전송하는 과정전에 이루어지게 된다. 연결을 만드는 과정은 이를테면 우리가 전화할때 어떤내용을 말하기에
앞서서, "안녕하세요 ?" "누구누구씨 맞아요" "아내 저 누구누구 맞습니다"라고 상대편을 먼저 확인하는 과정과 동일한
과정이다.
즉 데이타가 전송되기 전에, 먼저 Browser 는 Server 에 "서버 잘있읍니까?" 라고 메시지를 보내고, Server 는
다시 Browser 에게 "서버 준비되어 있으니, 데이타 보내시요" 라는 메시지를 보내고 Browser 는 다시 서버에게 "네,
그럼 지금부터 데이타를 보내겠습니다" 라고 서로 의 존재를 확인하는 절차를 수행한후, 정식 데이타를 교환하기 위한 통신선로를
개설하게 된다.(통신선로를 하나 만들기 위해서는 3번의 데이타 전송이 일어나게 되므로, 이것을 세번악수 기법(Three handshake) 이라고 한다. 자세한 내용은 나중에..)
모든 정식데이타는 연결된 통신선로를 통해서 교환되게 되며, 이러한 이유로 TCP를
"연결 지향" 프로토콜이라고 부르는 것이다. UDP 는 이러한 과정이 없이 단순히 데이타만을 전송함으로 "데이타 그램" 프로토콜이라고 부른다.
결론
이상 TCP/IP 의 개념에 대해서 알아보았읍니다.
위의 내용은 제가 대학원에서 배우는 강의 내용을 공부도 할겸, 복습도 할겸 해서 만든 내용입니다. 그러므로 내용은 강의순서와 비슷하게 구성될겁니다. 다음 번엔 TCP/IP에 대한 좀더 자세한 내용에 대해서 알아보도록 하겠습니다. :::

|