StrongSwan: modificare path dei certificati

SECRETS

le chiavi private, sia della “ca” che dei vari certificati “peer”, per default vengono cercate in /etc/ipsec.d/private , ma è possibile specificare i loro path assoluti in ipsec.secrets:
riferimento https://wiki.strongswan.org/projects/strongswan/wiki/RsaSecret

# This file holds shared secrets or RSA private keys for authentication.

# RSA private key for this host, authenticating it to any other host
# which knows the public part.

: RSA /etc/ssl/localcerts/name.domain.com.key
: RSA /path/to/ca.key "passphrase"

e poi indicare al daemon di rileggere i secrets:

ipsec rereadsecrets
# oppure:
ipsec rereadall

verificare in /var/log/syslog (dopo il riavvio del demone o dopo la rilettura della configurazione) se ci sono errori di apertura dei file:

Jul 16 15:26:43 myserver charon: 00[CFG]   loaded RSA private key from '/etc/ssl/localcerts/name.domain.com.key'
Jul 16 15:26:43 myserver charon: 00[CFG]   loaded RSA private key from '/path/to/ca.key'

CA

per specificare i path dei certificati (chiavi pubbliche) posti al di fuori della directory di default /etc/ipsec.d/cacerts bisogna creare una stanza “ca” in /etc/ipsec.conf:
riferimento https://wiki.strongswan.org/projects/strongswan/wiki/CaSection

ca name-of-ca
        cacert=/etc/ssl/certs/ca.pem
        auto=add

# NOTARE IL PARAMETRO auto=add !!!!
# questo permette alla ca di essere letta in automatico all'avvio del demone

dopo il riavvio del demone o dopo la rilettura della configurazione si può verificare che la ca sia stata letta correttamente con il comando

ipsec listcacerts

oppure in /var/log/syslog:

Jul 16 15:26:43 myserver charon: 05[CFG] received stroke: add ca 'name-of-ca'
Jul 16 15:26:43 myserver charon: 05[CFG]   loaded ca certificate "C=US, ST=Somewhere, O=My Organization, OU=Certificate Authority, CN=name.domain.com" from '/etc/ssl/certs/ca.pem'
Jul 16 15:26:43 myserver charon: 05[CFG] added ca 'name-of-ca'

SERVER

la configurazione del server si trova in /etc/ipsec.conf: notare che per un roadwarrior non è necessario indicare un certificato, perchè ci pensa il client.
invece il certificato del server viene indicato con leftcert:
riferimento https://wiki.strongswan.org/projects/strongswan/wiki/ConnSection

conn roadwarrior
        keyexchange=ikev2
        auto=add

        # Server Side
        left=%any
        leftupdown="/etc/ipsecupdown.sh"
        leftauth=pubkey
        leftcert=/etc/ssl/localcerts/name.domain.com.crt
        leftsubnet=0.0.0.0/0

        # Client side
        right=%any
        rightsourceip=%dhcp
        rightauth=pubkey
        rightauth2=eap-mschapv2
        #rightcert=clientCert.pem
        rightdns=208.67.222.222,208.67.220.220

si può rileggere la configurazione (o riavviare il demone) con:

ipsec reload

e in /var/log/syslog si può vedere se i certificati sono stati letti correttamente

Jul 16 15:26:43 myserver charon: 07[CFG] received stroke: add connection 'roadwarrior'
Jul 16 15:26:43 myserver charon: 07[CFG]   loaded certificate "C=US, ST=Somewhere, O=My Organization, OU=My Server, CN=name.domain.com" from '/etc/ssl/localcerts/name.domain.com.crt'
Jul 16 15:26:43 myserver charon: 07[CFG]   id '%any' not confirmed by certificate, defaulting to 'C=US, ST=Somewhere, O=My Organization, OU=My Server, CN=name.domain.com'
Jul 16 15:26:43 myserver charon: 07[CFG] added configuration 'roadwarrior'

AppArmor

se le chiavi o i certificati non vengono aperti, verificare se charon viene bloccato da apparmor: in /var/log/syslog

