<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Cyprien Avico on Medium]]></title>
        <description><![CDATA[Stories by Cyprien Avico on Medium]]></description>
        <link>https://medium.com/@akmot9?source=rss-e9c0456814d3------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*zJjsAegUo5CY-CNXbY8pog.png</url>
            <title>Stories by Cyprien Avico on Medium</title>
            <link>https://medium.com/@akmot9?source=rss-e9c0456814d3------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 09 Jun 2026 04:18:51 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@akmot9/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Episode .1  Lister ses interfaces réseau en Rust avec pcap (Linux)]]></title>
            <link>https://medium.com/@akmot9/episode-1-lister-ses-interfaces-r%C3%A9seau-en-rust-avec-pcap-linux-122286d7647b?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/122286d7647b</guid>
            <category><![CDATA[network]]></category>
            <category><![CDATA[rust]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Mon, 15 Sep 2025 15:04:38 GMT</pubDate>
            <atom:updated>2025-09-15T15:11:30.737Z</atom:updated>
            <content:encoded><![CDATA[<h3>Episode .1 🚀 Lister ses interfaces réseau en Rust avec pcap (Linux)</h3><p>Quand on commence à toucher à la capture réseau en Rust, la première étape est simple : savoir <strong>quelles interfaces réseau</strong> sont disponibles sur la machine. Avec la crate <a href="https://crates.io/crates/pcap">pcap</a>, c’est possible en quelques lignes de code.</p><p>Dans ce guide, on va voir comment :</p><ol><li>Installer les dépendances nécessaires sous Linux</li><li>Créer un projet Rust minimal</li><li>Lister les interfaces réseau et leurs adresses</li><li>Ajouter quelques tests unitaires simples</li></ol><h3>🛠️ Pré-requis sous Linux</h3><p>La crate pcap est un binding Rust de la librairie <strong>libpcap</strong>, très utilisée en C (par Wireshark, tcpdump…).<br> Pour que tout fonctionne, il faut installer les headers de développement :</p><pre>sudo apt update<br>sudo apt install libpcap-dev</pre><blockquote><em>⚠️ </em><strong><em>Note</em></strong><em> : lister les interfaces ne demande généralement </em><strong><em>pas de sudo</em></strong><em>. Mais si tu veux plus tard capturer des paquets, il faudra soit lancer ton programme avec </em><em>sudo, soit donner les droits à ton binaire avec </em><em>setcap.</em></blockquote><h3>📦 Création du projet</h3><pre>cargo new pcap-list-interfaces<br>cd pcap-list-interfaces</pre><p>Ajoute les dépendances dans ton Cargo.toml :</p><pre>[dependencies]<br>pcap = &quot;1&quot;<br>thiserror = &quot;1&quot;</pre><h3>💻 Le code complet</h3><p>Voici le contenu de src/main.rs :</p><pre>use pcap::Device;<br>use thiserror::Error;</pre><pre>fn main() -&gt; Result&lt;(), PcapError&gt; {<br>    // On récupère les interfaces réseau<br>    let interfaces = get_interfaces()?;</pre><pre>    // On affiche les noms<br>    print_interfaces_names(interfaces.clone());</pre><pre>    // On affiche les adresses IP associées<br>    print_interfaces_addresses(interfaces);</pre><pre>    Ok(())<br>}</pre><pre>#[derive(Debug, Error)]<br>pub enum PcapError {<br>    #[error(&quot;Impossible de lister les interfaces réseau&quot;)]<br>    DeviceListError(#[from] pcap::Error),<br>}</pre><pre>fn get_interfaces() -&gt; Result&lt;Vec&lt;Device&gt;, PcapError&gt; {<br>    let devices = Device::list()?;<br>    Ok(devices)<br>}</pre><pre>fn print_interfaces_names(interfaces: Vec&lt;Device&gt;) {<br>    for interface in interfaces {<br>        println!(&quot;{}&quot;, interface.name);<br>    }<br>}</pre><pre>fn print_interfaces_addresses(interfaces: Vec&lt;Device&gt;) {<br>    for interface in interfaces {<br>        for address in interface.addresses {<br>            println!(&quot;{:?}&quot;, address.addr);<br>        }<br>    }<br>}</pre><h3>🧪 Ajout de tests unitaires</h3><p>Même pour un petit utilitaire, écrire quelques tests aide à éviter les mauvaises surprises :</p><pre>#[cfg(test)]<br>mod tests {<br>    use super::*;</pre><pre>    #[test]<br>    fn get_interfaces_returns_ok() {<br>        let res = get_interfaces();<br>        assert!(res.is_ok(), &quot;expected Ok, got {:?}&quot;, res);<br>    }</pre><pre>    #[test]<br>    fn print_interfaces_names_does_not_panic() {<br>        let interfaces = get_interfaces().unwrap_or_else(|_| Vec::new());<br>        let outcome = std::panic::catch_unwind(|| {<br>            print_interfaces_names(interfaces.clone());<br>        });<br>        assert!(outcome.is_ok(), &quot;print_interfaces_names panicked&quot;);<br>    }</pre><pre>    #[test]<br>    fn print_interfaces_addresses_does_not_panic() {<br>        let interfaces = get_interfaces().unwrap_or_else(|_| Vec::new());<br>        let outcome = std::panic::catch_unwind(|| {<br>            print_interfaces_addresses(interfaces);<br>        });<br>        assert!(outcome.is_ok(), &quot;print_interfaces_addresses panicked&quot;);<br>    }<br>}</pre><p>Ces tests garantissent que :</p><ul><li>get_interfaces fonctionne correctement,</li><li>l’affichage des noms <strong>ne panique pas</strong>,</li><li>l’affichage des adresses <strong>ne panique pas</strong>.</li></ul><h3>▶️ Lancer le programme</h3><p>Exécute simplement :</p><pre>cargo run</pre><p>Sur une machine Linux classique, tu verras quelque chose comme :</p><pre>lo<br>eth0<br>wlan0<br>Some(192.168.1.42)<br>Some(127.0.0.1)<br>Some(::1)</pre><p>Chaque interface (lo, eth0, wlan0) est listée, suivie de ses adresses IP.<br> Ici, ::1 est l’adresse IPv6 de loopback.</p><h3>▶️ Lancer les tests</h3><pre>cargo test</pre><p>Tu devrais obtenir :</p><pre>running 3 tests<br>test tests::get_interfaces_returns_ok ... ok<br>test tests::print_interfaces_names_does_not_panic ... ok<br>test tests::print_interfaces_addresses_does_not_panic ... ok</pre><h3>✅ Conclusion</h3><p>En moins de 100 lignes de Rust, on a appris à :</p><ul><li>Lister les interfaces réseau d’une machine sous Linux</li><li>Afficher leurs adresses IP</li><li>Gérer proprement les erreurs avec thiserror</li><li>Écrire des tests unitaires basiques</li></ul><p>C’est une <strong>première étape</strong> avant d’aller plus loin : capturer des paquets, filtrer avec BPF, ou analyser du trafic réseau directement depuis Rust.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=122286d7647b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ CBOM et SBOM : Un besoin stratégique dans l’industrie et la défense, et pourquoi il n’existe…]]></title>
            <link>https://medium.com/@akmot9/cbom-et-sbom-un-besoin-strat%C3%A9gique-dans-lindustrie-et-la-d%C3%A9fense-et-pourquoi-il-n-existe-01b364bc459d?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/01b364bc459d</guid>
            <category><![CDATA[materials]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[community]]></category>
            <category><![CDATA[cyber]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Tue, 27 May 2025 11:57:41 GMT</pubDate>
            <atom:updated>2025-09-08T14:14:49.001Z</atom:updated>
            <content:encoded><![CDATA[<h3>📦 CBOM et SBOM : Un besoin stratégique dans l’industrie et la défense, et pourquoi il n’existe pas encore de solution adaptée</h3><p><strong>Par Cyprien Avico</strong><br> <em>Toulon, 2025</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K3I6WsOJ7RIAV8AvnVR86g.png" /></figure><h3>🧭 SBOM et CBOM : deux concepts, deux objectifs</h3><h3>✅ SBOM (Software Bill of Materials)</h3><p>Le <strong>SBOM</strong> est devenu un <strong>standard incontournable</strong> dans la cybersécurité logicielle.<br> Il représente une <strong>liste exhaustive des composants logiciels</strong> d’une application : bibliothèques, frameworks, dépendances, avec leurs versions exactes.</p><p>Pourquoi c’est important ?<br> Parce que le SBOM permet :</p><ul><li>D’identifier rapidement les <strong>vulnérabilités connues (CVE)</strong>,</li><li>D’assurer la <strong>conformité réglementaire</strong> (ISO 62443, NIS2, etc.),</li><li>De faciliter la <strong>gestion des risques liés à la supply chain logicielle</strong>.</li></ul><p>Il existe aujourd’hui des <strong>standards formalisés pour le SBOM</strong> :</p><ul><li><strong>SPDX</strong> (Software Package Data Exchange), développé par la Linux Foundation,</li><li><strong>CycloneDX</strong>, soutenu par OWASP.</li></ul><p>Ces formats sont <strong>interopérables</strong> et <strong>largement adoptés</strong> dans les pipelines DevSecOps, les audits logiciels, et la gestion de la sécurité des applications modernes.</p><h3>🔒 CBOM (Cyber Bill of Materials)</h3><p>Le <strong>CBOM</strong> va <strong>au-delà du logiciel</strong>.<br> C’est une <strong>vue globale</strong> de la chaîne d’approvisionnement numérique d’un système :</p><ul><li>Composants <strong>matériels</strong> (CPU, cartes réseau, disques, etc.),</li><li>Versions de <strong>firmware</strong> et de <strong>BIOS</strong>,</li><li><strong>Systèmes d’exploitation</strong> installés,</li><li><strong>Logiciels</strong> (SBOM inclus).</li></ul><p>Le CBOM répond à des besoins spécifiques des <strong>environnements industriels</strong>, <strong>OT</strong>, et <strong>défense</strong> :<br> 🎯 <strong>Identifier les risques matériels et firmware</strong> qui échappent au SBOM,<br> 🎯 <strong>Évaluer la surface d’attaque complète</strong> d’un système,<br> 🎯 <strong>Anticiper les menaces sur la supply chain hardware</strong>.</p><p>Problème :<br> 👉 Il <strong>n’existe pas de standard officiel</strong> (équivalent à SPDX ou CycloneDX) pour structurer un CBOM.<br> 👉 Aucun outil ne propose une <strong>solution complète</strong>, clé en main, pour générer un CBOM, en particulier dans les <strong>réseaux isolés</strong>.</p><h3>🏭 L’industrie et la défense : un besoin non couvert</h3><p>Dans les environnements <strong>industriels</strong>, <strong>SCADA</strong>, <strong>militaires</strong>, et <strong>défense</strong>, on rencontre une réalité spécifique :<br> Des <strong>postes isolés</strong>, sans connexion Internet, souvent vieillissants, qui pilotent des automates, des réseaux industriels ou des machines-outils critiques.</p><p>Ces <strong>PC de maintenance</strong>, <strong>stations d’ingénierie</strong>, ou <strong>systèmes air-gapped</strong> présentent des <strong>risques majeurs</strong> :</p><ul><li>Matériel obsolète ou compromis (ex: attaques type Supermicro),</li><li>Firmware non mis à jour,</li><li>Systèmes d’exploitation non patchés,</li><li>Logiciels spécifiques sans SBOM connu.</li></ul><p>Or, il <strong>n’existe aujourd’hui aucun outil desktop, portable, et multi-plateforme</strong> permettant de :<br> ✅ Scanner <strong>hardware + firmware + OS + logiciels</strong> sur un poste isolé,<br> ✅ Générer un <strong>CBOM structuré</strong> (JSON, YAML, PDF),<br> ✅ Fonctionner en <strong>100% offline</strong>, sans serveur ni cloud.</p><p>C’est une <strong>lacune critique</strong> pour la cybersécurité des environnements isolés.</p><h3>🛠️ Les outils existants : puissants, mais pas adaptés</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/976/1*AzRTWILCVe8sGjINhuYINg.png" /></figure><p><strong>OutilObjectifLimitesSPDX / CycloneDX</strong>Standards pour SBOMPas de support pour <strong>CBOM</strong> (matériel/firmware)<strong>Syft / Grype</strong>Génération d’un SBOM logiciel completPas de hardware/firmware, pas adapté au desktop<strong>Osquery</strong>Infos système via SQLPas user-friendly, pas un CBOM complet<strong>GLPI / FusionInventory</strong>Inventaire matériel + logicielDépend d’un serveur, pas portable<strong>Rudder</strong>Gestion d’inventaire réseauTrop lourd, nécessite une infrastructure réseau<strong>fwupdmgr / lshw</strong>Informations hardware/firmwarePas d’interface unifiée, pas de CBOM structuré<strong>Anchore / Trivy</strong>Analyse logicielle + vulnérabilitésFocalisé sur le <strong>SBOM</strong>, pas de prise en compte hardware</p><h3>🚀 Vers une solution à construire : une application desktop cross-platform pour les environnements isolés</h3><p>Ce qui manque aujourd’hui, c’est une <strong>application desktop</strong>, capable de tourner sur <strong>Windows, Linux, et Mac</strong>, qui soit :<br> ✅ <strong>Autonome et portable</strong> (ex : sur clé USB),<br> ✅ <strong>100% offline</strong>, sans dépendances réseau,<br> ✅ Capable de <strong>scanner une machine locale</strong> (hardware, firmware, OS, logiciel),<br> ✅ De générer un <strong>CBOM structuré</strong> et exploitable,<br> ✅ Avec une <strong>interface utilisateur claire</strong>, adaptée aux <strong>postes de maintenance industrielle</strong> et aux <strong>environnements défense</strong>.</p><p>Une telle solution serait un <strong>game changer</strong> pour la sécurité des systèmes isolés et critiques.</p><h3>🗣️ Appel à contribution</h3><p>Le besoin est là, les technologies sont là (Rust, Tauri, Osquery, Syft, etc.).<br> Il ne manque plus qu’un projet pour <strong>assembler ces briques</strong> et répondre à un besoin <strong>stratégique</strong> pour la sécurité des environnements isolés.</p><p>👉 Et si on lançait ce projet ensemble ?<br> 👉 Des idées, des retours, des besoins spécifiques ?<br> Je suis preneur de vos retours en commentaire ou en message privé. 🚀</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=01b364bc459d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ Building an Ultra-Robust Network Packet Sniffer in Rust — Episode 2]]></title>
            <link>https://medium.com/@akmot9/building-an-ultra-robust-network-packet-sniffer-in-rust-episode-2-367202c96973?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/367202c96973</guid>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[networking]]></category>
            <category><![CDATA[packet-capture]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Thu, 24 Apr 2025 12:55:33 GMT</pubDate>
            <atom:updated>2025-04-24T12:55:33.397Z</atom:updated>
            <content:encoded><![CDATA[<h3>🦀 Building an Ultra-Robust Network Packet Sniffer in Rust — Episode 2</h3><p>From Raw Performance to Modular, Buffered, Asynchronous Capture</p><p>In Episode 1, we built a blazing-fast packet sniffer in Rust using pcap, with low-latency configuration and minimal buffering.</p><p>Now in Episode 2, we go deeper:</p><p>✅ Modular design<br> ✅ Controlled CPU usage<br> ✅ Configurable buffering<br> ✅ Robust asynchronous processing with no packet loss.</p><h3>🧱 From Monolith to Modular: setup_capture()</h3><p>We now isolate the setup logic into a reusable function:</p><pre>pub fn setup_capture(device: Device, buffer_size: i32) -&gt; Result&lt;Capture&lt;Active&gt;, pcap::Error&gt; {<br>    Capture::from_device(device)?<br>        .promisc(true)<br>        .immediate_mode(true)<br>        .buffer_size(buffer_size)<br>        .open()?<br>        .setnonblock()<br>}</pre><h3>Why?</h3><ul><li>Cleaner code separation</li><li>Easier testing</li><li>Configurable for any architecture</li></ul><h3>🔄 Dynamic channel_size</h3><p>Just like buffer_size, the <strong>channel capacity</strong> between the capture and processing thread is now configurable:</p><pre>start_capture(&quot;veth0&quot;, buffer_size = 8_000_000, channel_size = 10_000)</pre><p>This allows:</p><ul><li>Fine-grained control over memory usage</li><li>Backpressure tuning</li><li>Easier performance testing</li></ul><h3>🧵 Two Threads, One Mission</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K74kMx-_kjyiDgM2kS_Cnw.png" /></figure><ul><li>tx.try_send(...) ensures <strong>non-blocking send</strong></li><li>rx.recv() runs in a <strong>dedicated processing thread</strong></li><li>Together, they prevent <strong>packet drops</strong></li></ul><h3>🕳️ Adaptive Backoff Strategy</h3><p>To avoid wasting CPU cycles when no packets are available:</p><pre>let mut backoff = 1; // microseconds<br>...<br>thread::sleep(Duration::from_micros(backoff));<br>backoff = (backoff * 2).min(10_000); // exponential backoff</pre><p>💡 The backoff resets to 1 µs after a successful packet.</p><h3>🧠 Channel Monitoring (Backpressure)</h3><p>We measure channel fill rate to avoid overflow:</p><pre>let fill = rx.len();<br>if fill &gt;= 0.9 * channel_size as f32 {<br>    println!(<br>        &quot;[BACKPRESSURE] Channel is {}% full&quot;,<br>        (fill * 100.0 / channel_size as f32).round()<br>    );<br>}</pre><p>Use this data to tune channel_size, buffer_size, or CPU affinity.</p><h3>🧪 Real-world Load Test</h3><p>Using the following setup:</p><ul><li>immediate_mode = true</li><li>buffer_size = 8 MB</li><li>channel_size = 10_000</li></ul><p>We pushed the sniffer to <strong>process over 1 million packets</strong> with:</p><p>✅ <strong>Zero drops</strong><br> ✅ <strong>Stable CPU usage</strong><br> ✅ <strong>Low-latency processing</strong></p><h3>🧭 Mental Map of the Architecture</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*g9aeHTa-cc0t2D4AYVlrQw.png" /></figure><h3>🖼️ Screenshots: With and Without Backpressure</h3><p>🧩 Example 1: CPU usage without backoff during low activity<br> 🧩 Example 2: CPU usage with backoff enabled</p><h3>🖼️ Screenshots: With and Without Backpressure</h3><p>🧩 Example 1: CPU usage without backoff during low activity</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cV84PlPZu8qG9P_MmD5jow.png" /><figcaption>Without backoff stategy</figcaption></figure><p>🧩 Example 2: CPU usage with backoff enabled</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NorNvqr1XY0cHn-jj3Qrjw.png" /><figcaption>With backoff stategy</figcaption></figure><h3>🚫 Goodbye Packet Drops</h3><p>Thanks to:</p><ul><li>immediate_mode</li><li>setnonblock</li><li>bounded() channel with enough size</li><li>dedicated <strong>processing thread</strong></li></ul><p>We hit <strong>zero packet loss</strong>, even with Gigabit-level input traffic.</p><h3>🔮 Coming Up Next</h3><p>In <strong>Episode 3</strong> we’ll explore: 📈 Real-time telemetry (Prometheus + Grafana?)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=367202c96973" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ Building an Ultra-Robust Network Packet Sniffer in Rust with pcap]]></title>
            <link>https://medium.com/@akmot9/building-an-ultra-robust-network-packet-sniffer-in-rust-with-pcap-5000034b7a04?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/5000034b7a04</guid>
            <category><![CDATA[rust]]></category>
            <category><![CDATA[libpcap]]></category>
            <category><![CDATA[packet-capture]]></category>
            <category><![CDATA[networking]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Wed, 23 Apr 2025 13:38:37 GMT</pubDate>
            <atom:updated>2025-04-23T13:38:37.701Z</atom:updated>
            <content:encoded><![CDATA[<p>How to capture every single packet on your network — with high performance, memory safety, and structured logging.</p><h3>🎯 Goal</h3><blockquote>Create a minimal yet <strong>production-grade</strong> network sniffer in Rust that <strong>never misses a packet</strong>, even under heavy load.</blockquote><p>We’ll build on the pcap crate and leverage best practices for memory control, error handling, and performance tuning at the system level.</p><h3>📦 Dependencies</h3><p>Add this to your Cargo.toml:</p><pre>[dependencies]<br>pcap = &quot;1&quot;<br>thiserror = &quot;1&quot;<br>log = &quot;0.4&quot;<br>env_logger = &quot;0.10&quot;</pre><h3>⚙️ Project Setup</h3><p>We will:</p><p>List available interfaces</p><p>Open the target interface in:</p><ul><li><strong>promiscuous mode</strong> (see all packets)</li><li><strong>immediate mode</strong> (no kernel buffering)</li><li><strong>non-blocking mode</strong> (responsive loop)</li></ul><p>Process packets in an infinite loop</p><ul><li>Handle all known error cases explicitly</li><li>Track and display dropped packets and receive/processing delta</li></ul><h3>🧱 Custom Error Management</h3><p>error.rs:</p><pre>use thiserror::Error;<br>use pcap::Error as PcapError;<br><br>#[derive(Error, Debug)]<br>pub enum CaptureError {<br>    #[error(&quot;Network interface not found: {0}&quot;)]<br>    InterfaceNotFound(String),<br><br>    #[error(&quot;Error listing network interfaces: {0}&quot;)]<br>    DeviceListError(#[from] PcapError),<br><br>    #[error(&quot;Failed to initialize capture: {0}&quot;)]<br>    CaptureInitError(#[from] PcapError),<br>}</pre><h3>🚀 Main Code</h3><pre>use error::CaptureError;<br>use pcap::{Capture, Device};<br>use std::{thread, time::Duration};<br>use log::{info, warn, error};<br><br>mod error;<br><br>fn main() -&gt; Result&lt;(), CaptureError&gt; {<br>    env_logger::init();<br>    start_capture(&quot;enxfeaa81e86d1e&quot;)?;<br>    Ok(())<br>}<br><br>pub fn start_capture(interface_name: &amp;str) -&gt; Result&lt;(), CaptureError&gt; {<br>    info!(&quot;Starting packet capture on &#39;{}&#39;&quot;, interface_name);<br><br>    let iface = Device::list()<br>        .map_err(CaptureError::DeviceListError)?<br>        .into_iter()<br>        .find(|d| d.name == interface_name)<br>        .ok_or_else(|| CaptureError::InterfaceNotFound(interface_name.to_string()))?;<br><br>    info!(&quot;Interface found: {}&quot;, iface.name);<br><br>    let mut cap = Capture::from_device(iface)?<br>        .promisc(true)<br>        .immediate_mode(true)<br>        .open()?<br>        .setnonblock()?;<br><br>    let mut count = 0;<br>    let mut last_stats = None;<br><br>    loop {<br>        match cap.stats() {<br>            Ok(stats) =&gt; {<br>                let current = (stats.received, stats.dropped, stats.if_dropped);<br>                if last_stats != Some(current) {<br>                    last_stats = Some(current);<br>                    let (received, dropped, if_dropped) = current;<br>                    info!(&quot;Stats =&gt; received: {}, dropped: {}, kernel drop: {}&quot;, received, dropped, if_dropped);<br>                    info!(&quot;Delta recv - processed: {}&quot;, received.saturating_sub(count));<br>                }<br>            }<br>            Err(e) =&gt; warn!(&quot;Unable to retrieve stats: {:?}&quot;, e),<br>        }<br><br>        match cap.next_packet() {<br>            Ok(packet) =&gt; {<br>                info!(<br>                    &quot;PACKET len = {}, ts = {}.{}&quot;,<br>                    packet.data.len(),<br>                    packet.header.ts.tv_sec,<br>                    packet.header.ts.tv_usec<br>                );<br>                count += 1;<br>            }<br>            Err(pcap::Error::PcapError(e)) if e.contains(&quot;Packets are not available&quot;) =&gt; {<br>                thread::sleep(Duration::from_micros(500));<br>            }<br>            Err(pcap::Error::TimeoutExpired) =&gt; {<br>                thread::sleep(Duration::from_micros(500));<br>            }<br>            Err(pcap::Error::PcapError(e)) if e.contains(&quot;Interrupted&quot;) =&gt; {<br>                warn!(&quot;Capture interrupted cleanly&quot;);<br>                break;<br>            }<br>            Err(pcap::Error::PcapError(e)) if e.contains(&quot;Operation not permitted&quot;) =&gt; {<br>                error!(&quot;Missing privileges. Try:\nsudo setcap cap_net_raw,cap_net_admin=eip ./your_binary&quot;);<br>                break;<br>            }<br>            Err(e) =&gt; {<br>                error!(&quot;Unknown error: {:?}&quot;, e);<br>                break;<br>            }<br>        }<br>    }<br><br>    info!(&quot;Capture completed. Total packets: {}&quot;, count);<br>    Ok(())<br>}</pre><h3>🔐 Required Capabilities (Linux)</h3><p>To capture packets without root:</p><pre>sudo setcap cap_net_raw,cap_net_admin=eip ./your_binary</pre><h3>📊 Process Overview</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5jQifQ-FHHcUnLv4bXJqeQ.png" /></figure><h3>🧩 Going Further</h3><ul><li>🧵 Use a <strong>dedicated thread</strong> to offload packet parsing</li><li>🧠 Implement a <strong>ring buffer</strong> to reduce allocations</li><li>📡 Expose stats via a local HTTP or Unix socket API</li><li>🔍 Add protocol parsing (e.g. etherparse, dns-parser)</li><li>🧪 Benchmark critical code with criterion</li></ul><h3>✅ Conclusion</h3><p>With Rust and pcap, you can build a <strong>low-level, high-performance, and secure network sniffer</strong> that rivals tools written in C — with far fewer risks.</p><p>This foundation is ideal for:</p><ul><li>IDS sensors,</li><li>industrial protocol analyzers (Modbus, Profinet),</li><li>telemetry collection agents,</li><li>or integration into a Tauri or CLI-based security tool.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5000034b7a04" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Comprendre les versions de Windows XP : SP1, SP2, SP3, x86, x64 et plus encore]]></title>
            <link>https://medium.com/@akmot9/comprendre-les-versions-de-windows-xp-sp1-sp2-sp3-x86-x64-et-plus-encore-224bcc015a17?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/224bcc015a17</guid>
            <category><![CDATA[retro]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[windows-xp]]></category>
            <category><![CDATA[cyber]]></category>
            <category><![CDATA[windows]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Thu, 27 Mar 2025 10:06:48 GMT</pubDate>
            <atom:updated>2025-03-27T10:06:48.398Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>Comprendre les versions de Windows XP : SP1, SP2, SP3, x86, x64 et plus encore</strong></h3><p>Voici une explication complète sur les différentes <strong>versions de Windows XP</strong>, notamment les notions de SP1, SP2, SP3, x86, x64, 32-bit et 64-bit :</p><h3>🧠 1. Windows XP : la base</h3><p>Windows XP est un système d’exploitation de Microsoft sorti en <strong>2001</strong>. Il a connu plusieurs <strong>Service Packs (SP)</strong> qui sont des <strong>mises à jour majeures</strong> cumulant sécurité, stabilité et nouvelles fonctionnalités.</p><h3>🛠️ 2. Les Service Packs (SP)</h3><ul><li><strong>SP0 (ou RTM)</strong> : version de lancement d’origine (2001).</li><li><strong>SP1</strong> (2002) : ajoute le support de l’USB 2.0 et corrige plusieurs bugs.</li><li><strong>SP2</strong> (2004) : grande mise à jour axée sur la <strong>sécurité</strong> (pare-feu, sécurité IE, Windows Security Center…).</li><li><strong>SP3</strong> (2008) : dernière mise à jour officielle majeure (stabilité, compatibilité, mais pas d’IE7/8 ni Media Player 11 inclus de base).</li></ul><blockquote><em>📌 À noter : </em><strong><em>XP x64 n’a jamais eu de SP3</em></strong><em>, seulement </em><strong><em>SP1 et SP2</em></strong><em>.</em></blockquote><h3>🧮 3. x86 vs x64 : 32-bit vs 64-bit</h3><h3>🖥️ x86 (32-bit)</h3><ul><li>Version la plus courante.</li><li>Limite de <strong>4 Go de RAM maximum</strong> (souvent seulement 3.2 Go utilisables).</li><li>Compatible avec la majorité des logiciels XP.</li><li>Plus stable à l’époque, meilleure compatibilité.</li></ul><h3>🖥️ x64 (64-bit)</h3><ul><li>Permet d’utiliser <strong>plus de 4 Go de RAM</strong> (jusqu’à 128 Go théorique).</li><li>Meilleures performances sur matériel 64-bit.</li><li>Moins de compatibilité avec anciens drivers et logiciels.</li><li>Basée sur <strong>Windows Server 2003 x64</strong>, donc un peu différente de XP 32 bits.</li></ul><blockquote><em>⚠️ Beaucoup de logiciels XP </em><strong><em>n’avaient pas de version 64-bit</em></strong><em>, et les pilotes étaient plus rares à l’époque. Pour cette raison, </em><strong><em>XP 32 bits (x86)</em></strong><em> est resté la norme.</em></blockquote><h3>🌍 4. Licences : Retail vs VL</h3><ul><li><strong>Retail</strong> : version boîte, vendue au grand public (activable avec clés individuelles).</li><li><strong>VL (Volume License)</strong> : pour entreprises, écoles… Permet l’utilisation d’une <strong>même clé sur plusieurs machines</strong>, sans activation Internet.</li></ul><h3>🌐 5. Langues disponibles</h3><p>Les ISO sont disponibles en :</p><ul><li><strong>EN</strong> = Anglais</li><li><strong>DE</strong> = Allemand</li><li><strong>RU</strong> = Russe</li><li><strong>TR</strong> = Turc</li></ul><h3>🔐 6. Clés de licence fournies</h3><p>Le document contient des <strong>clés génériques</strong> pour installation/test. Elles sont <strong>Volume License ou Retail</strong> selon les ISO. Ces clés ne sont pas valides pour l’activation en ligne aujourd’hui (serveurs d’activation fermés).</p><h3>🧪 7. Vérification des ISO</h3><p>Chaque fichier ISO est accompagné de :</p><ul><li><strong>MD5</strong> : somme de contrôle</li><li><strong>SHA1</strong> : autre méthode d’empreinte numérique</li></ul><p>Ces valeurs permettent de <strong>vérifier l’intégrité</strong> des fichiers téléchargés.</p><h3>🧾 8. Versions spécifiques</h3><p>Quelques éditions spéciales :</p><ul><li><strong>Windows XP Home</strong> : version familiale, plus limitée.</li><li><strong>Windows XP Professional</strong> : plus complète, pour pro et entreprises.</li><li><strong>Windows XP Tablet PC Edition 2005</strong> : pour ordinateurs avec écran tactile/stylet.</li><li><strong>Windows Fundamentals for Legacy PCs</strong> : version allégée pour vieux PC.</li></ul><h3>🧩 9. SP4 non-officiel</h3><ul><li>Il existe un <strong>“Service Pack 4 Unofficial”</strong>, regroupant toutes les mises à jour post-SP3 (jusqu’en 2019).</li><li>Utilisé par les passionnés pour <strong>prolonger la durée de vie de XP</strong> de manière sécurisée.</li></ul><h3>🔧 SP4 Unofficial en détail :</h3><ul><li>Fichier : WindowsXP-USP4-v3.1b-x86-ENU.exe</li><li>Langue : Anglais uniquement</li><li>Taille : ~992 Mo</li><li>Auteur : “Harkaz” (forum MSFN)</li><li>Intègre : IE8, Media Player 11, RDP 8.0, KB sécurité jusqu’en 2019, .NET 3.5/4.0 en option</li><li>Fonctionne offline, installable sur XP SP3</li><li>Prise en charge de POSReady 2009 (XP pour distributeurs de billets)</li></ul><h3>🖥️ Scénarios d’usage en 2025</h3><ul><li>Déploiement de VM XP sécurisées pour tests rétrocompatibles</li><li>Maintenance de logiciels embarqués ou industriels encore utilisés</li><li>Création d’une base propre et à jour pour le développement rétro</li><li>Utilisation dans un réseau isolé, avec snapshot régulier</li></ul><blockquote><em>📌 Astuce : On peut créer un ISO personnalisé avec SP4 intégré grâce à </em><strong><em>nLite</em></strong><em> ou </em><strong><em>RVM Integrator</em></strong><em>.</em></blockquote><blockquote><em>⚠️ Limitations : non supporté officiellement, uniquement en anglais, ne corrige pas les failles matérielles modernes (ex : Spectre/Meltdown)</em></blockquote><h3>📂 10. Fichiers MUI</h3><ul><li>Les <strong>MUI (Multilingual User Interface Packs)</strong> permettent de <strong>changer la langue de l’interface</strong> sans réinstaller.</li></ul><h3>📅 En résumé :</h3><p>Version Architecture SP Disponible Notes XP Pro SP0 x86 Non (version de base) 2001 XP Pro SP1 x86 / x64 Oui Ajoute USB 2.0, sécurité XP Pro SP2 x86 / x64 Oui Très axée sécurité XP Pro SP3 x86 seulement Oui Dernier SP officiel, le plus complet XP Pro x64 x64 seulement SP1 &amp; SP2 uniquement Basée sur Windows Server 2003 XP Home x86 Jusqu’à SP3 Pour particuliers XP Tablet PC x86 SP2 (2005) Pour PC à stylet XP FLP x86 SP2 Allégé pour vieux PC XP SP4 Unofficial x86 Non officiel Mises à jour post-SP3 jusqu’en 2019</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=224bcc015a17" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Utiliser Windows XP en 2025 : rétrocompatibilité, développement et survie logicielle]]></title>
            <link>https://medium.com/@akmot9/utiliser-windows-xp-en-2025-r%C3%A9trocompatibilit%C3%A9-d%C3%A9veloppement-et-survie-logicielle-526a21faa039?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/526a21faa039</guid>
            <category><![CDATA[xp]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[windows]]></category>
            <category><![CDATA[development]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Thu, 27 Mar 2025 09:56:16 GMT</pubDate>
            <atom:updated>2025-03-27T09:56:16.989Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>Utiliser Windows XP en 2025 : rétrocompatibilité, développement et survie logicielle</strong></h3><p><strong>Introduction</strong></p><p>Windows XP est mort… mais pas enterré.</p><p>En 2025, alors que Windows 11 est le standard imposé par Microsoft, et que la majorité des logiciels migrent vers le cloud, une réalité subsiste dans l’ombre des infrastructures modernes : certaines machines tournent encore sous Windows XP. Et ce, non par nostalgie, mais par nécessité.</p><p>Dans l’industrie, la défense, la santé ou les systèmes embarqués, XP reste un pilier, souvent parce que les coûts de migration sont prohibitifs, ou que des logiciels critiques n’ont jamais été portés sur des systèmes plus récents. Cet article s’adresse à ceux qui doivent encore faire vivre XP en 2025, en particulier pour des besoins de développement logiciel ou de maintenance de parcs informatiques vieillissants.</p><p><strong>1. Pourquoi Windows XP est encore utilisé aujourd’hui</strong></p><ul><li><strong>Dépendance à des logiciels anciens</strong> : logiciels industriels, médicaux ou militaires non migrés.</li><li><strong>Compatibilité matérielle</strong> : drivers spécifiques, ports série (RS232), interfaces PCI/E.</li><li><strong>Stabilité connue</strong> : XP est un environnement stable, documenté, connu par les techniciens.</li><li><strong>Coûts de remplacement élevés</strong> : remplacer le parc entier est souvent hors budget.</li></ul><p><strong>2. Les risques de continuer sous XP</strong></p><ul><li>Plus de mises à jour de sécurité.</li><li>Incompatibilité avec le matériel récent.</li><li>Pas de prise en charge du HTTPS moderne ou des outils cloud.</li><li>Risques en cas de connexion Internet (ransomwares, malware…)</li></ul><p>→ XP <strong>ne doit pas être utilisé comme poste de travail connecté au web</strong>. Il doit être considéré comme un “outil isolé”.</p><p><strong>3. Environnements techniques pour XP en 2025</strong></p><p><strong>A. Virtualisation</strong></p><ul><li>XP tourne très bien sous VirtualBox, VMware ou QEMU.</li><li>Idéal pour le développement ou les tests de compatibilité.</li><li>Possibilité d’import/export d’image VM.</li></ul><p><strong>B. Réinstallation native (hardware d’origine)</strong></p><ul><li>Requiert du matériel compatible : CPU avant 2010, 2 Go RAM, chipset Intel ou nVidia.</li><li>Disques IDE/SATA, pas de NVMe.</li><li>ISO disponibles sur Archive.org (versions MSDN de confiance).</li></ul><p><strong>C. Alternatives</strong></p><ul><li><strong>ReactOS</strong> : système libre compatible XP (encore instable).</li><li><strong>Wine</strong> : faire tourner des programmes XP sur Linux, selon les cas.</li></ul><p><strong>4. Développement logiciel pour Windows XP</strong></p><ul><li>Environnement classique : Visual Studio 6.0, 2005, ou 2008.</li><li>.NET Framework 2.0 ou 3.5.</li><li>Compilation avec /SUBSYSTEM:WINDOWS,5.1 pour compatibilité XP.</li><li>Tests via VM XP, émulation de matériel si nécessaire.</li></ul><p>Utiliser XP permet de vérifier la compatibilité descendante de logiciels modernes dans des contextes critiques.</p><p><strong>5. Où trouver des ISO fiables</strong></p><ul><li>Archive.org propose les versions <strong>officielles MSDN</strong> en anglais, allemand, russe et turc.</li><li>Toujours vérifier les <strong>MD5/SHA1</strong> pour s’assurer de l’intégrité.</li><li>Privilégier les versions :</li><li><strong>SP2</strong> : meilleure stabilité.</li><li><strong>SP3</strong> : le plus complet.</li><li><strong>x64</strong> : uniquement si besoin &gt; 4 Go RAM et drivers compatibles.</li></ul><p><strong>6. Bonnes pratiques de sécurité</strong></p><ul><li>Toujours <strong>isoler XP</strong> du réseau Internet.</li><li>Utiliser des snapshots, des sauvegardes et des images figées.</li><li>Lire seule sur le disque si besoin.</li><li>Désactiver les partages inutiles.</li></ul><p><strong>Conclusion</strong></p><p>Windows XP n’est plus une solution moderne, mais reste un outil valable pour des cas très spécifiques. Il permet de maintenir en vie des infrastructures critiques, de valider la compatibilité de certains logiciels ou encore de comprendre les anciens environnements logiciels.</p><p>En 2025, utiliser XP est un <strong>choix technique</strong>, à faire en connaissance de cause, avec rigueur et sécurité. Ce n’est pas un retour en arrière, mais un pont vers le passé pour ceux qui doivent encore le traverser.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=526a21faa039" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Simplifying Imports in Rust — Reducing Redundancy in Your Modules]]></title>
            <link>https://medium.com/@akmot9/simplifying-imports-in-rust-reducing-redundancy-in-your-modules-59dc23532254?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/59dc23532254</guid>
            <category><![CDATA[flatten-the-curve]]></category>
            <category><![CDATA[rust]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Mon, 18 Nov 2024 15:10:24 GMT</pubDate>
            <atom:updated>2024-11-18T15:10:24.094Z</atom:updated>
            <content:encoded><![CDATA[<h3>Simplifying Imports in Rust — Reducing Redundancy in Your Modules</h3><p>When developing in Rust, you often encounter situations where a module and a function have the same name. This can lead to redundant and verbose imports, such as:</p><pre>use commandes::get_interfaces::get_interfaces;</pre><p>This kind of repetition makes your code harder to read and maintain. Fortunately, there’s an elegant solution to flatten these hierarchies while preserving Rust’s modular structure. Here’s how I solved this issue.</p><h3>The Problem</h3><p>Let’s consider a concrete example. You have a module structure like this:</p><pre>src/<br>├── commandes/<br>│   ├── get_interfaces.rs<br>│   └── mod.rs<br>└── main.rs</pre><p>Contents of get_interfaces.rs:</p><pre>pub fn get_interfaces() {<br>    println!(&quot;Fetching interfaces...&quot;);<br>}</pre><p>Contents of mod.rs:</p><pre>pub mod get_interfaces;</pre><p>When importing this function in main.rs, you end up writing:</p><pre>use commandes::get_interfaces::get_interfaces;<br><br>fn main() {<br>    get_interfaces();<br>}</pre><p>While this works, repeating get_interfaces twice feels unnecessarily verbose. Here&#39;s how you can avoid this redundancy.</p><h3>The Solution: Use pub use to Re-export</h3><p>Rust allows you to <strong>re-export</strong> items from a module using pub use. This enables you to expose functions directly at a higher level, reducing the need to repeat their full path.</p><p>Here’s how to update your mod.rs file to re-export the get_interfaces function:</p><p><strong>Updated </strong><strong>mod.rs:</strong></p><pre>pub mod get_interfaces;<br><br>// Re-export the function<br>pub use get_interfaces::get_interfaces;</pre><p>Now, in main.rs, you can write:</p><pre>use commandes::get_interfaces;<br><br>fn main() {<br>    get_interfaces();<br>}</pre><p>This change makes the code more readable and intuitive while preserving the original modular structure.</p><h3>Why Re-export?</h3><ol><li><strong>Improved readability:</strong><br>Avoid unnecessary duplication in your import paths.</li><li><strong>Ease of access:</strong><br>Consumers of your module can directly access its key functions without diving into the full submodule hierarchy.</li><li><strong>Preserved modularity:</strong><br>Your code structure remains well-organized without manually flattening all your modules.</li></ol><h3>Extending This Approach</h3><p>If you’re working with multiple modules and want to expose their key functions, you can apply this strategy across your project.</p><h4>Example with Multiple Modules:</h4><p>mod.rs:</p><pre>pub mod get_interfaces;<br>pub mod set_interfaces;<br><br>// Re-export for simpler access<br>pub use get_interfaces::get_interfaces;<br>pub use set_interfaces::set_interfaces;</pre><p>In this case, main.rs can use the functions as follows:</p><pre>use commandes::{get_interfaces, set_interfaces};<br><br>fn main() {<br>    get_interfaces();<br>    set_interfaces();<br>}</pre><h3>When Not to Use This Approach</h3><ul><li>If you want to keep an explicit hierarchy for clarity in a complex project or for public API design.</li><li>If multiple modules contain functions with the same name. Re-exporting them can lead to conflicts.</li></ul><h3>Conclusion</h3><p>Re-exporting with pub use is a simple yet powerful technique to make your Rust imports cleaner and more intuitive. It shows that despite its strictness, Rust allows elegant solutions for managing modularity and reducing code complexity.</p><p>Want to learn more tricks to simplify your Rust code? Follow me for more practical tutorials!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=59dc23532254" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Writing an Efficient Profinet Packet Parser in Rust: Implementation, Error Handling, and…]]></title>
            <link>https://medium.com/@akmot9/writing-an-efficient-profinet-packet-parser-in-rust-implementation-error-handling-and-a827afbd23e4?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/a827afbd23e4</guid>
            <category><![CDATA[crate]]></category>
            <category><![CDATA[network]]></category>
            <category><![CDATA[rust]]></category>
            <category><![CDATA[profibus-profinet]]></category>
            <category><![CDATA[network-security]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Mon, 04 Nov 2024 11:55:04 GMT</pubDate>
            <atom:updated>2024-11-04T11:55:04.850Z</atom:updated>
            <content:encoded><![CDATA[<h3>Writing an Efficient Profinet Packet Parser in Rust: Implementation, Error Handling, and Benchmarking</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5WH7J2vgDDeNKxI8doegig.jpeg" /></figure><p>In this article, I’ll walk you through the journey of developing a profinet_parser crate in Rust, covering the implementation of TryFrom for parsing, enhanced error handling using thiserror, and the performance optimizations achieved by using references instead of copying data. Additionally, I’ll explain Rust’s lifetime annotations and their significance in building efficient and safe code.</p><h3>Introduction to ProfinetPacket</h3><p>Profinet is an industry-standard protocol widely used in industrial automation for communication between controllers and devices. Parsing Profinet packets accurately and efficiently is critical for applications that need to analyze or manage network traffic. The goal of this crate was to implement a Rust structure that can parse a Profinet packet from a byte slice and return a structured representation of it.</p><h3>Initial Implementation Using TryFrom</h3><p>Here’s how the TryFrom implementation was constructed:</p><pre>impl&lt;&#39;a&gt; TryFrom&lt;&amp;&#39;a [u8]&gt; for ProfinetPacket {<br>    type Error = ProfinetPacketError;<br><br>    fn try_from(data: &amp;&#39;a [u8]) -&gt; Result&lt;Self, Self::Error&gt; {<br>        validate_packet_length(data)?;<br>        let frame_id = validate_frame_id(data)?;<br>        validate_dcp_block(data)?;<br><br>        let service_id = data[2];<br>        let service_type = data[3];<br>        let xid = u32::from_be_bytes([data[4], data[5], data[6], data[7]]);<br>        let response_delay = u16::from_be_bytes([data[8], data[9]]);<br>        let dcp_data_length = u16::from_be_bytes([data[10], data[11]]);<br><br>        let option = data[12];<br>        let suboption = data[13];<br>        let dcp_block_length = u16::from_be_bytes([data[14], data[15]]);<br><br>        let name_of_station = extract_name_of_station(data)?;<br><br>        Ok(ProfinetPacket {<br>            frame_id,<br>            service_id,<br>            service_type,<br>            xid,<br>            response_delay,<br>            dcp_data_length,<br>            option,<br>            suboption,<br>            dcp_block_length,<br>            name_of_station,<br>        })<br>    }<br>}</pre><h3>Adding Error Handling with thiserror</h3><p>Robust error handling is essential for understanding what went wrong when parsing fails. We used the thiserror crate to create custom, user-friendly errors:</p><pre>use thiserror::Error;<br><br>#[derive(Error, Debug, PartialEq, Eq, Clone, Copy)]<br>pub enum ProfinetPacketError {<br>    #[error(&quot;Packet too short: {0} bytes&quot;)]<br>    PacketTooShort(usize),<br>    #[error(&quot;Unknown Frame ID: {0:#04x}&quot;)]<br>    UnknownFrameId(u16),<br>    #[error(&quot;Invalid DCP block length: {0}&quot;)]<br>    InvalidDcpBlockLength(usize),<br>    #[error(&quot;Invalid name of station: not valid UTF-8&quot;)]<br>    InvalidNameOfStation,<br>}</pre><blockquote>Those errors are propagated when validations fail.</blockquote><p>These descriptive error types provided clear feedback during parsing failures, improving the overall debugging experience.</p><h3>Benchmarking for Performance Optimization</h3><p>To measure the performance of the try_from implementation and optimize it, we used the criterion crate. Our initial benchmarks showed that copying data into a new array could be costly. By switching to referencing slices directly, we aimed to minimize unnecessary copies and improve parsing speed.</p><h3>Benchmark Results</h3><p>We ran benchmarks using Criterion and compared the performance of the initial implementation with one that used references instead of copying. Here’s an example of a benchmark:</p><pre>use criterion::{black_box, criterion_group, criterion_main, Criterion};<br>use profinet_parser::ProfinetPacket;<br><br>pub fn benchmark_packet_conversion(c: &amp;mut Criterion) {<br>    let data = black_box(vec![<br>        0xFE, 0xFE, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01,<br>        0x00, 0x10, 0x00, 0x0C, 0x02, 0x03, 0x00, 0x04,<br>        b&#39;T&#39;, b&#39;E&#39;, b&#39;S&#39;, b&#39;T&#39;<br>    ]);<br><br>    c.bench_function(&quot;profinet_packet_conversion&quot;, |b| {<br>        b.iter(|| ProfinetPacket::try_from(&amp;data[..]))<br>    });<br>}<br><br>criterion_group!(benches, benchmark_packet_conversion);<br>criterion_main!(benches);</pre><p>Here is an exemple of a modification</p><p>we change the fn extract_name_of_station so it returns a &amp;’a str and not a String:</p><pre>fn extract_name_of_station&lt;&#39;a&gt;(data: &amp;&#39;a [u8]) -&gt; Result&lt;&amp;&#39;a str, ProfinetPacketError&gt; {<br>    let block = &amp;data[12..];<br>    let dcp_block_length = u16::from_be_bytes([block[2], block[3]]) as usize;<br><br>    if block.len() &lt; (4 + dcp_block_length) {<br>        return Err(ProfinetPacketError::InvalidDcpBlockLength(block.len()));<br>    }<br><br>    std::str::from_utf8(&amp;block[4..4 + dcp_block_length])<br>        .map_err(|_| ProfinetPacketError::InvalidNameOfStation)<br>}</pre><p><strong>Results:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/946/1*SRlrujtbwxhA37SrX5yhPg.png" /><figcaption>In red the previous performance of the crate</figcaption></figure><ul><li><strong>Before optimization</strong>: Parsing time was around 25 ns.</li><li><strong>After optimization</strong>: Parsing time dropped significantly to around 13.7 ns, showing a 45% performance improvement.</li></ul><p>This result confirms that avoiding data copying and using references instead can lead to substantial performance gains.</p><blockquote>Understanding Lifetimes:</blockquote><blockquote>In Rust, lifetimes are crucial for ensuring that references are valid and safe throughout the program. In our `ProfinetPacket` implementation, lifetimes were used to tie the lifetime of the parsed packet to the byte slice it references. This avoided unnecessary allocations and allowed the `ProfinetPacket` struct to point directly to parts of the input slice:</blockquote><blockquote>By leveraging lifetimes, we ensured that the parsed data only lived as long as the input slice, thus maintaining safety and efficiency.</blockquote><pre>impl&lt;&#39;a&gt; TryFrom&lt;&amp;&#39;a [u8]&gt; for ProfinetPacket&lt;&#39;a&gt; {<br>    // Implementation that leverages lifetimes for zero-copy parsing.<br>}</pre><h3>Conclusion</h3><p>Creating a profinet_parser crate in Rust taught us valuable lessons about efficient parsing, error handling, and optimization. Implementing TryFrom allowed us to convert byte slices into structured packets seamlessly, while thiserror improved error clarity. Most importantly, performance benchmarks showed that using references instead of copying can have a substantial impact on parsing speed.</p><p>If you’re working on parsing network protocols or performance-critical applications, considering these techniques can help build robust and efficient solutions in Rust.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a827afbd23e4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deep Dive into Packet Capture with pnet: Understanding Raw Socket Operations in Rust]]></title>
            <link>https://medium.com/@akmot9/deep-dive-into-packet-capture-with-pnet-understanding-raw-socket-operations-in-rust-818a351ea484?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/818a351ea484</guid>
            <category><![CDATA[network-security]]></category>
            <category><![CDATA[rust]]></category>
            <category><![CDATA[socket-programming]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Thu, 24 Oct 2024 08:51:22 GMT</pubDate>
            <atom:updated>2024-10-24T08:51:22.517Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pv8k3mMu68E2X4cilVBQZg.jpeg" /></figure><h3>Introduction</h3><p>Rust’s ecosystem has grown to include several powerful crates for network programming, including pnet, a crate used for packet-level access to network interfaces. This article will explore what happens &quot;under the hood&quot; when pnet captures packets from a network interface. We will delve into the concept of raw sockets, system calls, and how Rust interacts with these low-level details using libc.</p><h4><strong>What Are Raw Sockets?</strong></h4><p>A raw socket is a special kind of network socket that allows applications to access packets directly at the network layer (OSI Layer 3). Unlike standard sockets, which handle protocol-specific parsing (TCP, UDP, etc.), raw sockets allow you to capture and inspect packets in their raw form — including headers and payloads. This capability is essential for network monitoring, intrusion detection systems, and packet manipulation tools.</p><h4><strong>How </strong><strong>pnet Uses Raw Sockets for Packet Capture</strong></h4><p>When you use pnet to capture packets, it sets up a raw socket and binds it to a specific network interface. This allows it to receive all packets traversing the interface without filtering based on a particular protocol. Here’s a breakdown of what happens step-by-step:</p><ol><li><strong>Creating a Raw Socket</strong> The first step is to create a raw socket using the socket system call. In Rust, this is done using the libc library to directly access OS-level functionality. Here&#39;s a code snippet that demonstrates this:</li></ol><pre>use libc::{socket, AF_PACKET, SOCK_RAW, ETH_P_ALL};<br><br>// Create a raw socket<br>let sock_fd = unsafe { socket(AF_PACKET, SOCK_RAW, (ETH_P_ALL as u16).to_be() as i32) };<br>if sock_fd &lt; 0 {<br>    panic!(&quot;Failed to create raw socket: {}&quot;, std::io::Error::last_os_error());<br>}</pre><ul><li>AF_PACKET: Specifies that the socket is for packet-level access, typically used on Linux.</li><li>SOCK_RAW: Indicates that the socket should operate in raw mode, giving access to all network layer packets.</li><li>ETH_P_ALL: Tells the socket to capture all Ethernet packets, regardless of protocol.</li></ul><p><strong>2. Binding the Socket to a Network Interface</strong> Once the socket is created, it must be bound to a specific network interface (e.g., eth0) to listen for incoming packets. This is done with the setsockopt system call:</p><pre>use libc::{setsockopt, SOL_SOCKET, SO_BINDTODEVICE};<br><br>// Convert the interface name (like &quot;eth0&quot;) to a CString<br>let interface_name = CString::new(&quot;eth0&quot;).unwrap();<br><br>// Bind the socket to the network interface<br>let result = unsafe {<br>    setsockopt(<br>        sock_fd,<br>        SOL_SOCKET,<br>        SO_BINDTODEVICE,<br>        interface_name.as_ptr() as *const libc::c_void,<br>        libc::IFNAMSIZ as libc::socklen_t,<br>    )<br>};<br>if result &lt; 0 {<br>    panic!(&quot;Failed to bind socket to interface: {}&quot;, std::io::Error::last_os_error());<br>}</pre><ul><li>SOL_SOCKET and SO_BINDTODEVICE are options used to configure the socket at the system level.</li><li>The network interface name is passed as a CString, a null-terminated string format expected by many C libraries.</li></ul><p><strong>3. Receiving Packets in a Loop</strong> With the socket bound to the interface, it is ready to capture packets. The recv system call reads packets from the socket, which are then processed:</p><pre>use libc::recv;<br><br>// Buffer to store received packets<br>let mut buffer = [0u8; 65536];<br><br>loop {<br>    // Receive packets from the socket<br>    let packet_size = unsafe { recv(sock_fd, buffer.as_mut_ptr() as *mut libc::c_void, buffer.len(), 0) };<br>    if packet_size &lt; 0 {<br>        panic!(&quot;Error receiving packet: {}&quot;, std::io::Error::last_os_error());<br>    }<br><br>    // Convert the buffer to a packet<br>    let packet: Vec&lt;u8&gt; = buffer[..packet_size as usize].to_vec();<br><br>    // Print the packet in hexadecimal format<br>    println!(&quot;Received packet: {:02X?}&quot;, packet);<br>}</pre><ul><li>recv: Reads data from the socket into a buffer. In the example, 65536 bytes are allocated to handle even large packets.</li><li>The packet data is then converted to a Vec&lt;u8&gt; for easier manipulation.</li></ul><h4><strong>What is </strong><strong>pnet Handling for You?</strong></h4><p>The pnet crate abstracts many of these low-level details, providing a higher-level API while still granting fine-grained control over network packets. Here&#39;s what pnet does behind the scenes:</p><ol><li><strong>Socket Creation and Binding</strong>: pnet manages socket creation and binding, supporting multiple platforms (Linux, Windows, macOS) with appropriate system calls for each OS.</li><li><strong>Packet Parsing</strong>: pnet provides pre-built structures to parse common network protocols like IPv4, IPv6, TCP, UDP, and ARP. This parsing is handled automatically, saving developers from manually dissecting each packet&#39;s binary structure.</li><li><strong>Error Handling</strong>: Errors during packet capture, such as socket creation failures or permission issues, are handled with meaningful Rust error types instead of raw error codes.</li><li><strong>Filter Application</strong>: pnet allows users to apply packet filters (e.g., using Berkeley Packet Filter syntax) to limit the type of traffic captured.</li></ol><h4>Why Use Raw Sockets with Rust?</h4><p>While crates like pnet make packet capture accessible, using raw sockets directly provides full control over how packets are captured and processed. This approach is beneficial for:</p><ul><li><strong>Performance Optimization</strong>: Fine-tuning the capture loop to handle high-throughput environments.</li><li><strong>Advanced Filtering</strong>: Implementing custom filters beyond the capabilities of pre-built filters.</li><li><strong>Protocol Development</strong>: Crafting new or niche protocols that require specific handling not covered by high-level libraries.</li></ul><h4>Conclusion</h4><p>Packet capture in Rust using raw sockets reveals the power and flexibility of the language for network programming. While pnet offers a great abstraction for common use cases, understanding what happens underneath allows developers to make more informed decisions when building network tools. Rust’s safety features combined with low-level access give you the best of both worlds for secure and performant network programming.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=818a351ea484" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Network Analysis in Rust: Using the pcap and pnet crates to Capture and Analyze Network Traffic]]></title>
            <link>https://medium.com/@akmot9/title-network-analysis-in-rust-using-the-pcap-and-pnet-crates-to-capture-and-analyze-network-94e1627536b1?source=rss-e9c0456814d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/94e1627536b1</guid>
            <category><![CDATA[rust]]></category>
            <category><![CDATA[network-security]]></category>
            <dc:creator><![CDATA[Cyprien Avico]]></dc:creator>
            <pubDate>Thu, 24 Oct 2024 08:26:23 GMT</pubDate>
            <atom:updated>2024-10-29T13:58:10.087Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XpFzN9XJmPios_ef3XSaRA.jpeg" /></figure><h3><strong>Introduction</strong></h3><p>Network analysis is crucial for monitoring, security, and diagnosing network infrastructure. <strong>Rust</strong>, with its performance and memory safety, is becoming an increasingly popular choice for developers building network tools. In this article, we will explore how to use Rust crates <em>pcap</em> and <em>pnet</em> to read PCAP files, capture live network traffic, and briefly discuss using <em>PF_RING</em> for high-performance packet capture.</p><p><strong>Reading PCAP Files with the <em>pcap</em> crate</strong></p><p>The <em>pcap</em> crate allows you to read network capture files, commonly known as PCAP (Packet Capture), which contain traces of network traffic. This step is essential for analyzing network incidents or debugging.</p><p>A simple example to read packets from a file:</p><pre>use pcap::Capture;<br><br>   fn main() {<br>       let mut cap = Capture::from_file(&quot;example.pcap&quot;).unwrap();<br>       while let Ok(packet) = cap.next() {<br>           println!(&quot;Packet : {:?}&quot;, packet);<br>       }<br>   }</pre><p><strong>Using <em>pnet</em> for Fine-Grained Packet Capture and Analysis</strong></p><p>The <em>pnet </em>crate allows working at a lower level with network packets in Rust. Unlike <em>pcap</em>, it offers a more detailed API to manipulate packet headers, protocols, and access the network card through system libraries.</p><p>Pnet embeddes raw sockets form the os informations to the user of the crate:</p><pre>   use pnet::datalink::{self, Channel::Ethernet};<br><br>   fn main() {<br>       let interfaces = datalink::interfaces();<br>       let interface = interfaces.into_iter()<br>           .find(|iface| iface.is_up() &amp;&amp; !iface.is_loopback())<br>           .expect(&quot;No suitable interface found.&quot;);<br><br>       let (_, mut rx) = match datalink::channel(&amp;interface, Default::default()) {<br>           Ok(Ethernet(tx, rx)) =&gt; (tx, rx),<br>           Ok(_) =&gt; panic!(&quot;Unhandled channel type.&quot;),<br>           Err(e) =&gt; panic!(&quot;An error occurred: {}&quot;, e),<br>       };<br><br>       loop {<br>           match rx.next() {<br>               Ok(packet) =&gt; println!(&quot;Packet : {:?}&quot;, packet),<br>               Err(e) =&gt; eprintln!(&quot;An error occurred while reading: {}&quot;, e),<br>           }<br>       }<br>   }</pre><p><strong>Accessing Network Cards with <em>pnet</em> and <em>libc</em></strong></p><p>To capture and filter packets efficiently, `pnet` can directly interact with system libraries. On Windows, this is done via `Npcap` (a fork of `WinPcap`), and on Linux through raw sockets and the Berkeley Packet Filter (BPF). `libc` is often used to access these system-level features.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-nRQ-HUEYhn1aifCgTXE3g.png" /></figure><p><em>Pnet</em> uses system calls to access network drivers through libraries like <em>libc</em>.</p><p><strong>High-performance capture with PF_RING:</strong></p><p>For environments requiring high performance, `PF_RING` can be used for optimized capture with direct access to the network card.</p><h3><strong>Conclusion</strong></h3><p>Rust offers a variety of powerful tools for network analysis and capture. The <em>pcap</em> and <em>pnet</em> crates provide features suited for different levels of abstraction. For detailed analysis and performance needs, <em>pnet</em> and <em>PF_RING</em> are particularly interesting.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=94e1627536b1" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>