DNS 쿼리 분석

BiteSnail·2023년 12월 2일
0

DNS

DNS(Domain Name System)이라고 불리는 인터넷 프로토콜은 IP(Internet Protocol) 기반의 주소 체계에서 숫자로 기억하기 힘든 서버 주소를 대체하기 위해 개발되었습니다.

인터넷

IP기반의 인터넷에서 각 노드들(예를 들어 개인용 컴퓨터 등)은 자신들을 구분하기 위해 자신만의 IP 주소를 가지고 있습니다.

이 IP 주소를 가지고 우리는 친숙한 네이버나 다음부터 미국의 구글에 접속할 수 있습니다.

도메인 네임

그런데 우리는 인터넷에서 어떤 사이트에 접근하고자 할때 웹 브라우저의 주소창에 IP 주소를 입력하지 않습니다.

대신에 다른 웹사이트와 구분되는 특정한 문자열을 입력합니다. 예를 들어 네이버에 접근하려면 naver.com 을 입력하고 다음에 접근하려면 daum.net을 입력합니다.

그 이유는 IP 주소가 도메인 네임이라는 것과 1:1로 매핑되어 있기 때문입니다.

도메인 네임(Domain Name)은 숫자로 이루어진 IP 주소를 특정한 문자열로 나타낸 것입니다.

그러면 IP Name이라고 하면 될 것을 왜 도메인이라는 용어를 사용했을까요?

도메인 계층구조

도메인 네임에는 계층구조가 존재합니다. 도메인 네임들을 떠올려 봅시다.
naver.com, google.com, gov.kr, wikipedia.org, chungbuk.ac.kr, velog.io

이들의 공통점은 중간에 점(dot: .)으로 구분된다는 것입니다. 도메인 네임은 점을 통해 계층을 분리하며 오른쪽에서 왼쪽으로 갈수록 도메인의 범위가 작아집니다.

그래서 도메인 쿼리를 보낼 때에는 보통 왼쪽에서 오른쪽의 DNS 서버에 요청을 보내게 됩니다.

chungbuk.ac.kr을 예시로 보겠습니다.

  1. kr은 대한민국 국가 코드 최상의 도메인으로 도메인 네임의 가장 우측에 존재하는 것을 알 수 있습니다.
  2. ac는 교육기관에만 발급받을 수 있는 도메인으로 교육기관 도메인 이라는 것을 알 수 있습니다.
  3. chungbuk은 충북대학교에서 사용하는 도메인입니다.

이러한 도메인 이름을 통해 구분되는 각각의 도메인 네임 서비스 서버들은 하나의 도메인 네임 서버가 너무 많은 도메인 네임을 처리하는 것을 방지할 수 있습니다.

또한 도메인 이름을 통해 해당 사이트가 어떤 성향을 가진 사이트인지도 유추가 가능해진다는 장점이 있습니다.

naver.comgoogle.com은 서로 다른 나라에 속한 서비스 입니다.
하지만 같은 com이라는 최상위 도메인(분야)안에 속하기 때문에 상업 조직이 만든 웹 사이트라는 것을 유추해볼 수 있습니다.

DNS 쿼리

이런 DNS를 사용하기 위해서 컴퓨터에서는 DNS 서버에 쿼리를 보내어 해당 도메인 네임에 대한 IP를 가져옵니다.
DNS 쿼리의 경우 크게 Request와 Reply로 구분할 수 있습니다.

아래는 DNS Request와 DNS Reply 패킷의 일부입니다. 어느쪽이 Request이고 Reply일까요?

플래그를 보면 알 수 있습니다. 가장 상위 flag를 보면 위 그림에는 Message is a query가 아래 그림에는 Message is a response라고 적혀 있는 것을 확인할 수 있습니다.


또한 Queries에 어떤 도메인 주소에 대한 IP 주소가 필요한지가 나타나 있습니다. 각각의 Query들의 총 개수는 Questions에 저장되어 보내집니다.

만약 더 딥한 내용이 궁금하시다면 RFC1035에서 DNS에 대한 더욱 상세한 내용을 확인해 볼 수 있습니다.
https://datatracker.ietf.org/doc/html/rfc1035

Python Scapy로 쿼리 보내기

from scapy.all import *
  
targetName = 'www.example.com'

dstIP = '8.8.8.8' #DNS 서버 주소

Qdsec = DNSQR(qname=targetName)
dns = DNS(id=100, qr=0, 		#id는 트랜잭션 ID입니다.
          qdcount=1, qd=Qdsec)	#questions은 1입니다.
ip = IP(dst=dstIP) 				#src가 없으면 자기 자신입니다.
udp = UDP(dport=53)				#DNS의 널리 알려진 포트 53을 이용합니다.

Requestpkt = ip/udp/dns

send(Requestpkt)

위 예시와 같이 적절하게 수정하여 DNS 쿼리를 보내볼 수 있습니다.

profile
느리지만 조금씩

0개의 댓글

관련 채용 정보