YubiKey VM Redirection Guide

Published by banasiak on

This documentation provides the complete, step-by-step process for making a physical YubiKey (on a Windows Host) accessible to Firefox on an Ubuntu VM running on Hyper-V using the open-source USB/IP project.


Phase 0: Ubuntu VM Installation Prerequisite & Network Security

The VM must run a standard kernel and be securely isolated for the USB tunnel.

  1. Use Canonical’s ISO: Install the latest Ubuntu LTS release directly using the ISO file downloaded from Canonical.
  2. Avoid Quick Create: Do NOT use “Quick Create” in Hyper-V Manager. This often installs an Azure-optimized kernel which lacks the essential vhci-hcd driver required for USB/IP.
  3. VM Network Configuration: The VM must use a private virtual network for communication with the Windows host. Avoid using a physical (external or bridged) network connection for the USB/IP tunnel to prevent interception.

Phase 1: YubiKey Pre-Configuration on Windows

Configure the YubiKey to ensure its FIDO/CCID interfaces are ready and the default OTP function doesn’t interfere.

  1. Install YubiKey Manager: Download and install the official YubiKey Manager application on your local Windows machine.
  2. Insert YubiKey: Plug in your YubiKey.
  3. Delete Short Touch OTP: Go to ApplicationsOTP. Under Short Touch (Slot 1), select Delete.
  4. Enable All Interfaces: Go to Interfaces. Ensure OTP, FIDO, and CCID are all enabled for the USB interface.

Phase 2: Windows Host Setup (usbipd-win Server)

This machine hosts the YubiKey and shares it across the network.

  1. Install usbipd-win: Open PowerShell as an Administrator and install the modern USB/IP server.
PowerShell
winget install --interactive --exact dorssel.usbipd-win
  1. Bind the YubiKey: Run the following command to list devices. The YubiKey often appears as USB Input Device, Microsoft Usbccid Smartcard Reader (WUDF). Find its Bus ID (e.g., 9-1), and then bind it.
PowerShell
usbpid list
usbipd list usbipd bind --busid <YubiKey-Bus-ID>
  1. Configure Windows Firewall: The usbipd service should run automatically. Ensure the Windows Firewall is configured to allow traffic on port 3240 only for your VM’s private network and is blocked on Public and Domain networks to prevent external access to your USB devices. Run the following command to create the firewall rule:
PowerShell
New-NetFirewallRule -DisplayName "USBIP Daemon (3240)" -Direction Inbound -LocalPort 3240 -Protocol TCP -Action Allow -Profile Private

Phase 3: Ubuntu VM Setup (usbip Client)

This configures the VM to receive the virtual USB device.

  1. Install usbip Tools: Install the client utilities that match your running kernel.
Bash
sudo apt update sudo apt install linux-tools-generic
  1. Load Kernel Modules (Temporary): Load the required modules for the current session.
Bash
sudo modprobe usbip_core sudo modprobe vhci-hcd
  1. Enable Modules on Boot: Configure the modules to load automatically every time the VM starts by adding them to the /etc/modules file.
Bash
echo "usbip_core" | sudo tee -a /etc/modules
echo "vhci-hcd" | sudo tee -a /etc/modules
  1. Attach the YubiKey: Run the command to attach the remote YubiKey, making it appear as a local device.
Bash
sudo usbip attach --remote <Windows-IP-Address> --busid <YubiKey-Bus-ID>
  1. Verify USB Mounting: Run the lsusb command to confirm the YubiKey was successfully mounted.
Bash
lsusb 
# Look for an entry similar to: ID 1050:0407 Yubico.com Yubikey 4/5 OTP+U2F+CCID

Phase 4: Ubuntu Permissions and Services

This phase installs necessary software and fixes security permissions using PolicyKit.

  1. Install PCSC and FIDO Tools: Install tools for smart card access (CCID), FIDO/U2F access, and the YubiKey manager.
Bash
sudo apt install pcscd libpcsclite1 libu2f-udev ykcs11 yubikey-manager 
sudo udevadm control --reload-rules
  1. Configure PolicyKit Rules (Access Control): Create a rule file to grant your user explicit permission to access the PC/SC daemon and the smart card.
Bash
sudo nano /etc/polkit-1/rules.d/50-pcsc-access.rules
  • Paste the following code (replace richard with your actual username):
    JavaScript
    polkit.addRule(function(action, subject) {
      if (action.id == "org.debian.pcsc-lite.access_pcsc" && subject.user == "richard") { 
        return polkit.Result.YES; 
      } 
    }); 
    
    polkit.addRule(function(action, subject) { 
      if (action.id == "org.debian.pcsc-lite.access_card" && subject.user == "richard") { 
        return polkit.Result.YES; 
      } 
    });
    1. Finalize Permissions: Set file permissions and restart the service.
    Bash
    sudo chmod 644 /etc/polkit-1/rules.d/50-pcsc-access.rules 
    sudo systemctl restart pcscd.service
    1. Crucially, log out of the RDP session and log back in to ensure all user permissions are updated.

    Phase 5: Firefox Installation and Configuration

    The Firefox Snap package must be replaced with the .deb package to ensure proper integration with system services like pcscd.

    1. Uninstall Firefox Snap: Close all Firefox windows, then remove the Snap package.
    Bash
    sudo snap remove --purge firefox
    1. Install Firefox Deb: Add the official Mozilla APT repository to get the system package.
    Bash
    sudo install -d -m 0755 /etc/apt/keyrings 
    wget -q <https://packages.mozilla.org/apt/repo-signing-key.gpg> -O- | sudo tee /etc/apt/keyrings/packages.mozilla.org.asc > /dev/null 
    echo "deb [signed-by=/etc/apt/keyrings/packages.mozilla.org.asc] <https://packages.mozilla.org/apt> mozilla main" | sudo tee -a /etc/apt/sources.list.d/mozilla.list > /dev/null 
    
    # Set priority to prefer the Mozilla package 
    echo 'Package: * 
    Pin: origin packages.mozilla.org 
    Pin-Priority: 1000' | sudo tee /etc/apt/preferences.d/mozilla 
    
    sudo apt update sudo apt install firefox
    1. Add PKCS#11 Module: Load the Yubico library into Firefox.
      • In Firefox, go to SettingsPrivacy & SecurityCertificatesSecurity Devices.
      • Click Load, name the module (e.g., “Yubico PKCS#11”), and enter the file path:
        /usr/lib/x86_64-linux-gnu/libykcs11.so
    2. Enable U2F/WebAuthn:
      • In the Firefox address bar, navigate to about:config.
      • Search for security.webauthn.u2f and set its value to true.

    Final Verification

    1. System Check: Run ykman info to ensure the key’s details are displayed.
    Device type: YubiKey 5C NFC 
    Serial number: <redacted> 
    Firmware version: 5.7.1 
    Form factor: Keychain (USB-C) 
    Enabled USB interfaces: OTP, FIDO, CCID 
    NFC transport is enabled. 
    
    Applications    USB     NFC
    OTP             Enabled Enabled
    FIDO U2F        Enabled Enabled
    FIDO2           Enabled Enabled
    OATH            Enabled Enabled
    PIV             Enabled Enabled
    OpenPGP         Enabled Enabled
    YubiHSM Auth    Enabled Enabled
    1. WebAuthn Test: Navigate to https://webauthn.io and successfully register or authenticate.
    Categories: DocumentationHome