Close Menu

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    AMD surges 10 percent in desktop PC share, again

    Google now lets you delete your personal info from search results

    Microsoft just forked Windows

    Facebook X (Twitter) Instagram
    • Artificial Intelligence
    • Business Technology
    • Cryptocurrency
    • Gadgets
    • Gaming
    • Health
    • Software and Apps
    • Technology
    Facebook X (Twitter) Instagram Pinterest Vimeo
    Tech AI Verse
    • Home
    • Artificial Intelligence

      Read the extended transcript: President Donald Trump interviewed by ‘NBC Nightly News’ anchor Tom Llamas

      February 6, 2026

      Stocks and bitcoin sink as investors dump software company shares

      February 4, 2026

      AI, crypto and Trump super PACs stash millions to spend on the midterms

      February 2, 2026

      To avoid accusations of AI cheating, college students are turning to AI

      January 29, 2026

      ChatGPT can embrace authoritarian ideas after just one prompt, researchers say

      January 24, 2026
    • Business

      The HDD brand that brought you the 1.8-inch, 2.5-inch, and 3.5-inch hard drives is now back with a $19 pocket-sized personal cloud for your smartphones

      February 12, 2026

      New VoidLink malware framework targets Linux cloud servers

      January 14, 2026

      Nvidia Rubin’s rack-scale encryption signals a turning point for enterprise AI security

      January 13, 2026

      How KPMG is redefining the future of SAP consulting on a global scale

      January 10, 2026

      Top 10 cloud computing stories of 2025

      December 22, 2025
    • Crypto

      Berachain Jumps 150% as Strategic Pivot Lifts BERA

      February 12, 2026

      Tom Lee’s BitMine (BMNR) Stock Faces Cost-Basis Risk — Price Breakdown at 10%?

      February 12, 2026

      Why the US Jobs Data Makes a Worrying Case for Bitcoin

      February 12, 2026

      MYX Falls Below $5 as Short Sellers Take Control — 42% Decline Risk Emerges

      February 12, 2026

      Solana Pins Its $75 Support on Short-Term Buyers — Can Price Survive This Risky Setup?

      February 12, 2026
    • Technology

      AMD surges 10 percent in desktop PC share, again

      February 12, 2026

      Google now lets you delete your personal info from search results

      February 12, 2026

      Microsoft just forked Windows

      February 12, 2026

      This Lenovo USB-C dock with 65 watts of power is just $76

      February 12, 2026

      Anker’s USB-C hub turns 1 laptop port into 8 ports (best ever price)

      February 12, 2026
    • Others
      • Gadgets
      • Gaming
      • Health
      • Software and Apps
    Check BMI
    Tech AI Verse
    You are at:Home»Technology»eBPF Mystery: When is IPv4 not IPv4? When it’s pretending to be IPv6
    Technology

    eBPF Mystery: When is IPv4 not IPv4? When it’s pretending to be IPv6

    TechAiVerseBy TechAiVerseMay 9, 2025No Comments7 Mins Read3 Views
    Facebook Twitter Pinterest Telegram LinkedIn Tumblr Email Reddit
    Share
    Facebook Twitter LinkedIn Pinterest WhatsApp Email

    eBPF Mystery: When is IPv4 not IPv4? When it’s pretending to be IPv6

    This adventures starts with a simple eBPF program to transparently redirect DNS requests on port 53 for a single program (or docker container).

    To do this I used BPF_CGROUP_INET4_CONNECT on a cgroup. That lets me inspect and redirect traffic when syscall.connect occurs from within the cgroup. Here is a simplified version 👇

    int handle_connect_redirect(struct bpf_sock_addr *ctx, __be32 original_ip,
                                bool is_connect4, struct redirect_result *result) {
      __be32 new_ip = original_ip;
      __be16 new_port = ctx->user_port;
    
      if (ctx->user_port == bpf_htons(53)) {
        new_ip = const_mitm_proxy_address; // Our MITM DNS server we're using for intercept
        new_port = bpf_htons(const_dns_proxy_port);
      }
    
      result->is_redirected = did_redirect;
      result->ip = new_ip;
      result->port = new_port;
      return 1;
    }
    
    SEC("cgroup/connect4")
    int connect4(struct bpf_sock_addr *ctx) {
      struct redirect_result r = {
          .ip = ctx->user_ip4,
          .port = ctx->user_port,
          .is_redirected = false,
      };
      handle_connect_redirect(ctx, ctx->user_ip4, true, &r);
      if (r.is_redirected) {
        // If we redirected the request then we need to update the socket
        // destination to the new IP and port
        ctx->user_ip4 = r.ip;
        ctx->user_port = r.port;
      }
      return 1;
    }

    The machines running the program don’t have IPv6 support, so my assumption was that I’d covered the bases.

    I then used an BPF_PROG_TYPE_CGROUP_SKB eBPF program to ensure that the redirect couldn’t be circumvented by making direct IP calls. Roughly this looked like 👇

    SEC("cgroup_skb/egress")
    int cgroup_skb_egress(struct __sk_buff *skb) {
      // Block IPv6 traffic. Currently not supported.
      if (skb->family == AF_INET6) {
        struct event info = {
            ...
            .eventType = PACKET_IPV6_TYPE,
        };
    
        bpf_ringbuf_output(&events, &info, sizeof(info), 0);
    
        return EGRESS_DENY_PACKET;
      }
    
      // .... then we'd check if outbound ip was allowed and deny/allow ...
    

    Note: I’m using bpf_ringbuf_output here to track events from the eBPF program and logging them from userspace. This was invaluable for tracking down this bug, without them, it would be very hard to reason about what was happening inside the eBPF portion of the progam.

    Everything was going very well, until a user tried dotnet CLI.

    When they ran dotnet add package x it would hang indefinitely and produce lots of PACKET_IPV6_TYPE blocked messages via the ringbuf_output.

    Oh dotnet is using IPv6

    The obvious conclusion was the machine was somehow making IPv6 requests, so I did some digging

    • ❓ My connect4 eBPF program was not getting hit, I added similar bpf_ringbuf_output events so I could stream to log in userspace
    • ❌ Hooking up wireshark, I confirmed that dotnet wasn’t making IPv6 calls off the box and the box couldn’t make IPv6 requests to the internet

    Now I’m baffled.

    • Network traffic shows IPv4 calls going out
    • egress eBPF program shows IPv6
    • connect4 eBPF program doesn’t fire suggesting no IPv4 connect call is made

    What! These contradict each other!

    Read more Kernel and dotnet source code

    At this point I knew there must be something I was misunderstanding.

    I spent a bunch of timing digging into the kernel, eBPF and dotnet to see if I could find anything that made the dotnet cli special, as no other tooling seemed to be impacted.

    I started changing the program to get more info, I added a connect6 eBPF program and hook that this would hit for syscall.connect on IPv6. Hopefully it would confirm thas dotnet was infact using IPv6 somehow?!

    SEC("cgroup/connect6")
    int connect6(struct bpf_sock_addr *ctx) {
      struct event info = {
          .eventType = IPV4_VIA_IPV6_REDIRECT_TYPE,
      };
      bpf_ringbuf_output(&events, &info, sizeof(info), 0);
      return 1;
    }

    Running the repro steps dotnet add package x with the above hook, I was immediately greeted by connect6 being hit, even though wireshark showed IPv4 traffic exiting the VM.

    At this point the only conclusion I could think of was that the kernel is seeing IPv6 but the traffic is actually IPv4.

    This triggered a memory about dual stack networking. Digging through dotnet repos I found this:

    Since .NET 5, we are using DualMode sockets in SocketsHttpHandler. This allows us to handle IPv4 traffic from an IPv6 socket, and is considered to be a favorable practice by RFC 1933
    link
    rfc1933

    The feature had a kill switch! I gave it a try, with DualMode sockets disabled everything worked as expected, connect4 got hit and the egress didn’t see the request as being IPv6. 🚀

    How the question was why? What was this feature doing under the covers.

    IPv4-Compatible IPv6 Address or “When IPv4 pretends to be IPv6 for a little bit”

    This 👇 line of the dotnet DualMode socket docs felt like the key 🗝

    This allows us to handle IPv4 traffic from an IPv6 socket

    But how! Digging more into the source and kernel I found:

    • IPv4-mapped IPv6 addresses

    This is a way to encode an IPv4 address inside an IPv6 address.

    When used you get an IPv6 address where the last 32bits are actually a IPv4 address.

    I updated my connect6 eBPF to output the IPv6 address to me bpf_ringbuf_output event, so I could have a look at it.

    Low and behold it was a IPv4 mapped address 🤯🎉

    When using DualMode sockets dotnet requests an IPv6 Socket, even for non-IPv6 requests, and sets the user_ip6 address field to be a IPv4-Mapped address.

    What does a IPv4 mapped address look like?
    These look like ::ffff:1.1.1.1 encoding the IPv4 address at the end of the IPv6 address.

    I thought I must have this wrong, surely you can’t just smash an ipv4 address in ipv6 field and magic happens?! Nope, didn’t have it wrong, that’s what happens. Linux supports this, and will go on to route the request as IPv4.

    My wireshark traces didn’t see the IPv6 traffic, as the kernel is translating it back to IPv4 when making the networking call, so this interim state is only visible to the eBPF programs/kernel.

    Fixing the eBPF to handle IPv4-mapped IPv6 addresses

    To make my original syscall.connect intercept work I have to now hook both IPv4 and IPv6 version of it. For this case I updated the connect6 from earlier to parse out the IPv4 address from the IPv6 address.

    SEC("cgroup/connect6")
    int connect6(struct bpf_sock_addr *ctx) {
      // Check if we have an IPv4-mapped IPv6 address (::ffff:x.x.x.x)
      // The first 10 bytes should be zeros, followed by 2 bytes of 0xffff
      // user_ip6[0] and user_ip6[1] should be 0 (first 64 bits)
      // user_ip6[2] should be 0x0000ffff (next 32 bits with pattern 0000...1111)
      if (ctx->user_ip6[0] != 0 || ctx->user_ip6[1] != 0 ||
          ctx->user_ip6[2] != bpf_htonl(0x0000ffff)) {
        return 1;
      }
    
      // See: https://en.m.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses As
      // bpf_sock_addr stores `user_ip6` as IPv6 is 4x32 bits to get the IPv4
      // address we ignore the first 96 bits and take the last 32 bits which is the
      // __u32 at index 3 of the user_ip6 array
      __be32 ipv4_address = ctx->user_ip6[3];
    
      struct event info = {
          .ip = bpf_ntohl(ipv4_address),
          .eventType = IPV4_VIA_IPV6_REDIRECT_TYPE,
      };
      bpf_ringbuf_output(&events, &info, sizeof(info), 0);
    
      struct redirect_result r = {
          .ip = ipv4_address,
          .port = ctx->user_port,
          .is_redirected = false,
      };
      handle_connect_redirect(ctx, ipv4_address, false, &r);
      if (r.is_redirected) {
        // If we redirected the request then we need to update the socket
        // destination to the new IP and port
        ctx->user_ip6[3] = r.ip;
        ctx->user_port = r.port;
      }
      return 1;
    }

    It pulls the original IPv4 address out and then calls the existing handle_connect_redirect method. Done right? Nope.

    This wasn’t quite enough though as my egress eBPF program would still block these requests as IPv6.

    I tracked this down to this check in the egress program:

    if (skb->family == AF_INET6) {
        // end up here
        return 0
    }

    The mapped IPv4 socket was identifying its family as IPv6, how do I work around this? I want to block IPv6 but not IPv4 mapped via IPv6 sockets 🤔

    After lots of playing I found this approach:

    if (skb->protocol == bpf_htons(ETH_P_IPV6)) {
        // IPv6 hits this but IPv4 Mapped doesn't
        return 0
    }

    By looking at the protocol on skb I was able to distinguish between IPv6 and IPv4 mapped onto IPv6 (TODO: more testing needed on this last bit).

    That’s it

    When is IPv4 not IPv4?

    When it’s using an IPv4-Compatible IPv6 Address to sending IPv4 over an IPv6 socket 🤯

    Share. Facebook Twitter Pinterest LinkedIn Reddit WhatsApp Telegram Email
    Previous ArticleDead Reckoning
    Next Article ChatGPT Deep Research can now connect to GitHub
    TechAiVerse
    • Website

    Jonathan is a tech enthusiast and the mind behind Tech AI Verse. With a passion for artificial intelligence, consumer tech, and emerging innovations, he deliver clear, insightful content to keep readers informed. From cutting-edge gadgets to AI advancements and cryptocurrency trends, Jonathan breaks down complex topics to make technology accessible to all.

    Related Posts

    AMD surges 10 percent in desktop PC share, again

    February 12, 2026

    Google now lets you delete your personal info from search results

    February 12, 2026

    Microsoft just forked Windows

    February 12, 2026
    Leave A Reply Cancel Reply

    Top Posts

    Ping, You’ve Got Whale: AI detection system alerts ships of whales in their path

    April 22, 2025667 Views

    Lumo vs. Duck AI: Which AI is Better for Your Privacy?

    July 31, 2025255 Views

    6.7 Cummins Lifter Failure: What Years Are Affected (And Possible Fixes)

    April 14, 2025152 Views

    6 Best MagSafe Phone Grips (2025), Tested and Reviewed

    April 6, 2025111 Views
    Don't Miss
    Technology February 12, 2026

    AMD surges 10 percent in desktop PC share, again

    AMD surges 10 percent in desktop PC share, again Image: Adam Patrick Murray / Foundry…

    Google now lets you delete your personal info from search results

    Microsoft just forked Windows

    This Lenovo USB-C dock with 65 watts of power is just $76

    Stay In Touch
    • Facebook
    • Twitter
    • Pinterest
    • Instagram
    • YouTube
    • Vimeo

    Subscribe to Updates

    Get the latest creative news from SmartMag about art & design.

    About Us
    About Us

    Welcome to Tech AI Verse, your go-to destination for everything technology! We bring you the latest news, trends, and insights from the ever-evolving world of tech. Our coverage spans across global technology industry updates, artificial intelligence advancements, machine learning ethics, and automation innovations. Stay connected with us as we explore the limitless possibilities of technology!

    Facebook X (Twitter) Pinterest YouTube WhatsApp
    Our Picks

    AMD surges 10 percent in desktop PC share, again

    February 12, 20262 Views

    Google now lets you delete your personal info from search results

    February 12, 20262 Views

    Microsoft just forked Windows

    February 12, 20262 Views
    Most Popular

    7 Best Kids Bikes (2025): Mountain, Balance, Pedal, Coaster

    March 13, 20250 Views

    VTOMAN FlashSpeed 1500: Plenty Of Power For All Your Gear

    March 13, 20250 Views

    This new Roomba finally solves the big problem I have with robot vacuums

    March 13, 20250 Views
    © 2026 TechAiVerse. Designed by Divya Tech.
    • Home
    • About Us
    • Contact Us
    • Privacy Policy
    • Terms & Conditions

    Type above and press Enter to search. Press Esc to cancel.