Jul 16 15:03:16 myserver kernel: [79272.207562] audit: type=1400 audit(1563282196.199:81): apparmor="DENIED" operation="open" profile="/usr/lib/ipsec/charon" name="/etc/ssl/localcerts/name.domain.com.key" pid=16046 comm="charon" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 16 15:03:16 myserver kernel: [79272.207563] audit: type=1400 audit(1563282196.199:82): apparmor="DENIED" operation="open" profile="/usr/lib/ipsec/charon" name="/path/to/ca.key" pid=16046 comm="charon" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 16 15:07:40 myserver kernel: [79536.592065] audit: type=1400 audit(1563282460.579:83): apparmor="STATUS" operation="profile_remove" profile="unconfined" name="/usr/lib/ipsec/charon" pid=16173 comm="apparmor_parser"
Jul 16 15:07:49 myserver charon: 08[CFG] received stroke: delete connection 'roadwarrior'
Jul 16 15:07:49 myserver charon: 08[CFG] deleted connection 'roadwarrior'
Jul 16 15:07:49 myserver charon: 10[CFG] received stroke: delete ca 'name-of-ca'

è possibile far rileggere ad apparmor la configurazione di charon:
riferimento https://raymii.org/s/tutorials/IPSEC_vpn_with_Ubuntu_16.04.html

apparmor_parser -R /etc/apparmor.d/usr.lib.ipsec.charon
# il seguente non è stato necessario nei miei test:
apparmor_parser -R /etc/apparmor.d/usr.lib.ipsec.stroke

e dopo un riavvio del server o una rilettura della configurazione, in /var/log/syslog dovremmo trovare:

Jul 16 15:26:43 myserver charon: 05[CFG] received stroke: add ca 'name-of-ca'
Jul 16 15:26:43 myserver charon: 05[CFG]   loaded ca certificate "C=US, ST=Somewhere, O=My Organization, OU=Certificate Authority, CN=name.domain.com" from '/etc/ssl/certs/ca.pem'
Jul 16 15:26:43 myserver charon: 05[CFG] added ca 'name-of-ca'
Jul 16 15:26:43 myserver charon: 07[CFG] received stroke: add connection 'roadwarrior'
Jul 16 15:26:43 myserver charon: 07[CFG]   loaded certificate "C=US, ST=Somewhere, O=My Organization, OU=My Server, CN=name.domain.com" from '/etc/ssl/localcerts/name.domain.com.crt'
Jul 16 15:26:43 myserver charon: 07[CFG]   id '%any' not confirmed by certificate, defaulting to 'C=US, ST=Somewhere, O=My Organization, OU=My Server, CN=name.domain.com'
Jul 16 15:26:43 myserver charon: 07[CFG] added configuration 'roadwarrior'

Linux: Disabilitare IPv6

aggiungere a /etc/sysctl.conf le seguenti:

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

# ricaricare sysctl con il comando:
sysctl -p

verificare con

cat /proc/sys/net/ipv6/conf/all/disable_ipv6
cat /proc/sys/net/ipv6/conf/default/disable_ipv6
cat /proc/sys/net/ipv6/conf/lo/disable_ipv6

se il risultato è “1”, ipv6 è disabilitato.

Apache 2 SSL

Gestione CA

riferimento: https://wiki.openssl.org/index.php/Command_Line_Utilities#Create_.2F_Handle_Public_Key_Certificates

Il tipo più comune di coppia di chiavi pubblica/privata è RSA; per utilizzare wildcard o altri nomi nello stesso certificato (subjectAltName) è necessario adoperare un file di configurazione. Si può prendere quello di default /etc/ssl/openssl.cnf, spostarlo in una directory a piacere, e modificarlo, aggiungendo una stringa del tipo subjectAltName = DNS:nome.dominio.xyz,DNS:*.dominio.xyz,IP:192.168.1.1 all’interno della stanza v3_req.

Continua a leggere “Apache 2 SSL”

NetFilter – IPTABLES

situazione di partenza: tutte le policy sono ACCEPT.

inserisco le le regole manualmente, verifico con iptables -vnL, poi le salvo in un file con il comando iptables-save:

# inserisco le policy di base: tutto chiuso
iptables -P INPUT DROP
iptables -P FORWARD DROP
# lasciamo libero il traffico di loopback
iptables -A INPUT -i lo -j ACCEPT
# consento il traffico richiesto da noi:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -vnL
iptables-save > iptables.rules.up

ora le connessioni dall’esterno sono chiuse: bisogna aprire le porte dei servizi che ci interessano.

