ARP ( Address Resolution Protocol ) 프로그래밍

2017. 6. 22. 16:31NetworkHacking/Network




1계층은 물리계층이며 2계층은 데이터 링크층이라고 한다

DataLink층은 상위계층의 패킷을 전달받아 프레임형태로변환하여 물리계층에 전달한다

이 때, 이더넷 헤더에는 상위계층의 프로토콜정보와 src,dst MAC Address정보가 담긴다


헤더

 물리계층

MAC 프레임 

 

 운영체제에서 볼 수 있는 영역

 

 Preamble SFD

DST 

SRC 

TYPE 

DATA 

PADDING 

FCS 

 1


1>Preamble SFD : 볼 수 없는 영역, 물리(NIC)

2 ~ 7 : 볼 수 있는 영역

2>DST(Destination address) : 프레임을 수신할 MAC주소정보 - 이더넷헤더

3>SRC(Source address) : 프레임을 송신한 호스트의 MAC주소정보 - 이더넷헤더

4>TYPE : 상위 계층 프로토콜 정보를 담고 있다 ( IPv4=0x0800, ARP=0x0806- 이더넷헤더

5>DATA : 상위계층으로부터 전달받은 데이터가 담긴다( 데이터의 최소길이 46byte이어야 한다)

6>PADDING : 데이터가 46byte가 되지 않는다면 채워준다

7>FCS(Frame Check Sequence) : 프레임의 에러 체크를 위한 것  => 장비 단계에서 확인하는 것, 운영체제에서는 볼 수 없다




* 다른 호스트와 통신을 하고자 한다면 그 호스트의 물리주소를 알아야 한다. 그 맥주소로 이더넷 헤더를 완성할 수 있다
이 때, 물리주소를 알아내기 위해 ARP프로토콜을 사용한다


[ ARP ] Address Resolution Protocol : 아이피 주소로 물리 주소를 확인할 수 있는 프로토콜

- IP 주소를 물리적 네트워크 주소( Mac Address 가 포함된 형태 )로 변환하는데 사용되는 프로토콜

- 데이터의 송수신 시 MAC주소를 이용해 통신하는 네트워크계층에서 IP주소로만 프레임을 전달하는 것은 불가능하다

- 따라서 하드웨어의 주소, 즉 MAC주소를 알기 위해 ARP를 사용해 IP와 MAC주소간의 동적매핑을 제공한다

- 처음 IP 주소만 가지고 통신을 시작할 때 해당 IP 주소(targetIP)에서 요청을 처리할 장비가 결정되고 해당 장비의 Mac Address
 요청한 쪽으로 전송이 된다. 이 때부터 실제 통신이 시작되는 것이라 볼 수 있다

- 윈도우: 주기적으로 같은 네트워크에 호스트들의 물리주소를 수집하고 캐시해놓는다
=> arp -a명령어로 확인 가능

- 리눅스: 통신하기 직전에 상대방의 물리 주소를 확인하고 일정시간 동안만 캐시를 유지
=> arp 명령어로 확인가능



# ARP Protocol

같은 네트워크 상에서 호스트들의 물리 주소를 얻어낼 때 사용하는 프로토콜

이전에 만든 sniffer 프로그램에서 packet.eth.type == 0x0806 조건으로 필터링해 얻을 수 있다. ( 아래소스코드있음 )


< ARP 요청 ( Request ) >

data: b'\xff\xff\xff\xff\xff\xff\x1c\xa\x05\x971\xa9\x08\x06

\x00\x01\x08\x00\x06\x04\x00\x01\x1c\xaf\x05\x971\xa9\xc0\xa8\x02I\x00\x00\x00\x00\x00\x00\xc0\xa8\x02\x85

\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' 


[1] 이더넷 헤더 (2계층)

[1] -1 도착지 맥주소

\xff\xff\xff\xff\xff\xff    : 맥 어드레스의 브로드캐스팅 주소

( = 같은네트워크상의 모든 장치에게 패킷을 전달한다)

[1] -2 출발지 맥주소

\x1c\xa\x05\x971\xa9    : 송신자의 맥 어드레스

[1] -3 타입

\x08\x06    : 0x0806 = ARP프로토콜


[2] ARP정보


[2] -1 네트워크 타입 (2byte) 이더넷, 토큰링 등등..

\x00\x01 : 이더넷

[2] -2 프로토콜 타입(2byte) IPv4 or IPv6

\x08\x00 : IPv4

[2] -3 하드웨어 길이(1byte) 맥주소의 길이

\x06

[2] -4 프로토콜 길이(1byte) \x04 or \x06

\x04 : IPv4

[2] -5 opcode ( request : \x00\x01 or response : \x00\x02 )

\x00\x01

[2] -6 송신지 MAC Address

\x1c\xaf\x05\x971\xa9

[2] -7 송신지 IP주소

\xc0\xa8\x02I

[2] -8 도착지 MACAddress ( 모르므로 0으로 초기화되어있음 )

\x00\x00\x00\x00\x00\x00    : 도착지의 호스트로부터 해당 정보가 채워져 패킷이 돌아올것이다

 => 맥주소를 알아냈으므로 네트워크 통신이 가능해진다

[2] -9 ( 도착지 IP주소 )

\xc0\xa8\x02\x85


[3] 패딩

해당 데이터의 크기가 46byte보다 작을 때 padding으로 46byte를 만들어준다


< ARP 응답 (Response) >

해당 패킷이 전달되어진 호스트에서 MACAddress정보를 넘겨줄것이다


[ ARP 프로토콜 Class정의 및 헤더를 직접 생성해보자 ]


#vi arp.py [arp정보]


#vi eth.py [이더넷헤더] - 전송관련 담당

   

#vi arping.py - setter를 통해 헤더에 정보를 추가하고 패킷전송


#vi sniffer.py - eth0장치로 들어오고 나가는 정보를 출력


[ 실행결과 ]

[ 그림1 ]

opcode : 1 : request

같은 네트워크 상에 있는 192.168.1.110 호스트에게 arp패킷을 전송했다


opcode : 2 : response

192.168.1.110 호스트의 MAC Address를 arp패킷의 정보에 추가해서 나에게 응답해준다


arp패킷을 통해 상대의 맥 주소를 알아내어 이제는 네트워크 통신이 가능해진다



* 참고

아래 그림2와 그림3은 Arp와 Eth클래스의 setter를 통해서 각 멤버에게 데이터를 할당하는 모습입니다

아래 처럼 직접 입력하지 않고 arping.py 코드를 짜서 쉽게 멤버변수들을 초기화 시킬 수 있다

[ 그림2 ]

[ 그림3 ]