본문 바로가기
코스웨어/10년 시스템제어

시스템 제어 일일 보고서 - 8조 김민철(4번)

by 알 수 없는 사용자 2010. 5. 18.
728x90
반응형

TCP/IP 프로토콜
 
- 인터넷에서 사용하는 핵심적인 프로토콜은 TCP 와 IP 로, 이를 포함한 각종 프로토콜을 총칭
 - 일반적으로 운영체제에서 그 구현을 제공, 일반 application 은 운영체제가 제공하는 TCP/IP 프로토콜의 서비스를 사용하여 통신을 수행

Application 간 통신을 수행하기 위한 요구조건
 
- 통신할 대상(종단 시스템 자체, 종단 시스템에서 수행되는 Application )
 - 상호 약속된 방법
 - 전송 오류 확인 기능
 - 오류 발생 시 재전송 기능
 - 데이터의 순서 관계 유지 등 

Network Access layer( 네트워크 엑세스 계층 : 1계층 )
 
- 물리적 네트워크를 통한 실제적인 데이터 전송을 담당
 - 구성요소 : 네트워크 하드웨어, 디바이스 드라이버
 - 물리 주소( Physical address = MAC address ) 를 사용하여 통신 수행

Internet layer( 인터넷 계층 : 2계층 )
 
- 네트워크 액세스 계층의 도움을 받아, 전송 계층이 내려 보낸 데이터를 종단 시스템까지 전달하는 역할
 - 주소를 지정하는 방법이 필요하며 물리 주소 대신 소프트웨어적으로 정의된 논리 주소를 사용한다. 이를 IP 주소( Internet Protocol address ) 라고 한다.

Routing ( 라우팅 )
 
- 목적지까지 데이터를 전달하기 위한 일련의 작업
 - 라우팅을 위한 정보 획득 작업
 - 라우팅 정보를 기초로 실제 데이터를 전달( Forward ) 하는 작업

Transport layer ( 전송 계층 : 3계층 )
 
- 최종적인 통신 목적지를 지정하고, 오류 없이 데이터를 전송하는 역할
 - 라우터
 - 통신의 최종 목적지는 해당 컴퓨터에서 실행되고 있는 프로그램(프로세스) 인데, 이를 지정하는 일종의 주소를 사용할 필요가 있다.
이것이 포트번호( Port number ) 가 된다.
 - TCP/IP 프로토콜에서 전송 계층에 해당하는 프로토콜로는 TCP( Transmission Control Protocol )UDP( User Datagram Protocol ) 가 있다. 

TCP

UDP

연결형(connection-oriented) 프로토콜

- 연결을 해야 통신 가능

비연결형(connectionless) 프로토콜

- 연결 없이 통신 가능

데이터 경계를 구분하지 않음

- 바이트 스트림(byte-stream) 서비스

데이터 경계를 구분함

- 데이터그램(datagram) 서비스

신뢰성 있는 데이터 전송

- 데이터를 재전송함, 순서보장 됨

비 신뢰적인 데이터 전송

- 데이터를 재전송하지 않음, 순서 보장 안됨

1 대 1 통신(unicast)

1대1 통신(unicast), 1대다 통신(broadcast), 다대다 통신(multicast)

Application layer ( 응용 계층 : 4계층 )
 - 응용계층( Application Layer) : 최상위 계층, 사용자 프로세스들이 접속하는 계층,
 - 표현계층(Presentation Layer) : 네트워크를 통해 전송되는 정보의 표현방식 관리, 암호화, 정보 압축
 - 세션계층( Session Layer ) : 두 통신 프로그램간의 데이터 교환을 관리하는 역할.

PCAP
- 연결된 장치명을 구해 낸다.

char * pcap_lookupdev(char * errbuf);

- 장치명을 이용해서 해당 장치의 ID를 획득한다.(장치를 연다.)
pcap_t * pcap_open_live(char * device,int snaplen,int promisc,int to_ms, char * ebuf);

- 열린 장치로 부터 패킷이 오길 기다리다 패킷이 도착하면 캡쳐한다.(대기 시간및 캡처 방식은 장치를 열대 설정)

u_char * pcap_next(pcap_t * p,struct pcap_pkthdr * h)

- 이더넷 구조체를 이용해서 이더넷 정보를 읽어 낸다.

struct ether_header * header;

- 장치 ID를 사용해서 열린 장치의 닫는다.
pcap_close(pcap_t * p);

 

pcap_next()를 통해 캡처한 패킷의 데이타를 사용해서 이더넷 정보를 구하기 위해 구조체를 이용해서 값을 구할수 있는데 이더넷 해더의

마지막 값인 ether_type을 통해 다음에 있을 프로토콜의 타입을 알 수 있다.

struct ether_header
{
  u_int8_t ether_dhost[ETH_ALEN];   //목적지 장치의 주소(물리주소) ETH_ALEN 은 6이다.
  u_int8_t ether_shost[ETH_ALEN];   //출발지 장치의 주소(물리주소)
  u_int16_6 ether_type;     //프로토콜 ID를 나타낸다.
}

 

