- How it works
- Values used
- Prerequisites
- Procedure
Hyper-V: Isolated NAT Network with Port Forwarding
- How it works
- Values used
- Prerequisites
- Procedure
This guide describes how to create an isolated NAT network for virtual machines in Hyper-V — the equivalent of VirtualBox's "NAT" mode — and how to expose selected services from that network to the host and to other machines on the local network.
host-ip:port.How it works
Hyper-V has no ready-made "NAT" mode like VirtualBox. The same behaviour is achieved by combining three separate components:
- Internal virtual switch — a private network between the host and the virtual machines, with no connection to the physical network adapter. The virtual machine is therefore not visible from the LAN.
- IP address on the host adapter — this makes the host the default gateway for virtual machines on that private network.
- NetNat — the Windows component that translates addresses from the private network out through the host's internet connection, and can also forward selected inbound ports back in.
The traffic flow looks like this:
Other PCs on the LAN ──► Host 192.168.1.50:8080
│ NAT + port forwarding
▼
vEthernet (NATSwitch) = 192.168.100.1
│
▼
VM 192.168.100.10:80 ──► internet via NAT
Values used
The whole guide uses the values below. Feel free to replace them with your own — just make sure you change them consistently in every command.
Item | Value |
Switch name |
|
NAT name |
|
Subnet |
|
Host IP (gateway) |
|
Virtual machine IP |
|
Service inside the VM | TCP port |
Port exposed on the host | TCP port |
192.168.1.0/24, then 192.168.100.0/24 is safe to use.Prerequisites
- Windows 10/11 Pro, Enterprise or Education, or Windows Server, with the Hyper-V role enabled. The Home edition does not include Hyper-V.
- All commands on the host must be run in PowerShell started as Administrator.
- Only one
NetNatinstance is allowed per host.
Before you start, check whether a NAT already exists on the machine:
Get-NetNat
Remove-NetNat -Name "<name>". Only remove it if you are certain nothing else depends on it — otherwise Docker containers, for example, will lose network connectivity.Procedure
1. Create the internal switch
New-VMSwitch -SwitchName "NATSwitch" -SwitchType Internal
This creates a virtual switch with no connection to the physical network adapter, plus a new virtual adapter on the host named vEthernet (NATSwitch).
2. Assign the gateway IP address to the host adapter
New-NetIPAddress -IPAddress 192.168.100.1 -PrefixLength 24 -InterfaceAlias "vEthernet (NATSwitch)"
The host now owns the address 192.168.100.1 on this network. This address will act as the default gateway for the virtual machine.
Verify:
Get-NetIPAddress -InterfaceAlias "vEthernet (NATSwitch)"
3. Create the NAT
New-NetNat -Name "NATNetwork" -InternalIPInterfaceAddressPrefix 192.168.100.0/24
This tells Windows to translate all traffic from the 192.168.100.0/24 subnet out through the host's active internet connection.
Verify:
Get-NetNat
4. Attach the virtual machine to the switch
Via the GUI: Settings → Network Adapter → Virtual switch → NATSwitch.
Or via PowerShell:
Connect-VMNetworkAdapter -VMName "MyVM" -SwitchName "NATSwitch"
5. Configure networking inside the virtual machine
Setting | Value |
IP address |
|
Subnet mask / prefix |
|
Default gateway |
|
DNS |
|
192.168.100.1 does not provide DNS, so it cannot be used as a DNS server. Always specify a public or corporate DNS server.Linux (Ubuntu, netplan)
File /etc/netplan/01-static.yaml:
network:
version: 2
ethernets:
eth0:
addresses: [192.168.100.10/24]
routes:
- to: default
via: 192.168.100.1
nameservers:
addresses: [1.1.1.1, 8.8.8.8]
Apply the configuration with sudo netplan apply. Verify the interface name (eth0) with ip a — it is often ens33 or similar.
Windows (PowerShell inside the VM)
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.168.100.10 -PrefixLength 24 -DefaultGateway 192.168.100.1
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 1.1.1.1,8.8.8.8
Sanity checks from inside the VM
ping 192.168.100.1 # gateway is reachable
ping 1.1.1.1 # internet via NAT works
nslookup example.com # DNS works
http://192.168.100.10:80 — with no port forwarding at all. The remaining two steps are only needed for access from other computers.6. Add the port forwarding rule
Forward host port 8080 to port 80 inside the virtual machine:
Add-NetNatStaticMapping -NatName "NATNetwork" -Protocol TCP -ExternalIPAddress 0.0.0.0 -ExternalPort 8080 -InternalIPAddress 192.168.100.10 -InternalPort 80
-ExternalIPAddress 0.0.0.0means listening on all host interfaces. If the service should only be available on one of them (for example on the wired connection but not on Wi-Fi), enter that interface's specific IP address instead of the zeros.- Create a separate rule with different ports for each additional service — for example
2222 → 22for SSH. - Only TCP and UDP are supported. If a service needs both, create two rules.
Managing existing rules:
Get-NetNatStaticMapping # list all rules
Remove-NetNatStaticMapping -StaticMappingID 0 # remove one (ID taken from the list above)
7. Open the host firewall
The forwarding rule alone is not enough — Windows Firewall still drops inbound connections from other computers. You need to allow the external port:
New-NetFirewallRule -DisplayName "Forward 8080 to VM web" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow
Optionally, the rule can be restricted to your own LAN, which is preferable from a security standpoint:
New-NetFirewallRule -DisplayName "Forward 8080 to VM web (LAN only)" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow -RemoteAddress 192.168.1.0/24
Adjust the 192.168.1.0/24 range to match your actual subnet.
Testing
- Find the host's LAN IP address with
ipconfig— for example192.168.1.50. - From the host, open
http://192.168.100.10:80— direct access must work. - From another computer on the network, open
http://192.168.1.50:8080— the service running inside the virtual machine must appear.
python3 -m http.server 80 (Linux). The server runs until you stop it with Ctrl+C.Troubleshooting
The virtual machine has no internet access
- Run
Get-NetNat— does the NAT exist and does its subnet match your configuration? - The gateway inside the virtual machine must be
192.168.100.1, and that address must exist on thevEthernet (NATSwitch)adapter. Re-check step 2 — the address can disappear if the switch was recreated in the meantime. - If
ping 1.1.1.1works but names do not resolve, the DNS servers inside the virtual machine are configured incorrectly.
The host cannot reach the VM directly
- The firewall inside the virtual machine — the guest system must allow the service port. This is by far the most common cause.
- Verify that the VM's network adapter is connected to
NATSwitchand that it has the correct IP address.
Other computers cannot connect, but direct access from the host works
- The host firewall rule is missing, or is configured for a different port (step 7).
- Typo in the forwarding rule — check the internal IP address and both ports with
Get-NetNatStaticMapping. - Some VPN clients on the host intercept inbound traffic. Try again with the VPN disconnected.
The New-NetNat command fails
Typically with "The parameter is incorrect" or a similar message.
- Another NetNat instance already exists on the host — verify with
Get-NetNat. Remove it, or reuse its subnet. - On some machines WSL2 or Docker Desktop conflicts here, as they create their own NAT automatically.
Everything stops working after a host reboot
The switch, IP address, NAT, forwarding rules and firewall rules are all persistent and survive a reboot. If the host-side IP address disappears after a major Windows update, simply repeat step 2.
Removing the configuration
Remove everything in the reverse order of creation:
Get-NetNatStaticMapping | Remove-NetNatStaticMapping -Confirm:$false
Remove-NetFirewallRule -DisplayName "Forward 8080 to VM web"
Remove-NetNat -Name "NATNetwork" -Confirm:$false
Remove-NetIPAddress -InterfaceAlias "vEthernet (NATSwitch)" -IPAddress 192.168.100.1 -Confirm:$false
Remove-VMSwitch -Name "NATSwitch" -Force
StaticMappingID.Quick reference
The entire setup in one block
Run on the host in PowerShell as Administrator:
New-VMSwitch -SwitchName "NATSwitch" -SwitchType Internal
New-NetIPAddress -IPAddress 192.168.100.1 -PrefixLength 24 -InterfaceAlias "vEthernet (NATSwitch)"
New-NetNat -Name "NATNetwork" -InternalIPInterfaceAddressPrefix 192.168.100.0/24
Connect-VMNetworkAdapter -VMName "MyVM" -SwitchName "NATSwitch"
Inside the virtual machine, set the static IP 192.168.100.10/24, gateway 192.168.100.1 and DNS 1.1.1.1.
Expose port 80 from the VM as port 8080 on the host:
Add-NetNatStaticMapping -NatName "NATNetwork" -Protocol TCP -ExternalIPAddress 0.0.0.0 -ExternalPort 8080 -InternalIPAddress 192.168.100.10 -InternalPort 80
New-NetFirewallRule -DisplayName "Forward 8080 to VM web" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow
Updated
by Frantisek Brych