소개
Scapy 는 Python 으로 작성된 강력한 대화형 패킷 조작 프로그램이자 라이브러리입니다. 이를 통해 다양한 프로토콜의 패킷을 제작하거나 디코딩하고, 네트워크로 전송하고, 캡처하며, 요청과 응답을 매칭할 수 있습니다.
Scapy 가 특별한 이유는 소켓이나 애플리케이션 계층뿐만 아니라 패킷 구성 계층에서 직접 작업할 수 있게 해주기 때문입니다. 즉, 일반적인 클라이언트 라이브러리에서는 숨겨져 있는 헤더, 플래그, 필드 및 프로토콜 조합을 명시적으로 제어할 수 있습니다.
이번 실습에서는 Scapy 를 사용한 패킷 제작의 기초를 배웁니다. 필요한 모듈을 가져오는 것부터 시작하여 ICMP(ping) 및 TCP 패킷을 계층별로 제작하는 방법을 알아봅니다. 마지막으로, 이러한 사용자 지정 패킷을 전송하고 네트워크 응답을 분석합니다. 이러한 실습 경험을 통해 네트워크 프로토콜이 내부적으로 어떻게 작동하는지, 그리고 보안 전문가들이 어떻게 네트워크 방어를 테스트하는지에 대해 더 깊이 이해하게 될 것입니다.
Scapy 모듈 가져오기
이 단계에서는 Python 환경을 설정하고 필요한 Scapy 모듈을 가져옵니다. Scapy 는 대화형 콘솔로도 사용할 수 있지만, 스크립트를 작성하면 패킷 제작 로직을 쉽게 저장, 수정 및 재사용할 수 있습니다.
이는 단순히 프로토콜을 사용하는 것에서 프로토콜을 직접 구성하는 것으로의 전환입니다. 기존 애플리케이션에 트래픽 전송을 요청하는 대신, 트래픽이 어떤 모습이어야 하는지를 직접 정의하는 것입니다.
먼저 기본 작업 디렉토리에 있는지 확인하십시오. pwd 명령어를 사용하여 확인할 수 있지만, 이미 ~/project에 있어야 합니다.
nano 텍스트 편집기를 사용하여 packet_crafter.py라는 새 Python 파일을 만듭니다.
nano packet_crafter.py
이 파일 내에서 Scapy 라이브러리를 가져와야 합니다. 스크립트에서 Scapy 를 사용하는 표준적인 방법은 scapy.all 모듈에서 모든 함수를 가져오는 것입니다. 스크립트에 다음 줄을 추가하십시오.
from scapy.all import *
print("Scapy modules imported successfully.")
Ctrl+O와 Enter를 눌러 파일을 저장합니다. 테스트하기 전에 스크립트를 계속 작성하려면 nano에 그대로 머물러도 됩니다. 터미널로 돌아갈 준비가 되면 Ctrl+X를 누르십시오.
이제 Python 을 사용하여 스크립트를 실행하여 구문 오류가 없는지, Scapy 라이브러리가 올바르게 로드되는지 확인합니다. 원시 네트워크 패킷을 제작하려면 높은 권한이 필요하므로 sudo를 사용하여 스크립트를 실행해야 합니다.
sudo python3 packet_crafter.py
성공했음을 나타내는 다음과 유사한 출력이 표시되어야 합니다.
Scapy modules imported successfully.
일부 실습 환경에서는 Scapy 가 성공 메시지 이전에 matplotlib와 같은 선택적 Python 패키지에서 추가 경고를 출력할 수 있습니다. 여전히 Scapy modules imported successfully.가 표시된다면 다음 단계로 진행해도 됩니다.
ICMP Echo Request 제작
이 단계에서는 일반적으로 "ping"이라고 알려진 ICMP Echo Request 패킷을 제작합니다. 네트워크 패킷은 OSI 모델에 따라 계층별로 구축됩니다. Scapy 에서는 / 연산자를 사용하여 이러한 계층을 함께 쌓을 수 있습니다.
계층화는 여기서 이해해야 할 가장 중요한 개념 중 하나입니다. 각 계층은 고유한 필드와 책임을 추가합니다. Scapy 는 해당 모델을 직접 반영하므로 구문을 통해 패킷 구조를 더 쉽게 추론할 수 있습니다.
ICMP ping 은 소스 및 대상 주소를 지정하기 위한 IP 계층 (네트워크 계층) 과 메시지 유형을 정의하기 위한 ICMP 계층이 필요합니다.
packet_crafter.py가 nano에서 열려 있다면 계속 편집하십시오. 그렇지 않다면 다시 여십시오.
nano packet_crafter.py
스크립트 끝에 다음 코드를 추가하십시오. 이 코드는 Google 의 공용 DNS 서버 (8.8.8.8) 를 대상으로 하는 IP 객체를 생성하고, ICMP 객체를 생성한 다음, 이들을 함께 쌓습니다. show() 메서드는 패킷 구조에 대한 자세한 분석을 출력합니다.
## Create an IP layer targeting Google's DNS
ip_layer = IP(dst="8.8.8.8")
## Create an ICMP layer (Echo Request)
icmp_layer = ICMP()
## Stack the layers to form the final packet
icmp_packet = ip_layer / icmp_layer
print("\n--- ICMP Packet Structure ---")
icmp_packet.show()
Ctrl+O와 Enter를 눌러 파일을 저장합니다. 스크립트를 더 작성하고 싶다면 nano에 머물러 다음 단계로 진행해도 됩니다.
업데이트된 스크립트를 실행하여 방금 제작한 패킷의 구조를 확인하십시오.
sudo python3 packet_crafter.py
Scapy 가 자동으로 채워준 프로토콜 버전, TTL(Time To Live), ICMP 유형 등 기본값들이 포함된 자세한 출력을 볼 수 있습니다.
--- ICMP Packet Structure ---
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = icmp
chksum = None
src = 10.0.2.15
dst = 8.8.8.8
\options \
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
unused = ''
사용자 지정 TCP SYN 패킷 제작
이 단계에서는 TCP SYN 패킷을 제작합니다. 이 특정 유형의 패킷은 연결을 완전히 설정하지 않고 대상 머신의 특정 포트가 열려 있는지 확인하기 위해 네트워크 스캔 (예: Nmap 의 스텔스 스캔) 에서 자주 사용됩니다.
이는 작은 헤더 변경이 어떻게 매우 다른 네트워크 동작을 생성하는지 보여주는 좋은 예입니다. 대상 호스트나 포트를 변경하는 것이 아니라 플래그와 프로토콜 필드만 변경하지만, 이러한 세부 사항이 패킷의 의미와 대상이 이를 해석하는 방식을 결정합니다.
ICMP 패킷과 마찬가지로 TCP 패킷도 기본 IP 계층이 필요합니다. 그 위에 대상 포트와 TCP 플래그를 지정할 수 있는 TCP 계층을 추가합니다. S 플래그는 SYN(Synchronize) 을 의미합니다.
동일한 nano 세션에 있다면 packet_crafter.py를 계속 편집하십시오. 그렇지 않다면 다시 여십시오.
nano packet_crafter.py
스크립트에 다음 코드를 추가하십시오. 이전 단계에서 만든 ip_layer를 재사용하고 그 위에 포트 80(HTTP) 을 대상으로 하는 새로운 TCP 계층을 쌓을 것입니다.
## Create a TCP layer targeting port 80 with the SYN flag
tcp_layer = TCP(dport=80, flags="S")
## Stack the IP and TCP layers
tcp_packet = ip_layer / tcp_layer
print("\n--- TCP SYN Packet Structure ---")
tcp_packet.show()
Ctrl+O와 Enter를 눌러 파일을 저장합니다. 터미널에서 스크립트를 실행하고 싶을 때만 Ctrl+X로 종료하거나, 계속 편집하여 마지막 단계로 진행하십시오.
스크립트를 다시 실행하여 새로운 TCP SYN 패킷의 구조를 검사하십시오.
sudo python3 packet_crafter.py
이제 출력에는 대상 포트가 http(포트 80) 로 설정되고 플래그가 S로 설정된 TCP 계층 세부 정보가 포함됩니다.
--- TCP SYN Packet Structure ---
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = tcp
chksum = None
src = 10.0.2.15
dst = 8.8.8.8
\options \
###[ TCP ]###
sport = ftp_data
dport = http
seq = 0
ack = 0
dataofs = None
reserved = 0
flags = S
window = 8192
chksum = None
urgptr = 0
options = []
네트워크 응답 전송 및 분석
마지막 단계에서는 제작한 ICMP 패킷을 실제로 네트워크를 통해 전송하고 응답을 캡처합니다.
패킷을 전송하면 계층 정의, 패킷 구축, 전송, 응답 해석이라는 정신적 모델이 완성됩니다. 이는 많은 사용자 지정 네트워크 테스트 도구의 기반이 되는 동일한 상위 수준 루프입니다.
Scapy 는 패킷을 전송하기 위한 여러 함수를 제공합니다. sr1() 함수는 패킷을 보내고 수신되는 첫 번째 응답을 기다리기 때문에 특히 유용합니다. "s"는 send(전송), "r"은 receive(수신), "1"은 하나의 패킷을 의미합니다.
파일을 열어두었다면 계속 편집하십시오. 그렇지 않다면 packet_crafter.py를 다시 여십시오.
nano packet_crafter.py
icmp_packet을 전송하고 응답을 분석하기 위해 다음 코드를 추가하십시오. 패킷이 삭제되거나 차단될 경우 스크립트가 무한정 대기하지 않도록 timeout 매개변수를 포함합니다.
print("\n--- Sending ICMP Packet ---")
## Send the packet and wait for 1 response, with a timeout of 2 seconds
## verbose=0 hides the default Scapy sending output for cleaner results
response = sr1(icmp_packet, timeout=2, verbose=0)
if response:
print(f"Response received from: {response[IP].src}")
print("\n--- Response Packet Structure ---")
response.show()
else:
print("No response received. The packet might have been dropped.")
파일을 저장하고 편집기를 종료합니다.
스크립트를 실행하여 인터넷으로 패킷을 보내고 Google 의 DNS 서버가 응답하기를 기다립니다.
sudo python3 packet_crafter.py
네트워크가 ICMP 요청을 허용하면 응답 패킷의 구조를 볼 수 있습니다. 응답의 ICMP 유형이 echo-reply인 것을 확인하십시오.
--- Sending ICMP Packet ---
Response received from: 8.8.8.8
--- Response Packet Structure ---
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 28
id = 0
flags =
frag = 0
ttl = 114
proto = icmp
chksum = 0x67d8
src = 8.8.8.8
dst = 10.0.2.15
\options \
###[ ICMP ]###
type = echo-reply
code = 0
chksum = 0xffff
id = 0x0
seq = 0x0
unused = ''
###[ Padding ]###
load = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
요약
Scapy 를 사용하여 Python 스크립트를 설정하고, / 연산자를 사용하여 ICMP 및 TCP 패킷을 계층별로 수동으로 제작하며, 이러한 패킷을 네트워크를 통해 전송하여 원시 응답을 분석하는 방법을 배웠습니다. 이 기초 지식은 네트워크 프로토콜이 어떻게 작동하는지 이해하고, 보안 평가를 수행하며, 사용자 지정 네트워크 분석 도구를 개발하는 데 매우 중요합니다.



