2012-01-04 60 views
16

Tôi đang cố gắng gửi lưu lượng truy cập đã ghi trước đây (được ghi ở định dạng pcap) bằng scapy. Hiện tại tôi đang bị mắc kẹt khi phân tách lớp Ether ban đầu. Lưu lượng truy cập đã được capture trên một máy chủ khác và về cơ bản tôi cần thay đổi cả lớp IP và Ether src và dst. Tôi quản lý để thay thế lớp IP và tính toán lại checksums, nhưng lớp Ether cho tôi gặp rắc rối.Gửi gói từ pcap với src/dst đã thay đổi trong scapy

Bất kỳ ai có kinh nghiệm gửi lại các gói từ tệp chụp với các thay đổi được áp dụng cho lớp IP và Ether (src và dst)? Ngoài ra, nắm bắt là khá lớn vài Gb, làm thế nào về hiệu suất scapy với số lượng lưu lượng truy cập như vậy?

+1

'scapy' là một công cụ tốt đẹp, nhưng làm bạn phải làm điều này với 'scapy'? Có những giải pháp khác có thể được tối ưu hóa cho việc này ... –

+1

Mike, bạn có thể đề xuất "các công cụ khác" nào? Dường như với tôi rằng Scapy là một lựa chọn tự nhiên cho nhiệm vụ này. –

+0