per vedere quali porte sono in ascolto, oltre a netstat è possibile usare lsof:

lsof -i

in output abbiamo le porte in ascolto in formato testuale: i corrispondenti valori numerici si trovano in /etc/services.

ad esempio, trovo che smbd ascolta su TCP *:microsoft-ds (Microsoft Naked CIFS) e TCP *:netbios-ssn (NETBIOS session service): sono le porte 139 e 445

invece nmbd ascolta su netbios-ns (NETBIOS Name Service) e netbios-dgm (NETBIOS Datagram Service), porte 137 e 138

  • UDP *:netbios-ns
  • UDP *:netbios-dgm
  • UDP nomehost.nomedominio:netbios-ns
  • UDP nomehost.nomedominio:netbios-dgm
  • UDP 192.168.1.255:netbios-ns
  • UDP 192.168.1.255:netbios-dgm

dunque devo solo aprire le porte 139 e 445 TCP e 137-138 UDP , limitando il traffico alla sola rete locale:

iptables -A INPUT -p tcp --dport 139 -m state --state NEW -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 445 -m state --state NEW -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p udp --dport 137 -m state --state NEW -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p udp --dport 138 -m state --state NEW -s 192.168.1.0/24 -j ACCEPT

per fare pulizia:

iptables -F #Cancellazione delle regole presenti nelle chains
iptables -X #Eliminazione delle chains non standard vuote
iptables -Z #Inizializzazione dei contatori (utile per il debugging)

per ripristinare le regole precedentemente salvate:

iptables-restore < iptables.up.rules

il file iptables.up.rules è simile a:

# Generated by iptables-save v1.6.2 on Xxx Xxx xx xx:xx:xx 2018
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 139 -m state --state NEW -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 445 -m state --state NEW -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p udp -m udp --dport 137 -m state --state NEW -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p udp -m udp --dport 138 -m state --state NEW -j ACCEPT
-A INPUT -p udp -m udp --dport 500 -m state --state NEW -j ACCEPT
-A INPUT -p udp -m udp --dport 4500 -m state --state NEW -j ACCEPT
COMMIT
# Completed on Xxx Xxx xx xx:xx:xx 2018

per gestire le regole:

# numerare le regole:
iptables -L INPUT --line-numbers
# cancellare una regola per numero, ad es. il 10:
iptables -D INPUT 10
# inserire una regola tra le esistenti 9 e 10:
# la 10ma diventa così 11esima
iptables -I INPUT 10 -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT

per caricare e rimuovere le regole di iptables quando si avvia o si disconnette una connessione di rete, ci sono gli script pre-up e pre-down di /etc/network/interfaces.

se le connessioni sono gestite da NetworkManager, vengono eseguiti gli script contenuti in /etc/networkManager/dispatcher.d , in particolare quelli contenuti nelle directories pre-up.d e pre-down.d: creo uno script iptables in ognuna di esse, e nel primo scrivo

#!/bin/sh
iptables-restore < /etc/iptables.up.rules

analogamente per il secondo, scrivo iptables.down.rules.
dò i permessi 0700 agli script e 0600 ai file delle regole.

NetworkManager può essere gestito da shell con nmcli:
soppando e riavviando la connessione possiamo testare gli script pre-up e pre-down delle regole iptables.

# senza argomenti fornisce una panoramica:
nmcli
# per vedere i dettagli delle connessioni
nmcli -p con show
nmcli con show
# per avviare|stoppare una connessione per nome
nmcli con up|down "Wired connection 1"

riferimenti

Debian StrongSwan e MiniSSDPd

Appunti di configurazione:

MiniSSDPd

Il file /var/log/daemon.log era pieno di avvisi del tipo

minissdpd[30585]: peer 192.168.1.200:32500 is not from a LAN

Per correggerlo bisogna modificare il file /etc/default/minissdpd specificando l’interfaccia su cui ascoltare:

MiniSSDPd_INTERFACE_ADDRESS=enp2s0 # non 0.0.0.0

StrongSwan

https://www.strongswan.org/

Host Debian Buster (testing).
Configurazione di un “roadwarrior” Android 7 con client StrongSwan scaricabile da Play Store, con doppia autenticazione Certificato + EAP.

