Installation d'OpenWRT en domU Xen avec activation du PCI passthrough

Jean Baptiste FAVRE

Janvier 2011

English version is available here: OpenWRT installation as Xen domU with PCI passthrough

Introduction

L'un des problèmes potentiels de sécurité de Xen vient du fait que le dom0 contrôle toutes les ressources matérielles de la machine, parmis lesquelles la ou les cartes réseau. De fait, le dom0 se retrouve un peu malgré lui en tête de pont sur Internet, là ou la logique voudrait au contraire qu'il soit protégé, puisqu'étant une machine invitée avec privilèges.

Un projet comme Qubes-os permet, entre autres, de contrôler les cartes réseaux depuis un domU dédié. Le document d'architecture de Qubes OS explique parfaitement le pourquoi du comment.

L'idée est donc d'isoler le dom0 au niveu réseau, en tout cas de le protéger derrière un domU spécifique.

Dans le principe, n'importe quelle distribution un tant soit peu orientée sécurité fait l'affaire. Dans mon cas, j'aime me faire mal, j'ai choisi OpenWRT pour sa taille, le fait que je connaisse cet OS et pour le défi technique :)

Préparation de l'environnement

Nous allons devoir compiler OpenWRT depuis les sources. La version actuelle, Backfire, ne propose pas le noyau 2.6.37. Si vous voulez absolument utiliser cette version, il faudra backporter le driver Xen PCI Frontend pour le noyau 2.6.32-27. Dans notre cas, nous allons utiliser la version trunk qui intègre le support du noyau 2.6.37.

Il faut préparer l'environnement de compilation. Pas de soucis, tout est parfaitement documenté par l'équipe OpenWRT. Pour les pressés:

Installation de l'environnement de développement
aptitude install subversion subversion-tools
aptitude install install build-essential asciidoc autoconf binutils bison bzip2 \
flex gawk gettext libncurses5-dev libz-dev patch unzip zlib1g-dev
aptitude install install build-essential asciidoc autoconf binutils bison bzip2 \
  flex gawk gettext libncurses5-dev libz-dev patch unzip zlib1g-dev \
  ia32-libs lib32gcc1 libc6-dev-i386
svn co svn://svn.openwrt.org/openwrt/trunk trunk
cd trunk
./scripts/feeds update
./scripts/feeds install -a
make prereq
vi target/linux/x86/Makefile
[.....]
LINUX_VERSION:=2.6.37
[.....]
vi package/kernel/modules/virtual.mk
[.....]
define KernelPackage/xen-evtchn
  SUBMENU:=$(VIRTUAL_MENU)
  TITLE:=Xen event channels
  DEPENDS:=@TARGET_x86_xen_domu
  KCONFIG:=CONFIG_XEN_DEV_EVTCHN
  FILES:=$(LINUX_DIR)/drivers/xen/xen-evtchn.ko
  AUTOLOAD:=$(call AutoLoad,06,evtchn)
endef
[.....]

Les 2 modifications ci-dessus visent forcer l'utilisation du noyau 2.6.37 et à corriger le nom d'un des modules Xen qui sera généré (ligne FILES). Si vous oubliez la dernière modification, la compilation générera une erreur.

Configuration & compilation d'OpenWRT

Configuration & compilation d'OpenWRT
make menuconfig
[.....]
Target System
  [x] x86
Subtarget
  [x] Xen Paravirt Guest
Global build settings
  [ ] Compile the kernel with Debug Filesystem enabled
Kernel modules
  Xen paravirtualized guest support
      [x] kmod-xen-evtchn
      [ ] kmod-xen-fbdev
      [x] kmod-xen-fs
      [x] kmod-xen-kbddev
      [x] kmod-xen-netdev
[.....]
[.....]
Utilities
  [x] pciutils
[.....]
make

Une fois la compilation terminée, il faut transférer le noyau ainsi que l'image disque vers votre dom0:

Déploiement de l'image OpenWRT sur le dom0
scp bin/x86/openwrt-x86-xen_domu-combined-ext4.img.gz bin/x86/openwrt-x86-xen_domu-vmlinuz dom0:/path_to_your_image/

Il est maintenant temps de configurer notre domU.

Configuration du domU OpenWRT

