<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Home on Clean Tech</title><link>http://www.lineon.fr/</link><description>Recent content in Home on Clean Tech</description><generator>Hugo</generator><language>en</language><lastBuildDate>Wed, 01 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="http://www.lineon.fr/index.xml" rel="self" type="application/rss+xml"/><item><title>Building a Threat Intel CLI Tool in Rust</title><link>http://www.lineon.fr/posts/rust-cli-threat-intel/</link><pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate><guid>http://www.lineon.fr/posts/rust-cli-threat-intel/</guid><description>&lt;p&gt;Python is the default language for security tooling, but Rust offers compelling advantages for CLI tools that need to be fast, distributable as a single binary, and safe by default. Here&amp;rsquo;s how I built a threat intelligence lookup tool in Rust.&lt;/p&gt;
&lt;h2 id="the-goal"&gt;The goal&lt;/h2&gt;
&lt;p&gt;A single binary that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accepts an IP, domain, or hash as input&lt;/li&gt;
&lt;li&gt;Queries VirusTotal, AbuseIPDB, and Shodan in parallel&lt;/li&gt;
&lt;li&gt;Outputs a unified JSON report&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="project-setup"&gt;Project setup&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo init threat-lookup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; threat-lookup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add reqwest --features json,rustls-tls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add tokio --features full
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add serde --features derive
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add serde_json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo add clap --features derive
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="cli-argument-parsing-with-clap"&gt;CLI argument parsing with Clap&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clap&lt;/span&gt;::&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#[derive(Parser, Debug)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#[command(name = &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;threat-lookup&amp;#34;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#[command(about = &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Query threat intel APIs for IOCs&amp;#34;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// The indicator to look up (IP, domain, or hash)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Output format
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;#[arg(short, long, default_value = &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;json&amp;#34;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Verbose output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;#[arg(short, long)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="parallel-api-queries-with-tokio"&gt;Parallel API queries with Tokio&lt;/h2&gt;
&lt;p&gt;The key advantage of Rust here is safe, zero-cost concurrency. All three API calls happen simultaneously:&lt;/p&gt;</description></item><item><title>Writing Effective YARA Rules for Cobalt Strike Beacon Detection</title><link>http://www.lineon.fr/posts/yara-rules-for-cobalt-strike/</link><pubDate>Sat, 28 Mar 2026 00:00:00 +0000</pubDate><guid>http://www.lineon.fr/posts/yara-rules-for-cobalt-strike/</guid><description>&lt;p&gt;Cobalt Strike remains one of the most prevalent post-exploitation frameworks used by both red teams and threat actors. Detecting its beacons through YARA rules is a fundamental skill for any SOC analyst or threat hunter.&lt;/p&gt;
&lt;h2 id="understanding-beacon-artifacts"&gt;Understanding beacon artifacts&lt;/h2&gt;
&lt;p&gt;Cobalt Strike beacons leave identifiable patterns in both their staged and stageless payloads. The key areas to target are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Configuration blocks&lt;/strong&gt; — the beacon stores its config in a predictable structure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sleep mask routines&lt;/strong&gt; — the obfuscation applied during sleep cycles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Named pipe patterns&lt;/strong&gt; — default pipe names are a common indicator&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="a-basic-detection-rule"&gt;A basic detection rule&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rule CobaltStrike_Beacon_Config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; meta:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; description = &amp;#34;Detects Cobalt Strike beacon configuration block&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; author = &amp;#34;SOC Team&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; date = &amp;#34;2026-03&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; severity = &amp;#34;high&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; strings:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $config_header = { 00 01 00 01 00 02 ?? ?? 00 02 00 01 00 02 ?? ?? }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $default_pipe = &amp;#34;\\\\.\\pipe\\msagent_&amp;#34; ascii wide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $watermark = { 00 09 00 02 00 04 }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; condition:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; uint16(0) == 0x5A4D and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; filesize &amp;lt; 1MB and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ($config_header or $default_pipe) and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; $watermark
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="hunting-in-memory"&gt;Hunting in memory&lt;/h2&gt;
&lt;p&gt;For in-memory detection, you&amp;rsquo;ll want rules that match against the decrypted beacon configuration. Use a tool like &lt;code&gt;pe-sieve&lt;/code&gt; or &lt;code&gt;BeaconEye&lt;/code&gt; to dump process memory first, then scan:&lt;/p&gt;</description></item><item><title>Deploying Ollama on a Jetson Nano for Private LLM Inference</title><link>http://www.lineon.fr/posts/deploying-ollama-on-jetson-nano/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>http://www.lineon.fr/posts/deploying-ollama-on-jetson-nano/</guid><description>&lt;p&gt;Running large language models locally is no longer reserved for beefy GPU rigs. With the right setup, a Jetson Nano can serve as a surprisingly capable inference endpoint for smaller models — completely air-gapped from the cloud.&lt;/p&gt;
&lt;h2 id="why-edge-inference-matters"&gt;Why edge inference matters&lt;/h2&gt;
&lt;p&gt;For security professionals, running models locally means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No data exfiltration risk&lt;/strong&gt; — queries never leave your network&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Predictable latency&lt;/strong&gt; — no API rate limits or outages&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full control&lt;/strong&gt; — choose your model, quantization, and context length&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="hardware-requirements"&gt;Hardware requirements&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Component&lt;/th&gt;
 &lt;th&gt;Specification&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Board&lt;/td&gt;
 &lt;td&gt;NVIDIA Jetson Nano (4GB)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Storage&lt;/td&gt;
 &lt;td&gt;64GB+ microSD (A2 rated)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Power&lt;/td&gt;
 &lt;td&gt;5V 4A barrel jack (not USB)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Cooling&lt;/td&gt;
 &lt;td&gt;Active fan recommended&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="installation"&gt;Installation&lt;/h2&gt;