Oltre ad installare il pacchetto StrongSwan con le sue dipendenze, ho dovuto installare manualmente altri due pacchetti:

  1. strongswan-pki : necessario per creare e gestire i certificati da linea di comando ipsec
  2. libcharon-extra-plugins : necessario per usare l’autenticazione EAP-MSCHAPv2

Configurazione di /etc/ipsec.conf

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
# strictcrlpolicy=yes
# uniqueids = no

# Add connections here.

# Sample VPN connections

#conn sample-self-signed
# leftsubnet=10.1.0.0/16
# leftcert=selfCert.der
# leftsendcert=never
# right=192.168.0.2
# rightsubnet=10.2.0.0/16
# rightcert=peerCert.der
# auto=start

#conn sample-with-ca-cert
# leftsubnet=10.1.0.0/16
# leftcert=myCert.pem
# right=192.168.0.2
# rightsubnet=10.2.0.0/16
# rightid="C=CH, O=Linux strongSwan CN=peer name"
# auto=start

conn roadwarrior
keyexchange=ikev2
auto=add

# Server Side
left=%any
leftauth=pubkey
leftcert=serverCert.pem
leftid=xyz.ddns.net
leftsubnet=0.0.0.0/0

# Client side
right=%any
# rightsourceip=192.168.2.0/24
rightsourceip=%dhcp
rightauth=pubkey
rightauth2=eap-mschapv2
rightcert=clientCert.pem
rightdns=208.67.222.222,208.67.220.220

include /var/lib/strongswan/ipsec.conf.inc

Configurazione di /etc/ipsec.secrets

: RSA serverKey.pem
nomeutente : EAP "password"

I certificati sono stati creati con lo script:
(ATTENZIONE: verificare se i parametri –san possono essere impostati diversamente)
Copiare sul client sia il clientCert.p12 che il caCert.pem

#!/bin/sh
ipsec pki --gen --outform pem > caKey.pem
ipsec pki --self --in caKey.pem --dn "C=IT, O=xyz.ddns.net, CN=Nome Autorità" --ca --outform pem > caCert.pem
ipsec pki --gen --outform pem > serverKey.pem
ipsec pki --pub --in serverKey.pem | ipsec pki --issue --cacert caCert.pem --cakey caKey.pem --dn "C=IT, O=xyz.ddns.net, CN=xyz.ddns.net" --san="xyz.ddns.net" --flag serverAuth --flag ikeIntermediate --outform pem > serverCert.pem
ipsec pki --gen --outform pem > clientKey.pem
ipsec pki --pub --in clientKey.pem | ipsec pki --issue --cacert caCert.pem --cakey caKey.pem --dn "C=IT, O=xyz.ddns.net, CN=Nome Client" --san="client" --outform pem > clientCert.pem
openssl pkcs12 -export -inkey clientKey.pem -in clientCert.pem -name "client" -certfile caCert.pem -caname "xxxx" -out clientCert.p12

# where to put them...
mv caCert.pem /etc/ipsec.d/cacerts/
mv serverCert.pem /etc/ipsec.d/certs/
mv serverKey.pem /etc/ipsec.d/private/
mv clientCert.pem /etc/ipsec.d/certs/
mv clientKey.pem /etc/ipsec.d/private/
mv caKey.pem /etc/ipsec.d/private/

Sul firewall, ho impostato il forwarding delle porte UDP 500 e 4500.

Per riavviare il server VPN, il tunnel IPSec, o per ricaricare le credenziali:

systemctl restart|status|stop|start strongswan
ipsec reload
ipsec rereadsecrets

Configurazione del FORWARDING per il traffico verso il roadwarrior

Bisogna aprire le porte nel firewall (iptables) e abilitare IP forwarding:

