OpenWrt on Hyper-V

Written on July 26, 2019

As my recent posts indicate, I have been exploring networking related tasks in PowerShell. Sticking with that theme, I thought it would be nice to play with an actual firewall in my lab. With that being said, lets get into the OpenWRT setup on Hyper-V.

NOTE: While I am targeting Hyper-V as the platform, the same general process can be used to setup OpenWRT on another Hypervisor.

Problems with Windows

Unfortunately, I was unable to get this whole thing setup using just my Windows host. Getting the image created, and adding in the necessary network drivers to the image required a Linux touch. If you can figure out a way without using Linux I would be willing to give it a try.

This makes step 1, setting up a Linux VM (if you don’t already have one).

Step 1: Create Linux VM

I won’t go into the details of setting up a Linux VM on Hyper-V. It is pretty straight forward, and if you are on a new Windows 10 version, you can setup Ubuntu incredibly easy following this guide.

Once you have a Linux VM configured, power it off and proceed to step 2.

Step 2 : The VHD

Time to create the VHD file that we will use for the openWrt VM.

mkdir "V:\VMs\$wrtName"
$vhd=New-VHD -Path "V:\VMs\$wrtName\$wrtName.vhd" -SizeBytes 500MB -Fixed
Write-Output $vhd

Now, we can attach this VHD to our Linux VM so we can write to it.

# Ensure your Linux VM is powered off

# change to your VM name

Add-VMHardDiskDrive -VMName $vmname `
  -ControllerType IDE `
  -ControllerNumber 0 `
  -ControllerLocation 1 `
  -Path $vhd.Path 

Get-VMHardDiskDrive -VMName $vmname
# You should see at least 2 disks show up
# with the 2nd one being the new vhd

Start-VM $vmname

Step 3: Download OpenWRT

This should be done on your Linux VM, from the terminal. I will be downloading the latest (at the time of writing) image available, 18.06.1. Feel free to choose your own.

sudo curl \
-o /tmp/openwrt-18.06.1.img.gz

# Unzip the openwrt img file
sudo gzip -dk /tmp/openwrt-18.06.1.img.gz

Step 4: Write the OpenWRT Image to Disk

We will need to identify the new disk we added to our Linux VM in step 2. You can list out the disks like so:

sudo fdisk -l

You should see something like this:

Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x57b7b33b

Device     Boot    Start      End  Sectors Size Id Type
/dev/sda1  *        2048 58720255 58718208  28G 83 Linux
/dev/sda2       58722302 62912511  4190210   2G  5 Extended
/dev/sda5       58722304 62912511  4190208   2G 82 Linux swap / Solaris

Partition 2 does not start on physical sector boundary.

Disk /dev/sdb: 500 MiB, 524288000 bytes, 1024000 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Note the first disk is shown: “Disk /dev/sda: 30 GiB”. Which makes the second one: “Disk /dev/sdb: 500MiB.

This means /dev/sdb is our target disk to write the OpenWrt image to.

sudo dd if=/tmp/openwrt-18.06.1.img of=/dev/sdb bs=4M conv=fsync status=progress

Now you can power off your Linux VM for the moment so you can remove this disk.

sudo poweroff

Step 5: Create your OpenWRT VM

Back on your Windows host machine:

# In PowerShell on your host machine

# Remove VHD from your Linux VM
Remove-VMHardDiskDrive -VMName $vmname `
  -ControllerType IDE `
  -ControllerNumber 0 `
  -ControllerLocation 1

# Create openWRT VM
New-VM -VMName $wrtName `
  -Path "V:\VMs\$wrtName" `
  -VHDPath $vhd.Path `
  -MemoryStartUpBytes 512MB `
  -Generation 1

Get-VMNetworkAdapter -VMName $wrtName | Remove-VMNetworkAdapter

Start-VM $wrtName
vmconnect localhost $wrtName

It should do its configuration and boot into the OS. After it has completed the boot, (you can press enter to get to the cmd line) you can run some commands to see what you have.

# Will only show you the loopback adapter 'lo'

Once you have looked around, you can power it off to get onto the next step


Step 6: Add VHD back on to Linux VM

Now we will need add this disk back onto our Linux VM for further processing.

I recommend removing all snapshots (in case there are any) from the VM, to make removing and adding disks easier.

# Back on your Windows host
$snapshots=Get-VMSnapshot -VMName $wrtName 
  $snapshots | Remove-VMSnapshot

Remove-VMHardDiskDrive -VMName $wrtName `
  -ControllerType IDE `
  -ControllerNumber 0 `
  -ControllerLocation 0

