How does WSL2 ubuntu 20.04 get its IP address?

I can't see what system is getting/assigning the IP. There are files from both NetworkManager and netplan in /etc but they both seem incomplete and systemd is not running. There are very few processes running and the network-manager init.d script reports it is not running. There is no /etc/network/interfaces file.

My understanding is that WSL2 has some special kind of DHCP server via the WSL virtual switch but what is contacting that server and getting an IP?


Solution 1:

An old'ish question that seems to have been bumped today, so I'll take a stab at it.

Short answer: init is responsible for setting up the networking (and much else)

Longer answer:

init is the "PID 1" process on all WSL (both version 1 and 2) instances. You'll find the same init in the root of all WSL instances, with the same size and timestamp.

It is responsible for the bring-up of the instance, including:

  • Reading /etc/wsl.conf and configuring the instance based on the contents of that file
  • Setting up networking, including auto-generating /etc/resolv.conf (assuming that isn't turned off in /etc/wsl.conf
  • Auto-mounting all Windows drives in /mnt/driveletter (e.g. /mnt/c) (again, assuming that feature hasn't been turned off)
  • Determining the current user - First checked from the -u flag on wsl.exe, then falling back to the /etc/wsl.conf setting, checking the Windows Registry setting for the user for the instance, and finally falling back to root if none of the above are found.
  • Appending the Windows path to the Linux path (assuming it is not turned off)
  • Setting WSL specific environment variables in instance
  • Probably a few other things, including setting up Windows interoperability through a socket in /run/WSL/, so that Windows executables can be run in WSL Linux sessions.

As far as I can tell, the WSL init is both closed-source and not really documented, so I'm honestly making some conjecture here, but some of this can be picked up from searching the WSL Github Issues repo for "init".

It's also likely that init is a proxy to other processes inside of the WSL subsystem that do the heavy lifting. For instance, WSL2 VMs will get their networking information from the Hyper-V virtual NIC, while WSL2 instances are "bridged" with the Windows NIC. The logic for this likely lives outside init in WSL "proper", but it is called by init during instance startup.

To test out the init functionality, I decided to remove just about everything else possible from a WSL instance to see how far I could take it before it broke:

  • I cloned an Alpine WSL instance, since this is about as "bare-bones" as you can get (about 8MB for the entire instance by default) and logged into it with wsl -u root.
  • Inside that instance, I removed everything but the passwd/group/shadow files from /etc
  • Removed everything from /lib except for libc.musl and its symlink
  • Removed /usr, /sbin, /root, /home
  • That pretty much just left busybox, groups, su, and login for the base executables in the instance in /bin. And, of course, /init.
  • Exited the session and did a wsl --terminate on it
  • Restarted the session as root

With all of that gone, and as barebones a system as possible (no net commands, no net scripts, etc.):

  • Login to busybox's ash shell still worked (also as the default, non-root user)
  • /etc/resolv.conf, /etc/hostname, and /etc/hosts were still automatically regenerated at boot.
  • Networking was up -- Ping by DNS worked, cat /proc/net/fib_trie returned the IP address (NAT'd, of course, as WSL2 is).
  • Windows drives were still auto-mounted
  • Windows interop (running Windows executables such as "powershell.exe") still worked
  • The Windows path was still appended to the Linux path.

I do wish the init process was a bit better documented, since it's such an important part of WSL. That said, at least the "how to configure it" doc is good, even if it doesn't go into the internals.