title: Easy Access to WSL2 on Windows
date: 2022-11-29 12:12:06
tags: ['wsl']
Many people have encountered issues with communicating with the Windows host when using WSL. In daily programming, it is common to access databases, web servers, or other services deployed in WSL from Windows. Windows itself does mapping, for example, starting an HTTP server with the following command:
➜ source git:(master) python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
In this case, accessing localhost:8000
on Windows will open the server normally. However, in some other scenarios (such as database connections), this mapping may fail. Is it because WSL only maps the ports for HTTP services by default? (doubtful)
To solve the above problem, we need a way to ensure that the Windows host can easily access WSL. Here are three solutions listed, and I will describe my solution in detail.
Manually Find the LAN IP of WSL and Access Using That IP
This method is the simplest and straightforward. Manually find the IP of WSL and access it.
Execute the ifconfig
command in WSL to get a lot of output:
➜ source git:(master) ifconfig
.....
eth0: .......
inet 172.21.255.188 .....
.....
Find the IP address after inet
above, which is the LAN IP of WSL.
However, the IP of WSL changes every time it starts, so this method is not a good choice if you frequently need to access WSL.
Connection Mapping
Use HobaiRiku/wsl2-auto-portproxy to map all TCP ports in WSL to Windows localhost (UDP is not supported yet).
This method only requires downloading the binary file and running it when you need to access WSL, without any additional operations.
Add WSL IP to Windows hosts File
The drawback of the first method mentioned earlier is that the IP changes every time it starts, which reminds us of domain names.
As we all know, domain name resolution first checks the hosts file. If not found, it will use DNS. Therefore, this method is to add the IP of WSL and a custom domain name to the Windows hosts file, so you only need to access the domain name you set.
The implementation idea is similar to "modify domain name resolution records when the local IP changes" in DDNS. It needs to achieve "modify the hosts file when the WSL IP changes". And we know that the change of WSL IP actually means the startup of WSL. So the final requirement becomes: Write the IP into the Windows hosts file when WSL starts.
From this requirement, two ideas have emerged:
- Complete this process on Windows. The specific method is to bind a custom task to the event triggered when WSL starts. This task executes
ifconfig
in WSL and uses regular expressions to obtain the IP, then writes it to the hosts file. - Complete this process on WSL. The specific method is to add a startup script that obtains the local IP by any means and writes it to
/mnt/c/Windows/System32/drivers/etc/hosts
(because Windows drives are automatically mounted under/mnt
in WSL).
Idea 1
The core of Idea 1 is a custom task, and the specific workflow can be implemented in many ways. A relatively simple one is shayne/go-wsl2-host, which automatically adds a custom task triggered when WSL starts. It should work theoretically (unfortunately, it didn't work properly for me, and I don't know why).
Idea 2
Idea 2 has fewer implementations because there was no effective "startup" method in the past for WSL. But this obstacle has disappeared with WSL's support for systemd, so I manually created a project that uses this method: amtoaer/wsl2-automatic-hosts.
To use this project, for Arch Linux:
- Make sure WSL can read and write the
/mnt/c/Windows/System32/drivers/etc/hosts
file normally. - Download the
.pkg.tar.zst
file from the release and install it withsudo pacman -U
. - Enable the service with
sudo systemctl enable --now wah.service
.
For other distributions, simply replace the second step above with manual installation:
install -D -m 755 $srcdir/wah $pkgdir/usr/bin/wah
install -D -m 755 $srcdir/wah.service $pkgdir/usr/lib/systemd/system/wah.service
install -D -m 755 $srcdir/domains $pkgdir/etc/wah/domains
The other steps are the same.
By default, this project uses the domain name arch.wsl
. If you need to customize it, you can edit the /etc/wah/domains
file. For multiple custom domain names, please separate them with a single space.
This project will automatically add the address of WSL to the bottom of the hosts file and update it every time WSL starts: