컴퓨터 네트워크

[Linux] traceroute 소스코드 분석

:) :) 2024. 9. 27. 17:21

네트워크 공부를 하던 중

패킷의 목적지까지의 경로분석을 해주는 유틸리티인 traceroute가 어떻게 생겼는 지(동작하는 지)를

알아보기 위한 포스팅입니다.

 


 

 

traceroute (8)

https://linux.die.net/man/8/traceroute

한 네트워크 호스트까지의 패킷 경로를 추적한 결과를 내주는 명령입니다.

https://linux.die.net/man/8/traceroute,traceroute 명령 개요

 

 

IP protocol의 TTL, 즉 time to live 필드를 사용합니다.

TTL 값은 우리가 지정할 수 있고,

패킷이 라우터를 한 개 거칠때마다 하나씩 줄어듭니다.

 

특정 목적지 도달 이전 TTL이 0이되면,

패킷은 source host에게 TIME_EXCEEDED 라는 ICMP 응답을 돌려주게 됩니다.

이 ICMP 응답에 어디서(어떤 라우터에서) TTL이 0이 되었는지에 대한 정보가 실려있습니다.

 

즉, TTL 값을 1에서부터 한 개씩 늘여가며

목적지 host에 패킷을 보내면,

목적지까지의 경로상 모든 라우터에 대한 정보를 확인할 수 있습니다.

 

각 TTL 값에서 3개의 조사 패킷(probe packet)이 전송되고(이는 기본 값입니다),

각 프로브의 ttl, 게이트웨이 주소 왕복 시간을 표시하는 줄이 인쇄됩니다.

5.0초(기본값) 이내에 응답이 없으면, 해당 프로브에 대해 "*" 가 인쇄됩니다.

 

 

 

 

 

옵션이 정말 많지만,

대부분 다음 명령을 통해 쉽게 사용합니다.

$ traceroute hostname

 

 

 

 

 

 

 

 

Practice

한 번 실행해볼까요?

 

우선 사용하기 전에 별도의 설치가 필요합니다.

우분투 리눅스 환경에서 다음 명령어로 설치합니다.

$ sudo apt install traceroute -y

 

 

현재 내 위치에서 구글에 패킷을 보낼 때, 어떤 곳을 거쳐가는 지 내용을 살펴보겠습니다.

$ traceroute google.com

 

ubuntu에서 traceroute 결과값, 공인IP는 자체 모자이크 처리

 

사실 제 개인 컴퓨터의 도커 컨테이너에서 실행한 명령어라,

처음 거쳐가는 네트워크 게이트웨이가

도커 브리지 네트워크의 주소 172.17.0.1로 나오네요!

이후는 모종의 이유로 다 별표로 찍혀 안보이네요

아마 이렇게 사설 네트워크에서 출발한 패킷은 다 차단하는 걸까요? 잘 모르겠습니다.

 

 

어쨌든 제대로 된 실행 결과를 확인하기 위해,

이번엔 컴퓨터의 host OS인 윈도우에서 tracert 명령을 사용해보겠습니다.

윈도우의 tracert 명령 실행 결과

 

건물 내부 무선 랜 환경에서 수행했습니다.

첫 4홉까지는 아직 건물 네트워크여서, 주석처리했습니다.

 

5홉의 기본 게이트웨이 이름을 보면 조금 신기한데요(아마 도메인인것 같습니다),

인천 브릿지에서 수원 브릿지 1로 이동하는 구간의 라우터를 거치는 것 같습니다.

 

6홉은 수원 브릿지 1에서 대전 브릿지 1로 넘어가는 것 같습니다.

 

이후 8홉째에서 대전에 있는 kreonet의 라우터1에서 홍콩의 라우터로 넘어가는 것 같네요?!

kreonet은 국가 R&D 연구망으로써 국내 최초로 TCP/IP 기반 인터넷 서비스를 제공해준 자랑스러운 기관입니다.

 

이제 홍콩에서 여러 라우터를 거친 뒤, 구글 호스트가 존재하는 네트워크를 12홉에서 진입합니다.

 

정말! 신기하네요!!

 

 

 

 

 

소스코드 분석

진짜 ttl에 따른 loop형태로 코드가 짜여져 있을까요?

궁금해져서 뜯어보기로 했습니다.

 

구글에

linux traceroute source code

라고 검색하면

 

 

 

Traceroute for Linux

T   R   A   C   E   R   O   U   T   E           f o r   L i n u x           Project Page             Download              Mail List This is a new modern implementation of traceroute(8) utility for Linux systems.

traceroute.sourceforge.net

라는 사이트가 나오는데요, 여기서 소스코드를 다운로드 했습니다.

 

헤더 및 다른 파일 다 빼고,

traceroute/traceroute.c 파일만 보겠습니다.

 

저자 및 라이센스

 

해당 유틸리티가 속한 프로젝트는 GPL v2 혹은 그 이후 버전의 라이센스를 적용받고 있습니다.

