I’ve been looking a way to run windows container on top of docker for sometimes and finally decided to run it along with virtual machine i.e virtualbox because the solution suit my use case. This is a bit of documentation in case others looking for similar solution.
I do realize that Microsoft release Windows Server 2016 as container that is available at docker hub, unfortunately that is not suitable to my use case at the moment. I’d like to have a complete Windows OS running i.e Microsoft Windows XP ala Virtual Machine but managed by cluster of containers. The main reason because I need to integrate it into cluster of containers that are running various other services.
I tested container from blacklabelops but it turns out the image built for Centos7 while my lab machine running Ubuntu. The running virtualbox container need to be mapped with host’s
/dev/vboxdrv, and according to provided documentation the container must be using same kernel as host machine. Since image from blacklabelops using different base OS I had to build the image from scratch.
It is very easy. In my case, just pull Ubuntu Xenial (16.04) from their official repository, and install VirtualBox.
$ docker pull ubuntu:16.04
$ docker run --rm -it --privileged=true ubuntu:16.04 bash
root@751c9e705b89:/# apt update && apt -y upgrade
root@751c9e705b89:/# apt install -y virtualbox
Make sure you can run VBoxManage after installation process finised.
root@751c9e705b89:/# VBoxManageOracle VM VirtualBox Command Line Management Interface Version 5.0.40_Ubuntu(C) 2005-2017 Oracle CorporationAll rights reserved.Usage:VBoxManage [<general option>] <command>General Options:[-v|--version] print version number and exit[-q|--nologo] suppress the logo[--settingspw <pw>] provide the settings password[--settingspwfile <file>] provide a file containing the settings passwordCommands:......
Once verified, commit the running container.
$ docker commit 751c9e705b89 curphoo/ubuntu:16.04_vbox
Build Windows Image
As written on blacklabelops documentation, the running virtualbox container must have these requirements:
- Mounts the hosts binaries
- Must used privileged mode
- Must mount host device
In order to satisfy above requirement, the host machine need to install VirtuaBox as well. If requirement has been set, it is time to run the container.
$ docker run --rm -it --privileged=true --device /dev/vboxdrv:/dev/vboxdrv -p 3389:3389 --name winxp32 curphoo/ubuntu:16.04_vbox bash
Why mapping port 3389? Because in order to install windows we need graphical interface. Graphical interface will be provided by VirtualBox running on ubuntu container through VRDE service opened on port 3389. We can connect to that port later using VNC Viewer to start GUI session. In order to use the service we shall map the opened port to host’s port hence we’ll connect to VRDE using host IP later on.
Once logged into ubuntu container it is time to setup virtual machine using virtualbox tools: VBoxManage.
Note: The setup of virtual machine such as disk controller based on my baremetal server. You must modify accordingly to what options available on your own server. Note also that below step assuming you already copied windows installer .ISO to running ubuntu container. In this case, I used Microsoft Windows XP SP3.
root@a89342c53815:/# mkdir -p /vbox/vmsroot@a89342c53815:/# mkdir -p /vbox/vdisksroot@a89342c53815:/# mkdir -p /vbox/isoroot@a89342c53815:/# VBoxManage createvm --name winxp32 --register --basefolder /vbox/vms/root@a89342c53815:/# VBoxManage createhd --filename /vbox/vdisks/winxp32.vdi --size 10240 --variant Standardroot@a89342c53815:/# VBoxManage storagectl winxp32 --name "IDE Controller" --add ide --controller PIIX4 --bootable onroot@a89342c53815:/# VBoxManage storageattach winxp32 --storagectl "IDE Controller" --type dvddrive --port 1 --device 0 --medium emptydriveroot@a89342c53815:/# VBoxManage storageattach winxp32 --storagectl "IDE Controller" --type hdd --port 0 --device 0 --medium /vbox/vdisks/winxp32.vdiroot@a89342c53815:/# VBoxManage modifyvm winxp32 --dvd /vbox/iso/winxp.isoroot@a89342c53815:/# VBoxManage modifyvm winxp32 --boot1 dvdroot@a89342c53815:/# VBoxManage modifyvm winxp32 --boot2 diskroot@a89342c53815:/# VBoxManage modifyvm winxp32 --memory 1024root@a89342c53815:/# VBoxManage modifyvm winxp32 --nic1 natroot@a89342c53815:/# VBoxManage modifyvm winxp32 --cableconnected1 onroot@a89342c53815:/# VBoxManage modifyvm winxp32 --nicpromisc1 allow-allroot@a89342c53815:/# VBoxManage modifyvm winxp32 --natpf1 "smb139,tcp,,139,10.0.2.15,139"root@a89342c53815:/# VBoxManage modifyvm winxp32 --natpf1 "smb445,tcp,,445,10.0.2.15,445"root@a89342c53815:/# VBoxManage modifyvm winxp32 --natpf1 "lport4444,tcp,,4444,10.0.2.15,4444"
Since the Windows container is going to be part of penetration testing labs, I need to setup NAT rules accordingly. This is the method I used to let Windows container reachable from the rest of clusters:
- Setup VM using NAT networking mode
- Setup NAT rules to let port forwarding between VirtualBox host and VM
VirtualBox host in this case is a docker container so any traffic reaching particular docker container’s port will be routed inside NAT towards Windows VM. You can use VBoxManage to determine the assigned NAT IP address of WIndows VM if you’d like, here in my case the internal NAT IP for Windows VM is 10.0.2.15.
By using above methods I can get full benefit of integrating Windows with rest of containers in the cluster.
For example: I can have a cluster where container distributed across several host located in different datacenter able to communicate with windows container through VXLAN. One of feasible scenario that is being deployed currently to let windows container running on specific baremetal, and being integrated with webservices running on public cloud.
Once setup finished, run the virtual machine.
$ VBoxHeadless -v on -startvm winxp32
Oracle VM VirtualBox Headless Interface 5.0.40_Ubuntu(C) 2008-2017 Oracle CorporationAll rights reserved.05/12/2017 00:51:10 Listening for VNC connections on TCP port 338905/12/2017 00:51:10 Listening for VNC connections on TCP6 port 5900VRDE server is listening on port 3389.
As you can see, once virtualbox running it will open TCP port 3389. Now, we can connect to host’s IP port 3389 through VNC viewer and start with normal windows installation.
After finished with installation process, we can add any other configuration or add additional software i.e as Fuzzing target to start looking for vulnerability.
Once all required setup for VM itself finish, we can safely stopped the VM and commit the container to build it as container image. If you’d like, since it is running on top of VirtualBox we can take snapshot as well to keep some state of VM itself.
$ docker commit d07997b0afe3 curphoo/lab:winxp32_sp3
Running The Container
Now, the fun part. Run the container, make it available to the rest of cluster, and start hacking :)
$ docker run --rm -it --privileged=true --device /dev/vboxdrv:/dev/vboxdrv --name winxp32_sp3 curphoo/lab:winxp32_sp3 VBoxHeadless -v on -startvm winxp32
As said earlier, there are lot of benefits running Windows on docker. We can scale-up the lab to 10s or 100s or 1000s with one command by utilizing cluster facility such as docker swarm or kubernetes in order to simulate penetration testing, we can recreate the container any time to start looking for any vulnerabilities, or we can integrate with any other tools / services we have to analyze windows behaviour.
On above sample, I use metasploit framework running on kali linux container to hack into windows container for testing purpose.
I am still not quite sure about license related of using Microsoft Windows OS on top of containers (even though Microsoft has stopped support for XP), so this write-up was for information and educational purpose only, or personal use.
The main goal is to setup docker + virtualbox + windows and how we can take benefit out of it especially with the raise of containers.