OpenWRT va tourner en para-virtualisation. C'est pour cette raison que le noyau est séparé de l'image disque. En revanche, les modules noyau sont, eux, bien intégrés à l'image puisqu'ils devront être accessibles depuis le domU.

Configuration Xen pour le domU OpenWRT
cd /path_to_your_image
gunzip -d openwrt-x86-xen_domu-combined-ext4.img.gz
kernel       = '/path_to_your_image/openwrt-x86-xen_domu-vmlinuz'
root         = '/dev/xvda2 rw'

memory       = '256'
vcpus        = '1'
cpus         = '1'
localtime    = 0
serial       = 'pty'

disk         = [ 'file:/path_to_your_image/openwrt-x86-xen_domu-combined-ext4.img,xvda,w' ]

on_poweroff  = 'destroy'
on_reboot    = 'restart'
on_crash     = 'restart'

extra = "console=hvc0 xencons=tty"
#extra = "iommu=soft swiotlb=force console=hvc0 xencons=tty"
#pci = [ '04:00.0' ]

name         = 'openwrt'
hostname     = 'openwrt.yourdomain.tld'

Commençons par tester le domU sans PCI passthrough. Si les tests sont concluant, vous pourrez commenter la ligne extra = "console=hvc0 xencons=tty" et décommenter les 2 suivantes pour activer le PCI passthrough.

Premier démarrage du domU
xm create /etc/xen/auto/openwrt.cfg -c
[.....]
blkfront: xvda: barriers enabled
 xvda: xvda1 xvda2
xvda: p2 size 98721 extends beyond EOD, truncated
XENBUS: Device with no driver: device/console/0
EXT4-fs (xvda2): mounted filesystem without journal. Opts: (null)
VFS: Mounted root (ext2 filesystem) on device 202:2.
Freeing unused kernel memory: 304k freed
- preinit -
Press the [f] key and hit [enter] to enter failsafe mode
- regular preinit -
EXT4-fs (xvda2): re-mounted. Opts: (null)
- init -

Please press Enter to activate this console.

BusyBox v1.17.3 (2011-01-05 16:42:08 CET) built-in shell (ash)
Enter 'help' for a list of built-in commands.

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 KAMIKAZE (bleeding edge, r24906) ------------------
  * 10 oz Vodka       Shake well with ice and strain
  * 10 oz Triple sec  mixture into 10 shot glasses.
  * 10 oz lime juice  Salute!
 ---------------------------------------------------
root@OpenWrt:/#

Si vous obtenez ceci, ou quelque chose d'approchant, c'est gagné. Votre domU fonctionne. Voyons maintenant comment transférer le contrôle d'un périphérique PCI au domU.

Xen PCI passthrough

Je vous la fais en version courte, le temps pour moi de rédiger une publication plus complète. Il faut:

Ceci va induire un changement de l'architecture réseau de votre serveur Xen:

Architecture réseau Xen par défaut
Architecture réseau Xen après PCI passthrough

Evidemment, je suis sous GNU/Linux Debian, nous allons donc faire ces opérations "à la Debian".

Mise en place du PCI passthrough
lspci | grep Ethernet
01:05.0 Ethernet controller: D-Link System Inc DGE-528T Gigabit Ethernet Adapter (rev 10)
03:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet Controller (rev 06)
03:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet Controller (rev 06)
04:00.0 Ethernet controller: Marvell Technology Group Ltd. 88E8056 PCI-E Gigabit Ethernet Controller (rev 12)
[.....]
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX="xen-pciback.permissive xen-pciback.hide=(04:00.0) pci=resource_alignment=04:00.0"
[.....]
GRUB_CMDLINE_XEN_DEFAULT=""
GRUB_CMDLINE_XEN="dom0_mem=256M dom0_max_vcpus=1 dom0_vcpus_pin"
update-grub
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-2.6.32-5-xen-amd64
Found initrd image: /boot/initrd.img-2.6.32-5-xen-amd64
Found linux image: /boot/vmlinuz-2.6.32-5-xen-amd64
Found initrd image: /boot/initrd.img-2.6.32-5-xen-amd64
done

A ce stade, vous pouvez rebooter. Veillez cependant à avoir un accès simple au dom0. Soit un accès physique, soit un accès console ou KVM, soit encore un accès réseau. Si vous n'utilisez pas de bonding et/ou n'avez pas d'interface réseau de secours, soyez bien conscient que le réseau ne fonctionnera pas après reboot car il faudra configurer OpenWRT !

Dans mon cas pas de soucis, le réseau externe est configuré en bonding, il est donc simple de retirer une carte réseau sans pour autant perdre l'accès à la machine. De plus, la machine est accessible en console RS232 depuis une autre machine. Ceinture et bretelles :)

Vérifications d'après reboot

Une fois la machine hôte redémarrée, nous pouvons faire quelques vérifications:

Contrôler la mise en place du PCI passthrough sur le dom0
lspci | grep Ethernet
01:05.0 Ethernet controller: D-Link System Inc DGE-528T Gigabit Ethernet Adapter (rev 10)
03:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet Controller (rev 06)
03:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet Controller (rev 06)
04:00.0 Ethernet controller: Marvell Technology Group Ltd. 88E8056 PCI-E Gigabit Ethernet Controller (rev 12)
lspci -v -s 0000:04:00
04:00.0 Ethernet controller: Marvell Technology Group Ltd. 88E8056 PCI-E Gigabit Ethernet Controller (rev 12)
        Subsystem: ASUSTeK Computer Inc. Device 81f8
        Flags: fast devsel, IRQ 18
        Memory at feb00000 (64-bit, non-prefetchable) [disabled] [size=16K]
        I/O ports at e800 [disabled] [size=256]
        Expansion ROM at 10100000 [disabled] [size=128K]
        Capabilities: [48] Power Management version 3
        Capabilities: [50] Vital Product Data
        Capabilities: [5c] MSI: Enable- Count=1/1 Maskable- 64bit+
        Capabilities: [e0] Express Legacy Endpoint, MSI 00
        Capabilities: [100] Advanced Error Reporting
        Kernel driver in use: pciback
        Kernel modules: sky2

Cela peut paraître surprenant de voir la carte réseau apparaître, mais en fait non :p

Nous voyons ici que tout va bien: la carte est gérée par le module pciback (donc par Xen) alors qu'en théorie il s'agit du module sky2 (réseau). Vous pouvez vérifier par ip ad sh, vous ne verrez bien que 3 interfaces réseaux sur les 4 "détectées".

Contrôler la mise en place du PCI passthrough sur le domU
lspci | grep Ethernet
04:00.0 Ethernet controller: Marvell Technology Group Ltd. 88E8056 PCI-E Gigabit Ethernet Controller (rev 12)

Voilà, tout fonctionne. Vous pouvez maintenant configurer OpenWRT de manière à ce qu'il opère en tant que passerelle du dom0 et des domU. Vous pourrez devrez bien sûr mettre en place les règles de pare-feu qui vont bien. Vous pourrez même installer un IDS pour détecter les attaques contre vos domU sans pour autant surcharger le dom0 :)

Have fun !

Source et références

OpenWRT

How build OpenWRT
  • //wiki.openwrt.org/doc/howto/build

Xen

Xen PCI passthrough
  • //wiki.xensource.com/xenwiki/XenPCIpassthrough

À propos de Jean Baptiste FAVRE

Je passe le plus clair de mon temps libre sur Internet à travailler sur GNU/Linux avec Debian ou CentOS, la virtualisation avec Xen et KVM et les technologies cluster avec Corosync et OpenAIS. Particulièrement intéressé par Linux, Netfilter, la virtualisation, le monitoring et les clusters, la plupart de mes travaux personnels sont publiés sur ce site et les autres ne sauraient tarder.
A titre professionnel, j'administre des serveurs sous RedHat ou CentOS ainsi qu'une ferme de serveurs VMware ESXi version 4.
De temps, à autre, je parviens à lâcher mon clavier pour lire un bon bouquin tout en écoutant de la musique, mais ça ne dure jamais longtemps.

License

Creative Commons License Cette publication est publiée sous contrat Creative Common by-nc-sa

Valid XHTML 1.0 Strict |  Valid CSS |  contrat Creative Common by-nc-sa

Table des matières

  1. Introduction
  2. Préparation de l'environnement
  3. Configuration & compilation d'OpenWRT
  4. Configuration du domU OpenWRT
  5. Xen PCI passthrough
  6. Vérifications d'après reboot
  7. Source et références
  8. À propos
  9. License