Privacy Implications of Windows 10 Telemetry, Part 1: Setting Up the Network

Windows 10 will run in the virtual machine powered by bhyve hypervisor, under FreeBSD 11.0 operating system. It will have access to the internet via virtual local network, and all its traffic will be recorded for further analysis. This virtual network will consist of two hosts: DHCP server/router and Windows 10 virtual machine.

In this part of the guide, we will configure network interfaces, firewall, routing, NAT, DHCP server, and also set up sshd and tmux for convenient remote access to our FreeBSD server.


Installing software

Besides bhyve hypervisor and tcpdump traffic recorder (which are components of the base OS), we will need dnsmasq DHCP server for IP address assignment, bash shell to run our scripts and nano text editor (but if you are confortable with vi, last one may be skipped):

# pkg install dnsmasq
# pkg install bash
# chsh -s /usr/local/bin/bash root
# pkg install nano

Also, for convenience, we will set up remote access to our FreeBSD server via sshd service (which is a part of base OS) and tmux terminal multiplexer.

# pkg install tmux


Network topology

Virtual local network tap0 (whose traffic will be recorded) consists of just two hosts:

  • DHCP server/router
  • 172.21.97.x (2 ≤ x ≤ 254): Windows 10 virtual machine

In this guide, server physical network interface is igb0 and IP address is If your server has different network card or IP address, then make appropriate adjustments in the text below. Network configuration is displayed using ipconfig command.


Setting up network address translation

In order to connect virtual network with Windows 10 to the internet, we will need to enable Network Address Translation (NAT) between Windows 10 virtual network and real physical network which this server is connected to. FreeBSD offers multiple NAT implementations, but we prefer ipfw_nat (a module of ipfw firewall), because of speed and simplicity.

First of all, let’s create /etc/firewall.rules with following contents:

nat 100 config ip log
add 1000 check-state
add 2000 nat 100 ip from{2-254} to any
add 3000 nat 100 ip from any to via igb0
add 60000 allow all from any to any

Then we need to enable firewall and its rules in FreeBSD configuration. Add the following lines to /etc/rc.conf:


Then we need to instruct FreeBSD loader to load NAT ipfw_nat firewall kernel module on each reboot. The following line should be added to /boot/loader.conf:


Also, routing must be enabled in /etc/rc.conf:


Also, NAT requires multi-pass firewall. Add this to /etc/sysctl.conf:


Then, either reboot the server or execute the following shell script:

export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
kldload ipfw
kldload ipfw_nat
sysctl net.inet.ip.forwarding=1
sysctl net.inet.ip.fw.one_pass=0
ipfw -f flush
ipfw nat 100 config ip log
ipfw add 1000 check-state
ipfw add 2000 nat 100 ip from{2-254} to any
ipfw add 3000 nat 100 ip from any to via igb0
ipfw add 60000 allow all from any to any


Preparing virtual network card for Windows 10

Windows 10 VM will have its own dedicated virtual network card tap0, and tcpdump will record all network traffic flowing through tap0.

To create tap0, add the following lines to /etc/rc.conf:

ifconfig_tap0="ether 00:bd:7c:e8:49:dc up"

And the following lines to /boot/loader.conf:


MAC address should be chosen as random, but constant vector of bytes (otherwise, after each reboot of FreeBSD server, Windows 10 in VM will think it was moved and connected to a different network). The first two bytes of MAC address should remain equal to 00:bd to avoid collision with physical network cards.

To enable tap0 without rebooting the server, enter the following shell commands:

# ifconfig tap0 create
# ifconfig tap0 ether 00:bd:7c:e8:49:dc up


Configuring DHCP server (dnsmasq)

dnsmasq configuration is stored in /usr/local/etc/dnsmasq.conf file. Let’s start from default configuration and change a few details:

cp /usr/local/etc/dnsmasq.conf.sample /usr/local/etc/dnsmasq.conf
nano /usr/local/etc/dnsmasq.conf

Enable domain-needed, bind-interfaces and local-service options. Set listen-address= and dhcp-range=,

That’s all. There’s no need to enable dnsmasq in rc.conf, because it will be started via virtual machine control script, in concordance with bhyve and tcpdump.


Enabling remote access to the server via SSHd

Make sure /etc/rc.conf contains the following line:


and /etc/ssh/sshd_config should contain the following line:

PermitRootLogin yes

In this configuration, it is essential for root user to have long random password (12-16 characters over large alphabet, distributed uniformly). Change root password using passwd command if necessary. sshd server can be restarted using the following command:

# /etc/rc.d/sshd restart

From this moment, we can connect to our FreeBSD server from other computers, e.g. from Windows using PuTTY software.

If further server security hardening is required, we may generate a pair of RSA keys using the following command:

# cd ~
# ssh-keygen -t rsa -b 2048

Then ~/id_rsa (private key file) should be moved to the client (e.g. using WinSCP software and temporary password-based root access as explained above) and ~/ (public key file) should be renamed to ~/.ssh/authorized_keys. Additionally, the following changes in /etc/ssh/sshd_config are to be made:

Protocol 2
PermitRootLogin without-password
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
UsePAM no
RhostsRSAAuthentication no
HostbasedAuthentication no
IgnoreRhosts yes
IgnoreUserKnownHosts yes
PermitUserEnvironment no
UsePrivilegeSeparation sandbox


# /etc/rc.d/sshd restart
to restart SSH service.


Setting up terminal multiplexer tmux

tmux enables us to disconnect from our FreeBSD server at any time, and reconnect later as needed, without interrupting running processes, such as bhyve hypervisor.

tmux configuration file ~/tmux.conf should have the following content:

set -g status-fg white
set -g status-bg red
set -g prefix C-a
unbind C-b
bind C-a send-prefix
set -g base-index 1

To run tmux automatically for all SSH sessions, add the following lines to ~/.bash_profile:

if [ $TERM = "xterm" ]; then
 ( (tmux has-session -t remote && tmux attach-session -t remote) || \
   (tmux new-session -s remote) ) && exit 0
 echo "tmux failed to start"
if [ $TERM = "screen" ]; then
 cat /etc/motd
tmux key combinationeffect
Ctrl+A Ccreate a new window
Ctrl+A 1, Ctrl+A 2, …   activate window 1, 2, …
Ctrl+A Ddisconnect from server, leaving all processes running