Skip to main content

Secure nested LCOW: Part 2

What's in Part 2?

After the configuration of the Host VM hypervisor (part 1), we will get the following components configured:
  1. Windows 2016 with nested Hyper-V, Containers and WSL roles
  2. Docker daemon installed (no SSL)
  3. Docker daemon configured with SSL

Setup: Windows 2016 Server

this one will be longer, even if I will only list the commands and reference the guides I followed to have my Docker host configured inside the Hyper-V VM. Which means it will not contain any output and, more importantly, I won't put the explanations that the guides provide.
I strongly recommend that you click on the "source" links and look at their great content.

Also, I won't explain how to install the OS, just note that you should choose the Windows 2016 Server 1709 version (I picked the Standard version).

Adding the roles

  • Add Hyper-V and the Containers roles
PS> Enable-WindowsOptionalFeature -Online -FeatureName containers -All -NoRestart

PS> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All -NoRestart
  • Add WSL role with Ubuntu as default distribution (source)
PS> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

PS> Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1604 -OutFile ~/Ubuntu.zip -UseBasicParsing

PS> mkdir c:\distros

PS> Expand-Archive ~/Ubuntu.zip c:\distros\Ubuntu

PS> [System.Environment]::SetEnvironmentVariable("Path", $env:Path + ";c:\distros\ubuntu", [System.EnvironmentVariableTarget]::Machine)

Docker daemon install

PS> Invoke-WebRequest -OutFile "$env:TEMP\linuxkit-lcow.zip" "https://23-111085629-gh.circle-artifacts.com/0/release.zip"

PS> Expand-Archive -Path "$env:TEMP\linuxkit-lcow.zip" -DestinationPath "$env:ProgramFiles\Linux Containers" -Force

PS> Invoke-WebRequest -OutFile "$env:TEMP\docker-master.zip" "https://master.dockerproject.com/windows/x86_64/docker.zip"

PS> Expand-Archive -Path "$env:TEMP\docker-master.zip" -DestinationPath $env:ProgramFiles -Force

PS> . $env:ProgramFiles\docker\dockerd.exe --register-service --experimental
  • You can reboot the VM now.

Securing the Docker daemon

  • After the reboot, now comes the fun part, enter a WSL session and generate the SSL certificates for the Docker TLS connection (source)
PS> ubuntu.exe

bash:~$ cd /mnt/c/Program\ Files/docker && mkdir certs && cd certs

bash:certs$ export HOST=`hostname`

bash:certs$ export NAT_IP=`hostname -I | cut -f1 -d' '`

bash:certs$ openssl genrsa -aes256 -out ca-key.pem 4096

bash:certs$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem

bash:certs$ openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr

bash:certs$ echo subjectAltName = DNS:$HOST,IP:$NAT_IP,IP:127.0.0.1 >> extfile.cnf

bash:certs$ echo extendedKeyUsage = serverAuth >> extfile.cnf

bash:certs$ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf

bash:certs$ chmod -v 0400 ca-key.pem server-key.pem

bash:certs$ chmod -v 0444 ca.pem server-cert.pem
  • Continuing in WSL (because we can and love VI), create the Docker config file
bash:certs$ cd /mnt/c/ProgramData/docker/config/ && vi daemon.json
{
        "hosts": ["tcp://0.0.0.0:2376","npipe://"],
        "tlsverify": true,
        "tlscacert": "c:\\Program Files\\docker\\certs\\ca.pem",
        "tlscert": "c:\\Program Files\\docker\\certs\\server-cert.pem",
        "tlskey": "c:\\Program Files\\docker\\certs\\server-key.pem"
}
:wq!
  • Finally, exit WSL shell to Powershell again and restart the Docker service
bash:config$ exit

PS> Restart-Service docker

PS> Get-Service docker
  • Your install should look something like this


Your Docker daemon is now ready to accept TLS connections and, thanks to the "npipe://" connection, you can also already use it on your Server.

I know this part was the "heavy" one and if you are reading these lines, then I truly thank you and please contact me on Twitter (@nunixtech) for any remark on this guide or even better, if you spot a typo or something really wrong (hopefull not, right).

This is the end of the Part 2. I will publish the part 3, Client configuration, in the next coming days.


>>> Nunix Out <<<

Comments

Popular posts from this blog

WSL: One Home to host them all

Introduction This blog post will explain how a single home mount can be shared accross all  the WSL instances. It was quite fun to find the idea and then make it happen. It will use all the tools currently available from WSL, so please don't expect a "Linux only" as Interopability will be heavily used. And before I start, here is my point of view about WSL: It's not only  Linux! It's different, just like GNU is different from Unix (yes I said it). We have finally the strength of both worlds combined. And while I do understand the "dev" aspect is meant to be reproducible in a Linux prod environment, the "ops" side is meant to take advantages of everything that can make the full environment feeling Home. Setup requirements In order to really enjoy this solution, I do recommend having 2 or more WSL distros installed or, if you fell like a real WSLCorsair, try @bketelsen crazy setup (I love it)! While the distros are downlo

Docker + WSL: Get 2 daemon for the price of 1

Introduction almost two years ago, Docker announced the capability of switching between the Linux and Windows containers "mode" (far from the right click that we have today). At that time, I wrote a blog post on how to run both daemons at the same time ( http://darthnunix.blogspot.ch/2016/10/docker-for-windows-2-daemons-enter-in.html ) Fast forward to 2018, and while we were blogging on how to get the TLS connection from WSL docker client with  Rory McCune  ( https://raesene.github.io/blog/2018/03/29/WSL-And-Docker/ ), another blog post, by Stefan Stranger drew my attention (read: blew my mind) as I was trying to reproduce the same: how could I "bind" the docker socket in WSL with the Docker for Windows Linux mode socket ( https://blogs.technet.microsoft.com/stefan_stranger/2018/04/02/access-my-docker-for-windows-kubernetes-cluster-from-debian-wsl/ ) From 1 to 2 daemon: DemonHunter mode achieved Now that we have all the required setup resources, let's b

Secure nested LCOW: Part 3

Part 3: Getting all together After the configuration of the Docker daemon on the Nested Hyper-V VM ( part 2 ), it's now finally time to configure the Docker client that will connect to it. Once again, I will be using WSL as the main shell. However, if you choose to go with Powershell, it's OK too (simply I won't explain it here :). Setup: Window 10 Docker Client first of all, the docker client needs to be installed in the WSL environment. And this will be as easy as one command line, thanks to the Docker install script: client:~$ curl -sSL https://get.docker.com/ | sudo sh As the end of the log suggests, add your user to the docker group. This will require you to logoff in order to apply the change. You can either close the WSL console window and open a new one (logoff / login), or a small trick is to "login again" using the "su" command: client:~$ sudo usermod -aG docker $LOGNAME client:~$ sudo su - $LOGNAME Generate Docker client