diff options
Diffstat (limited to 'docs/system/tls.texi')
-rw-r--r-- | docs/system/tls.texi | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/docs/system/tls.texi b/docs/system/tls.texi new file mode 100644 index 0000000000..c233531d3a --- /dev/null +++ b/docs/system/tls.texi @@ -0,0 +1,329 @@ +@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 +* tls_generate_ca:: +* tls_generate_server:: +* tls_generate_client:: +* tls_creds_setup:: +* tls_psk:: +@end menu +@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 +and secure. If this key is compromised the entire trust chain of the certificates +issued with it is lost. + +@example +# certtool --generate-privkey > ca-key.pem +@end example + +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 <<EOF +cn = Name of your organization +ca +cert_signing_key +EOF +# certtool --generate-self-signed \ + --load-privkey ca-key.pem + --template ca.info \ + --outfile ca-cert.pem +@end example + +The @code{ca} keyword in the template sets the v3 basic constraints extension +to indicate this certificate is for a CA, while @code{cert_signing_key} sets +the key usage extension to indicate this will be used for signing other keys. +The generated @code{ca-cert.pem} file should be copied to all servers and +clients wishing to utilize TLS support in the VNC server. The @code{ca-key.pem} +must not be disclosed/copied anywhere except the host responsible for issuing +certificates. + +@node tls_generate_server +@subsection Issuing server certificates + +Each server (or host) needs to be issued with a key and certificate. When connecting +the certificate is sent to the client which validates it against the CA certificate. +The core pieces of information for a server certificate are the hostnames and/or IP +addresses that will be used by clients when connecting. The hostname / IP address +that the client specifies when connecting will be validated against the hostname(s) +and IP address(es) recorded in the server certificate, and if no match is found +the client will close the connection. + +Thus it is recommended that the server certificate include both the fully qualified +and unqualified hostnames. If the server will have permanently assigned IP address(es), +and clients are likely to use them when connecting, they may also be included in the +certificate. Both IPv4 and IPv6 addresses are supported. Historically certificates +only included 1 hostname in the @code{CN} field, however, usage of this field for +validation is now deprecated. Instead modern TLS clients will validate against the +Subject Alt Name extension data, which allows for multiple entries. In the future +usage of the @code{CN} field may be discontinued entirely, so providing SAN +extension data is strongly recommended. + +On the host holding the CA, create template files containing the information +for each server, and use it to issue server certificates. + +@example +# cat > server-hostNNN.info <<EOF +organization = Name of your organization +cn = hostNNN.foo.example.com +dns_name = hostNNN +dns_name = hostNNN.foo.example.com +ip_address = 10.0.1.87 +ip_address = 192.8.0.92 +ip_address = 2620:0:cafe::87 +ip_address = 2001:24::92 +tls_www_server +encryption_key +signing_key +EOF +# 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-hostNNN-key.pem \ + --template server-hostNNN.info \ + --outfile server-hostNNN-cert.pem +@end example + +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. + +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. + + +@example +# cat > client-hostNNN.info <<EOF +country = GB +state = London +locality = City Of London +organization = Name of your organization +cn = hostNNN.foo.example.com +tls_www_client +encryption_key +signing_key +EOF +# 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-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 <<EOF +country = GB +state = London +locality = City Of London +organization = Name of your organization +cn = hostNNN.foo.example.com +dns_name = hostNNN +dns_name = hostNNN.foo.example.com +ip_address = 10.0.1.87 +ip_address = 192.8.0.92 +ip_address = 2620:0:cafe::87 +ip_address = 2001:24::92 +tls_www_server +tls_www_client +encryption_key +signing_key +EOF +# certtool --generate-privkey > 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 + +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 + +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. + +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 @code{endpoint} parameter indicates whether the credentials will +be used for a network client or server, and determines which PEM +files are loaded. + +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. + +To load server credentials with client certificate validation +enabled + +@example +@value{qemu_system} -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server +@end example + +while to load client credentials use + +@example +@value{qemu_system} -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=client +@end example + +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: + +@example +@value{qemu_system} -vnc 0.0.0.0:0,tls-creds=tls0 +@end example + +@node tls_psk +@subsection TLS Pre-Shared Keys (PSK) + +Instead of using certificates, you may also use TLS Pre-Shared Keys +(TLS-PSK). This can be simpler to set up than certificates but is +less scalable. + +Use the GnuTLS @code{psktool} program to generate a @code{keys.psk} +file containing one or more usernames and random keys: + +@example +mkdir -m 0700 /tmp/keys +psktool -u rich -p /tmp/keys/keys.psk +@end example + +TLS-enabled servers such as qemu-nbd can use this directory like so: + +@example +qemu-nbd \ + -t -x / \ + --object tls-creds-psk,id=tls0,endpoint=server,dir=/tmp/keys \ + --tls-creds tls0 \ + image.qcow2 +@end example + +When connecting from a qemu-based client you must specify the +directory containing @code{keys.psk} and an optional @var{username} +(defaults to ``qemu''): + +@example +qemu-img info \ + --object tls-creds-psk,id=tls0,dir=/tmp/keys,username=rich,endpoint=client \ + --image-opts \ + file.driver=nbd,file.host=localhost,file.port=10809,file.tls-creds=tls0,file.export=/ +@end example + |