Supporting IPv4 and IPv6 dual mode network with one socket

IP version 6 has not become the de facto standard yet, even though we are close to have exhausted all IPv4 addresses. I set out to learn more about IPv6 and how to support both protocols when building a network solution. It was fueled by lack of understanding and some issues I ran into when using DotNetty to build a protocol translation gateway. I ran into error messages like:

System.Net.Sockets.SocketException: An address incompatible with the requested protocol was used. Error Code: 10047

Which means that I have specified one type of protocol but are using another. So why not figure out how to create an IPv4 and IPv6 agnostic solution? Which I did.

Initially the problem I ran into was caused by the Dns.GetHostAddressesAsync method, as it resolves a DNS name to possible multiple IP addresses (e.g. IPv4 and IPv6), but which one should the system choose? With this protocol agnostic solution, it doesn’t matter.

As the BCL (Base Class Library) is not designed to support more than one protocol at the time, it looks at bit clunky when IPv4 addresses are imitating IPv6 adresses, but it works. IPv4 will appear like ::ffff:, so you will have to use properties and methods like IsIPv4MappedToIPv6 and MapToIPv4.

First you need to specify IPv6 as the protocol via AddressFamily.InterNetworkV6 and then set DualMode to true, which in effect sets SocketOptionName.IPv6Only to false.

// TCP Server
var listener = new TcpListener(new IPEndPoint(IPAddress.IPv6Any, 8080));
listener.Server.DualMode = true;
// TCP Client
var client = new TcpClient(AddressFamily.InterNetworkV6);
client.Client.DualMode = true;
await client.ConnectAsync("", port: 8080);
// UDP Server
var listener = new UdpClient(AddressFamily.InterNetworkV6);
listener.Client.DualMode = true;
listener.Client.Bind(new IPEndPoint(IPAddress.IPv6Any, 8080));
// UDP Client
var client = new UdpClient(AddressFamily.InterNetworkV6);
client.Client.DualMode = true;
client.Connect("", port : 8080);

For simplicity I used TcpListener, TcpClient and UdbClient event for the UDP server. I set the DualMode property on the underlying Socket via the client.Client property. The server will open a dual Socket and the client will open either an IPv4 or IPv6 depending on the address given.

Full code samples for both TCP and UDP can be found at my DotNetCore-DualNetwork-IPv4IPv6 GitHub repo.

During my investigations, I discovered that depending on the Socket class constructor used, the DualMode property was set to true or false. The Socket(SocketType, ProtocolType) constructor defaulted the DualMode to true, but all others to false. None of the TcpListener, TcpClient or UdbClient instanciates a Socket with DualModel true.

Security nightmare – It is time to update all your device

What a week – security wise. Many vulnerabilities have been uncovered. You are most likely affected by one or more of these. Read on and start updating all your devices.

Wi-Fi WPA2 vulnerability

Years ago, we all moved our Wi-Fi to WPA security protocol as WEP was deemed unsecure. Now vulnerability is found in WPA1/2 too, making it possible for malicious attackers to inspect and modify the tracking between computer and access point.

The vulnerability is known as KRACK (Key Reinstallation Attacks) and are in the Wi-Fi standard, so all devices are affected – laptops, access points, printers, phones… anything with Wi-Fi. The vulnerability is at client side, but many access points acts are repeaters etc., so do patch all Wi-Fi devices, otherwise the communication might be compromised.

Bleeping Computers are keeping a list of affected devices and firmware and driver updates to mitigate the problem.

Microsoft fixed the issue on October 10th and rolled out the update on Patch Tuesday, so if you are keeping your device up-to-date, then you are all safe. Apple has not yet released a patch.

Read more about KRACK.

RSA key generation vulnerability

It does not sound intimidating, but this is a major vulnerability affecting Google Chromebooks, HP, Lenovo and Fujitsu PCs and laptops, SmartCards, routers, IoT devices – all devices that has a hardware secure chip (like TPM) from Infineon Technologies produced since 2012.

RSA keys are used to securely store secrets such as passwords, encrypt data (e.g. BitLocker) and generate certificate keys used in secure communication and sender/receiver attestation. It also affects digital ID’s such as those used by the Estonian government, based on SmartCard technology.

The RSA generated prime numbers are not truly random, making it possible to crack the private key via the public key. Depending on the size of the RSA key, they estimate it takes:

  • 512-bit RSA keys – 2 CPU hours (the cost of $0.06)
  • 1024-bit RSA keys – 97 CPU days (the cost of $40-$80)
  • 2048-bit RSA keys – 140.8 CPU years, (the cost of $20,000 – $40,000)

Based on an Intel E5-2650 v3@3GHz Q2/2014. 97 CPU days are nothing, as the crack can run in parallel and compute resources have become cheap with all the Cloud offerings.

To mitigate the ROCA security vulnerability requires firmware upgrades of the hardware secure chip. Microsoft (Windows 7+) and Google and others has released patches.

Read more about the ROCA CVE-2017-15361 vulnerability.

Securing my devices

It is time to update all my devices, but it is going to take time.

This is the list of devices I need to update: 5 Laptops, 1 Chromebook, 1 Xbox One, 1 Windows tablet, 2 iPads, 2 iPhones, 1 Android, 1 Windows Phone, 1 Ubiquity Access Point, 1 Sagemcom router (Owned by the ISP), 1 Amazon Echo, 1 Samsung TV, 1 Panasonic TV and countless IoT devices

Who am I kidding. Some of my devices are old (like my TVs), so the manufacturer will properly never release a patch.

Like it is not worrisome enough, then a privilege-escalation vulnerability in Linux kernel was also discovered. This means even more stuff to update.


Installing Windows with Secure Boot from USB drive

Once and a while I reinstall my machine. It feels nice with a clean slate as I tend to install all kinds of applications that pollutes my machine. A newly installed machine just runs better somehow.

My machine needs to be secure, so Secure Boot and encrypted drive via BitLocker is a must. It limits the risk of someone messing with my machine and stealing my data.

Here is how to create a bootable USB that works with Secure Boot enabled:

  1. Download 64-bit Windows ISO file and download Rufus, a portable utility to create bootable USB drives.
  2. Connect a 4+ GB USB drive. The data on the drive will be deleted, so make sure to backup the content.
  3. Run Rufus and accept the UAC prompt to launch the tool.
  4. Select the USB drive that you want to make bootable, select GTP partition scheme for UEFI, FAT32 and select the Windows ISO image.

Do remember to enable Secure Boot in the BIOS settings and set it in setup mode/clear the keys.

GTP (GUID Partition Table) is a replacement form MBR partitioning allowing for larger disk sizes which requires a 64-bit OS. Read more.

Composing your own Windows Container with a Dockerfile

In the previous blog post Getting Started with Windows Containers I showed how to run containers and pull existing containers from the public repository Docker Hub. Now it is time to create a new image and add it to Docker Hub.

I wanted to create a Hello World image that works on Windows Containers. I chose to create the Hello-World program using .NET Core – it runs cross platform (Linux, Mac & Windows), but I’m using Windows.

On the Windows Server 2016 container host I created in the previous blog post, I needed to install .NET Core. You can either go to to download or execute the following PowerShell to download the installer.

Invoke-WebRequest -OutFile c:\dotnetinstall.exe

I created a folder called HelloWorld and executed the following commands in a command prompt:

PS C:\Users\aly\Desktop\HelloWorld> dotnet new
Created new C# project in C:\Users\aly\Desktop\HelloWorld.
PS C:\Users\aly\Desktop\HelloWorld> dotnet restore
log : Restoring packages for C:\Users\aly\Desktop\HelloWorld\project.json...
log : Writing lock file to disk. Path: C:\Users\aly\Desktop\HelloWorld\project.lock.json
log : C:\Users\aly\Desktop\HelloWorld\project.json
log : Restore completed in 1049ms.
PS C:\Users\aly\Desktop\HelloWorld> dotnet run
Project HelloWorld (.NETCoreApp,Version=v1.0) will be compiled because expected outputs are missing
Compiling HelloWorld for .NETCoreApp,Version=v1.0

Compilation succeeded.
0 Warning(s)
0 Error(s)

Time elapsed 00:00:01.8161040

