<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aomi Qaza</title>
    <description>The latest articles on DEV Community by Aomi Qaza (@aomiqaza).</description>
    <link>https://dev.to/aomiqaza</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3518049%2F86cc2c42-d371-45ba-8ebd-440886cd6173.jpg</url>
      <title>DEV Community: Aomi Qaza</title>
      <link>https://dev.to/aomiqaza</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aomiqaza"/>
    <language>en</language>
    <item>
      <title>Linux Auditd Blueprint: Real-Time Kernel Event Tracking &amp; Security Auditing</title>
      <dc:creator>Aomi Qaza</dc:creator>
      <pubDate>Fri, 14 Aug 2026 13:39:35 +0000</pubDate>
      <link>https://dev.to/aomiqaza/linux-auditd-blueprint-real-time-kernel-event-tracking-security-auditing-2n2p</link>
      <guid>https://dev.to/aomiqaza/linux-auditd-blueprint-real-time-kernel-event-tracking-security-auditing-2n2p</guid>
      <description>&lt;h1&gt;
  
  
  Linux Auditd Blueprint: Real-Time Kernel Event Tracking &amp;amp; Security Auditing
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Security guide for configuring Linux Audit Framework (auditd) to log execve system calls, file integrity changes, and privilege escalation events.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Executive Summary &amp;amp; Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Execve Process Auditing: Track all executed commands across system users.&lt;/li&gt;
&lt;li&gt;File Integrity Monitoring: Monitor write and attribute modifications on /etc/passwd and /etc/sudoers.&lt;/li&gt;
&lt;li&gt;Audit Ruleset Modularization: Structure rules inside /etc/audit/rules.d/.&lt;/li&gt;
&lt;li&gt;Log Analysis via ausearch: Query security event logs efficiently with aureport and ausearch.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Auditd Framework Architecture &amp;amp; Kernel Interception
&lt;/h2&gt;

&lt;p&gt;The Linux Audit Subsystem is embedded directly inside the Linux kernel. It hooks system calls at the kernel boundary, capturing process executions, file access attempts, network socket creations, and user authentication events before processes complete.&lt;/p&gt;

&lt;p&gt;Unlike standard syslog daemons (which depend on applications choosing to log messages), auditd intercepts events unconditionally at the system call level, making it tamper-resistant against user-space log manipulation.&lt;/p&gt;

&lt;p&gt;The user-space auditd daemon collects events from kernel netfilter buffers and writes them to /var/log/audit/audit.log.&lt;/p&gt;

&lt;p&gt;This granular logging capability forms the core foundation of Digital Forensics and Incident Response (DFIR) on Linux servers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install auditd on Debian/Ubuntu&lt;/span&gt;
systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; auditd

&lt;span class="c"&gt;# Verify audit daemon status&lt;/span&gt;
auditctl &lt;span class="nt"&gt;-s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Auditing Process Execution (execve) across All Users
&lt;/h2&gt;

&lt;p&gt;Attackers who gain initial shell access execute reconnaissance commands (such as whoami, id, uname -a, netstat). Standard bash history can be deleted or bypassed by executing binaries directly.&lt;/p&gt;

&lt;p&gt;Adding execve audit rules records every single binary execution across the entire system, capturing exact command-line arguments, working directories, parent PIDs, and effective user IDs (EUID).&lt;/p&gt;

&lt;p&gt;Filter by arch=b64 to capture 64-bit system calls efficiently.&lt;/p&gt;

&lt;p&gt;Capturing full command-line arguments provides immutable forensic evidence during post-compromise investigations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Track 64-bit and 32-bit execve system calls&lt;/span&gt;
&lt;span class="nt"&gt;-a&lt;/span&gt; always,exit &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nb"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;b64 &lt;span class="nt"&gt;-S&lt;/span&gt; execve &lt;span class="nt"&gt;-k&lt;/span&gt; process_exec
&lt;span class="nt"&gt;-a&lt;/span&gt; always,exit &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nb"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;b32 &lt;span class="nt"&gt;-S&lt;/span&gt; execve &lt;span class="nt"&gt;-k&lt;/span&gt; process_exec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. File Integrity Monitoring (FIM) for Critical System Files
&lt;/h2&gt;

&lt;p&gt;File Integrity Monitoring (FIM) rules watch critical system configuration files for write (w), read (r), execute (x), or attribute change (a) operations.&lt;/p&gt;

&lt;p&gt;Configure file watches on /etc/passwd, /etc/shadow, /etc/sudoers, and /etc/pam.d/ to alert DFIR incident responders immediately if account credentials or privilege policies are modified.&lt;/p&gt;

&lt;p&gt;Assign custom key tags (-k ) to audit rules to facilitate rapid filtering in log analysis tools.&lt;/p&gt;

&lt;p&gt;Monitoring permissions changes on SSH configuration files (/etc/ssh/sshd_config) prevents unauthorized backdoor insertion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# File Integrity Watch Rules&lt;/span&gt;
&lt;span class="nt"&gt;-w&lt;/span&gt; /etc/passwd &lt;span class="nt"&gt;-p&lt;/span&gt; wa &lt;span class="nt"&gt;-k&lt;/span&gt; identity_changes
&lt;span class="nt"&gt;-w&lt;/span&gt; /etc/shadow &lt;span class="nt"&gt;-p&lt;/span&gt; wa &lt;span class="nt"&gt;-k&lt;/span&gt; identity_changes
&lt;span class="nt"&gt;-w&lt;/span&gt; /etc/sudoers &lt;span class="nt"&gt;-p&lt;/span&gt; wa &lt;span class="nt"&gt;-k&lt;/span&gt; privilege_changes
&lt;span class="nt"&gt;-w&lt;/span&gt; /etc/sudoers.d/ &lt;span class="nt"&gt;-p&lt;/span&gt; wa &lt;span class="nt"&gt;-k&lt;/span&gt; privilege_changes
&lt;span class="nt"&gt;-w&lt;/span&gt; /var/log/tallylog &lt;span class="nt"&gt;-p&lt;/span&gt; wa &lt;span class="nt"&gt;-k&lt;/span&gt; auth_logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Structuring Modular Audit Rules in /etc/audit/rules.d/
&lt;/h2&gt;

