Soru Python'da Ham Soket Nasıl Kullanılır?


Bozuk verileri işlemek için bir ağ sürücüsünü test etmek için bir uygulama yazıyorum. Ve bu veriyi ham soket kullanarak göndermeyi düşündüm, bu yüzden gönderen makinenin TCP-IP yığını tarafından düzeltilmeyecek.

Bu uygulamayı sadece Linux'ta yazıyorum. Sistem çağrılarında ham soket kullanma kod örneklerine sahibim, ancak testimi olabildiğince dinamik tutmayı ve Python'da olmasa bile yazmayı çok isterim.

Web'i python'daki ham soketlerin kullanımıyla ilgili açıklamalar ve örnekler için biraz yönlendirdim, ancak gerçekten aydınlatıcı hiçbir şey bulamadım. Sadece bu fikri gösteren çok eski bir kod örneği, ama hiçbir şekilde işe yaramaz.

Topladığım kadarıyla, Python'daki Raw Socket kullanımı, UNIX'in ham soketinin semantiğinde neredeyse aynıdır. structPaket yapısını tanımlayan s.

Python'da testin ham soket kısmını değil, sistem çağrılarıyla C'yi yazıp, ana Python kodundan bunu yazmanın daha iyi olup olmayacağını merak ediyordum?


32
2017-07-13 06:36


Menşei




Cevaplar:


Bunu böyle yaparsın:

İlk önce ağ kartınızın otomatik kontrol toplamasını devre dışı bırakın:

sudo ethtool -K eth1 tx off

Ve sonra tehlikeli çerçevenizi python'dan gönderin:

#!/usr/bin/env python
from socket import socket, AF_PACKET, SOCK_RAW
s = socket(AF_PACKET, SOCK_RAW)
s.bind(("eth1", 0))

# We're putting together an ethernet frame here, 
# but you could have anything you want instead
# Have a look at the 'struct' module for more 
# flexible packing/unpacking of binary data
# and 'binascii' for 32 bit CRC
src_addr = "\x01\x02\x03\x04\x05\x06"
dst_addr = "\x01\x02\x03\x04\x05\x06"
payload = ("["*30)+"PAYLOAD"+("]"*30)
checksum = "\x1a\x2b\x3c\x4d"
ethertype = "\x08\x01"

s.send(dst_addr+src_addr+ethertype+payload+checksum)

Bitti.


39
2018-06-16 15:57