프로토콜의 타입은 /usr/include/net/ethernet.h 에  이더넷 구조체와 함께 정의 되어 있으

며 다음과 같다.

ETHERNET_PUP  0x0200  /*Xerox PUP*/
ETHERNET_IP  0x0800  /*IP*/
ETHERNET_ARP  0x0806  /*Address resolution*/
ETHERNET_REVARP  0x8035  /*Reverse ARP*/

 

위와 같이 정의되어 있으며 이더넷 정보를 담은 구조체를 header라 가정하면 header->ether_type의 값과 위값을 비교해서 프로토콜의 타입을 알아낼 수 있다. 여기서 주의 할 점은 header->ether_type의 값은 네트워크 바이트인 빅인디안 방식이기 때문에 리틀엔디안 방식을 사용하는 인텔 CUP에서는 리틀 엔디안 방식으로 변형 후 비교를 해야한다. 네트워크 바이트 오더를 호스트 바이트 오더인 리틀 엔디안을 변형 시켜주는 함수인 ntohs()를 사용해서 변형 할수 있다. ntohs함수의 기능은 man 페이지를 이용해서 알수 있다.

변형 후 에는 다음과 같이 케이스문을 사용하거나  if문을 사용는 등의 비교를 할 수 있게 된다. 

switch( ntohs( header->ether_type ) )
{
  case ETHERNET_PUP:
  break;
  case ETHERNET_IP:
  break;
}

 

- 아이피 헤더 정보 분석

이더넷 헤더의 프로토콜 타입이 IP 인 경우라면 패킷의 이더넷 다음부분에는 IP 헤더정보가 오게 된다.

IP 헤더는 이더넷과 마찬가지로 헤더 구조체가  존재하며 구조체의 내용은 다음과 같으며 구조체와 프로토콜 타입에 대한 정의는

/usr/include/netinet/in.h 에 프로토콜에 타입에 대한 정의가 되어 있으며 /usr/include/netinet/ip.h 에 IP구조체가 정의 되어 있다.

ip 구조체의 내용은 다음과 같으며 리틀엔디안과 빅 엔디안의 구조체 맴버가 다르게 설정되어 있다는 것을 볼 수 있다.


struct ip
{#if __BYTE_ORDER == __LITTLE_ENDIAN
  unsigned int ip_hl:4;  /*header length */
  unsigned int ip_v:4;    /*version*/
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
  unsigned int ip_v:4;    /*version*/
  unsigned int ip_hl:4;  /*header length*/
#endif
  u_int8_t ip_tos;  /*type of service*/
  u_short ip_len;  /*total length*/
  u_short ip_id;  /*identification*/
  u_short ip_off;  /*fragment offset field */
#define IP_RF 0x8000  /*reserved fragment flag*/
#define IP_DF 0x4000  /*dont fragment flag*/
#define IP_MF 0x2000  /*more fragments flag*/
#define IP_OFFMASK 0x1fff  /*mask for fragmenting bits*/
u_int8_t ip_ttl;  /*time to live*/
u_int8_t ip_p;  /*protocol*/
u_short ip_sum;  /*checksum*/
struct in_addr ip_src, ip_dst;    /*source and dest address*/
}; 

읽어 들이 패킷정보를 IP구조체가 가리키게 하기 위해선 이더넷 헤더 크기만큼을 이동해야 한다. 사용예는 다음과 같다.

pcap_next를 통해 구한 패킷의 시작 주소에서 이더넷 해더 만큼을 이동하면 그만이다.

struct ip * IPheader;
IPheader = (IP*)(date+sizeof(struct ether_header));

 

이후 부턴 IPheader 의 맴버를 통해 IP헤더의 내용을 구할수 있게 된다.

 

IP헤더는 다음과 같은 내용으로 구성 되어 있다.

VER(버전)                  구조체맴버 =>    IPheader->ip_v

버전을 나타내는 필드로서 IPv4 패킷일 경우에는 4가 들어가고 IPv6일 경우에는 6이 들어가게 된다. 현재는 거의 4를 사용하기 때문에 4로 설정되어 있지만 향후 6이 많이 생기게 되면 6으로 포기될 부분이다.

 

HLEN (헤더 길이)          구조체맴버 =>    IPheader->ip_hl

IP헤더 길이를 나타내는 필드며 길이는 보통 옵션의 유무에 따라서 20~60바이트 까지로 가변적이다. 이러한 헤더의 길이는 워드 단위로(4바이트) 나누어 나타내며 헤더의 길이가 20바이트라면 20/4 = 5 이기때문에 HLEN

의 값은 5가 된다.

 

Total length(전체 길이)   구조체맴버 =>    IPheader->ip_len

헤더와 데이터 길이를 포함한 전체 길이를 바이트 단위로 나타낸다. 16비트 크기이기 때문에 65535바이트 까지 표현할 수 있지만 네트워크의 물리적 NIC에 의해 제한 받는다. 일반적으로 사용하는 이더넷은 1500 바이트가 최대 이며 46바이트가 최소이다. 참고로 물리 매체에 따라 최대로 보낼수 있는 데이터그램 크기를 MTU(Maximum Transfer Unit)라 부르는데 각 물리 매체에 따른 MTU는 아래와 같다.

  네트워크                         MTU