Ho risolto così:

  1. ho creato gli script iptables.up.rules e iptables.up.rules con tutte le regole necessarie in /etc/NetworkManager/dispatcher.d/pre-up.d/ e /pre-down.d, ho impostato root come proprietario, ho tolto ogni permesso agli altri utenti, e li ho resi eseguibile: Network Manager lo eseguirà ogni volta che l’interfaccia di rete starà per essere avviata o spenta, impostando le regole iptables
    pre-up

    #!/bin/sh
    
    
    LOGFILE=/var/log/iptables.log
    
    if [ "$1" = lo ]; then
    echo "$0: ignoring $1 for \`$2'" >> $LOGFILE
    exit 0
    fi
    
    case "$2" in
    pre-up)
    echo "$0: restoring iptables rules for $1" $(date +%c) >> $LOGFILE
    /sbin/iptables-restore /etc/iptables.up.rules >> $LOGFILE 2>&1
    #/sbin/ip6tables-restore /etc/network/ip6tables.up.rules >> $LOGFILE 2>&1
    ;;
    *)
    echo "$0: nothing to do with $1 for \`$2'" $(date +%c) >> $LOGFILE
    ;;
    esac
    
    exit 0
    

    pre-down

    #!/bin/sh
    
    
    LOGFILE=/var/log/iptables.log
    if [ "$1" = lo ]; then
    echo "$0: ignoring $1 for \`$2'" >> $LOGFILE
    exit 0
    fi
    
    case "$2" in
    pre-down)
    echo "$0: restoring iptables rules for $1 " $(date +%c) >> $LOGFILE
    /sbin/iptables-restore /etc/iptables.down.rules >> $LOGFILE 2>&1
    #/sbin/ip6tables-restore /etc/network/ip6tables.up.rules >> $LOGFILE 2>&1
    ;;
    *)
    echo "$0: nothing to do with $1 for \`$2'" >> $LOGFILE
    ;;
    esac
    
    exit 0
    
  2. il file /etc/iptables.up.rules contiene la policy di DROP per il FORWARD, ovviamente può (e deve) essere rifinito meglio:
    # Generated by xtables-save v1.8.2 on xxx xxx xx 15:25:18 2019
    *filter
    :INPUT DROP [0:0]
    :FORWARD DROP [0:0]
    :OUTPUT ACCEPT [0:0]
    -A INPUT -i lo -j ACCEPT
    -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    -A INPUT -p udp -m udp --dport 500 -m state --state NEW -j ACCEPT
    -A INPUT -p udp -m udp --dport 4500 -m state --state NEW -j ACCEPT
    COMMIT
    # Completed on xxx xxx xx 15:25:18 2019
    

    il file /etc/iptables.down.rules riporta allo stato iniziale di Debian:

    # Generated by iptables-save v1.6.2 on xxx xxx xx 11:12:06 2018
    *filter
    :INPUT ACCEPT
    :FORWARD ACCEPT
    :OUTPUT ACCEPT
    COMMIT
    # Completed on xxx xxx xx 11:12:06 2018
    
  3. Bisogna ancora abilitare IP Forwarding:
    Per gestire le connessioni dietro NAT, si può usare lo script di default di strongSwan con l’opzione “leftfirewall=yes”.
    Ma per personalizzare la configurazione, è necessario usare uno script diverso: per fare questo si usa l’opzione “leftupdown=/path/to/myscript-updown.sh”.
    Io ho copiato lo script di default da /usr/lib/ipsec/_updown e ho modificato le stanze up-client e down-client: queste sono eseguite quando una connessione IPv4 ad un client stà per essere attivata o disattivata:
    up_client:

    echo "$0: roadwarrior subnet coming up" $(date +%c) >> /var/log/iptables.log 2>&1
    echo 1 > /proc/sys/net/ipv4/ip_forward
    

    down_client:

    echo "$0: roadwarrior subnet going down" $(date +%c) >> /var/log/iptables.log 2>&1
    echo 0 > /proc/sys/net/ipv4/ip_forward
    

RIFERIMENTI:

  1. abilitare ipv4 forwarding:
    echo 1 > /proc/sys/net/ipv4/ip_forward
    # per renderlo persistente:
    nano /etc/sysctl.conf
    net.ipv4.ip_forward = 1
  2. impostare le regole iptables:
    iptables -I INPUT -m policy –dir in –pol ipsec –proto esp -j ACCEPT
    iptables -I FORWARD -m policy –dir in –pol ipsec –proto esp -j ACCEPT
    iptables -I FORWARD -m policy –dir out –pol ipsec –proto esp -j ACCEPT
    iptables -I OUTPUT -m policy –dir out –pol ipsec –proto esp -j ACCEPT
  3. vedere https://wiki.strongswan.org/projects/strongswan/wiki/ForwardingAndSplitTunneling
  4. NetworkManager pre-up e pre-down: https://feeding.cloud.geek.nz/posts/using-iptables-with-network-manager/
  5. https://wiki.archlinux.org/index.php/StrongSwan
  6. https://wiki.openwrt.org/doc/howto/vpn.ipsec.roadwarrior

