Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Haeyzed/1092b6b5dbd11de09716f13c738ae525 to your computer and use it in GitHub Desktop.
Save Haeyzed/1092b6b5dbd11de09716f13c738ae525 to your computer and use it in GitHub Desktop.

Revisions

  1. @wllmsash wllmsash revised this gist Dec 31, 2022. 2 changed files with 111 additions and 71 deletions.
    71 changes: 0 additions & 71 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,71 +0,0 @@
    # Assigning a Static IP Address to a WSL2 Distribution

    Hyper-V creates a hidden virtual switch for WSL2. In Windows, the virtual NIC `vEthernet (WSL)` is connected to the
    switch. In WSL2 (Ubuntu), the virtual NIC `eth0` is connected to the switch. Communication between the two network
    endpoints happens over the switch. The virtual NICs (and possibly the switch) are ephemeral and disappear at host system
    restart time. The NICs are recreated on demand when WSL2 first runs.

    To use a custom static IP address we can assign each of the NICs to IP addresses on a shared subnet. It's a good idea to
    pick a subnet in the [Private Address](https://en.wikipedia.org/wiki/Private_network) range.

    The following steps help set up a fixed IP address for a WSL2 distribution from the host and a fixed IP address for the
    host from WSL2, with this configuration in mind:

    * Subnet: `192.168.2.0/24`
    * WSL2 Distribution: `Ubuntu-20.04`

    1. Assign a new IP address to the virtual NIC in Windows

    Assign the virtual NIC connected to WSL2 an additional IP address `192.168.2.1` _(Requires "Run as Administrator")_:

    `netsh interface ip add address "vEthernet (WSL)" 192.168.2.1 255.255.255.0`

    To remove in the future:

    `netsh interface ip delete address "vEthernet (WSL)" 192.168.2.1`

    2. Assign a new IP address to the virtual NIC in WSL2

    Assign the virtual ethernet NIC an additional IP address `192.168.2.2`:

    `sudo ip addr add 192.168.2.2/24 broadcast 192.168.2.255 dev eth0 label eth0:1`

    To remove in the future:

    `sudo ip addr del 192.168.2.201/24 dev eth0:1`

    3. Set up Windows firewall allow rule _(once only)_

    The `vEthernet (WSL)` network device uses the `Public` Windows network profile, where all traffic is blocked by
    default. We need to allow traffic from the new `192.168.2.0/24` subnet to access the host Windows machine from WSL2.

    1. Open Windows Defender Firewall with Advanced Security
    2. In Inbound rules, add a new Inbound Rule
    1. Select "Custom Rule"
    2. Select "All programs"
    3. Select "Any" Protocol Type
    4. Scope to remote IP addresses `192.168.2.0/24`
    5. Select "Allow the connection"
    6. Select only "Public" for the rule to apply
    7. Name `WSL2` or similar
    3. In Inbound rules, remove any existing block rules for applications that WSL2 needs to access, as these will
    take precedence over the allow rule. These are usually created by Windows when you first run an application (the
    UAC modal warning asking you about firewall rules sets these up).

    > **Note:** As the NICs are ephemeral these changes must be applied following every host system restart
    PowerShell script to set up static IP addresses:

    ```ps1
    $WslDistribution = "Ubuntu-20.04"
    $Subnet = "192.168.2" # /24
    $HostAddress = "$Subnet.1"
    $WslAddress = "$Subnet.2"
    $BroadcastAddress = "$Subnet.255"
    Start-Process pwsh -Verb RunAs -Wait -ArgumentList "-ExecutionPolicy Bypass", "-Command `"& { netsh interface ip add address \`"vEthernet (WSL)\`" $HostAddress 255.255.255.0; Write-Host -NoNewLine \`"Press any key to continue...\`"; `$Host.UI.RawUI.ReadKey(\`"NoEcho,IncludeKeyDown\`"); }`""
    echo "Finished configuring host network"
    wsl --distribution $WslDistribution /bin/bash -c "sudo ip addr add $WslAddress/24 broadcast $BroadcastAddress dev eth0 label eth0:1;"
    echo "Finished configuring WSL2 network"
    ```
    111 changes: 111 additions & 0 deletions assigning-static-ip-addresses-in-wsl2.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,111 @@
    # Assigning Static IP Addresses in WSL2

    WSL2 uses Hyper-V for networking. The WSL2 network settings are ephemeral and configured on demand when any WSL2
    instance is first started in a Windows session. The configuration is reset on each Windows restart and the IP addresses change each time. The Windows host creates a hidden switch named "WSL" and a network adapter named "WSL" (appears as
    "vEthernet (WSL)" in the "Network Connections" panel). The Ubuntu instance creates a corresponding network interface
    named "eth0".

    Assigning static IP addresses to the network interfaces on the Windows host or the WSL2 Ubuntu instance enables support
    for the following scenarios:

    - Connect to an Ubuntu instance from the Windows host using a static IP address
    - Connect to the Windows host from an Ubuntu instance using a static IP address

    This guide assumes [PowerShell 7](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows) and:

    | **Variable** | **Value** |
    | ---------------------------- | ------------------------------ |
    | WSL distribution | Ubuntu 20.04 |
    | WSL instance name | Ubuntu-20.04 |
    | Windows host IP address | 192.168.2.1 |
    | Ubuntu instance IP address | 192.168.2.2 |
    | Network subnet (subnet mask) | 192.168.2.0/24 (255.255.255.0) |

    > **Note:** It's best to pick a subnet in the [private address range](https://en.wikipedia.org/wiki/Private_network).
    ## Manual Steps

    Configure connectivity from the Windows host to the Ubuntu instance:

    1. Assign the Ubuntu instance IP address to the "eth0" network interface in Ubuntu _(after every restart)_.

    ```shell
    sudo ip address add 192.168.2.2/24 brd + dev eth0
    ```

    Configure connectivity from the Ubuntu instance to the Windows host:

    2. Add a Windows firewall allow rule _(once only)_.

    The "vEthernet (WSL)" network interface uses the "Public" Windows network profile so all traffic from the Ubuntu
    instance to the host is blocked by default. Allow all inbound traffic from the "vEthernet (WSL)" network interface.

    ```powershell
    # Requires "Run as Administrator"
    New-NetFirewallRule -Name 'WSL' -DisplayName 'WSL' -InterfaceAlias 'vEthernet (WSL)' -Direction Inbound -Action Allow
    ```

    > **Note:** Any existing rules blocking inbound traffic for applications on the Windows host will take precedence
    > over this rule, so remove or disable these where required. Such rules can be created automatically by Windows
    > when an application is first run. Windows shows the user a UAC modal asking for permission to create a firewall
    > rule.

    3. Assign the Windows host IP address to the "WSL" network interface in Windows _(after every restart)_.

    ```powershell
    # Requires "Run as Administrator"
    New-NetIPAddress -InterfaceAlias 'vEthernet (WSL)' -IPAddress '192.168.2.1' -PrefixLength 24
    ```

    ## PowerShell Script

    All the steps above in a PowerShell script.

    ```powershell
    $WslInstanceName = 'Ubuntu-20.04'
    $WindowsHostIPAddress = '192.168.2.1'
    $UbuntuInstanceIPAddress = '192.168.2.2'
    $SubnetMaskNumberOfBits = 24
    $WslFirewallRuleName = 'WSL'
    $WslNetworkInterfaceName = 'vEthernet (WSL)'
    $UbuntuNetworkInterfaceName = 'eth0'
    # Ensure the "vEthernet (WSL)" network adapter has been created by starting WSL.
    Write-Host 'Ensure WSL network exists...'
    wsl --distribution "Ubuntu-20.04" /bin/false
    Write-Host 'WSL network exists'
    # All inbound traffic from Ubuntu through Windows firewall and assign a static IP address to the "vEthernet (WSL)"
    # network adapter in Windows.
    Write-Host 'Configuring Windows host network...'
    Start-Process 'pwsh' -Verb RunAs -Wait -ArgumentList '-ExecutionPolicy Bypass', @"
    -Command & {
    Write-Host 'Checking firewall...'
    If (-Not (Get-NetFirewallRule -Name '$WslFirewallRuleName' -ErrorAction SilentlyContinue)) {
    Write-Host 'Configuring firewall...'
    New-NetFirewallRule -Name '$WslFirewallRuleName' -DisplayName '$WslFirewallRuleName' -InterfaceAlias '$WslNetworkInterfaceName' -Direction Inbound -Action Allow
    Write-Host 'Finished configuring firewall'
    }
    Else {
    Write-Host 'Already configured firewall'
    }
    Write-Host 'Checking network interface...'
    If (-Not (Get-NetIPAddress -InterfaceAlias '$WslNetworkInterfaceName' -IPAddress '$WindowsHostIPAddress' -PrefixLength $SubnetMaskNumberOfBits -ErrorAction SilentlyContinue)) {
    Write-Host 'Configuring network interface...'
    New-NetIPAddress -InterfaceAlias '$WslNetworkInterfaceName' -IPAddress '$WindowsHostIPAddress' -PrefixLength $SubnetMaskNumberOfBits
    Write-Host 'Finished configuring network interface'
    }
    Else {
    Write-Host 'Already configured network interface'
    }
    }
    "@
    Write-Host 'Finished configuring Windows host network'
    # Assign a static IP address to the "eth0" network interface in Ubuntu.
    Write-Host 'Configuring Ubuntu instance network...'
    wsl --distribution "$WslInstanceName" --user root /bin/sh -c "if !(ip address show dev $UbuntuNetworkInterfaceName | grep -q $UbuntuInstanceIPAddress/$SubnetMaskNumberOfBits); then ip address add $UbuntuInstanceIPAddress/24 brd + dev $UbuntuNetworkInterfaceName; fi"
    Write-Host 'Finished configuring Ubuntu instance network'
    ```
  2. @wllmsash wllmsash created this gist Dec 5, 2020.
    71 changes: 71 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,71 @@
    # Assigning a Static IP Address to a WSL2 Distribution

    Hyper-V creates a hidden virtual switch for WSL2. In Windows, the virtual NIC `vEthernet (WSL)` is connected to the
    switch. In WSL2 (Ubuntu), the virtual NIC `eth0` is connected to the switch. Communication between the two network
    endpoints happens over the switch. The virtual NICs (and possibly the switch) are ephemeral and disappear at host system
    restart time. The NICs are recreated on demand when WSL2 first runs.

    To use a custom static IP address we can assign each of the NICs to IP addresses on a shared subnet. It's a good idea to
    pick a subnet in the [Private Address](https://en.wikipedia.org/wiki/Private_network) range.

    The following steps help set up a fixed IP address for a WSL2 distribution from the host and a fixed IP address for the
    host from WSL2, with this configuration in mind:

    * Subnet: `192.168.2.0/24`
    * WSL2 Distribution: `Ubuntu-20.04`

    1. Assign a new IP address to the virtual NIC in Windows

    Assign the virtual NIC connected to WSL2 an additional IP address `192.168.2.1` _(Requires "Run as Administrator")_:

    `netsh interface ip add address "vEthernet (WSL)" 192.168.2.1 255.255.255.0`

    To remove in the future:

    `netsh interface ip delete address "vEthernet (WSL)" 192.168.2.1`

    2. Assign a new IP address to the virtual NIC in WSL2

    Assign the virtual ethernet NIC an additional IP address `192.168.2.2`:

    `sudo ip addr add 192.168.2.2/24 broadcast 192.168.2.255 dev eth0 label eth0:1`

    To remove in the future:

    `sudo ip addr del 192.168.2.201/24 dev eth0:1`

    3. Set up Windows firewall allow rule _(once only)_

    The `vEthernet (WSL)` network device uses the `Public` Windows network profile, where all traffic is blocked by
    default. We need to allow traffic from the new `192.168.2.0/24` subnet to access the host Windows machine from WSL2.

    1. Open Windows Defender Firewall with Advanced Security
    2. In Inbound rules, add a new Inbound Rule
    1. Select "Custom Rule"
    2. Select "All programs"
    3. Select "Any" Protocol Type
    4. Scope to remote IP addresses `192.168.2.0/24`
    5. Select "Allow the connection"
    6. Select only "Public" for the rule to apply
    7. Name `WSL2` or similar
    3. In Inbound rules, remove any existing block rules for applications that WSL2 needs to access, as these will
    take precedence over the allow rule. These are usually created by Windows when you first run an application (the
    UAC modal warning asking you about firewall rules sets these up).

    > **Note:** As the NICs are ephemeral these changes must be applied following every host system restart
    PowerShell script to set up static IP addresses:

    ```ps1
    $WslDistribution = "Ubuntu-20.04"
    $Subnet = "192.168.2" # /24
    $HostAddress = "$Subnet.1"
    $WslAddress = "$Subnet.2"
    $BroadcastAddress = "$Subnet.255"
    Start-Process pwsh -Verb RunAs -Wait -ArgumentList "-ExecutionPolicy Bypass", "-Command `"& { netsh interface ip add address \`"vEthernet (WSL)\`" $HostAddress 255.255.255.0; Write-Host -NoNewLine \`"Press any key to continue...\`"; `$Host.UI.RawUI.ReadKey(\`"NoEcho,IncludeKeyDown\`"); }`""
    echo "Finished configuring host network"
    wsl --distribution $WslDistribution /bin/bash -c "sudo ip addr add $WslAddress/24 broadcast $BroadcastAddress dev eth0 label eth0:1;"
    echo "Finished configuring WSL2 network"
    ```