TCP/IP Illustrated Vol. 1의 관련 내용을 요약한 것이고 이하 전부 IPv4 기준 내용임.
ICMP 메시지 일반 형태IP 헤더 20 + 타입 1 + 코드 1 + 체크썸 2 + 내용
- ICMP 에러 메시지 보낼 때는 내용에 IP 헤더와 IP 데이터그램 첫 8바이트를 붙여서 보낸다.
- ICMP 에러 메시지, IP 브로드캐스트/멀티캐스트 패킷, 링크 계층 브로드캐스트, 첫번째가 아닌 IP 프래그먼트, 출발지 주소가 단일 호스트를 지정하지 않는 경우는 ICMP 에러 메시지를 발생시키면 안 된다. (패킷 스톰 위험 -_-)
ICMP type / code / 설명0 / 0 / echo reply
3 / 0 / network unreachable
3 / 1 / host unreachable
3 / 2 / protocol unreachable
3 / 3 / port unreachable
3 / 4 / fragmentation needed but don't-fragment bit set
3 / 5 / source route failed
3 / 6 / destination network unknown
3 / 7 / destination host unknown
3 / 8 / source host isolated
3 / 9 / destination network administratively prohibited
3 / 10 / destination host administratively prohibited
3 / 11 / network unreachable for TOS
3 / 12 / host unreachable for TOS
3 / 13 / communication administratively prohibited by filtering
3 / 14 / host precedence violation
3 / 15 / precedence cutoff in effect
4 / 0 / source quench
5 / 0 / redirect for network
5 / 1 / redirect for host
5 / 2 / redirect for type-of-service and network
5 / 3 / redirect for type-of-service and host
8 / 0 / echo request
9 / 0 / router advertisement
10 / 0 / router solicitation
11 / 0 / time-to-live equals 0 during transit
11 / 1 / time-to-live equals 0 during reassembly
12 / 0 / IP header bad (catchall error)
12 / 1 / required option missing
13 / 0 / timestamp request
14 / 0 / timestamp reply
15 / 0 / information request (obsolete)
16 / 0 / informatino reply (obsolete)
17 / 0 / address mask request
18 / 0 / address mask reply
여기부터 타입/코드는 위의 표를 참조하고 아래는 체크썸 이후 패킷 부분에 대해서만 기술함.
ICMP Address Mask Request and Replyidentifier 2 + sequence number 2 + subnet mask 4
identifier와 sequence number는 아무거나 원하는대로 쓰면 됨. 응답은 당연히 맞춰서 해야 하고. 디스크 없는 장비들이 서브넷 마스크를 얻어올 때 사용함. 이것 대신 BOOTP 프로토콜 사용할 수도 있음. 마스크 응답할 때 유니캐스트로 해야 하는데 고대의 장비 중에는 브로드캐스트하는 녀석도 있다고 함.
ICMP Timestamp Request and Replyidentifier 2 + sequence number 2 + 요청 보낼 때 타임스탬프 4 + 요청 수신한 시점의 타임스탬프 4 + 응답 전송할 시점의 타임스탬프 4
타임스탬프는 UTC 기준이고 지난 자정부터 경과한 시간을 밀리세컨드 단위로 계산한 값임. 요청 보낼 때 타임스탬프 - 요청 수신한 시점의 타임스탬프한게 음수가 나올 수도 있음을 유의할 것. 원래 수신 시점과 전송 시점 타임스탬프는 미묘하게 차이가 있어야 되는데 다들 무시하고 동일하게 쓴다고 함.
시간대까지 고려하더라도 아무튼 하루 정도 밖에 보정할 수 없음. 제대로 맞추고 싶으면 NTP 써야 함. 마지막으로 UTC가 아닌 값을 타임스탬프로 찍을 때는 최상위 비트를 켜서 UTC가 아님을 표시해야 함.
ICMP Port Unreachable Error오류를 일으킨 IP 데이터그램의 헤더 20 + UDP 헤더 8
IP 헤더와 UDP 헤더를 내용에 포함해서 전송해주니까, IP 헤더의 프로토콜, UDP 헤더의 출발지/목적지 포트를 이용해서 실제 문제를 일으킨 유저 프로세스를 찾아 ICMP 오류를 보내주면 됨. UDP인데 connect 함수가 있는 이유가 이것임. connect 안 하면 ICMP 와도 그냥 씹고 버리는거고~
Ping: ICMP Echo Request and Replyidentifier 2 + sequence number 2 + 아무거나 데이터
유닉스는 identifier 부분에 프로세스 ID를 박고, sequence number는 echo 패킷 보낼 때마다 1씩 증가시킨다고 함. 응답 받을 때 identifier를 보고 유저 프로세스에게 다시 전달해주고, 유저 프로세스는 sequence를 보고 자기가 보낸 패킷에 대한 응답인지 확인한다. 데이터 부분에 타임스탬프를 박아놓으면, 에코 응답은 똑같이 복사해서 보내게 되어있으니 나중에 얼마나 시간이 소요되었는지 확인할 수 있다.
Traceroute: ICMP time exceeded and ICMP port unreachable원래 IP Record Route 옵션으로 IP 헤더의 옵션 필드에 저장할 수 있긴 한데, 너무 옵션 길이를 박하게 줘서 지나간 라우터 주소를 최대 9개까지만 기록 가능하다. 단방향성은 대부분의 구현에서 에코 쓰면 옵션도 복사를 해주니까 별 문제가 안 되는데, 막상 돌아오는 경로를 담기엔 역시 옵션 길이가 너무 딸린다. 그래서 TTL을 이용하는 방식을 널리 쓰게 된 것이다.
TTL을 1부터 하나씩 늘려가면서 보내면 ICMP time exceeded 메시지가 날아오고, 최종적으로 호스트에 도착했을 때는 ICMP port unreachable 메시지가 날아오게 만들어서 경로를 식별한다. 물론 마지막에 ICMP port unreachable이 뜨게 하려면 거의 쓰일 가능성이 없는 높은 포트 번호(33435)를 찍어야 되고, 이 포트 번호도 하나씩 늘려가면서 요청과 응답을 연관시킨다. 응답을 프로세스로 연결하는 부분은 처음에 요청 보낼 때 출발지 포트 번호를 32768과 OR해서 만들어내는 것으로 해결한다.
IP Record Route 옵션을 쓰는 경우는 항상
밖으로 나가는 인터페이스 기준으로 IP가 기록되지만, TTL을 이용한 경우에는 항상 UDP 데이터그램이
도착한 인터페이스의 IP가 기록된다.
ICMP Redirect새로운 라우터 IP 주소 4 + 원본 IP 헤더 + 원본 IP 데이터그램의 첫 8바이트
라우터로 들어온 패킷의 다음 경로를 살펴봤더니
들어온 인터페이스로 다시 나가야 되는 상황인 경우, 호스트가 라우터를 잘못 찍어 보낸 것이므로 호스트에게 ICMP Redirect 패킷을 보내준다. 호스트는 ICMP Redirect를 받으면 악성 패킷이 아닌지 몇 가지 확인을 해보고 라우팅 테이블에 경로를 추가한다.
4.4BSD는 ICMP Redirect 패킷을 수신하면 아래와 같은 기준으로 검사한다.
- 새 라우터는 직접 연결된 네트워크에 있어야 한다.
- 현재 라우팅 테이블을 이용했을 때 목적지에 대응하는 해당 라우터에서 온 패킷이어야 한다.
- 원래 Redirect 목적이 다른 라우터를 이용하라는 것이니 자기 자신을 쓰라고 하는 패킷은 버린다.
- 변경되는 경로는 indirect 경로이어야 한다. (indirect는 전송 시 IP 주소와 링크 계층 주소가 다른 것을 의미함.)
ICMP Redirect는 라우터만 전송할 수 있으며 호스트에게만 전송한다. 라우터끼리 라우팅을 조정할 때는 별도의 라우팅 프로토콜을 이용해야지 ICMP Redirect를 쓰면 안 된다.
호스트는 관리의 귀찮음으로 인해 기본 게이트웨이만 설정하는 경우가 대부분인데, 다수의 네트워크가 물려있는 경우 ICMP Redirect로 호스트의 라우팅 테이블을 자동 조정할 수 있게 되니 네트워크 관리자 입장에서는 편한 것이라. 이 외에 ICMP로 라우터를 검색하는 방법이 또 있다.
ICMP Router Descovery (RFC 1256)
ICMP router solicitation message
미사용 4 (0으로 고정)
ICMP router Advertisement message
라우터 주소 수 1 + 항목 크기 1 (2로 고정) + 유효기간 (초 단위, 보통 30분) 2 +
{라우터 주소 4 + 선호도 4} 여러 개
선호도는 큰 값일수록 같은 서브넷의 다른 라우터보다 선호된다는 것을 의미하고, 0x80000000으로 쓰면 (최상위 비트 1) 기본 라우터로는 쓰지 말라는 의미임. 광고 주기는 450~600초 정도. 라우터 인터페이스를 다운시키는 경우에는 유효기간을 0으로 해서 전송하니 호스트는 이런 패킷을 받으면 라우팅 테이블에서 바로 삭제하면 된다. 호스트는 보통 부팅 후 3초 간격으로 3번 라우터 주소 요청 (solicitation)을 전송한다.
프라이머리와 백업 라우터가 있는 경우 프라이머리 라우터의 선호도 값을 크게 해놓으면 만사 오케이~
ICMP Source Quench Error미사용 4 (0으로 고정) + IP 헤더와 원본 IP 데이터그램의 첫 8바이트
버퍼가 고갈되면 전송자에게 그만 보내라고 에러 메시지를 보낸다. 흐름 제어용. 1987년 나온 RFC 1009에서는 라우터의 버퍼가 고갈되면 Source Quench 에러를 반드시 보내도록 되어 있으나, 1993년 새로 나온 RFC에서는 라우터에서 Source Quench 에러를 내지 말도록 명시하고 있다. 네트워크 대역폭만 잡아먹고 비효율적인 방식인데다 혼잡 제어를 공정하게 할 수 없기 때문.