Hello World!
PS C:\Users\aly\Desktop\HelloWorld> dotnet publish
Publishing HelloWorld for .NETCoreApp,Version=v1.0
Project HelloWorld (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
publish: Published to C:\Users\aly\Desktop\HelloWorld\bin\Debug\netcoreapp1.0\publish
Published 1/1 projects successfully
PS C:\Users\aly\Desktop\HelloWorld>

You can use any executable, I just needed something simple to work with. .NET Core is my simple choice.
I am going to base my image on the microsoft/windowsservercore image. But instead of installing .NET Core myself, I can use an image that already has .NET Core installed called microsoft/dotnet:windowsservercore. See all the official Microsoft Docker images at the Microsoft Docker Hub repository. So pull down the microsoft/dotnet:windowsservercore image

docker pull microsoft/dotnet:windowsservercore

If you want to play with it run the following command to start a container and a command prompt will appear. Type exit when you want to go back to the container host.

docker run -it microsoft/dotnet:windowsservercore

Now let’s create the Hello World image. Create a file called Dockerfile without extension outside the /HelloWorld folder and add this:

FROM microsoft/dotnet:windowsservercore
MAINTAINER Anders Lybecker (@Lybecker)
ADD /helloworld/bin/Debug/netcoreapp1.0/publish/ c:\\code
ENTRYPOINT dotnet c:\\code\\helloworld.dll

Line 1 dictates that I’m basing the Hello World image on the official image microsoft/dotnet:windowsservercore
Line 2 is just maintainer information and is optional
Line 3 adds the content of the publish folder of the container host to the image in c:\code
Line 4 sets the default command to execute the Hello World program

For more details see the Dockerfile reference.

Build the container by executing the docker build command. The image is named myhelloword and tagged with v1 for version 1. The last . specifies where the Dockerfile is located.

PS C:\Users\aly\Desktop> docker build -t myhelloworld:v1 .
Sending build context to Docker daemon 341.5 kB
Step 1 : FROM microsoft/dotnet:windowsservercore
---> 1e21a0790e96
Step 2 : MAINTAINER Anders Lybecker (@Lybecker)
---> Running in 6812a0ecf67d
---> 5dce994e32a4
Removing intermediate container 6812a0ecf67d
Step 3 : ADD /helloworld/bin/Debug/netcoreapp1.0/publish/ c:\\code
---> 22fade758f23
Removing intermediate container 665f9e677611
Step 4 : ENTRYPOINT dotnet c:\\code\\helloworld.dll
---> Running in dad461888c4c
---> 204ed6ed0b59
Removing intermediate container dad461888c4c
Successfully built 204ed6ed0b59

That’s it. You have now created your own image. Let’s try to run it

PS C:\Users\aly\Desktop> docker run myhelloworld:v1
Hello World!

You can see the image in the local image repository with the docker images command.

PS C:\Users\aly\Desktop> docker images
REPOSITORY                  TAG               IMAGE ID     CREATED        SIZE
myhelloworld                v1                204ed6ed0b59 10 minutes ago 8.111 GB
microsoft/dotnet            windowsservercore 1e21a0790e96 2 weeks ago    8.111 GB
microsoft/windowsservercore 10.0.14300.1030   02cb7f65d61b 10 weeks ago   7.764 GB
microsoft/windowsservercore latest            02cb7f65d61b 10 weeks ago   7.764 GB

The myhelloworld:v1 image is based on the microsoft/dotnet:windowsservercore which is based om microsoft/windowsservercore:10.0.14300.1030. You can see all the layers via the docker history command

PS C:\Users\aly\Desktop> docker history myhelloworld:v1
204ed6ed0b59 12 minutes ago cmd /S /C #(nop) ENTRYPOINT ["cmd" "/S" "/C" 46.58 kB
22fade758f23 12 minutes ago cmd /S /C #(nop) ADD dir:4bef0fa9bcfacdaa9bb8 40.96 kB
5dce994e32a4 12 minutes ago cmd /S /C #(nop) MAINTAINER Anders Lybecker 181.2 MB
1e21a0790e96 2 weeks ago cmd /S /C mkdir warmup && cd warmup & 40.96 kB
2 weeks ago cmd /S /C #(nop) ENV NUGET_XMLDOC_MODE=skip 4.756 MB
2 weeks ago cmd /S /C setx /M PATH "%PATH%;%ProgramFiles% 160.7 MB
2 weeks ago cmd /S /C powershell -NoProfile -Command 40.96 kB
2 weeks ago cmd /S /C #(nop) ENV DOTNET_SDK_DOWNLOAD_URL 40.96 kB
2 weeks ago cmd /S /C #(nop) ENV DOTNET_SDK_VERSION=1.0. 7.764 GB

I have made my Hello World image available on Docker Hub, so you can pull and run the image on your Windows Container host like so:

PS C:\Users\aly\Desktop> docker pull anderslybecker/dotnet-hello-world:windowsservercore
windowsservercore: Pulling from anderslybecker/dotnet-hello-world
Digest: sha256:1df17a8a38d969b71b38333be25f76757e69f1537c7a86a6ee966bca87163464
Status: Image is up to date for anderslybecker/dotnet-hello-world:windowsservercore
PS C:\Users\aly\Desktop> docker run anderslybecker/dotnet-hello-world:windowsservercore
Hello World!

Getting started with Windows Containers

Soon Windows Server 2016 will be released and so will the Docker Engine compatible Windows Containers feature. Here is a tutorial for you to get started with Windows Containers.

One thing to be aware of when working with containers is that the underlying host must be of the same type of operating system as the container running on the host. Linux containers on Linux hosts and Windows containers on Windows hosts.

First a container host is needed – you can use Windows 10 Anniversary Update or a Windows Server 2016.

The easiest way of getting started is to spin up a Windows Server 2016 on Azure (get a free trial) with the Container feature enabled.

  1. Select new
  2. Type “container” to filter only for container images
  3. Select the “Windows Server 2016 with Containers” equivalent (as of writing Tech Preview 5)CreateWindowsServer2016Container
  4. Follow the wizard to specify VM size etc.

Alternatively, you can follow Windows Containers on Windows Server guide to install the Container feature on an existing Windows Server 2016.

Once you have created the host you can connect to the host via RDP (in the Azure portal use the ”Connect” button in the top menu).

Start up a command prompt or the PowerShell. You can use PowerShell for Docker or the Docker CLI to execute Docker commands. The commands are the same across platform – no matter if you are using Linux or Windows-based containers. I’ll be using the Docker CLI commands. The common commands are:

  • Docker info – which will show you version etc.
  • Docker images – shows all the images in the local repository
  • Docker ps – show all the running containers
  • Docker ps -a – the -a (or -all) shows all containers including containers that are no longer running
  • Docker run – run an instance of an image

Let’s get started.

Run the following command to see which images are available in the local repository.

PS C:\Users\aly\Desktop> docker images
REPOSITORY                  TAG             IMAGE ID     CREATED      SIZE
microsoft/windowsservercore 10.0.14300.1030 02cb7f65d61b 10 weeks ago 7.764 GB
microsoft/windowsservercore latest          02cb7f65d61b 10 weeks ago 7.764 GB
PS C:\Users\aly\Desktop>

On my Windows Server 2016 Tech Preview 5 there are two images both with the name microsoft/windowsservercore with two different tags. Both of them has the same image id, so they are the same image with two different tags.

To start a container of the image tagged with ‘latest’ run the following:

PS C:\Users\aly\Desktop> docker run microsoft/windowsservercore:latest
Microsoft Windows [Version 10.0.14300]
(c) 2016 Microsoft Corporation. All rights reserved.

PS C:\Users\aly\Desktop>

The tag is optional, but the default value is ‘latest’.

The container was started and a command prompt appeared, but then it shut down again and it returned to my PowerShell prompt.

If you want to interact with the container, add the -it (interactive) option. You also have the option of specifying which process should be run in the container (cmd is default for this image):

docker run -it microsoft/windowsservercore:latest cmd

Now a command prompt appears and you are in the context of the container. If you modify a file e.g. adds or deletes a file, then the changes will only apply to the container and not the host.

Create a simple file like this:

echo "Hello Windows Containers" > hello.txt

You can exit the container by typing exit, and the container will terminate. Alternatively, you can press CTRL + P + Q to exit and leave the container running.
If you left the container running, you can see the container by listing the Docker processes:

PS C:\Users\aly\Desktop> docker ps
CONTAINER ID IMAGE                             COMMAND   CREATED       STATUS    PORTS NAMES
23ca16bb6fdb microsoft/windowsservercore:latest "cmd" 4 minutes ago Up 4 minutes pedantic_lamport

If the container was terminated, the -a option needs to be appended.
You can reattach to the container by specifying the container id or name. In my case 23ca16bb6fdb or pedantic_lamport like so:

Docker attach 23ca16bb6fdb

You only have the Windows Server Core image in the local repository, but you can download others by pulling from Docker Hub.

docker pull microsoft/nanoserver

Remember that only Windows-based images will run on a Windows host, so if you try the Hello-World Linux-based image, it will fail with a not so elaborate error message.

PS C:\Users\aly\Desktop> docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
c04b14da8d14: Extracting [==================================================>] 974 B/974 B
failed to register layer: re-exec error: exit status 1: output: ProcessBaseLayer C:\ProgramData\docker\winc266a137b0b1fffedf91d8cd6fcb6560f12afe5277e44bca8cb34ec530286: The system cannot find the path specified.

For now it is not easy to differentiate between Linux or Windows-based images on Docker Hub. I would have wished for a filter, making it easier to find relevant images.

Microsoft has a public repository of all the official released Microsoft container images.