VGA passthrough con OVMF e QEMU-KVM

libvirt: parametri per QEMU

Bisogna modificare lo XML creato da virt-manager:

virsh edit nome_della_VM

per modificare i parametri passati a QEMU per fare lo spoof per i driver NVIDIA:

https://forum.level1techs.com/t/play-games-in-windows-on-linux-pci-passthrough-quick-guide/108981?source_topic_id=110696

<!-- modificare il namespace-->
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<!-- aggiungere i seguenti parametri -->
<qemu:commandline>
<qemu:arg value='-cpu'/>
<qemu:arg value='host,hv_time,kvm=off,hv_vendor_id=null'/>
</qemu:commandline>

Installare i driver VirtIO

Scaricare la ISO da:  https://fedoraproject.org/wiki/Windows_Virtio_Drivers, e cercare i driver nelle seguenti directory:

  • NetKVM/: Virtio Network driver
  • viostor/: Virtio Block driver
  • guest-agent/: QEMU Guest Agent 32bit and 64bit MSI installers
  • qemupciserial/: QEMU PCI serial device driver
  • Balloon/: Virtio Memory Balloon driver

https://forum.proxmox.com/threads/ovmf-uefi-windows-10-boot-option-wont-stick.27376/

How I setup the VM

  1. Set up VM
  2. Select Windows 10
  3. Add a new vDisk using Virtio Bus (iothread + Write back Cache) as Virtio0
  4. add Qemu agent -> yes
  5. Add windows 10 Iso as First DVD on Sata0
  6. Add Virtio-win-0.1.117 as secondary DVD on Sata1
  7. Select Virtio Controller via Options Tab (afaik best practice is to use SCSI ontop of Virtio controller for Windows on SSDs)
  8. Verify your boot Orders. —> Disk then CD-Rom
  9. Install windows 10
  10. Start Windows VM
  11. Boot from Windows ISO (press any key to start from DVD/CD . . .) select “Install Now”, select windows 10 pro x64, custom install, “load Driver” option
  12. Select Virtio-DVD > Viostor > w8.1 > amd64
  13. Install Red Hat VirtIO SCSI controller (driver for your virtio0)
    “load Driver” option
  14. Select Virtio-DVD > VioSCSI > w8.1 > amd64
    uncheck the checkbox
  15. Install Red Hat VirtIO SCSI pass-through controller (in case you need it later)
    “load Driver” option
  16. Select Virtio-DVD > netKVM > w8.1 > amd64
    uncheck the checkbox
  17. Install Red Hat VirtIO Ethernet Adapter (you will need this later)
  18. Install windows regularly (like you’d normally do)

Debian QEMU – VGA passthrough – Virt-Manager

Binding e unbinding dei driver

https://lwn.net/Articles/143397/
One new feature in the 2.6.13-rc3 kernel release, is the ability to bind and unbind drivers from devices manually from user space. Previously, the only way to disconnect a driver from a device was usually to unload the whole driver from memory, using rmmod.

In the sysfs tree, every driver now has bind and unbind files associated with it:

$ tree /sys/bus/usb/drivers/ub/
/sys/bus/usb/drivers/ub/
|-- 1-1:1.0 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0
|-- bind
|-- module -> ../../../../module/ub
`-- unbind

In order to unbind a device from a driver, simply write the bus id of the device to the unbind file:

echo -n "1-1:1.0" > /sys/bus/usb/drivers/ub/unbind

and the device will no longer be bound to the driver:

$ tree /sys/bus/usb/drivers/ub/
/sys/bus/usb/drivers/ub/
|-- bind
|-- module -> ../../../../module/ub
`-- unbind

To bind a device to a driver, the device must first not be controlled by any other driver. To ensure this, look for the “driver” symlink in the device directory:

$ tree /sys/bus/usb/devices/1-1:1.0
/sys/bus/usb/devices/1-1:1.0
|-- bAlternateSetting
|-- bInterfaceClass
|-- bInterfaceNumber
|-- bInterfaceProtocol
|-- bInterfaceSubClass
|-- bNumEndpoints
|-- bus -> ../../../../../../bus/usb
|-- modalias
`-- power
`-- state

