PyTCP adalah tumpukan TCP/IP yang berfungsi penuh yang ditulis dengan Python. Ini mendukung transportasi berbasis aliran TCP dengan pengiriman paket yang andal berdasarkan mekanisme jendela geser dan kontrol kemacetan dasar. Ini juga mendukung protokol IPv6/ICMPv6 dengan konfigurasi alamat SLAAC. Ini beroperasi sebagai program ruang pengguna yang melekat pada antarmuka Linux TAP. Ini telah menerapkan perutean sederhana dan dapat mengirim dan menerima lalu lintas melalui jaringan lokal dan Internet.
Versi 2.7, tidak seperti pendahulunya, berisi kode tumpukan PyTCP dalam bentuk perpustakaan sehingga dapat dengan mudah diimpor dan digunakan oleh kode eksternal. Hal ini akan membuat pengalaman pengguna lebih lancar dan pada akhirnya memberikan kemampuan penuh untuk menggantikan panggilan tumpukan Linux standar (misalnya, perpustakaan soket) dengan panggilan PyTCP di aplikasi pihak ketiga mana pun.
Proyek ini awalnya dimulai sebagai upaya pendidikan murni yang bertujuan untuk meningkatkan keterampilan Python saya dan menyegarkan pengetahuan jaringan saya sebagai bagian dari persiapan untuk peran Network Engineer di Facebook. Sejak itu, hal ini menjadi lebih seperti 'proyek kesayangan' yang mana saya mendedikasikan sebagian waktu saya secara tidak teratur. Namun, beberapa pembaruan biasanya ditambahkan setiap satu atau dua bulan.
Saya menyambut baik kontribusi dan bantuan dari siapa pun yang tertarik dengan pemrograman jaringan. Setiap masukan dihargai. Selain itu, perlu diingat bahwa beberapa fitur tumpukan mungkin hanya diimplementasikan sebagian (sesuai kebutuhan untuk pengoperasian tumpukan). Mereka mungkin diimplementasikan dengan cara yang kurang optimal atau tidak 100% sesuai dengan RFC (karena kurangnya waktu), atau mungkin mengandung bug yang masih perlu saya perbaiki.
Silakan memeriksa dua proyek terkait saya lainnya:
RusTCP - Mencoba menulis ulang beberapa fungsi PyTCP di Rust dan menggunakannya untuk membuat router lab IPv6/SRv6.
SeaTCP - Mencoba membuat tumpukan latensi rendah menggunakan bahasa C dan Majelis.
Prinsip operasi dan pengaturan pengujian
Tumpukan PyTCP bergantung pada antarmuka Linux TAP. Antarmuka TAP adalah antarmuka virtual yang, di ujung jaringan, dapat 'dicolokkan' ke infrastruktur jaringan virtual yang ada melalui jembatan Linux atau Open vSwitch. Di sisi internal, antarmuka TAP dapat digunakan seperti NIC lainnya dengan mengirim dan menerima paket secara terprogram ke/dari NIC tersebut.
Jika Anda ingin menguji tumpukan PyTCP di jaringan lokal Anda, saya sarankan untuk membuat pengaturan jaringan berikut yang memungkinkan Anda menghubungkan kernel Linux (pada dasarnya OS Linux Anda) dan tumpukan PyTCP ke jaringan lokal Anda secara bersamaan. .
Setelah program contoh (baik klien atau layanan) memulai tumpukan, ia dapat berkomunikasi dengannya melalui Soket BSD yang disederhanakan seperti antarmuka API. Ada juga kemungkinan mengirim paket secara langsung dengan memanggil salah satu metode _*_phtx() dari kelas PacketHandler .
Mengkloning PyTCP dari repositori GitHub
Dalam kebanyakan kasus, PyTCP harus dikloning langsung dari repositori GitHub, karena jenis instalasi ini menyediakan lingkungan pengembangan dan pengujian penuh.
git clone http://github.com/ccie18643/PyTCP
Setelah kloning, kita dapat menjalankan salah satu contoh yang disertakan:
Buka direktori root tumpukan (disebut 'PyTCP').
Jalankan perintah sudo make bridge untuk membuat jembatan 'br0' jika diperlukan.
Jalankan perintah sudo make tap untuk membuat antarmuka tap7 dan tetapkan ke jembatan 'br0'.
Jalankan perintah make untuk membuat lingkungan virtual yang tepat untuk pengembangan dan pengujian.
Berlari . venv/bin/activate perintah . venv/bin/activate untuk mengaktifkan lingkungan virtual.
Jalankan contoh apa pun, misalnya example/run_stack.py .
Tekan Ctrl-C untuk menghentikannya.
Untuk menyempurnakan berbagai parameter operasional tumpukan, harap edit file pytcp/config.py sesuai kebutuhan.
Menginstal PyTCP dari repositori PyPi
PyTCP juga dapat diinstal sebagai modul reguler dari repositori PyPi.
python -m pip install PyTCP
Setelah instalasi, pastikan antarmuka TAP beroperasi dan ditambahkan ke jembatan.
sudo ip tuntap add name tap7 mode tapsudo ip link set dev tap7 upsudo brctl addbr br0sudo brctl addif br0 tap7
Tumpukan PyTCP dapat diimpor dan mulai menggunakan kode berikut. Ini memulai subsistem tumpukan dan secara otomatis mengkonfigurasi alamat protokol IPv4 dan IPv6 masing-masing menggunakan DHCPv4 dan IPv6 SLAAC.
Subsistem tumpukan berjalan di threadnya sendiri. Setelah dimulai, tumpukan memberikan kontrol kembali ke kode pengguna dan dapat dihentikan menggunakan panggilan berikut.
stack . stop ()
Fitur
Telah dilaksanakan:
Stack - Fast Packet Parser menggunakan pendekatan 'zero copy'.
Stack - Fast Packet Assembler menggunakan pendekatan 'zero copy'.
Stack - Perpustakaan manipulasi alamat MAC - Kompatibel dengan protokol buffer (Memoryview).
Stack - Pustaka manipulasi alamat IPv4 - Kompatibel dengan protokol buffer (Memoryview) dan tidak bergantung pada pustaka standar Python.
Stack - Pustaka manipulasi alamat IPv6 - Kompatibel dengan protokol buffer (Memoryview) dan tidak bergantung pada pustaka standar Python.
Kode - Pengujian unit untuk beberapa perpustakaan dan modul (berdasarkan kerangka Testslide Facebook)
Protokol Ethernet - Dukungan frame standar Ethernet II.
Protokol ICMPv6 - Implementasi protokol Multicast Listener Discovery v2 (MLDv2) (hanya pesan yang diperlukan oleh tumpukan).
Protokol UDP - Dukungan penuh. Stack dapat bertukar data dengan host lain menggunakan protokol UDP.
Soket UDP - Dukungan penuh, API 'pengguna akhir' tumpukan mirip dengan soket Berkeley.
Layanan UDP - Layanan Echo, Discard, dan Daytime diimplementasikan untuk tujuan pengujian (dalam 'contoh').
Protokol TCP - Implementasi penuh dari TCP Finite State Machine. Pada titik ini, tumpukan dapat bertukar data massal dengan host lain melalui protokol TCP.
Protokol TCP - Mekanisme jendela geser TCP dengan transmisi ulang data (transmisi ulang cepat dan skenario berbasis waktu).
Protokol TCP - Mekanisme backoff TCP / kontrol kemacetan dasar.
Protokol TCP - transmisi ulang paket TCP SYN/FIN.
Soket TCP - Dukungan penuh, API 'pengguna akhir' tumpukan mirip dengan soket Berkeley
Untuk dilaksanakan:
ICMPv6 - Dukungan MLDv2 cukup berantakan sekarang. Perlu menyelesaikannya.
Pengujian - Perlu memfaktorkan ulang pengujian aliran paket (tests/packet_flow_ .py) untuk menggunakan format dan direktori yang sama dengan pengujian FPA berdasarkan test_frames.*
Pengujian - Membuat pengujian unit FPA untuk Laporan MLDv2 (len, str, assemble).
IPv4 - Menerapkan kembali defragmentasi paket untuk menyimpan seluruh paket di aliran DB alih-alih membuat salinan header IP dan data.
Stack - Menerapkan dukungan soket RAW - untuk digunakan sebagai contoh, klien ICMP-Echo.
Kode - Pengujian unit untuk perpustakaan dan modul yang tersisa (berdasarkan perpustakaan Testslide Facebook).
Kode - Tulis ulang dukungan protokol DHCPv4 untuk menggunakan pendekatan FPA/FPP standar, bukan kode lama.
Tumpukan - Kembali menerapkan konsol debugging tumpukan sehingga informasi tertentu tentang komponen tumpukan dapat ditampilkan sesuai permintaan dengan mengirimkan perintah. misalnya, 'tampilkan icmpv6 nd cache', 'tampilkan rute ipv6', dll... ini juga memungkinkan Anda menjalankan perintah interaktif seperti ping atau klien gema UDP/TCP tumpukan.
Protokol QUIC - Penelitian dan rencana implementasi. Hal ini tergantung pada kemampuan menciptakan lingkungan laboratorium untuk itu.
Protokol IPv6 - Mendesain ulang penanganan opsi RA PI dan konfigurasi otomatis awalan ND untuk menggunakan flag A dan L dengan benar. Beberapa penelitian juga diperlukan ketika awalan yang berbeda dari /64 diiklankan.
Protokol IPv6 - Menerapkan header ekstensi yang tersisa.
Protokol IPv6 - Memvalidasi dan mungkin menerapkan kembali mekanisme/proses IPv6 tertentu sesuai dengan aturan RFC.
Protokol IPv6 - Selidiki header Opsi Hop-by-Hop dan hubungannya dengan pesan Laporan MLD2, terapkan jika diperlukan agar MLD2 berfungsi dengan baik.
Protokol ICMPv6 - Menerapkan pesan ND Redirect.
Protokol ICMPv6 - Implementasi penuh Multicast Listener Discovery v2 (MLDv2) <-- mungkin diperlukan oleh tumpukan untuk merespons kueri MLD.
Protokol TCP - Penanganan paket RST yang tepat di berbagai negara bagian. Perlu meneliti ini. Ada laporan bug yang dikirimkan tentang itu.
Protokol TCP - Perlu pengerjaan ulang mekanisme CLOSE syscall sehingga flag FIN dapat disetel pada paket data terakhir alih-alih dibawa secara terpisah.
Protokol TCP - transmisi ulang paket ACK jika kami mendapat transmisi ulang FIN dalam status TIME_WAIT. Perlu diselidiki hal ini.
Protokol TCP - menerapkan respons yang tepat terhadap paket yang berisi nomor SEQ dan/atau ACK lama. Perlu diselidiki hal ini.
Protokol IPv6/IPv4 - mekanisme perutean yang tepat, tabel rute, dll...
Protokol IPv6/IPv4 - kemampuan tumpukan untuk bertindak sebagai router
Cache ARP - terapkan FSM yang tepat
Cache ICMPv6 ND - terapkan FSM yang tepat
Logging - Ganti Loguru dengan logger buatan sendiri untuk meningkatkan kinerja dan fleksibilitas.
Stack - Konversikan tumpukan PyTCP ke perpustakaan sehingga aplikasi eksternal dapat dengan mudah mengimpornya.
Stack - Penghitung aliran paket untuk membantu mengumpulkan statistik paket dan membiarkan aliran paket dilacak untuk pengujian unit.
Stack - Menerapkan mekanisme umpan balik untuk jalur TX sehingga kegagalan pengiriman paket dapat dikomunikasikan ke soket.
Protokol IPv6 - Kemampuan untuk merutekan lalu lintas ke tujuan eksternal melalui gateway default.
Protokol TCP - Pastikan komunikasi acara dari sesi TCP ke soket berfungsi dengan baik (misalnya, koneksi disetel ulang oleh rekan).
Protokol IPv4 - Diperlukan peningkatan mekanisme defragmentasi IP, penanganan fragmen yang tidak sesuai, dan pembersihan fragmen yang tidak memiliki induk.
Protokol UDP - Membutuhkan klien dan mekanisme UDP Echo untuk melaporkan penerimaan pesan ICMP Port Unreachable ke soket UDP.
Soket UDP - Perombakan diperlukan untuk membuat antarmuka 'pengguna akhir' lebih cocok dengan soket Berkeley sehingga aplikasi pihak ketiga dapat menggunakannya tanpa porting.
Soket TCP - Perbaikan diperlukan untuk membuat antarmuka 'pengguna akhir' lebih cocok dengan soket Berkeley sehingga aplikasi pihak ketiga dapat menggunakannya tanpa porting.
Contoh
Beberapa paket ping dan dua monyet dikirimkan melalui TCP melalui protokol IPv6.
Stack mencoba mengonfigurasi alamat tautan-lokalnya secara otomatis. Ini menghasilkannya sebagai alamat EUI64. Sebagai bagian dari proses DAD, ia bergabung dengan grup multicast node yang diminta dan mengirimkan permintaan tetangga untuk alamat yang dihasilkannya.
Stack tidak menerima Iklan Tetangga apa pun untuk alamat yang dihasilkannya, sehingga ia menetapkannya ke antarmukanya.
Stack mencoba menetapkan alamat statis yang telah dikonfigurasi sebelumnya. Sebagai bagian dari proses DAD, ia bergabung dengan grup multicast node yang diminta dan mengirimkan permintaan tetangga untuk alamat statis.
Host lain dengan alamat yang sama telah menetapkan balasan dengan pesan Iklan Tetangga. Ini memberi tahu tumpukan bahwa host lain telah menetapkan alamat yang ingin diberikannya, sehingga tumpukan tidak dapat menggunakannya.
Stack mengirimkan pesan Permintaan Router untuk memeriksa apakah ada awalan global yang harus digunakan.
Router merespons dengan Iklan Router yang berisi awalan tambahan.
Stack mencoba menetapkan alamat yang dihasilkan berdasarkan awalan yang diterima dan bagian host EUI64. Sebagai bagian dari proses DAD, ia bergabung dengan grup multicast node yang diminta dan mengirimkan permintaan tetangga untuk alamat statis.
Stack tidak menerima Iklan Tetangga apa pun untuk alamat yang dihasilkannya, sehingga ia menetapkannya ke antarmukanya.
Setelah semua alamat ditetapkan, tumpukan mengirimkan satu lagi laporan Multicast Listener yang mencantumkan semua alamat multicast yang ingin didengarkannya.
TCP Fast Retransmit beraksi setelah paket TX hilang.
Paket keluar 'hilang' karena mekanisme kehilangan paket yang disimulasikan.
Rekan memperhatikan ketidakkonsistenan dalam nomor paket SEQ dan mengirimkan 'permintaan pengiriman ulang cepat'.
Stack menerima permintaan dan mengirimkan kembali paket yang hilang.
Antrean rusak saat terjadi peristiwa kehilangan paket RX
Paket masuk 'hilang' karena simulasi mekanisme kehilangan paket.
Stack memperhatikan ketidakkonsistenan dalam nomor SEQ paket masuk dan mengirimkan permintaan 'transmisi ulang cepat'.
Sebelum rekan menerima permintaan, ia mengirimkan beberapa paket dengan SEQ lebih tinggi dari yang diharapkan tumpukan. Tumpuk antrian semua paket itu.
Rekan mengirimkan kembali paket yang hilang.
Stack menerima paket yang hilang, menarik semua paket yang disimpan dalam antrian rusak, dan memprosesnya.
Stacks mengirimkan paket ACK untuk mengetahui paket terbaru yang ditarik dari antrian.
TCP Finite State Machine - tumpukan menjalankan layanan TCP Echo.
Rekan membuka koneksi.
Rekan mengirimkan data.
Stack menggemakan kembali data.
Rekan menutup koneksi.
TCP Finite State Machine - tumpukan menjalankan klien TCP Echo.
Stack membuka koneksi.
Stack mengirimkan data.
Rekan menggemakan kembali data tersebut.
Stack menutup koneksi.
Tindakan pemeriksaan kewarasan paket sebelum diurai.
Tangkapan layar pertama menunjukkan tumpukan dengan pemeriksaan kewarasan dimatikan. Paket ICMPv6 yang salah format dapat menyebabkan crash.
Tangkapan layar kedua menunjukkan tumpukan dengan pemeriksaan kewarasan diaktifkan. Paket ICMPv6 yang rusak akan dibuang sebelum diteruskan ke parser protokol ICMPv6.
Tangkapan layar ketiga menunjukkan paket yang salah format. Jumlah bidang catatan MA telah diatur ke 777 meskipun paket hanya berisi satu catatan.
Mekanisme Penyelidikan/Pengumuman ARP.
Stack menggunakan Probe ARP untuk menemukan kemungkinan konflik untuk setiap alamat IP yang dikonfigurasi.
Salah satu alamat IP (192.168.9.102) sudah dipakai, sehingga tumpukan mendapat pemberitahuan tentang hal itu dan melewatkannya.
Alamat IP lainnya gratis, jadi tumpukan mengklaimnya dengan mengirimkan Pengumuman ARP untuk masing-masing alamat tersebut.
Resolusi ARP dan penanganan paket ping.
Host 192.168.9.20 mencoba melakukan ping ke tumpukan. Untuk dapat melakukannya, terlebih dahulu mengirimkan paket ARP Request untuk mengetahui alamat MAC stack.
Stack merespons dengan mengirimkan paket ARP Reply (stack tidak perlu mengirimkan permintaannya karena sudah mencatat MAC host dari permintaan host).
Host mengirimkan paket ping, dan tumpukan meresponsnya.
fragmentasi IP.
Host mengirimkan datagram UDP 4Kb menggunakan tiga paket IP terfragmentasi (tiga fragmen).
Stack menerima paket dan merakitnya menjadi satu bagian, lalu meneruskannya (melalui pengendali protokol UDP dan Soket UDP) ke layanan UDO Echo.
Layanan UDP Echo mengambil data dan memasukkannya kembali ke dalam UDP Socket.
Datagram UDP diteruskan ke pengendali protokol IP, yang membuat paket IP, dan setelah memeriksa apakah paket tersebut melebihi tautan, MTU memecahnya menjadi tiga paket IP terpisah.
Paket IP dienkapsulasi dalam frame Ethernet dan dipasang pada cincin TX.