WSL 2, the next generation of Windows Subsystem for Linux has a dirty little secret.
This falls down to the classic: 99% of users will never encounter this Networking situation, but 1000s of individuals will.
What's worse is that it worked perfectly in WSL 1
What am I talking about?
Networking. Specifically the way WSL is allocated virtual networking interfaces.
In WSL 1, the network interface was
Bridged, meaning that the any traffic to and from both the host machine and the WSL instance would be seen as the same place. They shared the same IP address.
In turn, this meant I could spin up a web server in WSL and connect to it from any computer on the same network.
With WSL 2, the network interface is handled by Hyper-v and is defaulted to
NAT (Network Address Translation). This means there is no direct route for any service running in the WSL 2 instance to be addressable from any machine other than the host. It has not only a different IP address it is on a completely different subnet.
This should be easy to rectify, but ... well I am blogging about it ...
In theory, the Hyper-v virtual networking switch should be configurable and can be set back to
Bridged mode. Except that if you do then *all* networking goes directly to the WSL 2 instance, your Windows loses then ability to do any other networking. Not to mention Windows Home users do not have access to the Hyper-v manager.
Microsoft have a little note on their WSL 2 page stating that the networking is different from WSL 1 and that the user should treat it like any other virtual machine and setup virtual networking. Except that all the other virtual machine systems have GUI configuration options to handle this task (and default to sensible defaults).
So ... what if we forwarded the destination port from the host to the WSL 2 instance? This is how home internet routers work.
Some early explorers into this issue were very pleased to find that running a single command in Windows
netsh (as
portproxy) did successfully do this. Unfortunately, Microsoft in their infinite wisdom decided to randomise the IP address that WSL 2 got each and every time it was started. That meant that every time you rebooted you had to run the command again. And ... you had to have the random IP address (which only exists when you start WSL 2).
This was very painful, as firewall rules had to also match the virtual interface's details, which changed on every reboot.
It appears all this was reported back in
June 2019 and although it has 459 comments (at time of writing) and there are many many other such threads on a multitude of platforms nothing is being done about it.
Near the bottom of the thread on
the GitHub issues page for this issue there is a Powershell script that performs all the tasks for you, but ...
You have to have already started WSL 2
You have to have Administrator permissions and then, you can run it.
(and you have to have edited it for the ports you want)
(and you get loads of errors the first time, but then it works OK)
To test that other devices on the network could see my machine at all I tried to Ping the IP address and ... Windows blocks that by default now.
You need to go into Firewall settings, Advanced and incoming. Then enable the 3-4 rules that a named "File and Printer Sharing (Echo Request - ICMPv4-In)".
Oh, and did I mentioned all this doesn't work for IPv6 and loads of people have had issues with UDP and Multicast.
All this was so I could test a revision to my Godot VR tests on the Oculus Quest 2.
Many hours were lost to trying to fix this ... YMMV