Bunun yanlış olduğunu sanıyorum; AF_PACKET arabirimi sağlama toplamını kullanıcı alanına göstermez, bu nedenle sürücü / donanım tarafından otomatik olarak oluşturulur ve denetlenir ve bu konuda yapabileceğimiz hiçbir şey yoktur. Wireshark, gönderdiğim "sağlama toplamı" nın "veri" nin bir parçası olduğunu söylüyor. - lvella
Donanımınıza / sürücünüze bağlıdır. Bazı sürücüler zaten mevcutsa bir sağlama toplamı görmezden gelirken, bazıları bunu verilerin bir parçası olarak alır. Aslında, farklı sürücülere güvenmek için boyundaki bir ağrıdır. Bu problem bir C uygulamasında da var olacaktır. Sağlama toplamı her zaman doğru davranışa neden olmaz (örneğin: paket toplamı sürücü / donanım tarafından hesaplanır). - brice
Bu pek anlamlı değil. Açık bir sağlama toplamını idare edebilecek sürücülerde, bu 4 boş baytın (ya da bu konular için herhangi bir 4 bayt) sağlama toplamı olarak kullanıldığını nasıl bilmeliyiz? Baytlar doğru sağlama toplamıyla eşleştiğinde bile, bu, sürücünün bunu hesaplaması gerektiği anlamına gelir, ancak bunu yalnızca son 4 bayt, hesapladığı değerden değilse çerçeveye ekler: oldukça olası ve hata eğilimli bir davranış. - lvella
Davranışı, kart / sürücüye bağlı olarak kendiniz ayarlayabilirsiniz. Bir bak bakalım ethtool. Gibi bir şey olacak ethtool -K tx off (Linux'ta zaten ...) - brice
Yani, eğer arayüzde otomatik sağlama nesnesini açıkça devre dışı bırakırsanız, AF_PACKET üzerinden göndermemelisiniz. Bu bilginin cevapta belirtilmesi gerektiğini düşünüyorum ... ya da değil, çünkü Python hakkında özellikle konuşuyor. - lvella


Soket sistemi çağrıları (veya Windows'ta Winsocks), standart modülde zaten sarılmış socket: intro, referans.

Hiç bir zaman ham priz kullanmamıştım ama bu modülle birlikte kullanılabiliyor gibi görünüyor:

Son örnek, nasıl yazılacağını gösterir.   ham ile çok basit ağ sniffer   Windows'ta yuvalar. Örnek   yönetici ayrıcalıkları gerektirir   arayüzü değiştirmek

import socket

# the public network interface
HOST = socket.gethostbyname(socket.gethostname())

# create a raw socket and bind it to the public interface
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((HOST, 0))

# Include IP headers
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# receive all packages
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

# receive a package
print s.recvfrom(65565)

# disabled promiscuous mode
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

9
2017-07-13 06:52



Bu tam olarak kod örneğinde onun cevabındaki linkleri çözer. Bu iyi bir şey ama ham veriyi nasıl gönderdiğimi bilmem gerek. Bu örneklere dayanan tüm girişimlerimde, inşa ettiğim ham veriler basitçe gönderilmedi. Ham örneklenmiş paketler göndermeyi denediğimde bile, kendi başıma inşa etmek yerine işe yaradı. - Avihu Turzion
Ham soketler ile IP ve TCP veya UDP başlığını kendiniz de oluşturmanız gerekir. Belki de sadece uygulama verilerinizi göndermeye çalışıyorsunuz ve işletim sisteminin sizin için gerisini halledeceğini umuyoruz. Bir kez, ham priz kullanırsınız, tüm bahisler kapalıdır. Her şey senin tarafından yapılmalı. - Aditya Sehgal
ve TCP ya da UDP dediğimde, gerçekten kendinizin üzerine inşa etmek istediğiniz IP üzerinde bir protokolü kastediyorum. - Aditya Sehgal
@Amey: Bunu yeni bir soruda yazmalısın. Şahsen, sana yardım edemem. - Bastien Léonard


Sonuç olarak, bu dava için en iyi çözüm, tüm şeyi C'ye yazmaktı, çünkü bu büyük bir uygulama değil, bu yüzden küçük bir şeyi 1'den fazla dilde yazmak için daha büyük bir cezaya çarptırılmış olurdu.

Hem C hem de python RAW soketleriyle çok fazla oynamadan sonra, sonunda C RAW soketlerini tercih ettim. RAW soketleri, paket başlıkları yazmak için 8 bit grubundan daha az bit düzeyinde değişiklikler gerektirir. Bazen sadece 4 bit veya daha az yazıyor. python buna bir yardımda bulunmazken, Linux C'nin bunun için tam bir API'si vardır.

Ancak, kesinlikle bu küçük başlık başlığının pythonda rahatça ele alınabilmesi durumunda, C'yi asla burada kullanamayacağına inanıyorum.


3
2017-07-27 06:58



Bu soruya cevap vermiyor. - Humphrey Bogart
Python RAW soketlerinin C RAW soketlerine tercih edilip edilmediğine dair genel bir bakış açısı olarak bu sorunun yanıtı olmadığını kabul ediyorum. Ama sonuçta bu zamanla uğraştığım problemle ilgiliydi ve bu da sorunu çözdü, ve endişelendiğim sürece doğru cevaptı. - Avihu Turzion
Hayır, bir göz atın bu soru - brice


bu Bulduğun eski kod mu? Bana mantıklı geliyor, ama ben kendim test etmedim (ya da çok fazla ham soket kullandım). Bu örnek belgelerden, paketleri sokmak için ham soketlerin nasıl kullanılacağını gösterir ve yeterince benzer görünür.


2
2017-07-13 06:50



Bu tam olarak bahsettiğim kod örneğidir!. Sorun şu ki, soketin başlatılmasının kullanılması ve protokollerin tamamen kullanımdan kaldırılması. Üstelik, bir kavram uygulaması içine sunucu ve istemci tarafının bir çeşit mish-mash olduğunu düşünüyorum. - Avihu Turzion
Doğru, AF_PACKET adres ailesi artık yok gibi görünüyor. İkinci örnek (Bastien'in cevabında çoğaltılan) AF_INET kullanıyor, sanırım bu mantıklı olabilir. Test etmek istediğiniz tek şey veri gönderiyorsa (örneğin, örüntüye dayalı bozulmayı veya herhangi bir şeyi kontrol etmek için), adresleme önemli olmamalıdır. Bence ilk örnek, "senkronize bir gönderme" yaparak "çağrıları karıştırır" ve ardından çağrı alır. Çok yaygın veya güzel değil, yasal olmalı. - unwind


s = socket(AF_PACKET, SOCK_RAW)
s = socket(PF_PACKET, SOCK_RAW)

sonuç:

[root@localhost python]# tcpdump -i eth0

capture size 96 bytes
11:01:46.850438 

01:02:03:04:05:06 (oui Unknown) > 01:02:03:04:05:06 (oui Unknown), ethertype Unknown (0x0801), length 85:

        0x0000:  5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b  [[[[[[[[[[[[[[[[
        0x0010:  5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5041  [[[[[[[[[[[[[[PA
        0x0020:  594c 4f41 445d 5d5d 5d5d 5d5d 5d5d 5d5d  YLOAD]]]]]]]]]]]
        0x0030:  5d5d 5d5d 5d5d 5d5d 5d5d 5d5d 5d5d 5d5d  ]]]]]]]]]]]]]]]]
        0x0040:  5d5d 5d00 0000 00                        ]]]....

1
2017-09-28 03:15





Priz sınıfı yardımcı olmalıdır. Değilse ya C'ye bir Python modülü yazmanız ya da C'yi kullanmanız gerekecektir. http://mail.python.org/pipermail/python-list/2001-April/077454.html.

Temel Googling bunu buldu.

Aslında "gevşetme" nin işaret ettiği kod örneğini denedim. AF_PACKET, python 2.7.4'te benim için işe yaradı


0
2017-07-13 06:49



Bu gönderiyi ilk google gezilerim için gözden geçirdim ve bu kadar yararlı olmadı. Tartışmaların çoğu çok eskidir. AF_PACKET Python'da artık görünmez. - Avihu Turzion
Bu son satır, yorum olması gereken bir düzenleme gibi görünüyor ... - dragonx


Bu Python kütüphanesini kullanabilirsiniz: rawsocketpy Katman 2 => IP / TCP / UDP başlıklarında ham soket kullanılmasına izin verir.

#!/usr/bin/env python
from rawsocketpy import RawSocket

sock = RawSocket("wlp2s0", 0xEEFA)
sock.send("some data")
sock.send("personal data", dest="\xAA\xBB\xCC\xDD\xEE\xFF")

veya sunucu formu:

#!/usr/bin/env python
from rawsocketpy import RawRequestHandler, RawAsyncServerCallback
import time

def callback(handler, server):
    print("Testing")
    handler.setup()
    handler.handle()
    handler.finish()

class LongTaskTest(RawRequestHandler):
    def handle(self):
        time.sleep(1)
        print(self.packet)

    def finish(self):
        print("End")

    def setup(self):
        print("Begin") 

def main():
    rs = RawAsyncServerCallback("wlp2s0", 0xEEFA, LongTaskTest, callback)
    rs.spin()

if __name__ == '__main__':
    main()

0
2017-08-09 10:54