이 소프트웨어의 더 자세한 내용을 보고싶다면 COPYING 파일을 참고하세요.

 

참조한 헤더들

 

네트워크 유틸리티 답게 여러 네트워크 관련 헤더가 보입니다.

fcntl과 같은 파일 제어 함수도 보이네요.

 

netinet이 많이 보이는데 뭘까요,

Unix나 Linux OS에서 사용하는 네트워킹 관련 라이브러리라고 합니다.

sockaddr_in 이나 sockaddr_in6 같은 소켓통신을 위한 struct 정의도 있고,

포트 번호 변환을 위한 함수인 htons, ntohs 함수도 가지고 있다고 하네요.

네트워크 어플리케이션을 개발할 때 필수적인 요소라고 합니다.

 

소켓을 만들어 통신하는 경우도 있나봅니다.

 

전처리문 중 형태 정의, #define

여러 주요한 전역상수를 봅시다.

 

  • MAX_HOPS
    • 최대로 탐색가능한 홉 수
  • MAX_PROBES
    • 각 홉당 시도 가능한 최대 탐색(probe) 횟수
  • DEF_NUM_PROBES
    • default probe number, 각 홉에 대해 시도하는 기본 프로브 횟수입니다.
    • 3으로 지정되어있는 것이 보이시나요?!
  • DEF_WAIT_SECS
    • 기본 대기 시간입니다. 5초로 되어있는 것이 보이시나요?!
  • DEF_DATA_LEN
    • IP datagram에서 헤더를 제외한 데이터의 바이트 수를 의미합니다.
    • 디폴트가 40입니다!

 

 

쭉쭉 내려서 main 함수를 찾아봅시다.

main 함수 상단

뭔가 되게 많은데요!

 

앞부분은 대부분 상정가능한 예외에 대한 처리인 것 같습니다!

 

간단하게 훑어보자면,

  • 로케일 설정
  • parameter 범위 예외처리
  • 지정되지 않은 parameter 입력값 처리 등
  • 소켓 설정
    • source의 port 가 있다면 소스 포트도 설정
  • 소켓이 standard file descriptor를 사용하지 않게 하기 위한 설정
  • ip 옵션 초기화
    • 주어진 게이트웨이 주소를 확인하고 라우팅 버퍼에 집어넣습니다
    • 라우팅 버퍼의 초기 4개 element는 여러 option이 들어가네요
      • ip 헤더의 옵션 중 No Option을 의미하는 NOP와 Loose Source Routing을 의미하는 LSRR도 보입니다

  • 이후 do_it이라는 함수에서 실제로 경로를 추적하기 시작합니다.
    • start와 end는 루프의 기준이 될 것입니다.

  • print_header를 보면, traceroute 처음 실행 시 나오는 문자를 확인할 수 있습니다.

  • 다음은 실제 trace를 하는 코드의 전문입니다.

  • 코드 순서 상보다 이해하기 쉽게 재구성해보겠습니다.
    • 아직 프로브를 전송하지 않았다면, TTL을 계산하고 [1092 line] send_probe() 를 통해 프로브를 전송합니다.
    • 이후 각 프로브에 대해 응답을 받지 못했는지 검사합니다. 만약 시간이 초과되었다면 expire_probe()를 호출해 만료시킵니다.
    • 프로브가 완료되면 출력할 준비를 하고, print_probe(pb) 함수를 통해 출력합니다.
    • timeout은 다음 프로브를 언제 전송할 지 계산한 결과입니다.
      • do_poll()을 통해 timeout 시간동안 I/O 이벤트를 대기합니다.

 

 

결론

결론적으로, TTL을 1씩 증가시켜감에 따라 프로브를 전송해, 그 결과값을 print하는 것을 확인할 수 있었습니다.

 

소스코드를 보고 로직을 바로 이해하는 것은 어려운 것 같습니다.

그래서 주석이 정말정말 중요한 것 같습니다.

 

주석이 코드의 내용을 잘 반영하고 있다면,

프로그램을 모듈형으로 쉽게 이해할 수 있기 때문입니다.

 

 

 

 

번외

 

Linux section number 8

traceroute(8)은 섹션 넘버가 8로, 관리자 명령에 속합니다.

 

예전 리눅스는 일부 패킷을 생성할 때 루트 권한이 필요했기 때문에

시스템 관리자용 명령어로 분류되어왔던 것입니다.

 

그러나 최근 traceroute 의 일부 옵션은 일반 사용자도 사용할 수 있도록 개선되었기 때문에,

루트 권한 없이 실행 가능한 방식이 있습니다.

 

그러나 별도의 매뉴얼 섹션 번호가 할당되지 않고,

여전히 기본적으로 시스템 관리자 명령어로 분류되어

'8' 이라는 섹션 번호가 붙어있습니다.

 

 

(섹션 2는 시스템 콜을 의미합니다. read (2) 는 read 시스템 콜을 의미하는게 되겠죠??)