[Solved] A 2-day adventure in networking, Windows, IPv6 and WSL

My servers all are IPv6-only, or they would be if I didn’t use WSL. I’ve always preferred Windows to virtually anything else, but I like the Linux command line better. (I’m not too fond of PowerShell… and that’s a hill I’m willing to die on.) So, back to the story. I finally got absolutely tired of not having IPv6 in WSL, so I pulled a Rob and did something no one else on the internet has done — again — at least according to Google.

I got IPv6 working in WSL.

Like, for real this time. No VPN, no gimmicks … well, if we don’t count the fact that it literally works via voodoo as a “gimmick.”

No seriously, look!

Er-mer-god, it feels so nice to be in the 21’st century!

If you don’t feel like reading all about this, there’s a repo to check out. I highly recommend giving it a star or two so that maybe just maybe, Microsoft will fix this tiny bug.

The adventure begins

The first thing I did, was finally move over to a bridged network configuration instead of the default NAT’d configuration. There’s an issue for this that I guarantee will cause you to waste half your day reading to try and figure out what to do. This gave my WSL virtual machine a proper IP address on my network (both v4 and v6), but I noticed that v6 was completely borked.

So, I whipped out my handy WireShark and started looking at packets while I pinged an ipv6 address. Sure as water freezes in summer, the packets were making it from the VM to the network, and then back again … but Windows was eating the packets like a Cookie Monster let loose in a bakery. BUT WHY!

After some trial and error, I realized I could just change the IPv6 packet’s destination MAC address to the VM’s MAC address, injecting them into the local network. This caused all hell to break loose due to the fact that I was also forwarding ICMP packets.

In IPv4, ICMP packets are pretty much just used to ping things. They aren’t that important. But in v6, ICMP packets replace DHCP and ARP (via NDP), among other things. Soooo, suddenly my Windows computer and VM were fighting over the exact same IPv6 packets and confused my whole network.

“Nope,” I said to my wife, “I have no idea why Netflix stopped working.”

That was an easy fix.

Once I got that straightened out, I was able to start up firefox in my Linux (😘to the team that made GUI WSL apps to work so flawlessly with Windows btw) and browse the IPv6 internet in all of its glory. Sorta.

First of all, I’m using winpcap to capture packets … and it doesn’t capture all of them. Like 80% of them to be precise. Secondly, after a few minutes, I saw tons of spurious retransmissions in WireShark which pretty much made everything slow to a crawl.

So, I was really confused. And I went to bed.

When I woke up, I started 4 different captures to understand why I was seeing so many retransmissions and out-of-order packets after a while. Also, whoever at Google made ipv6.google.com NOT require SSL, I could hug you.

  1. tcpdump inside WSL
  2. Manually capturing rewritten packets
  3. Wireshark from inside the bridge
  4. Wireshark from outside the bridge

After carefully reviewing the captures, I learned of an epic tale of packets. Needless to say, the epic tale had me weeping in joy, sorrow, and madness … all at once. I don’t even understand how that is possible, but I learned it at that moment. Sadly, I cannot describe this tale, for I do not understand it.

The gist is, after a few minutes of rewriting the packets, the network learned.

Yes, you read that right.

After a few minutes, my rewriting of packets was no longer necessary. In fact, it was harmful! But, if I stopped for even a few minutes, the rewriting was in fact, necessary. It was needed until it was not needed and then it was needed but not.

Perhaps you can try to understand how a story of this confusitisity would confuse you into weeping, at least in madness.

The Climax

I learned that in order to keep perfect IPv6 connectivity, a small amount of voodoo was required:

  1. I must rewrite the packets
  2. I must do IPv6 traffic (like a ping)
  3. Once I see duplicate packets, I must stop rewriting packets
  4. I must never stop IPv6 traffic

And then I adjusted my program to do this. Simple right?

I cried in joy, to see it work…

It was a sigh of relief to see this. This has bothered me since the beginning of times eternal. Since WSL2 was first announced. Since Jesus was born. Since the last dinosaur let out its final breath… it’s been a long time.

I… should probably apply to work at Microsoft. If you’re hiring, look me up.

Now What?

Well, I published the thing on GitHub, maybe someone at Microsoft can use it to figure out wtf is wrong with their bridge. Maybe it only works for me. Maybe, there’s actually a network fairy just flying packets back and forth for me because I have pizza (Dresden Files reference). And maybe, just maybe, it works for everyone.

Anyway, it works for me at least. Hopefully, people will give it a go and find out if it works for them. Seriously, go leave a star on GitHub and tell your friends about this who are stuck using WSL with IPv4. I’m not, and I’m loving it.

Want an inside scoop?

Check out PHP Shenanigans for only €5/mo or €30/yr