Then, simply write the bus id of the device you wish to bind, into the bind file for that driver:

echo -n "1-1:1.0" > /sys/bus/usb/drivers/usb-storage/bind

And check that the binding was successful:

$ tree /sys/bus/usb/devices/1-1:1.0
/sys/bus/usb/devices/1-1:1.0
|-- bAlternateSetting
|-- bInterfaceClass
|-- bInterfaceNumber
|-- bInterfaceProtocol
|-- bInterfaceSubClass
|-- bNumEndpoints
|-- bus -> ../../../../../../bus/usb
|-- driver -> ../../../../../../bus/usb/drivers/usb-storage
|-- host2
| `-- power
| `-- state
|-- modalias
`-- power
`-- state

As the example above shows, this capability is very useful for switching devices between drivers which handle the same type of device (both the ub and usb-storage drivers handle USB mass storage devices, like flash drives.)

A number of “enterprise” Linux distributions offer multiple drivers of different version levels in their kernel packages. This manual binding feature will allow configuration tools to pick and choose which devices should be bound to which drivers, allowing users to upgrade only specific devices if they wish to.

In order for a device to bind successfully with a driver, that driver must already support that device. This is why you can not just arbitrarily bind any device to any driver. To help with the issue of adding new devices support to drivers after they are built, the PCI system offers a dynamic_id file in sysfs so that user space can write in new device ids that the driver should bind too. In the future, this ability to add new driver IDs to a running kernel will be moved into the driver core to make it available for all buses.


Metodo alternativo

https://www.kernel.org/doc/Documentation/vfio.txt

echo 1002 6739 | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id

http://stackoverflow.com/questions/442833/forcing-driver-to-device-match

/sys/bus/usb-serial/drivers/cp2101

In this directory, there is a new_id file entry that can be used to dynamically add VID PID pair like this :

echo VID PID >new_id

Per caricare i moduli VFIO all’accensione e assegnarli ai dispositivi:

https://medium.com/@calerogers/gpu-virtualization-with-kvm-qemu-63ca98a6a172
Edit the initramfs at /etc/initram-fs/modules to ensure it has VFIO modules loaded on boot:

sudo vim /etc/initram-fs/modules

# Add to file
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

sudo update-initramfs -u

Create a new module file located at /etc/modprobe.d/local.conf. This step binds the video cards to VFIO on boot so they are not claimed by the host OS (this script also binds VFIO post boot):

sudo vim /etc/modprobe.d/local.conf

# Add to file
options vfio-pci ids=10de:1b80,10de:10f0
options vfio-pci disable_vga=1

Reboot the server.

Note: 10de:1b80, 10de:10f0 are specific to our GPU hardware (GTX 1080s). These numbers refer to the video card and onboard audio. You can find your specific model / vendor numbers by running:

lspci -nnk | grep -i nvidia

4b:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:1b80] (rev a1)
4b:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10f0] (rev a1)

At this point your physical host should be setup and ready to passthrough GPUs to guest VMs. You can verify IOMMU and VFIO are working by running the following:

sudo find /sys/kernel/iommu_groups/ -type l

# Your output should be a long listing of lines like this

/sys/kernel/iommu_groups/0/devices/0000:ff:0b.0
/sys/kernel/iommu_groups/0/devices/0000:ff:0b.1
/sys/kernel/iommu_groups/0/devices/0000:ff:0b.2
/sys/kernel/iommu_groups/1/devices/0000:ff:0c.0
...
...

lspci -nnk

# Find your VGA controllers, it should look similar to this

4b:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:1b80] (rev a1)
    Subsystem: ASUSTeK Computer Inc. Device [1043:8591]
    Kernel driver in use: vfio-pci

GPU primaria: estrazione ROM

https://medium.com/@calerogers/gpu-virtualization-with-kvm-qemu-63ca98a6a172
Primary GPU Workaround

Another quirk that needs to be addressed is only necessary if you are passing through your primary GPU but interesting nonetheless. This behavior occurs with the GTX 1080, but did not with a Geforce 210 in my testing, so your results may vary.

Like motherboards, GPUs have their own BIOS (aka ROM) and when the computer boots the primary GPU is using a “shadowed” copy of the ROM file. This causes issues when doing passthrough. To workaround this you need to get a copy of a non-shadowed ROM file which is specific to the GPU model. In our case we had other non-primary GPUs we could dump the ROM from. You can also try 3rd party websites that provide ROMs but I did not have success with those.