xem [tcpreplay] (http://tcpreplay.synfin.net/) –

Trả lời

5

Vâng, với scapy tôi đã đưa ra những điều sau đây (xin lỗi cho Python của tôi). Hy vọng rằng nó sẽ giúp một ai đó. Có một kịch bản có thể đơn giản hơn, nơi tất cả các gói từ tệp pcap được đọc vào bộ nhớ, nhưng điều này có thể dẫn đến các vấn đề với các tệp chụp lớn.

from scapy.all import * 
global src_ip, dst_ip 
src_ip = 1.1.1.1 
dst_ip = 2.2.2.2 
infile = "dump.pcap" 

try: 
    my_reader = PcapReader(infile) 
    my_send(my_reader) 
except IOError: 
    print "Failed reading file %s contents" % infile 
    sys.exit(1) 

def my_send(rd, count=100): 
    pkt_cnt = 0 
    p_out = [] 

    for p in rd: 
     pkt_cnt += 1 
     np = p.payload 
     np[IP].dst = dst_ip 
     np[IP].src = src_ip 
     del np[IP].chksum 
     p_out.append(np) 
     if pkt_cnt % count == 0: 
      send(PacketList(p_out)) 
      p_out = [] 

    # Send remaining in final batch 
    send(PacketList(p_out)) 
    print "Total packets sent %d" % pkt_cn 
22

kiểm tra ví dụ này

from scapy.all import * 
from scapy.utils import rdpcap 

pkts=rdpcap("FileName.pcap") # could be used like this rdpcap("filename",500) fetches first 500 pkts 
for pkt in pkts: 
    pkt[Ether].src= new_src_mac # i.e new_src_mac="00:11:22:33:44:55" 
    pkt[Ether].dst= new_dst_mac 
    pkt[IP].src= new_src_ip # i.e new_src_ip="255.255.255.255" 
    pkt[IP].dst= new_dst_ip 
    sendp(pkt) #sending packet at layer 2 

nhận xét:

  • sử dụng rdpcap, phương pháp scapy wrpcap để đọc và viết từ pcap định dạng tập tin
  • bạn có thể sử dụng sniff(offline="filename") để đọc các gói dữ liệu và bạn có thể sử dụng tham số prn như thế này sniff(offline="filename",prn=My_Function) trong trường hợp này My_Functions sẽ được áp dụng cho mọi pkt sniffed
  • cách chính xác để viết ip hoặc mac mới của bạn là xem xét nó như một chuỗi cũ: ip="1.1.1.1" và cứ như minh họa ở trên.
  • trong ví dụ: Phương pháp sendp trong vòng lặp for mà là chậm hơn so với làm cho vòng lặp khác để gửi các gói tin
  • hiệu suất đỉnh: trong python sử dụng cho vòng lặp là quá chậm sử dụng map thay vì nếu bạn muốn có một tốc độ giống như một vòng lặp for trong C, Ref
  • rdpcap như đã sử dụng ở trên đọc tệp cùng một lúc, nếu bộ nhớ có sẵn trong khi đọc nói 1,5 Gb và bạn đang đọc 2,3, .. Gb tệp sẽ không thành công.
  • nếu vấn đề hiệu suất là rất quan trọng đối với bạn có thể sử dụng winpcap nhưng bạn phải viết mã phức tạp hơn trong C, thực hiện cùng một tác vụ bằng python/scapy khá đơn giản nhưng không nhanh hơn c
  • cái nào để sử dụng ở mức hiệu năng cần thiết
  • nếu tôi đoán là bạn đang gửi gói luồng video trong trường hợp này tôi sẽ sử dụng winpcap nếu tôi gửi video hoặc mút 1 mega pixel trong các trường hợp khác (kích thước thấp hơn trên mỗi khung hình)
  • trong trường hợp sử dụng C/winpcap, bạn sẽ nhận được hiệu suất tuyệt vời trong việc đọc pcaps và thay đổi dữ liệu và gửi lại nhưng bạn phải biết cùng một vấn đề (tệp lớn). pr kích thước hoạt động để sử dụng nó để đọc gửi gói theo hiệu suất khá
  • nếu kích thước gói là không đổi (hiếm khi xảy ra trong hầu hết các trường hợp). bạn muốn sử dụng python/scapy cho toàn bộ "project/program", bạn có thể tạo các hàm hiệu năng cao trong C/Wincap và biên dịch thành dll, sau đó bạn có thể nhập dll này vào chương trình python của bạn và bạn có thể sử dụng nó trong chương trình python.Bằng cách này bạn sẽ nhận được lợi ích của python/Scapy tuyệt vời và bạn chỉ viết một hàm cụ thể trong c để bạn có thể hoàn thành công việc của mình nhanh hơn và mã của bạn được tập trung và duy trì được
+1

Cảm ơn lời khuyên, Abdurahman, đặc biệt là những vấn đề liên quan đến hiệu suất! Scapy là một công cụ tốt, nhưng có thể không phù hợp cho mô phỏng giao thông nặng (ít nhất là "ra khỏi hộp"). –

+0

Về các gợi ý của bạn cho việc sử dụng 'map', tôi sẽ không chắc chắn liệu điều đó có cải thiện hiệu năng hay không, vì các phương thức scapy send/sendp nhận danh sách các gói như một tham số và bên trong các hàm mà chúng có một' for' loop ('__gen_send'). Vì vậy, có thể những gì bạn đạt được bằng cách gọi 'map' packet-by-packet thay vì truyền danh sách các gói trực tiếp đến send/sendp bị mất với các vòng lặp' for' bên trong. – newlog

5

Nếu tôi là bạn, tôi sẽ để Scapy đối phó với lớp Ether và sử dụng hàm send(). Ví dụ:

ip_map = {"1.2.3.4": "10.0.0.1", "1.2.3.5": "10.0.0.2"} 
for p in PcapReader("filename.cap"): 
    if IP not in p: 
     continue 
    p = p[IP] 
    # if you want to use a constant map, only let the following line 
    p.src = "10.0.0.1" 
    p.dst = "10.0.0.2" 
    # if you want to use the original src/dst if you don't find it in ip_map 
    p.src = ip_map.get(p.src, p.src) 
    p.dst = ip_map.get(p.dst, p.dst) 
    # if you want to drop the packet if you don't find both src and dst in ip_map 
    if p.src not in ip_map or p.dst not in ip_map: 
     continue 
    p.src = ip_map[p.src] 
    p.dst = ip_map[p.dst] 
    # as suggested by @AliA, we need to let Scapy compute the correct checksum 
    del(p.chksum) 
    # then send the packet 
    send(p) 
+2

Làm việc cho tôi, vấn đề duy nhất tôi nhận được là kiểm tra IP sai, dễ dàng sửa bằng cách thêm del p.chksum trước khi gửi (p) – AliA

+0

Bạn nói đúng, tôi đã quên điều đó! Cảm ơn! – Pierre

0

Đối với checksum đúng, tôi cũng cần thêm del p[UDP].chksum