NixOS-WSL
NixOS-WSL copied to clipboard
Inclusion of wsl-vpnkit
I have already implemented this and is wondering if it makes sense to include in this project.
Problem
Some VPN solutions causes problem when used together with WSL, there is wsl-vpnkit to address this issue.
Solution
wsl-vpnkit can be run within NixOS and requires the following:
Packing wsl-vpnkit
:
{
lib,
stdenv,
fetchFromGitHub,
makeWrapper,
# Runtime
gvproxy,
dnsutils,
gawk,
iproute2,
iptables,
iputils,
wget,
}:
let
gvproxyCross = gvproxy.overrideAttrs (_: {
buildPhase = "make cross qemu-wrapper vm";
});
in stdenv.mkDerivation rec {
pname = "wsl-vpnkit";
version = "0.4.1";
src = fetchFromGitHub {
owner = "sakai135";
repo = "wsl-vpnkit";
rev = "v${version}";
sha256 = "sha256-Igbr3L2W32s4uBepllSz07bkbI3qwAKMZkBrXLqGrGA=";
};
nativeBuildInputs = [makeWrapper];
postPatch = ''
substituteInPlace wsl-vpnkit \
--replace "/app/wsl-vm" "${gvproxyCross}/bin/vm" \
--replace "/app/wsl-gvproxy.exe" "${gvproxyCross}/bin/gvproxy-windows.exe"
'';
installPhase = ''
mkdir -p $out/bin
cp wsl-vpnkit $out/bin
'';
postFixup = ''
wrapProgram "$out/bin/wsl-vpnkit" \
--prefix PATH : "${lib.makeBinPath [ dnsutils gawk iproute2 iptables iputils wget ]}"
'';
}
Creating a systemd service:
{
systemd.services.wsl-vpnkit = {
enable = true;
description = "wsl-vpnkit";
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${pkgs.wsl-vpnkit}/bin/wsl-vpnkit";
Restart = "always";
KillMode = "mixed";
};
};
}
It looks like wsl-vpnkit could be useful for other distros with nix installed as well. I suggest you try to get the derivation merged into nixpkgs instead of here. Once it's in there, we could add the systemd service here
As i'm on a coporate Laptop with Windows and VPN i'm very grateful for wsl-vpnkit :) Thanks for adding it to nixpkgs.
Creating a systemd service:
{ systemd.services.wsl-vpnkit = { enable = true; description = "wsl-vpnkit"; after = [ "network.target" ]; serviceConfig = { ExecStart = "${pkgs.wsl-vpnkit}/bin/wsl-vpnkit"; Restart = "always"; KillMode = "mixed"; }; }; }
adding wantedBy
works:
# see https://github.com/sakai135/wsl-vpnkit/blob/5084c6d/wsl-vpnkit.service
systemd.services.wsl-vpnkit = {
enable = true;
description = "wsl-vpnkit";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.wsl-vpnkit}/bin/wsl-vpnkit";
Restart = "always";
KillMode = "mixed";
};
};
I explicitly didn't add wantedBy
as I'm not always on VPN and when I'm not on VPN it breaks certain things to have this running. For example SSH access to GitHub didn't work when enabled.
Is this still needed? There are some experimental network options in the latest WSL which sound like they make wsl-vpnkit obsolete (I haven't used it myself, so I can't test)
Yes potentially, but there is a while until we get there. I tried to test this new feature, but it requires a bleeding edge windows version which is not under my control where needed.
Please note: You need to be on a Windows Insiders version to use the new networking settings (Any channel of Windows Insiders will do, including release preview). If you see the "These are not supported" messages it means that your current Windows version doesn't have support, and you will need to upgrade. These features will eventually be coming to Windows 11 22H2.
Friendly ping @terlar
As of
wsl.exe -v WSL-Version: 2.0.9.0 Kernelversion: 5.15.133.1-1 WSLg-Version: 1.0.59 MSRDC-Version: 1.2.4677 Direct3D-Version: 1.611.1-81528511 DXCore-Version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp Windows-Version: 10.0.19045.3570
❯ cat /etc/wsl.conf [automount] enabled=true mountFsTab=false options=metadata,uid=1000,gid=100 root=/mnt
[boot] command= systemd=true
[interop] appendWindowsPath=true enabled=true
[network] generateHosts=true generateResolvConf=true hostname=DANIELKNB1
[user] default=nixos
wsl-vpnkit stopped working.
... wsl-vpnkit[19026]: /nix/store/ifayrgnd020y38gssz3x4y3sld0sdry5-gvproxy-0.7.1/bin/gvproxy-windows.exe is not executable due to WSL interop settings or Windows permissions
(as in https://github.com/sakai135/wsl-vpnkit#wsl-gvproxyexe-is-not-executable-due-to-wsl-interop-settings-or-windows-permissions)
Which configuration would reenable it ?
Currently I have boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
in my configuration.nix
EDIT: Running directly though does seem to prove it is still executable
❯ /nix/store/ifayrgnd020y38gssz3x4y3sld0sdry5-gvproxy-0.7.1/bin/gvproxy-windows.exe time="2023-11-23T22:21:04+01:00" level=info msg="waiting for clients..."
@573 Yes, this is an issue with the newer WSL (since 2.0.5) requires you to use WSL_INTEROP
environment variable. There is a patch to fix this here:
https://github.com/sakai135/wsl-vpnkit/pull/250
I am currently running this override until this gets merged:
{
lib,
fetchFromGitHub,
findutils,
pstree,
resholve,
wsl-vpnkit,
}:
wsl-vpnkit.override {
resholve =
resholve
// {
mkDerivation = attrs @ {solutions, ...}:
resholve.mkDerivation (lib.recursiveUpdate attrs {
src = fetchFromGitHub {
owner = "sakai135";
repo = "wsl-vpnkit";
rev = "28992229fedfa64979faa9ec84b1b4bcf5c8f449";
sha256 = "sha256-6VKFUoPAhVOmORTGELZu00SnGmYSbumPOZ64giWq14Q=";
};
solutions.wsl-vpnkit = {
inputs =
solutions.wsl-vpnkit.inputs
++ [
findutils
pstree
];
execer =
solutions.wsl-vpnkit.execer
++ ["cannot:${pstree}/bin/pstree"];
};
});
};
}
Thank you so much, @terlar this now explains why I was able to even run
sudo -i /mnt/c/Windows/system32/wsl.exe -d wsl-vpnkit --cd /app ./wsl-vpnkit
or just plain
/mnt/c/Windows/system32/wsl.exe -d wsl-vpnkit --cd /app ./wsl-vpnkit
but not the exact same commands via systemd service. The env variable (set in NixOS-WSL correctly) was just not exported then.
Glad, you figred it out, even tried setting absolute paths and systemd.services.wsl-vpnkit.environment
as suggested there and changed /etc/wsl.conf
🤣
I have tested the new options:
[wsl2]
networkingMode=mirrored
dnsTunneling=true
Unfortunately neither worked well with my company VPN and I still had to resort to wsl-vpnkit
.
Since WSL 2.0.14, the mentioned issue with wsl-vpnkit
has been solved. So WSL 2.0.5-2.0.13 are the problematic ones that can be used together with my mentioned patch. But for later versions it is not needed.
I have also added a custom service like this:
{
systemd.services = {
wsl-vpnkit-auto = {
enable = cfg.autoVPN;
description = "wsl-vpnkit";
path = [pkgs.iputils];
script = ''
has_internet () {
ping -q -w 1 -c 1 8.8.8.8 >/dev/null
}
has_company_network () {
ping -q -w 1 -c 1 ${cfg.checkURL} >/dev/null
}
is_active_wsl-vpnkit () {
systemctl is-active -q wsl-vpnkit.service
}
main () {
if is_active_wsl-vpnkit; then
if has_internet && ! has_company_network; then
echo "Stopping wsl-vpnkit..."
systemctl stop wsl-vpnkit.service
fi
else
if ! has_internet; then
echo "Starting wsl-vpnkit..."
systemctl start wsl-vpnkit.service
fi
fi
}
while :
do
main
sleep 5
done
'';
wantedBy = ["multi-user.target"];
};
wsl-vpnkit = {
enable = true;
description = "wsl-vpnkit";
serviceConfig = {
ExecStart = "${pkgs.wsl-vpnkit}/bin/wsl-vpnkit";
Type = "idle";
Restart = "always";
KillMode = "mixed";
};
};
};
}
This way I can automatically connect to the wsl-vpnkit when needed and shut it down when off VPN. I can try to clean it up and make a PR if people think it is useful. At least for me it had made the VPN situation within WSL seemless.
@terlar thank you so much! I would really appreciate a PR for this.