2012년 7월 28일 토요일

TCP IP info

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 프로토콜은 "연결지향 프로토콜" 이라고 말한다.
그림 1. 전 이중통신 선로
TCP 는 이러한 연결을 설정시 위에서의 그림에서와 같은 전 이중 통신 선로를 개설한다. 하나는 읽기 전용의 선로이며, 다른 하나는 쓰기 전용의 선로로써, 각각의 전용선로를 이용함으로 써 읽기와 쓰기를 동시에 할수 있게 된다. 이것은 Unix 에서 IPC 목적으로 pipe 를 생성할때, 읽기와 쓰기전용의 파이프를 동시에 생성하는것과 동일한 원리이다.
TCP 헤더에는 위의 TCP 의 특성을 충족시켜주기 위한 여러가지 기능을 가지는 필드들로 구성되어 있다. 우리는 다음장에서 TCP 헤더의 이러한 필드들을 분석함으로써, 어떻게 TCP 가 서버 클라이언트간 연결을 만들고, 신뢰성 있도록 데이타를 전달하는지 알아보게 될것이다.

1. TCP 헤더 구조

TCP 는 다음과 같은 헤더 구조를 가진다. 두 호스트 사이에 전송되는 TCP 데이타 단위를 세그먼트라고 부른다. 그러므로 TCP 세그먼트는 TCP 헤더 + DATA 가 될것이다. 다음은 TCP 세그먼트의 구조이다.
그림 2. TCP 헤더 구조


source port 는 메시지를 보내는 측에서 통신을 위해 사용하는 port 번호이며, destination port 는 목적지, 즉 메시지를 받는측의 통신 port 번호이다.
여기에 있는 port 번호와 더불어 IP 헤더에 있는 source/destination address 를 이용하면 유일하게 식별되는 통신연결을 만들수 있게 된다.
아마도 IP 의 출발지/목적지 주소와 TCP 헤더의 출발지/목적지 포트 번호가 어플리케이션간 통신을 위한 가장 핵심이라고 할수 있을것이다. 다른 정보들은 통신을 원할하도록 도와주기 위해서 부가적으로 존재하는 것이라고 볼수 있다.
이들 포트번호의 크기는 16bit 크기를 가진다. 그러므로 대략 65536 만큼의 포트를 가질수 있을것이다.

SEQUENCE NUMBERTCP 세그먼트안의 데이터의 송신 바이트 흐름의 위치를 가리킨다.

ACKacknowledgment number 라고 말한다. 다음에 받을것으로 예상되는 데이타 옥텟의 순서번호를 나타낸다.

HLENTCP 세그먼트의 길이를 정의한다.

RESERVED현재는 사용하지 않지만, 나중을 위해서 예약된 필드이다.

CODE BITS세그먼트의 용도와 내용을 결정하기 위해서 사용된다. 각각 URG, ACK, PSH, RST, SYN, FIN 을 나타낸다.

OPTION & PADDING옵션은 말그대로 옵션이다. TCP 헤더의 정보를 좀더 확장시키고자 할때 사용한다. PADDING 은 32bit 크기를 채우기 위해서 사용된다.

CHECKSUMTCP 세그먼트 데이타는 중간에 훼손될수 있으며, 변조될수도 있다. 그러므로 이를 체크할수 있는 장치가 필요하다. CHECKSUM 을 만드는 방법(알고리즘)은 기회가 되면 별도로 설명하도록 하겠다.

2. 실제 통신상에서 TCP 패킷의 내용을 살펴보자

위에서 각 TCP 필드에 대한 설명을 해보았지만, 솔직히 위의 정보만을 가지고는 뭐가 뭔지 도대체 알수가 없을 것이다. 그래서 이번에는 실제 TCP/IP 통신이 어떻게 이루어지는지에 대해서 알아보고 이러한 통신이 이루어지도록 어떻게 TCP/IP 패킷(세그먼트)가 전송되어지는지 알아보도록 하겠다.

테스트 프로그램 준비
셈플로 알아보는 소켓프로그램 에서 제작한 적이 있는 우편번호 서버/클라이언트 프로그램을 이용해서 테스트 하도록 할것이다. 서버 프로그램의 이름은 zipcode 이며 클라이언트 프로그램의 이름은 zipcode_cl 이다.
이와 더불어 tcp/ip 패킷분석을 위해서 tcpdump 를 사용할것이니 준비해놓기 바란다. (아마도 기본 설치되어 있겠지만)

테스트 방법테스트를 가장 효과적으로 수행하기 위해서는 서버와 클라이언트가 별도의 네트웍에 묶여 있는게 가장 좋겠지만, 여의치 않을경우 하나의 서버에 서버와 클라이언트를 두고 테스트를 해도 관계 없다.
여기에서의 테스트는 서버와 클라이언트가 별도의 네트웍환경에 묶여있는 것을 기준하여 이루어질것이다.
그림 3. 서버/클라이언트 테스트 환경

Server 은 Port 번호 4445 로 연결하도록 할것이다.

서버와 클라이언트간의 연결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  (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  (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  (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 헤더정보만을 포함하고 있으며, 그외의 아무런 다른 정보도 포함하고 있지 않음을 알수 있다.


패킷 분석을 통해서 알아보는 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 가 세팅되어 있음을 알수 있다.
이상 꽤 복잡한것 같지만 곰곰히 생각해 보면 별거 아니란걸 알수 있을것이다.

패킷 분석을 통해서 알아보는 연결 종료연결과는 좀 다르다. 완전한 종료를 위해서는 아래와 같이 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  (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  (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  (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 
패킷 분석방법은 위에서 모두 설명했으니 굳이 다시 설명하진 않겠다. 주의 해서 볼점은 CODE BITS 부분이다. ---- 1 번을 보면 CODE BITS 가 11 로 설정되어 있음을 볼수 있다. 이를 2진수로 변환하면 10 00 01 이다. FIN 비트 가 세팅되어 있음을 알수 있다.

실 데이타 전송실 데이타를 전송할때는 연결/종료 와 같은 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  (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  (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  (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  (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 에서 부터 edfd 까지가 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 내용이다.

댓글 없음:

댓글 쓰기

국정원의 댓글 공작을 지탄합니다.

UPBIT is a South Korean company, and people died of suicide cause of coin investment.

 UPBIT is a South Korean company, and people died of suicide cause of coin. The company helps the people who control the market price manipu...