Now add the VHD back onto your Linux VM:

# Add the vhd file back to your linux vm
Add-VMHardDiskDrive -VMName $vmname `
  -ControllerType IDE `
  -ControllerNumber 0 `
  -ControllerLocation 1 `
  -Path $vhd.Path

Start-VM $vmname

Step 7: Get OpenWRT network driver

You will need the ‘tulip’ drivers for the VM Network adapters to work on Hyper-V. We can download this on our Linux VM like so:

# Download the tulip driver
sudo curl \
-o /tmp/tulip-driver.ipk

Now we can copy this file to our OpenWRT disk.

# check for the disk we added 
# There should be 2 partitions under that disk now
sudo fdisk -l

You should see something like this:

Disk /dev/sdb: 500 MiB, 524288000 bytes, 1024000 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xcbad8a62

Device     Boot Start    End Sectors  Size Id Type
/dev/sdb1  *      512  33279   32768   16M 83 Linux
/dev/sdb2       33792 558079  524288  256M 83 Linux

We want to copy the tulip driver to the non-boot partition on this disk. This is accomplished by mounting the non-boot partition.

sudo mount /dev/sdb2 /mnt

# you should be able to ls /mnt and see the folder structure
ls /mnt

Now, copy the tulip driver to the mounted partition

sudo cp /tmp/tulip-driver.ipk /mnt/root/tulip-driver.ipk

# Un-mount the partition
sudo umount /dev/sdb2

We are now finished with the Linux VM, and you can power it down.

sudo poweroff

Step 8: Add VHD Back and Add Network Adapters

After this, we are done playing hot-potato with this VHD file. We can add it to our OpenWRT VM for good this time.

# Back into the host powershell session
Remove-VMHardDiskDrive -VMName $vmname `
  -ControllerType IDE `
  -ControllerNumber 0 `
  -ControllerLocation 1

Add-VMHardDiskDrive -VMName $wrtName `
  -ControllerType IDE `
  -ControllerNumber 0 `
  -ControllerLocation 0 `
  -Path $vhd.Path

Now we can add our Hyper-V network adapters to our OpenWRT VM. You will need to use your own names for you VMNetadapters.

Ensure you use the IsLegacy parameter with $true.

# Add network adapters to vm
$switch1='External vSwitch'

Add-VMNetworkAdapter -VMName $wrtName `
  -IsLegacy $true `
  -SwitchName $switch1

Add-VMNetworkAdapter -VMName $wrtName `
  -IsLegacy $true `
  -SwitchName $switch2

# Start your VM
Start-VM -VMName $wrtName

Step 9: Install Network Driver

On your OpenWRT VM you can now install your tulip driver, and get your networking…working.

# Inside the openwrt vm
opkg install /root/tulip-driver.ipk

Now you can take a look at your network interfaces:

# you should now have some network adapters visible
ifconfig -a

Now you can edit your network config file to setup your networks. Do this by editing the /etc/config/network file.

vi /etc/config/network


config interface 'loopback'
  option ifname 'lo'
  option proto 'static'
  option ipaddr ''
  option netmask ''

config globals 'globals'
  option ula_prefix 'fd72:83ef:4007::/48'

config interface 'wan'
  option ifname eth0
  option proto dhcp

config interface 'lan1'
  option type 'bridge'
  option ifname 'eth1'
  option proto 'static'
  option ipaddr ''
  option netmask ''
  option ip6assign '60'

In this file, I have configured my ‘wan’ interface, which is on the same network as my host machine, to use DHCP and be assigned an IP Address from my router. My ‘lan1’ interface is using my internal VM Switch, giving it access to my VMs using the same VM Switch. I will be assigning it a static IP, along with the other network configuration.

Once you have your network settings just right, restart the network deamon.

# Restart the network deamon
/etc/init.d/network restart

# check the interface settings
ifconfig -a

Step 10: OPTIONAL: Setup https on management GUI (LUCI)

This will create a self-signed certificate to use on the web UI, so you can use a secure connection (https).

# Install Luci SSL
opkg install luci-ssl-openssl

# restart uhttp daemon to generate self-sigend cert for the website
/etc/init.d/uhttpd restart

Now you can access the LUCI (web UI) over https in your browser. ‘’ for my example.

Thanks for reading

PS> exit