&lt;p&gt;Modern Linux distributions manage audit rules through modular files in /etc/audit/rules.d/*.rules, which augments auditctl when auditd starts.&lt;/p&gt;

&lt;p&gt;Organize rules into numbered files (e.g., 10-base.rules, 30-fim.rules, 90-finalize.rules) to maintain clear rule precedence.&lt;/p&gt;

&lt;p&gt;Enforce rule immutability by appending -e 2 as the final directive, preventing attackers from disabling audit rules without a reboot.&lt;/p&gt;

&lt;p&gt;Immutable rules guarantee log integrity even if an attacker achieves temporary root privileges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# /etc/audit/rules.d/99-finalize.rules&lt;/span&gt;
&lt;span class="c"&gt;# Lock audit rules until next reboot&lt;/span&gt;
&lt;span class="nt"&gt;-e&lt;/span&gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Performance Tuning &amp;amp; Buffer Backlog Management
&lt;/h2&gt;

&lt;p&gt;Under high system load, kernel audit buffers can overflow if the auditd daemon cannot write to disk fast enough, causing kernel event drops.&lt;/p&gt;

&lt;p&gt;Tune kernel backlog buffer limits (-b) and set failure response actions (-f) in /etc/audit/rules.d/10-base.rules to handle burst traffic gracefully.&lt;/p&gt;

&lt;p&gt;Configuring backlog buffers to 8192 prevents event drops during bursty web application workloads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# /etc/audit/rules.d/10-base.rules&lt;/span&gt;
&lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;span class="nt"&gt;-b&lt;/span&gt; 8192
&lt;span class="nt"&gt;-f&lt;/span&gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Incident Response &amp;amp; Log Querying via ausearch &amp;amp; aureport
&lt;/h2&gt;

&lt;p&gt;The audit log file (/var/log/audit/audit.log) contains dense key-value pairs. Use built-in utilities ausearch and aureport for forensic queries.&lt;/p&gt;

&lt;p&gt;Use aureport --summary to generate high-level executive reports on failed authentications, executable events, and file access violations.&lt;/p&gt;

&lt;p&gt;Combine ausearch with jq or SIEM log forwarders (Elastic Filebeat, Vector) to stream structured audit events to central security operating centers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Query process execution events by key tag&lt;/span&gt;
ausearch &lt;span class="nt"&gt;-k&lt;/span&gt; process_exec &lt;span class="nt"&gt;-i&lt;/span&gt;

&lt;span class="c"&gt;# Generate summary report of failed login attempts&lt;/span&gt;
aureport &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;--failed&lt;/span&gt;

&lt;span class="c"&gt;# Query modifications to /etc/sudoers&lt;/span&gt;
ausearch &lt;span class="nt"&gt;-k&lt;/span&gt; privilege_changes &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frequently Asked Questions (FAQ)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Does auditd affect system CPU performance?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With optimized filter rules (-F arch=b64), auditd overhead is less than 1-2% CPU under heavy workloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What does -e 2 mean in audit rules?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;-e 2 locks the audit configuration permanently until system reboot, preventing an attacker who gains root from disabling audit logging.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://zyekh.com/blog/auditd-kernel-event-monitoring-and-dfir-logging.html" rel="noopener noreferrer"&gt;https://zyekh.com/blog/auditd-kernel-event-monitoring-and-dfir-logging.html&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>auditddfir</category>
    </item>
    <item>
      <title>Rust in the Linux Kernel: Securing Core Subsystems &amp; Memory Safety</title>
      <dc:creator>Aomi Qaza</dc:creator>
      <pubDate>Fri, 14 Aug 2026 12:24:26 +0000</pubDate>
      <link>https://dev.to/aomiqaza/rust-in-the-linux-kernel-securing-core-subsystems-memory-safety-4cd4</link>
      <guid>https://dev.to/aomiqaza/rust-in-the-linux-kernel-securing-core-subsystems-memory-safety-4cd4</guid>
      <description>&lt;h1&gt;
  
  
  Rust in the Linux Kernel: Securing Core Subsystems &amp;amp; Memory Safety
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Comprehensive engineering guide on how Rust eliminates spatial and temporal memory vulnerabilities in modern Linux kernel drivers and network modules.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Executive Summary &amp;amp; Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Memory Safety Enforcement: Eliminate use-after-free, double-free, and buffer overflow vulnerabilities at compile time.&lt;/li&gt;
&lt;li&gt;Safe Abstraction Layers: Use C bindings wrapped in safe Rust traits to prevent undefined behavior in kernel modules.&lt;/li&gt;
&lt;li&gt;Strict Concurrency Control: Utilize Rust ownership rules to eliminate data races in multi-threaded kernel worker threads.&lt;/li&gt;
&lt;li&gt;Kernel Driver Modernization: Write Linux network and device drivers using idiomatic safe Rust abstractions.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. The Memory Safety Paradigm in Kernel Development
&lt;/h2&gt;

&lt;p&gt;Historically, over 70% of high-severity vulnerabilities in the Linux kernel stem from C memory safety flaws, including spatial out-of-bounds access, temporal use-after-free conditions, uninitialized memory reads, and race conditions in interrupt handlers. As kernel complexity expands to support high-throughput cloud infrastructure and heterogenous multi-core hardware, manual memory management in C becomes increasingly unsustainable for security engineering teams.&lt;/p&gt;

&lt;p&gt;Rust introduces compile-time memory safety guarantees without relying on garbage collection algorithms or runtime execution overhead. By enforcing strict ownership rules, borrow checking, and explicit variable lifetimes, the Rust compiler proves the absolute absence of memory safety bugs before kernel code is ever assembled into binary ELF object files.&lt;/p&gt;

&lt;p&gt;In the Linux kernel tree, Rust infrastructure complements existing C subsystems by allowing new device drivers, network protocol stacks, and virtual file system abstractions to be authored in safe Rust code, isolating raw pointer dereferences to audited, explicitly documented unsafe code blocks.&lt;/p&gt;

&lt;p&gt;By mandating that all memory allocations and pointer operations pass strict static analysis, Rust eliminates entire classes of Common Vulnerabilities and Exposures (CVEs) that have historically plagued Linux kernel deployments across enterprise data centers.&lt;/p&gt;

&lt;p&gt;Implementing automated continuous monitoring across production nodes ensures that compliance policies remain enforced during infrastructure updates.&lt;/p&gt;

&lt;p&gt;Regular security audits should be integrated into DevOps CI/CD pipelines to verify that system configurations conform to zero-trust architecture standards.&lt;/p&gt;

&lt;p&gt;Documenting system architecture and access control rules facilitates compliance verification during independent third-party security audits.&lt;/p&gt;

&lt;p&gt;Enforcing strict runtime isolation boundaries prevents privilege escalation vectors across multi-tenant cloud environments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example: Safe Linux Kernel Module in Rust&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;module!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RustKernelDemo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"rust_kernel_security"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Zyekh Abdul Qadir Jailani"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Rust Memory Safety Kernel Subsystem&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;,"&lt;/span&gt;
    &lt;span class="n"&gt;license&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"GPL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;RustKernelDemo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;RustKernelDemo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="n"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="n"&gt;ThisModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;pr_info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Rust kernel module initialized with strict memory safety&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RustKernelDemo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Data Race Elimination &amp;amp; Concurrency Safety
&lt;/h2&gt;

&lt;p&gt;Data races in kernel space occur when two execution contexts (such as hardware interrupt service routines or concurrent SMP worker threads) access the exact same memory location simultaneously without synchronization, where at least one thread executes a write operation. Data races cause subtle kernel memory corruption and non-deterministic panics that are notoriously difficult to capture in production.&lt;/p&gt;

&lt;p&gt;Rust guarantees data race freedom at compile time through the type system using the Send and Sync auto traits. A type is automatically marked as Send if ownership of its underlying data can be safely transferred across execution thread boundaries, while a type is Sync if references to it can be shared concurrently across multiple processing cores.&lt;/p&gt;

&lt;p&gt;When developing Linux kernel device drivers in Rust, synchronization primitives such as Mutex and SpinLock wrap data types directly (e.g., Mutex). This structural encapsulation ensures that accessing inner state is physically impossible without acquiring the lock guard, which automatically releases the lock when going out of scope.&lt;/p&gt;

&lt;p&gt;Furthermore, Rust's borrow checker enforces the aliasing XOR mutability rule: data may have either multiple immutable references (&amp;amp;T) or exactly one mutable reference (&amp;amp;mut T) at any given moment, permanently preventing race conditions during concurrent state updates.&lt;/p&gt;

&lt;p&gt;Implementing automated continuous monitoring across production nodes ensures that compliance policies remain enforced during infrastructure updates.&lt;/p&gt;

&lt;p&gt;Regular security audits should be integrated into DevOps CI/CD pipelines to verify that system configurations conform to zero-trust architecture standards.&lt;/p&gt;

&lt;p&gt;Documenting system architecture and access control rules facilitates compliance verification during independent third-party security audits.&lt;/p&gt;

&lt;p&gt;Enforcing strict runtime isolation boundaries prevents privilege escalation vectors across multi-tenant cloud environments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Safe Concurrency Control in Kernel Driver State&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;DriverState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;packets_processed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;SafeDevice&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;SafeDevice&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;update_stats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;guard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.state&lt;/span&gt;&lt;span class="nf"&gt;.lock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;guard&lt;/span&gt;&lt;span class="py"&gt;.packets_processed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Mutex guard drops automatically, releasing lock&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. C Interoperability &amp;amp; Safe Wrapper Design
&lt;/h2&gt;

&lt;p&gt;Integrating Rust into a multi-million-line C kernel codebase requires robust Foreign Function Interface (FFI) interoperability infrastructure. The kernel build system utilizes bindgen to generate raw Rust bindings directly from C header files, while safe Rust abstractions encapsulate raw C pointers inside safe types.&lt;/p&gt;

&lt;p&gt;Designing safe kernel wrappers involves isolating raw pointer dereferences to audited, minimalist unsafe blocks. Once the public Rust wrapper API is proven mathematically sound, external callers can consume kernel functions without any risk of triggering undefined behavior or memory corruption.&lt;/p&gt;

&lt;p&gt;This modular architecture enables an incremental modernization strategy: legacy C subsystems remain intact while newly developed hardware drivers, eBPF helper extensions, and security-critical modules are authored exclusively in safe Rust.&lt;/p&gt;

&lt;p&gt;Modern Linux distributions are increasingly adopting LLVM toolchain builds, enabling Link-Time Optimization (LTO) between C and Rust compilation units to eliminate cross-language function call overhead entirely.&lt;/p&gt;

&lt;p&gt;Implementing automated continuous monitoring across production nodes ensures that compliance policies remain enforced during infrastructure updates.&lt;/p&gt;

&lt;p&gt;Regular security audits should be integrated into DevOps CI/CD pipelines to verify that system configurations conform to zero-trust architecture standards.&lt;/p&gt;

&lt;p&gt;Documenting system architecture and access control rules facilitates compliance verification during independent third-party security audits.&lt;/p&gt;

&lt;p&gt;Enforcing strict runtime isolation boundaries prevents privilege escalation vectors across multi-tenant cloud environments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build kernel with Rust support enabled&lt;/span&gt;
make &lt;span class="nv"&gt;LLVM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 rustavailable
make &lt;span class="nv"&gt;LLVM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 menuconfig
&lt;span class="c"&gt;# Enable CONFIG_RUST=y in Kernel Hacking -&amp;gt; Rust support&lt;/span&gt;
make &lt;span class="nv"&gt;LLVM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Verification &amp;amp; Kernel Security Audit Checklist
&lt;/h2&gt;

&lt;p&gt;Auditing Rust kernel modules requires verifying that every unsafe block contains an explicit // SAFETY: rationale comment explaining why the invariants cannot be violated by callers. Static analysis tools like Clippy and KASAN (Kernel Address Sanitizer) enforce strict coding standards.&lt;/p&gt;

&lt;p&gt;Ensure that error handling in Rust kernel modules relies strictly on the kernel Result type instead of unwinding panics. Unwinding across FFI boundaries is undefined behavior in C, so Rust kernel code must use panic=abort configuration.&lt;/p&gt;

&lt;p&gt;Automated CI/CD security pipelines should execute Clippy lints with warning-as-error flags enabled, verifying that no unapproved unsafe blocks are introduced into upstream kernel pull requests.&lt;/p&gt;

&lt;p&gt;Regular security audits must review macro expansions and generated FFI bindings to ensure kernel memory layouts remain binary-compatible across architecture targets.&lt;/p&gt;

&lt;p&gt;Implementing automated continuous monitoring across production nodes ensures that compliance policies remain enforced during infrastructure updates.&lt;/p&gt;

&lt;p&gt;Regular security audits should be integrated into DevOps CI/CD pipelines to verify that system configurations conform to zero-trust architecture standards.&lt;/p&gt;

&lt;p&gt;Documenting system architecture and access control rules facilitates compliance verification during independent third-party security audits.&lt;/p&gt;

&lt;p&gt;Enforcing strict runtime isolation boundaries prevents privilege escalation vectors across multi-tenant cloud environments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify Rust kernel code with Clippy and KASAN&lt;/span&gt;
make &lt;span class="nv"&gt;LLVM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;CLIPPY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 path/to/module.o

&lt;span class="c"&gt;# Audit kernel logs for Rust initialization&lt;/span&gt;
dmesg | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"Rust"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frequently Asked Questions (FAQ)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Does Rust add runtime overhead to the Linux kernel?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Rust compiles directly to native machine code via LLVM without garbage collection or runtime overhead, yielding performance identical to C.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can Rust completely replace C in the Linux kernel?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Rust is designed to coexist alongside C. Core kernel architecture remains in C while drivers, filesystems, and security modules leverage Rust.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://zyekh.com/blog/rust-in-linux-kernel-security-and-memory-safety-blueprint-2026.html" rel="noopener noreferrer"&gt;https://zyekh.com/blog/rust-in-linux-kernel-security-and-memory-safety-blueprint-2026.html&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linuxsecurity</category>
      <category>kernelarchitecture</category>
    </item>
    <item>
      <title>vLLM PagedAttention: Memory Optimization &amp; High-Throughput LLM Inference Tuning</title>
      <dc:creator>Aomi Qaza</dc:creator>
      <pubDate>Fri, 14 Aug 2026 12:18:41 +0000</pubDate>
      <link>https://dev.to/aomiqaza/vllm-pagedattention-memory-optimization-high-throughput-llm-inference-tuning-3mk9</link>
      <guid>https://dev.to/aomiqaza/vllm-pagedattention-memory-optimization-high-throughput-llm-inference-tuning-3mk9</guid>
      <description>&lt;h1&gt;
  
  
  vLLM PagedAttention: Memory Optimization &amp;amp; High-Throughput LLM Inference Tuning
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Deep dive into OS-inspired virtual memory management for LLM KV caches, maximizing GPU utilization, and achieving 20x throughput scaling for production inference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Executive Summary &amp;amp; Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;KV Cache Bottleneck: Understand why traditional LLM inference wastes up to 80% of GPU memory due to fragmentation.&lt;/li&gt;
&lt;li&gt;PagedAttention Mechanism: Inspired by OS virtual memory, allocate KV cache non-contiguously to eliminate memory waste.&lt;/li&gt;
&lt;li&gt;High-Throughput Tuning: Optimize vLLM batch sizes, tensor parallelism, and quantization for massive concurrent requests.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. The Anatomy of the KV Cache Bottleneck
&lt;/h2&gt;

&lt;p&gt;In auto-regressive Transformer models, generating the next token requires attending to all previously generated tokens. Recomputing these attention scores for every new token is computationally prohibitive. Therefore, inference engines cache the Key (K) and Value (V) tensors for past tokens. This is known as the KV cache.&lt;/p&gt;

&lt;p&gt;As sequence lengths grow, the KV cache expands linearly, consuming massive amounts of high-bandwidth memory (HBM) on the GPU. In traditional inference frameworks, memory for the KV cache is allocated statically and contiguously based on the maximum possible sequence length of the request.&lt;/p&gt;

&lt;p&gt;Because the actual generation length is unpredictable, this static allocation leads to severe internal fragmentation. A request might reserve memory for 2048 tokens but only generate 20 tokens. Additionally, external fragmentation occurs as requests of varying lengths interleave, creating unusable gaps in memory.&lt;/p&gt;

&lt;p&gt;Profiling reveals that in naive deployments, up to 80% of GPU memory dedicated to the KV cache is wasted. This memory starvation prevents the engine from batching more concurrent requests, severely limiting the overall throughput of the inference server, regardless of how much raw compute power the GPU possesses.&lt;/p&gt;

&lt;p&gt;Addressing this bottleneck requires a fundamental shift in how GPU memory is managed during the decoding phase of LLM inference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Traditional static allocation (Pseudocode)
&lt;/span&gt;&lt;span class="n"&gt;kv_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;allocate_gpu_memory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Wastes memory if actual_seq_len &amp;lt;&amp;lt; max_seq_len
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. PagedAttention: OS Virtual Memory for LLMs
&lt;/h2&gt;

&lt;p&gt;vLLM introduces PagedAttention, an algorithm that elegantly solves the KV cache fragmentation problem by borrowing concepts from operating system virtual memory management. Instead of allocating memory contiguously, PagedAttention divides the KV cache into fixed-size blocks (pages).&lt;/p&gt;

&lt;p&gt;Each block contains the KV vectors for a fixed number of tokens. When a request is processed, the engine dynamically allocates these blocks on demand. The logical blocks associated with a specific request are mapped to non-contiguous physical blocks in GPU memory via a block table, mirroring how an OS maps virtual pages to physical frames.&lt;/p&gt;

&lt;p&gt;During the attention computation, the PagedAttention kernel fetches the KV vectors by traversing the block table. Because the blocks do not need to be contiguous, external fragmentation is entirely eliminated. Internal fragmentation is restricted only to the final, partially filled block of a request.&lt;/p&gt;

&lt;p&gt;This dynamic allocation allows the inference engine to pack significantly more concurrent requests into the same GPU memory footprint. Furthermore, it enables memory sharing across different requests. For example, if multiple requests share the same system prompt, the blocks containing the prompt's KV cache can be shared, drastically reducing memory consumption.&lt;/p&gt;

&lt;p&gt;By near-optimally utilizing GPU memory, PagedAttention allows vLLM to achieve state-of-the-art throughput, outperforming traditional engines like Hugging Face Transformers by up to 24x in high-concurrency scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. vLLM Deployment &amp;amp; Throughput Tuning
&lt;/h2&gt;

&lt;p&gt;Deploying vLLM in a production environment requires careful tuning of its core parameters to maximize hardware utilization. The most critical configuration is the &lt;code&gt;--gpu-memory-utilization&lt;/code&gt; flag. This dictates what percentage of the GPU's HBM is reserved for the KV cache pool versus the model weights.&lt;/p&gt;

&lt;p&gt;For large models (e.g., Llama-3 70B) spanning multiple GPUs, Tensor Parallelism (TP) is essential. vLLM utilizes Megatron-LM's tensor parallel algorithms to shard the model's weight matrices across multiple devices. Configuring &lt;code&gt;--tensor-parallel-size&lt;/code&gt; correctly ensures that the compute load is balanced and the inter-GPU communication overhead is minimized.&lt;/p&gt;

&lt;p&gt;To further increase throughput, operators must tune the &lt;code&gt;--max-num-batched-tokens&lt;/code&gt; and &lt;code&gt;--max-num-seqs&lt;/code&gt; parameters. These dictate the aggressiveness of the continuous batching scheduler. Pushing these values too high can lead to GPU Out-Of-Memory (OOM) errors during the prefill phase, while setting them too low leaves compute resources idle.&lt;/p&gt;

&lt;p&gt;Quantization is another powerful lever. vLLM supports AWQ (Activation-aware Weight Quantization) and GPTQ, allowing 16-bit models to be compressed into 4-bit representations. This drastically reduces the memory footprint of the model weights, freeing up more HBM for the PagedAttention KV cache pool, which directly translates to higher concurrency.&lt;/p&gt;

&lt;p&gt;Finally, enabling CUDA Graph capture for the decoding phase eliminates CPU dispatch overhead, significantly reducing latency for small batch sizes. Tuning these parameters in tandem transforms a standard GPU node into a high-octane inference engine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Starting vLLM server with optimized parameters for production&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; vllm.entrypoints.openai.api_server &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--model&lt;/span&gt; meta-llama/Meta-Llama-3-8B-Instruct &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tensor-parallel-size&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--gpu-memory-utilization&lt;/span&gt; 0.90 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--max-num-batched-tokens&lt;/span&gt; 8192 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--quantization&lt;/span&gt; awq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Continuous Batching and Iteration-Level Scheduling
&lt;/h2&gt;

&lt;p&gt;Traditional inference engines use static batching, where a batch of requests is processed together, and the engine must wait for the longest request in the batch to complete before accepting new requests. This leads to massive idle times for early-finishing requests.&lt;/p&gt;

&lt;p&gt;vLLM employs continuous batching (or iteration-level scheduling). The scheduler evaluates the state of all requests at every single token generation step. As soon as a request completes, its KV cache blocks are instantly freed, and a new request is immediately injected into the active batch.&lt;/p&gt;

&lt;p&gt;This fine-grained scheduling, coupled with PagedAttention's dynamic memory management, ensures that the GPU remains fully saturated at all times. The continuous influx and eviction of requests create a steady-state pipeline that maximizes overall system throughput.&lt;/p&gt;

&lt;p&gt;When deployed behind an OmniRouter gateway, vLLM nodes provide a highly predictable, high-throughput backend capable of absorbing massive traffic spikes without catastrophic latency degradation.&lt;/p&gt;

&lt;p&gt;The combination of OmniRouter's intelligent traffic shaping and vLLM's ruthless hardware optimization represents the pinnacle of modern AI engineering.&lt;/p&gt;

&lt;p&gt;Frequently Asked Questions (FAQ)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can vLLM run on consumer-grade GPUs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, vLLM supports consumer GPUs (e.g., RTX 3090/4090) provided the model weights and the configured KV cache pool fit within the available VRAM (e.g., 24GB). Quantization is highly recommended for consumer hardware.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://zyekh.com/blog/vllm-pagedattention-high-throughput-inference-tuning.html" rel="noopener noreferrer"&gt;https://zyekh.com/blog/vllm-pagedattention-high-throughput-inference-tuning.html&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aiengineering</category>
      <category>performance</category>
    </item>
    <item>
      <title>High-Speed eBPF/XDP Packet Filtering for Linux Server DDoS Mitigation</title>
      <dc:creator>Aomi Qaza</dc:creator>
      <pubDate>Fri, 14 Aug 2026 12:18:11 +0000</pubDate>
      <link>https://dev.to/aomiqaza/high-speed-ebpfxdp-packet-filtering-for-linux-server-ddos-mitigation-1hcp</link>
      <guid>https://dev.to/aomiqaza/high-speed-ebpfxdp-packet-filtering-for-linux-server-ddos-mitigation-1hcp</guid>
      <description>&lt;h1&gt;
  
  
  High-Speed eBPF/XDP Packet Filtering for Linux Server DDoS Mitigation
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Technical guide for writing eBPF eXpress Data Path (XDP) kernel programs to drop malicious DDoS traffic at the network driver level.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Executive Summary &amp;amp; Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;XDP_DROP Early Decision: Drop malicious UDP/SYN floods before allocating sk_buff memory.&lt;/li&gt;
&lt;li&gt;Kernel Map Invalidation: Dynamic IP blocklists via eBPF BPF_MAP_TYPE_HASH maps.&lt;/li&gt;
&lt;li&gt;Zero-Copy Performance: Process 10M+ packets per second on commodity server hardware.&lt;/li&gt;
&lt;li&gt;Clang/LLVM BPF Compilation: Build C programs directly into BPF bytecode targets.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Understanding XDP Architecture vs Traditional Linux SKB Allocation
&lt;/h2&gt;

&lt;p&gt;Standard Linux network processing allocates a complex kernel socket buffer data structure (sk_buff) for every incoming packet before firewall rules (iptables/nftables) can evaluate the packet.&lt;/p&gt;

&lt;p&gt;Under volumetric DDoS attacks (such as 10 Million Packets Per Second UDP floods), the CPU time spent allocating and freeing sk_buff structures exhausts kernel memory and CPU cache lines, causing severe packet drops and server unresponsiveness.&lt;/p&gt;

&lt;p&gt;eXpress Data Path (XDP) provides a high-performance bare-metal packet processing framework. XDP programs execute eBPF bytecode directly inside the network driver's RX ring buffer before sk_buff memory allocation occurs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Inspect network interface driver XDP support&lt;/span&gt;
ip &lt;span class="nb"&gt;link &lt;/span&gt;show eth0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. XDP Packet Processing Actions (XDP_DROP vs XDP_PASS)
&lt;/h2&gt;

&lt;p&gt;An XDP program evaluates raw packet data directly from driver memory and returns one of five verdict codes to the network card driver:&lt;/p&gt;

&lt;p&gt;XDP_DROP: Immediately recycles the packet buffer in the driver RX ring without allocating memory or notifying the CPU TCP/IP stack.&lt;/p&gt;

&lt;p&gt;XDP_PASS: Passes the packet up to the normal Linux TCP/IP network stack for standard processing.&lt;/p&gt;

&lt;p&gt;XDP_TX: Bounces the packet back out the same network interface it arrived on (useful for high-speed load balancers).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// XDP Action Constants&lt;/span&gt;
&lt;span class="c1"&gt;// XDP_DROP = 1&lt;/span&gt;
&lt;span class="c1"&gt;// XDP_PASS = 2&lt;/span&gt;
&lt;span class="c1"&gt;// XDP_TX   = 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Writing a Production XDP Packet Filter in C
&lt;/h2&gt;

&lt;p&gt;XDP C code uses eBPF helpers and header pointers to parse Ethernet, IPv4, and UDP/TCP protocol headers safely.&lt;/p&gt;

&lt;p&gt;The eBPF verifier verifies memory bounds checking before loading bytecode into the kernel, ensuring the XDP program can never crash the Linux kernel.&lt;/p&gt;

&lt;p&gt;The following C program parses incoming IPv4 headers and drops packets matching blacklisted source IP addresses stored in an eBPF hash map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include 
#include 
#include 
#include 
&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;__uint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BPF_MAP_TYPE_HASH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;__uint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;__type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__be32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;__type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__u64&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;blacklist&lt;/span&gt; &lt;span class="nf"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"maps"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"xdp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;xdp_firewall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;xdp_md&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;ethhdr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;h_proto&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;__constant_htons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ETH_P_IP&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;iphdr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;iph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;iph&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;__be32&lt;/span&gt; &lt;span class="n"&gt;src_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;iph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;saddr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;__u64&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bpf_map_lookup_elem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;blacklist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;src_ip&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;XDP_DROP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;_license&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;SEC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"GPL"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Compiling &amp;amp; Loading Bytecode Targets via Clang/LLVM
&lt;/h2&gt;

&lt;p&gt;Compile XDP C code into BPF Executable and Linkable Format (ELF) targets using Clang and LLVM compiler toolchains.&lt;/p&gt;

&lt;p&gt;Attach the compiled BPF bytecode to a network interface using standard iproute2 ip link commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Compile C code to BPF bytecode&lt;/span&gt;
clang &lt;span class="nt"&gt;-O2&lt;/span&gt; &lt;span class="nt"&gt;-target&lt;/span&gt; bpf &lt;span class="nt"&gt;-c&lt;/span&gt; xdp_firewall.c &lt;span class="nt"&gt;-o&lt;/span&gt; xdp_firewall.o

&lt;span class="c"&gt;# Attach XDP program to eth0 network interface&lt;/span&gt;
ip &lt;span class="nb"&gt;link set &lt;/span&gt;dev eth0 xdp obj xdp_firewall.o sec xdp

&lt;span class="c"&gt;# Detach XDP program from eth0&lt;/span&gt;
ip &lt;span class="nb"&gt;link set &lt;/span&gt;dev eth0 xdp off
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Dynamic Blocklist Management via BPF Maps
&lt;/h2&gt;

&lt;p&gt;BPF Maps are high-speed shared memory structures bridging kernel space and user-space daemons.&lt;/p&gt;

&lt;p&gt;User-space monitoring daemons (such as Fail2ban or custom Go/Python agents) populate blocked IP addresses into the BPF map dynamically without reloading the XDP program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add blocked IP (e.g. 198.51.100.45) to BPF map via bpftool&lt;/span&gt;
bpftool map update &lt;span class="nb"&gt;id &lt;/span&gt;4 key 198 51 100 45 value 1 0 0 0 0 0 0 0

&lt;span class="c"&gt;# Dump current BPF map contents&lt;/span&gt;
bpftool map dump &lt;span class="nb"&gt;id &lt;/span&gt;4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. High-Throughput Packet Benchmark Verification
&lt;/h2&gt;

&lt;p&gt;Verify XDP packet drop counters using ethtool or bpftool stats.&lt;/p&gt;

&lt;p&gt;Benchmark packet processing throughput under simulated UDP floods using pktgen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Inspect XDP active interface stats&lt;/span&gt;
ip &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nb"&gt;link &lt;/span&gt;show dev eth0

&lt;span class="c"&gt;# View eBPF program list&lt;/span&gt;
bpftool prog show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frequently Asked Questions (FAQ)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the difference between XDP_DROP and iptables DROP?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;XDP_DROP drops packets in driver memory before Linux creates socket buffers, yielding 10x higher throughput.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Does XDP require special network card hardware?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. XDP supports native mode (driver level), offloaded mode (SmartNIC hardware), and generic mode (fallback for any network driver).&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://zyekh.com/blog/ebpf-xdp-packet-filtering-and-ddos-mitigation.html" rel="noopener noreferrer"&gt;https://zyekh.com/blog/ebpf-xdp-packet-filtering-and-ddos-mitigation.html&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linuxkernel</category>
      <category>xdpddosdefense</category>
    </item>
    <item>
      <title>Zero-Trust SSH Access Blueprint: FIDO2 Hardware Keys &amp; SSH Certificate Authority</title>
      <dc:creator>Aomi Qaza</dc:creator>
      <pubDate>Fri, 14 Aug 2026 03:21:24 +0000</pubDate>
      <link>https://dev.to/aomiqaza/zero-trust-ssh-access-blueprint-fido2-hardware-keys-ssh-certificate-authority-55gj</link>
      <guid>https://dev.to/aomiqaza/zero-trust-ssh-access-blueprint-fido2-hardware-keys-ssh-certificate-authority-55gj</guid>
      <description>&lt;h1&gt;
  
  
  Zero-Trust SSH Access Blueprint: FIDO2 Hardware Keys &amp;amp; SSH Certificate Authority
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Comprehensive technical blueprint for securing Linux SSH infrastructure using FIDO2/YubiKey hardware tokens, SSH Certificate Authority (SSH CA), and short-lived certificates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Executive Summary &amp;amp; Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Eliminate Static Keys: Migrate from static authorized_keys deployment to short-lived SSH Certificates.&lt;/li&gt;
&lt;li&gt;FIDO2 Hardware Bound: Enforce ed25519-sk key pairs tied to physical security tokens (YubiKey/FIDO2).&lt;/li&gt;
&lt;li&gt;Centralized Authority: Use an offline SSH Certificate Authority (CA) to sign user access requests with automatic 8-hour expiration.&lt;/li&gt;
&lt;li&gt;Zero Administrative Sprawl: Adding or revoking user permissions requires zero modifications on target servers.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Traditional SSH key management across growing server fleets suffers from a critical flaw: static public key sprawl. Managing thousands of ~/.ssh/authorized_keys files across production instances creates massive administrative overhead, increases the blast radius of compromised developer workstations, and makes offboarding security audits nearly impossible.&lt;/p&gt;

&lt;p&gt;A true Zero-Trust SSH Access Model replaces static SSH keys with two cryptographic pillars:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FIDO2 / Security Key Hardware Tokens (ed25519-sk): Private key material never leaves the physical YubiKey token and requires physical touch plus user PIN.&lt;/li&gt;
&lt;li&gt;SSH Certificate Authority (SSH CA): Short-lived SSH certificates (e.g., valid for 8 hours) signed by a centralized CA key, eliminating manual authorized_keys deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. The Problem with Static SSH Public Keys
&lt;/h2&gt;

&lt;p&gt;In standard SSH deployments, when an engineer needs access to a production server, their public key is appended to the server's authorized_keys file. Over time, this leads to significant vulnerabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No Expiration: Public keys remain valid indefinitely until manually purged.&lt;/li&gt;
&lt;li&gt;Workstation Compromise: Unprotected SSH private keys stored on developer disk drives can be exfiltrated by malware.&lt;/li&gt;
&lt;li&gt;Lack of Centralized Revocation: Revoking access requires executing cleanup scripts across every instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Hardware Security Keys: OpenSSH FIDO2 / U2F
&lt;/h2&gt;

&lt;p&gt;Since OpenSSH 8.2, native support for security keys (FIDO2 / U2F) is supported via the ed25519-sk and ecdsa-sk key types. Key generation requires the physical hardware token connected to the machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate an SSH key backed by a hardware token with user-presence verification&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519-sk &lt;span class="nt"&gt;-O&lt;/span&gt; touch-required &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"engineer@company.com (YubiKey)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[ NOTE ] For enhanced security, generate resident keys (discoverable credentials) with PIN protection so the key stub can be retrieved directly from the token on new devices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate a resident key with mandatory PIN and touch requirement&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519-sk &lt;span class="nt"&gt;-O&lt;/span&gt; resident &lt;span class="nt"&gt;-O&lt;/span&gt; verify-required &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"engineer@company.com (Resident)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Setting Up a Centralized SSH Certificate Authority
&lt;/h2&gt;

&lt;p&gt;Instead of copying individual public keys to every target machine, servers are configured to trust a single CA Public Key. The CA signs engineer public keys with short expiration times and restricted permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step A: Generate the CA Key Pair
&lt;/h3&gt;

&lt;p&gt;Generate a secure host CA key on an isolated offline machine or Hardware Security Module (HSM):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate the SSH Certificate Authority key pair&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-f&lt;/span&gt; /etc/ssh/ca/ssh_user_ca &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"Production SSH User CA 2026"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step B: Configure Target Linux Servers to Trust the CA
&lt;/h3&gt;

&lt;p&gt;On all Linux production servers, place the CA public key in /etc/ssh/ssh_user_ca.pub and update /etc/ssh/sshd_config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# Append to /etc/ssh/sshd_config
&lt;/span&gt;&lt;span class="n"&gt;TrustedUserCAKeys&lt;/span&gt; /&lt;span class="n"&gt;etc&lt;/span&gt;/&lt;span class="n"&gt;ssh&lt;/span&gt;/&lt;span class="n"&gt;ssh_user_ca&lt;/span&gt;.&lt;span class="n"&gt;pub&lt;/span&gt;
&lt;span class="n"&gt;AuthorizedPrincipalsFile&lt;/span&gt; /&lt;span class="n"&gt;etc&lt;/span&gt;/&lt;span class="n"&gt;ssh&lt;/span&gt;/&lt;span class="n"&gt;authorized_principals&lt;/span&gt;/%&lt;span class="n"&gt;u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create principal definitions for target system accounts (e.g., /etc/ssh/authorized_principals/ubuntu containing the line admin-role).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step C: Signing User Keys with Expiration &amp;amp; Principals
&lt;/h3&gt;

&lt;p&gt;When an engineer requests access, the CA signs their public key to produce a certificate (id_ed25519_sk-cert.pub):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Sign engineer's public key valid for 8 hours for principal 'admin-role'&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/ssh/ca/ssh_user_ca &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="s2"&gt;"engineer@company.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"admin-role"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-V&lt;/span&gt; +8h &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-z&lt;/span&gt; 20260803001 &lt;span class="se"&gt;\&lt;/span&gt;
  id_ed25519_sk.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Related Privacy &amp;amp; Security Tools
&lt;/h2&gt;

&lt;p&gt;To assist with infrastructure configuration, security audits, and key validation, use these privacy-first client-side web tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secure Password &amp;amp; Passphrase Generator -&amp;gt; Generate high-entropy PINs for hardware tokens.&lt;/li&gt;
&lt;li&gt;Cryptographic Hash Generator -&amp;gt; Verify SHA-256 fingerprints of SSH public keys and certificates.&lt;/li&gt;
&lt;li&gt;Side-by-Side Diff Checker -&amp;gt; Audit differences between server sshd_config templates.&lt;/li&gt;
&lt;li&gt;Environment Variables &amp;amp; Secrets Formatter -&amp;gt; Format SSH environment variables safely in-browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Verification &amp;amp; Security Audit Checklist
&lt;/h2&gt;

&lt;p&gt;Verify that your setup enforces Zero-Trust principles using the following checklist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Inspect certificate properties and expiration details&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; id_ed25519_sk-cert.pub

&lt;span class="c"&gt;# Test SSH login using explicit certificate credential&lt;/span&gt;
ssh &lt;span class="nt"&gt;-i&lt;/span&gt; id_ed25519_sk &lt;span class="nt"&gt;-i&lt;/span&gt; id_ed25519_sk-cert.pub engineer@server.company.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Frequently Asked Questions (FAQ)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Q: What happens when an SSH certificate expires?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the certificate validity period expires (e.g., +8h), OpenSSH automatically rejects all authentication attempts using that certificate. No server-side cleanup or manual key removal is required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can FIDO2 SSH keys be used without internet connectivity?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. OpenSSH communicates directly with the FIDO2 hardware token over USB/NFC via standard libfido2 drivers, requiring zero external internet connection.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://zyekh.com/blog/zero-trust-ssh-access-with-fido2-and-ssh-ca.html" rel="noopener noreferrer"&gt;https://zyekh.com/blog/zero-trust-ssh-access-with-fido2-and-ssh-ca.html&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>zerotrustssh</category>
    </item>
  </channel>
</rss>