&lt;p&gt;First, flash JetPack 4.6 and update the system:&lt;/p&gt;</description></item><item><title>Building a ZFS-Based NAS with TrueNAS Scale</title><link>http://www.lineon.fr/posts/truenas-zfs-homelab/</link><pubDate>Fri, 20 Feb 2026 00:00:00 +0000</pubDate><guid>http://www.lineon.fr/posts/truenas-zfs-homelab/</guid><description>&lt;p&gt;After years of running a makeshift NAS on an old desktop, I finally built a proper TrueNAS Scale server. Here&amp;rsquo;s what I learned about ZFS pool design, hardware selection, and avoiding common pitfalls.&lt;/p&gt;
&lt;h2 id="hardware-selection"&gt;Hardware selection&lt;/h2&gt;
&lt;p&gt;Budget was a constraint, so I optimized for reliability over raw speed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Motherboard&lt;/strong&gt;: ASRock B550M with ECC support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CPU&lt;/strong&gt;: Ryzen 5 5600G (low TDP, enough for transcoding)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RAM&lt;/strong&gt;: 32GB ECC DDR4 (ZFS loves RAM for ARC cache)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boot&lt;/strong&gt;: 2x 120GB SSD in mirror (TrueNAS boot pool)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data&lt;/strong&gt;: 4x 8TB Seagate Exos in RAIDZ2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="why-raidz2"&gt;Why RAIDZ2&lt;/h2&gt;
&lt;p&gt;With 4 drives, RAIDZ2 gives you two-drive redundancy at the cost of usable space. The math:&lt;/p&gt;</description></item><item><title>Competitive List Building for 10th Edition 40K: A Data-Driven Approach</title><link>http://www.lineon.fr/posts/warhammer-40k-list-building/</link><pubDate>Sat, 10 Jan 2026 00:00:00 +0000</pubDate><guid>http://www.lineon.fr/posts/warhammer-40k-list-building/</guid><description>&lt;p&gt;List building in competitive 40K is part art, part science. While gut feeling and local meta knowledge matter, tournament data gives you a statistical edge most players ignore.&lt;/p&gt;
&lt;h2 id="gathering-the-data"&gt;Gathering the data&lt;/h2&gt;
&lt;p&gt;Sites like Stat Check and 40kstats aggregate tournament results. The key metrics to track:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Win rate by faction&lt;/strong&gt; — overall faction strength in the current meta&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internal win rate by unit&lt;/strong&gt; — which datasheets actually contribute to wins&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Points efficiency&lt;/strong&gt; — damage output or objective scoring per point invested&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="building-for-objectives-not-kills"&gt;Building for objectives, not kills&lt;/h2&gt;
&lt;p&gt;The most common mistake in competitive list building is optimizing for damage output. 10th edition rewards board control and objective scoring heavily. A useful heuristic:&lt;/p&gt;</description></item><item><title>About</title><link>http://www.lineon.fr/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://www.lineon.fr/about/</guid><description>&lt;h2 id="about-this-blog"&gt;About this blog&lt;/h2&gt;
&lt;p&gt;This is a technical blog covering a broad range of IT topics — from cybersecurity and threat hunting to AI/ML experiments, homelab builds, and gaming strategy.&lt;/p&gt;
&lt;h2 id="about-me"&gt;About me&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m a cybersecurity professional based in France, working across SOC operations, threat detection, malware analysis, and infrastructure automation. Outside of work, I enjoy building homelab systems, tinkering with local AI models, learning Rust, and playing Warhammer 40K.&lt;/p&gt;
&lt;h2 id="contact"&gt;Contact&lt;/h2&gt;
&lt;p&gt;Feel free to reach out via email or find me on GitHub.&lt;/p&gt;</description></item></channel></rss>