diff --git a/qemu-doc.texi b/qemu-doc.texi index 89fa80518a2fd1cce00b5099fbb35ec60a67a2d6..5813d276156a4be6516c80b5d133c747fcd48733 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -140,6 +140,7 @@ accelerator is required to use more than one host CPU for emulation. * direct_linux_boot:: Direct Linux Boot * pcsys_usb:: USB emulation * vnc_security:: VNC security +* network_tls:: TLS setup for network services * gdb_usage:: GDB usage * pcsys_os_specific:: Target OS specific information @end menu @@ -1041,7 +1042,6 @@ considerations depending on the deployment scenarios. * vnc_sec_certificate_pw:: * vnc_sec_sasl:: * vnc_sec_certificate_sasl:: -* vnc_generate_cert:: * vnc_setup_sasl:: @end menu @node vnc_sec_none @@ -1161,25 +1161,105 @@ with the aforementioned TLS + x509 options: qemu-system-i386 [...OPTIONS...] -vnc :1,tls,x509,sasl -monitor stdio @end example +@node vnc_setup_sasl -@node vnc_generate_cert -@subsection Generating certificates for VNC +@subsection Configuring SASL mechanisms -The GNU TLS packages provides a command called @code{certtool} which can -be used to generate certificates and keys in PEM format. At a minimum it -is necessary to setup a certificate authority, and issue certificates to -each server. If using certificates for authentication, then each client -will also need to be issued a certificate. The recommendation is for the -server to keep its certificates in either @code{/etc/pki/qemu} or for -unprivileged users in @code{$HOME/.pki/qemu}. +The following documentation assumes use of the Cyrus SASL implementation on a +Linux host, but the principles should apply to any other SASL implementation +or host. When SASL is enabled, the mechanism configuration will be loaded from +system default SASL service config /etc/sasl2/qemu.conf. If running QEMU as an +unprivileged user, an environment variable SASL_CONF_PATH can be used to make +it search alternate locations for the service config file. + +If the TLS option is enabled for VNC, then it will provide session encryption, +otherwise the SASL mechanism will have to provide encryption. In the latter +case the list of possible plugins that can be used is drastically reduced. In +fact only the GSSAPI SASL mechanism provides an acceptable level of security +by modern standards. Previous versions of QEMU referred to the DIGEST-MD5 +mechanism, however, it has multiple serious flaws described in detail in +RFC 6331 and thus should never be used any more. The SCRAM-SHA-1 mechanism +provides a simple username/password auth facility similar to DIGEST-MD5, but +does not support session encryption, so can only be used in combination with +TLS. + +When not using TLS the recommended configuration is + +@example +mech_list: gssapi +keytab: /etc/qemu/krb5.tab +@end example + +This says to use the 'GSSAPI' mechanism with the Kerberos v5 protocol, with +the server principal stored in /etc/qemu/krb5.tab. For this to work the +administrator of your KDC must generate a Kerberos principal for the server, +with a name of 'qemu/somehost.example.com@@EXAMPLE.COM' replacing +'somehost.example.com' with the fully qualified host name of the machine +running QEMU, and 'EXAMPLE.COM' with the Kerberos Realm. + +When using TLS, if username+password authentication is desired, then a +reasonable configuration is + +@example +mech_list: scram-sha-1 +sasldb_path: /etc/qemu/passwd.db +@end example + +The @code{saslpasswd2} program can be used to populate the @code{passwd.db} +file with accounts. + +Other SASL configurations will be left as an exercise for the reader. Note that +all mechanisms, except GSSAPI, should be combined with use of TLS to ensure a +secure data channel. + + +@node network_tls +@section TLS setup for network services + +Almost all network services in QEMU have the ability to use TLS for +session data encryption, along with x509 certificates for simple +client authentication. What follows is a description of how to +generate certificates suitable for usage with QEMU, and applies to +the VNC server, character devices with the TCP backend, NBD server +and client, and migration server and client. + +At a high level, QEMU requires certificates and private keys to be +provided in PEM format. Aside from the core fields, the certificates +should include various extension data sets, including v3 basic +constraints data, key purpose, key usage and subject alt name. + +The GnuTLS package includes a command called @code{certtool} which can +be used to easily generate certificates and keys in the required format +with expected data present. Alternatively a certificate management +service may be used. + +At a minimum it is necessary to setup a certificate authority, and +issue certificates to each server. If using x509 certificates for +authentication, then each client will also need to be issued a +certificate. + +Assuming that the QEMU network services will only ever be exposed to +clients on a private intranet, there is no need to use a commercial +certificate authority to create certificates. A self-signed CA is +sufficient, and in fact likely to be more secure since it removes +the ability of malicious 3rd parties to trick the CA into mis-issuing +certs for impersonating your services. The only likely exception +where a commercial CA might be desirable is if enabling the VNC +websockets server and exposing it directly to remote browser clients. +In such a case it might be useful to use a commercial CA to avoid +needing to install custom CA certs in the web browsers. + +The recommendation is for the server to keep its certificates in either +@code{/etc/pki/qemu} or for unprivileged users in @code{$HOME/.pki/qemu}. @menu -* vnc_generate_ca:: -* vnc_generate_server:: -* vnc_generate_client:: +* tls_generate_ca:: +* tls_generate_server:: +* tls_generate_client:: +* tls_creds_setup:: @end menu -@node vnc_generate_ca -@subsubsection Setup the Certificate Authority +@node tls_generate_ca +@subsection Setup the Certificate Authority This step only needs to be performed once per organization / organizational unit. First the CA needs a private key. This key must be kept VERY secret @@ -1190,11 +1270,10 @@ issued with it is lost. # certtool --generate-privkey > ca-key.pem @end example -A CA needs to have a public certificate. For simplicity it can be a self-signed -certificate, or one issue by a commercial certificate issuing authority. To -generate a self-signed certificate requires one core piece of information, the -name of the organization. - +To generate a self-signed certificate requires one core piece of information, +the name of the organization. A template file @code{ca.info} should be +populated with the desired data to avoid having to deal with interactive +prompts from certtool: @example # cat > ca.info < server.info < server-hostNNN.info < server-key.pem +# certtool --generate-privkey > server-hostNNN-key.pem # certtool --generate-certificate \ --load-ca-certificate ca-cert.pem \ --load-ca-privkey ca-key.pem \ - --load-privkey server-key.pem \ - --template server.info \ - --outfile server-cert.pem + --load-privkey server-hostNNN-key.pem \ + --template server-hostNNN.info \ + --outfile server-hostNNN-cert.pem @end example -The @code{server-key.pem} and @code{server-cert.pem} files should now be securely copied -to the server for which they were generated. The @code{server-key.pem} is security -sensitive and should be kept protected with file mode 0600 to prevent disclosure. +The @code{dns_name} and @code{ip_address} fields in the template are setting +the subject alt name extension data. The @code{tls_www_server} keyword is the +key purpose extension to indicate this certificate is intended for usage in +a web server. Although QEMU network services are not in fact HTTP servers +(except for VNC websockets), setting this key purpose is still recommended. +The @code{encryption_key} and @code{signing_key} keyword is the key usage +extension to indicate this certificate is intended for usage in the data +session. -@node vnc_generate_client -@subsubsection Issuing client certificates +The @code{server-hostNNN-key.pem} and @code{server-hostNNN-cert.pem} files +should now be securely copied to the server for which they were generated, +and renamed to @code{server-key.pem} and @code{server-cert.pem} when added +to the @code{/etc/pki/qemu} directory on the target host. The @code{server-key.pem} +file is security sensitive and should be kept protected with file mode 0600 +to prevent disclosure. + +@node tls_generate_client +@subsection Issuing client certificates + +The QEMU x509 TLS credential setup defaults to enabling client verification +using certificates, providing a simple authentication mechanism. If this +default is used, each client also needs to be issued a certificate. The client +certificate contains enough metadata to uniquely identify the client with the +scope of the certificate authority. The client certificate would typically +include fields for organization, state, city, building, etc. + +Once again on the host holding the CA, create template files containing the +information for each client, and use it to issue client certificates. -If the QEMU VNC server is to use the @code{x509verify} option to validate client -certificates as its authentication mechanism, each client also needs to be issued -a certificate. The client certificate contains enough metadata to uniquely identify -the client, typically organization, state, city, building, etc. On the host holding -the secure CA private key: @example -# cat > client.info < client-hostNNN.info < client-key.pem +# certtool --generate-privkey > client-hostNNN-key.pem # certtool --generate-certificate \ --load-ca-certificate ca-cert.pem \ --load-ca-privkey ca-key.pem \ - --load-privkey client-key.pem \ - --template client.info \ - --outfile client-cert.pem + --load-privkey client-hostNNN-key.pem \ + --template client-hostNNN.info \ + --outfile client-hostNNN-cert.pem +@end example + +The subject alt name extension data is not required for clients, so the +the @code{dns_name} and @code{ip_address} fields are not included. +The @code{tls_www_client} keyword is the key purpose extension to indicate +this certificate is intended for usage in a web client. Although QEMU +network clients are not in fact HTTP clients, setting this key purpose is +still recommended. The @code{encryption_key} and @code{signing_key} keyword +is the key usage extension to indicate this certificate is intended for +usage in the data session. + +The @code{client-hostNNN-key.pem} and @code{client-hostNNN-cert.pem} files +should now be securely copied to the client for which they were generated, +and renamed to @code{client-key.pem} and @code{client-cert.pem} when added +to the @code{/etc/pki/qemu} directory on the target host. The @code{client-key.pem} +file is security sensitive and should be kept protected with file mode 0600 +to prevent disclosure. + +If a single host is going to be using TLS in both a client and server +role, it is possible to create a single certificate to cover both roles. +This would be quite common for the migration and NBD services, where a +QEMU process will be started by accepting a TLS protected incoming migration, +and later itself be migrated out to another host. To generate a single +certificate, simply include the template data from both the client and server +instructions in one. + +@example +# cat > both-hostNNN.info < both-hostNNN-key.pem +# certtool --generate-certificate \ + --load-ca-certificate ca-cert.pem \ + --load-ca-privkey ca-key.pem \ + --load-privkey both-hostNNN-key.pem \ + --template both-hostNNN.info \ + --outfile both-hostNNN-cert.pem @end example -The @code{client-key.pem} and @code{client-cert.pem} files should now be securely -copied to the client for which they were generated. +When copying the PEM files to the target host, save them twice, +once as @code{server-cert.pem} and @code{server-key.pem}, and +again as @code{client-cert.pem} and @code{client-key.pem}. +@node tls_creds_setup +@subsection TLS x509 credential configuration -@node vnc_setup_sasl +QEMU has a standard mechanism for loading x509 credentials that will be +used for network services and clients. It requires specifying the +@code{tls-creds-x509} class name to the @code{--object} command line +argument for the system emulators. Each set of credentials loaded should +be given a unique string identifier via the @code{id} parameter. A single +set of TLS credentials can be used for multiple network backends, so VNC, +migration, NBD, character devices can all share the same credentials. Note, +however, that credentials for use in a client endpoint must be loaded +separately from those used in a server endpoint. -@subsection Configuring SASL mechanisms +When specifying the object, the @code{dir} parameters specifies which +directory contains the credential files. This directory is expected to +contain files with the names mentioned previously, @code{ca-cert.pem}, +@code{server-key.pem}, @code{server-cert.pem}, @code{client-key.pem} +and @code{client-cert.pem} as appropriate. It is also possible to +include a set of pre-generated Diffie-Hellman (DH) parameters in a file +@code{dh-params.pem}, which can be created using the +@code{certtool --generate-dh-params} command. If omitted, QEMU will +dynamically generate DH parameters when loading the credentials. -The following documentation assumes use of the Cyrus SASL implementation on a -Linux host, but the principals should apply to any other SASL impl. When SASL -is enabled, the mechanism configuration will be loaded from system default -SASL service config /etc/sasl2/qemu.conf. If running QEMU as an -unprivileged user, an environment variable SASL_CONF_PATH can be used -to make it search alternate locations for the service config. +The @code{endpoint} parameter indicates whether the credentials will +be used for a network client or server, and determines which PEM +files are loaded. -If the TLS option is enabled for VNC, then it will provide session encryption, -otherwise the SASL mechanism will have to provide encryption. In the latter -case the list of possible plugins that can be used is drastically reduced. In -fact only the GSSAPI SASL mechanism provides an acceptable level of security -by modern standards. Previous versions of QEMU referred to the DIGEST-MD5 -mechanism, however, it has multiple serious flaws described in detail in -RFC 6331 and thus should never be used any more. The SCRAM-SHA-1 mechanism -provides a simple username/password auth facility similar to DIGEST-MD5, but -does not support session encryption, so can only be used in combination with -TLS. +The @code{verify} parameter determines whether x509 certificate +validation should be performed. This defaults to enabled, meaning +clients will always validate the server hostname against the +certificate subject alt name fields and/or CN field. It also +means that servers will request that clients provide a certificate +and validate them. Verification should never be turned off for +client endpoints, however, it may be turned off for server endpoints +if an alternative mechanism is used to authenticate clients. For +example, the VNC server can use SASL to authenticate clients +instead. -When not using TLS the recommended configuration is +To load server credentials with client certificate validation +enabled @example -mech_list: gssapi -keytab: /etc/qemu/krb5.tab +$QEMU -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server @end example -This says to use the 'GSSAPI' mechanism with the Kerberos v5 protocol, with -the server principal stored in /etc/qemu/krb5.tab. For this to work the -administrator of your KDC must generate a Kerberos principal for the server, -with a name of 'qemu/somehost.example.com@@EXAMPLE.COM' replacing -'somehost.example.com' with the fully qualified host name of the machine -running QEMU, and 'EXAMPLE.COM' with the Kerberos Realm. - -When using TLS, if username+password authentication is desired, then a -reasonable configuration is +while to load client credentials use @example -mech_list: scram-sha-1 -sasldb_path: /etc/qemu/passwd.db +$QEMU -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=client @end example -The saslpasswd2 program can be used to populate the passwd.db file with -accounts. +Network services which support TLS will all have a @code{tls-creds} +parameter which expects the ID of the TLS credentials object. For +example with VNC: -Other SASL configurations will be left as an exercise for the reader. Note that -all mechanisms except GSSAPI, should be combined with use of TLS to ensure a -secure data channel. +@example +$QEMU -vnc 0.0.0.0:0,tls-creds=tls0 +@end example @node gdb_usage @section GDB usage diff --git a/qemu-options.hx b/qemu-options.hx index 3ece30d216a1350fade9869eda3a475bc4eeb0ea..ca4e412f2f89d9cb7cc202449bc211313b209e4b 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4112,7 +4112,7 @@ expensive operation that consumes random pool entropy, so it is recommended that a persistent set of parameters be generated upfront and saved. -@item -object tls-creds-x509,id=@var{id},endpoint=@var{endpoint},dir=@var{/path/to/cred/dir},verify-peer=@var{on|off},passwordid=@var{id} +@item -object tls-creds-x509,id=@var{id},endpoint=@var{endpoint},dir=@var{/path/to/cred/dir},priority=@var{priority},verify-peer=@var{on|off},passwordid=@var{id} Creates a TLS anonymous credentials object, which can be used to provide TLS support on network backends. The @option{id} parameter is a unique @@ -4145,6 +4145,15 @@ version by providing the @var{passwordid} parameter. This provides the ID of a previously created @code{secret} object containing the password for decryption. +The @var{priority} parameter allows to override the global default +priority used by gnutls. This can be useful if the system administrator +needs to use a weaker set of crypto priorities for QEMU without +potentially forcing the weakness onto all applications. Or conversely +if one wants wants a stronger default for QEMU than for all other +applications, they can do this through this parameter. Its format is +a gnutls priority string as described at +@url{https://gnutls.org/manual/html_node/Priority-Strings.html}. + @item -object filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}][,status=@var{on|off}] Interval @var{t} can't be 0, this filter batches the packet delivery: all diff --git a/tests/test-crypto-tlssession.c b/tests/test-crypto-tlssession.c index 1a4a066d76c8597bfd06ca091e8082e35e4da916..82f21c27f270bc10f9e72e0beec33b6024d87df4 100644 --- a/tests/test-crypto-tlssession.c +++ b/tests/test-crypto-tlssession.c @@ -75,6 +75,7 @@ static QCryptoTLSCreds *test_tls_creds_create(QCryptoTLSCredsEndpoint endpoint, "server" : "client"), "dir", certdir, "verify-peer", "yes", + "priority", "NORMAL", /* We skip initial sanity checks here because we * want to make sure that problems are being * detected at the TLS session validation stage, diff --git a/tests/test-io-channel-tls.c b/tests/test-io-channel-tls.c index 32743b2c9637beb99601d269293106d6656d2c8b..bb88ee870f0e26a9f8f3052631c3261dc0507191 100644 --- a/tests/test-io-channel-tls.c +++ b/tests/test-io-channel-tls.c @@ -78,6 +78,7 @@ static QCryptoTLSCreds *test_tls_creds_create(QCryptoTLSCredsEndpoint endpoint, "server" : "client"), "dir", certdir, "verify-peer", "yes", + "priority", "NORMAL", /* We skip initial sanity checks here because we * want to make sure that problems are being * detected at the TLS session validation stage,