hyperchannel                  65535

16Mbps token ring(IBM)   17914

4Mbps token ring(IBM)      464

ATM                               9180

FDDI                               4352

Ethernet                         1500

X.25                                576

 

Identification(식별자)        구조체맴버 =>    IPheader->ip_id

Identification필드는 패킷의 유일한 식별자로서 각각의 IP패킷을 유일하게 구분해 준다. 특히 패킷이 단편화 되었을때 사용되는 부분으로써 어떤 원본의 일부임을 나타내는지를 알리는 부분이기도 하다. 단편화란 물리 매체마다 전송 패킷의 길이가 달라 해당 매체에 맞게 자르는 것을 말하는데 다음에 있을 Flags비트를 이용해서 이 단편화를 하지 못하게 설정할수 있다. 이렇게 설정되어 단편화 되지 못하게 한다면 이패킷은 그곳에서 폐기되며 폐기되었다는 정보를 출발지로 보내게 된다.

 

Flags(플래그)        구조체맴버 =>    IPheader->ip_off

IPheader->ip_off의 상위 3비트가 Flags 비트이며 3비트중 제일 처음오는 비트는 사용되지 않으며 두번째 오는 비트(Do not fragment)가 1이라면 해당 패킷에 대해서는 단편화할 수 없다는 표시다. 마지막 비트는 More fragment 비트로 이비트가 1로 설정되었다면 패킷이 단편화 되었는데 아직 끝이 아니라는 의미다.

 

Fragmentation offset(단편화 오프셋)      구조체맴버 =>    IPheader->ip_off

IPheader->ip_off의 상위 3비트를 제외한 나머지 13비트가 단편화 오프셋에 해당된다.

단편화 오프셋은 패킷이 단편화 되었을 때 단편화 순서를 설정하는 부분이다. 1400바이트 짜리 패킷이 최대 데이타 크기 512바이트의 세 개의 패킷으로 단편화 되었다면 단편화 오프셋의 값은 데이터 시작부분의 값에 8을 나눈 값이 된다. 예를 들어 첫번째 단편화 패킷은 데이터의 0바이트 부터 시작하기 때문에 0/8 = 0의 결과에 따라 단편화 오프셋 필드의 값은 0이되고 두번째 패킷은 512 바이트 부터 시작하기 때문에 512/8 = 64의 결과에 따라 64가 된다.

 

Time to live(수명)           구조체맴버 =>    IPheader->ip_ttl

Time to live는 줄여서 TTL이라 부르는데 , TTL 값은 패킷이 네트워크 내에서 영원히 떠돌아 다니지 않도록 하기위해 패킷의 생존 기간을 설정하기 위한 필드이다. 처름 설정된 TTL값이 라우터또는 호스트를 하나씩 지나갈때마다 1씩 감소하여 0이되면 해당 패킷을 받은 라우터는 패킷을 버리고 발신지로 ICMP패킷을 보내준다.

 

Protocol(프로토콜)             구조체맴버 =>    IPheader->ip_p

IP패킷이 담고 있는 데이터가 어떤 프로토콜인지 나타내는 필드다. 해당 프로토콜 분석을 위해서는

 /usr/include/netinet/in.h 내에 정의되어 있는 값을 비교 하면 된다.

 

Header checksum(헤더 체크섬)   구조체맴버 =>    IPheader->ip_sum

IP 패킷의 헤더가 정상적인지 검사하는 데 사용되는 체크섬 값이 설정된 필드다. 패킷을 받는 목적지 호스트는 체크섬을 확인하여 결과가 다르다면 패킷을 버린다.

 

Source IP Adderss와 Destination IP Address(발신지 IP와 목적지 IP)

구조체맴버 =>    IPheader->ip_src, IPheader->ip_dst

목적지와 출발지의 IP가 설정되어 있으며 헤더 분석을 위해 값을 보기 위해선 inet_ntoa(IPheader->ip_src)

를 사용해서 네트워크 바이트 오더인 아이피를 .표기 방식으로 바꾸어 문자로 변형해 준후 문자열로 출력하면 확인 할수 있다.

 

 - 패킷 분석을 위한 구조체 사용

패킷의 내용을 분석 하기위해선 구조체의 맴버를 이용해야 하는데 패킷이 네트워크 바이트 오더인 빅엔디안 방식이기 때문에 호스트 오더형인 리틀엔디안으로 변형후 출력하거나 비교 해야 한다. 2바이트 형인 맴버들은 ntohs함수를 사용해 변형해 주어야 하며 IP같은 경우는 inet_ntoa함수를 사용해 변형해 주어야 한다.

변형해 주어야 하는 맴버로는 ip_src,ip_dstip_len,ip_id,ip_off,ip_sum 이 있다.

ip_off 같은 경우 상위 3비트와 하위 13비트를 분리해야 하므로 /usr/include/netinet/ip.h 에 정의 되어 있는 마스크 값을이용해서 &연산을 해서 원하는 값을 비교 할 수 있다.

728x90