First unbind a non-primary GPU from vfio-pci (if it is bound), for example:

echo “0000:4b:00.0” | sudo tee /sys/bus/pci/drivers/vfio-pci/unbind

Then dump the ROM contents to a file:

echo 0 | sudo tee /sys/devices/pci0000:00/0000:00:03.0/0000:4b:00.0/rom

sudo cat /sys/devices/pci0000:00/0000:00:03.0/0000:4b:00.0/rom &gt; gpu.rom

echo 1 | sudo tee /sys/devices/pci0000:00/0000:00:03.0/0000:4b:00.0/rom

Note: The echo 0 and echo 1 basically just switches the ROM into a readable state and then back again if you’re curious.

After you have a good ROM file you need to add this code to your VMs XML in the definition of the GPU which added earlier:


Patch dei driver NVIDIA

https://forums.linuxmint.com/viewtopic.php?t=229122

  1. Using KVM/qemu, boot your Windows 10 VM using the kvm=off option described above.
  2. Inside Windows, download the Nvidia graphics driver for your graphics card from here http://www.nvidia.com/Download/index.aspx?lang=en-us.
    The latest driver for my Nvidia GTX 970, as of this writing, is 372.54.
  3. Run the Nvidia driver installer. It will unpack the files to C:/NVIDIA/DisplayDriver/{version}/Win10_64/International/Display.Driver, with the driver as of this writing it will be C:\NVIDIA\DisplayDriver\372.54\Win10_64\International\Display.DriverExit the Nvidia installer once it unpacked the files !!!
  4. Download the Windows WDK from here: https://developer.microsoft.com/en-us/windows/hardware/windows-driver-kitOn the webpage that opens, go to step 2, then click “Install Windows Driver Kit (WDK) 10”. You do NOT need to install the other stuff!

    Run the installer and install the Windows Driver Kit (WDK).

  5. Download Python from https://www.python.org/downloads/. As of this writing the latest version is 3.5.2Run the installer.
  6. To enable testsigning:
    1. Right-click on the Windows menu icon and select “Command Prompt (Admin)”
    2. On the command prompt, enter
      Bcdedit.exe -set TESTSIGNING ON</code>

      and press Enter

    Later, if you wish to disable testsigning, use the following command:

    Bcdedit.exe -set TESTSIGNING OFF

    Important: Please be aware of the security risks when you run testsigned drivers.

  7. Reboot your Windows 10 VM.
  8. Open https://github.com/sk1080/nvidia-kvm-patcher and download the two script files (a Powershell script and a Python script):
    • gencert.ps1
    • patcher.py

    Both files must reside in the same location. (Note: I opened the file, copied the content into an empty Notepad file and saved it.)

  9. Open the Windows File Explorer and go to the folder where you saved the two files.Click “File”, then select “Open command prompt” -> “Open command prompt as administrator”.
  10. Before running the script, open the patcher.py file in Notepad or with IDLE (right click on the file and select) and check that the driver version you are going to install is actually supported by this patch. See below for reference:
    # TODO: Wildcard Search
    PATCHES = {
    “41FF978804000085C0”: “31C0909090909085C0”, # 361.91 – 368.39
    “41FF97B804000085C0”: “31C0909090909085C0”, # 372.54
    }
  11. Copy and paste the following onto the command line:
    patcher.py C:\NVIDIA\DisplayDriver\372.54\Win10_64\International\Display.Driver

    and hit Enter.Note: Replace the version (here “372.54”) in the path name with the Nvidia driver version you downloaded.

    The patcher.py script will run for a few minutes, after which you see “Warnings: None”. Hit Enter.

    The Python script will now execute the Powershell script and testsign the driver.

  12. Using the File Explorer, go to
    C:\NVIDIA\DisplayDriver\372.54\Win10_64\International

    and run “setup.exe” to install the patched Nvidia driver.

  13. Shutdown Windows and modify your qemu start script:
    -cpu host,hv_vapic,hv_time,hv_relaxed,hv_spinlocks=0x1fff \
    

    Note: Remove the “kvm=off” option and instead add “hv_vapic,hv_time,hv_relaxed,hv_spinlocks=0x1fff”