As as release 2.0.0 of WSL2, there are two separate networking modes available. The use-case mentioned in this question would now best be handled with the new "Mirrored" networking mode.
Mirrored Mode
Notes:
Available in Windows 11 23H2 and WSL2 2.0.0 and later*
From @KenvixZure in the comments:
There are still many issues about mirrored mode. If your application runs fine in NAT mode, don't change it.
This is good and appreciated advice. Mirrored Mode is a relatively new feature of WSL2 and, while I haven't personally experienced issues directly, it is expected that there will be some issues to work out.
In Mirrored Mode, the network interfaces from Windows are mirrored into WSL2, allowing them to be treated separately again similar to (but improved from) the way they were in WSL1 (mentioned below). Communicating with devices on your local network that are connected to different NICs in the Windows host should now be completely possible with this mode enabled.
To enable Mirrored mode:
Add the following to your <windows_user_profile>/.wslconfig
:
[wsl2]
networkingMode=mirrored
Exit your WSL distribution
Run wsl --shutdown
from PowerShell then restart WSL
Running ip addr
and ip link
should now show you all of the physical interfaces (and some virtual ones as well) from Windows, with the ability to route between them as desired.
Note that WiFi interfaces in Windows will appear at wired NICs in this mode. Some other limitations may apply, but you are at least able to bring these interfaces up and down from within WSL2 (unlike WSL1 mentioned below).
NAT Networking Mode
This was the original answer to this question. It still applies for the default, NAT networking mode. If you are on an older version of Windows and/or WSL, then you'll definitely be in this mode.
As you've seen, WSL1 gives you a better mapping of Windows interfaces to "Linux interfaces", but it's important to understand the differences between WSL1 and WSL2 in this regard:
Under WSL1, when a Linux app calls a Linux API, WSL1 is responsible for trying to map this to Windows APIs. So when ifconfig
(or ip
) trys to call getifaddrs to get the available interfaces, WSL1 pops in the list that the Windows kernel knows about.
WSL2, on the other hand, is running a real Linux kernel in a virtualized environment (a subset of Hyper-V). A getifaddrs
there enumerates the interfaces that the virtual machine provides to the Linux kernel.
There are advantages and disadvantages to both:
The biggest problem in WSL1 is that you are going to be very limited in what you can do with these interfaces. Microsoft's Windows->Linux API mapping only goes so deep when it comes to hardware.
For instance, even a very basic task like bringing an interface up or down isn't going to work. E.g. sudo ip link set wifi0 down
will always return RTNETLINK answers: Operation not permitted
. You can't put the interface into promiscuous mode, run WireShark, or anything like that.
And WSL2's virtualization means, of course, that you don't even see the Windows interfaces when calling Linux commands. On the other hand, you get full access to the virtual interfaces.
There may be some WSL2 possibilities for you, depending on your use-case. You mentioned that you have multiple interfaces installed, with each connected to a different endpoint device.
The simplest scenario, if it works for you, would simply be to assign a different subnet to each interface in Windows and rely on Windows routing table to handle the packets to the devices based on their IP address. The virtual interface in WSL2 should "just work" and send the packets out to the Windows host for the correct routing.
If that doesn't work, then check out socat
as another option. There's a Windows version available (although I haven't tried it), along with the standard Linux one that you'll find available in most distributions. I've had success creating TAP/TUN devices in WSL2 that map to other endpoints, although it's been a while since I've done it and don't quite remember the details off the top of my head. In theory, you could shuffle packages between a socat
running on WSL2 and one running on the Windows host itself for more complicated use-cases.
And while it's not part of your use-case, I'll mention this for others who might read this, since it relates to the question. If you need to do something like enable or disable a Windows interface from within WSL (either 1 or 2) for some reason, consider calling out through powershell.exe
. E.g.:
powershell.exe -c "Disable-NetAdapter -name 'Wi-Fi'"
Note that this would need to be done in a UAC-elevated terminal, since WSL cannot do anything (even as root) that your Windows user can't do. Also note that in a UAC-elevated session, you may need to specify the full path to powershell.exe
.
Finally, and I say this simply because I've seen some folks be critical of WSL limitations recently, I don't see any of this as a limitation of WSL. You'd run into the same issue with virtual interfaces if running under VMWare, VirtualBox, or any other virtualization environment. IMHO, WSL gives us quite a few more options to at least attempt to deal with this than other virtualization environments do.
ifconfig
muscle-memory. It's a deprecated command that has already disappeared from some distributions (openSUSE Leap and Tumbleweed, at least, although many other distros keep it around for compatibility). Tryip link
as its modern replacement. Bonus --ip --color=always link
(if you're into that kind of thing -- I think it improves readability).