mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-27 22:03:47 +00:00 
			
		
		
		
	 c5ba621954
			
		
	
	
		c5ba621954
		
	
	
	
	
		
			
			Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-Id: <20211118192744.64325-1-philmd@redhat.com> Reviewed-by: Darren Kenny <darren.kenny@oracle.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
		
			
				
	
	
		
			329 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			329 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| .. _network_005ftls:
 | |
| 
 | |
| 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 ``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
 | |
| ``/etc/pki/qemu`` or for unprivileged users in ``$HOME/.pki/qemu``.
 | |
| 
 | |
| .. _tls_005fgenerate_005fca:
 | |
| 
 | |
| 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.
 | |
| 
 | |
| ::
 | |
| 
 | |
|    # certtool --generate-privkey > ca-key.pem
 | |
| 
 | |
| To generate a self-signed certificate requires one core piece of
 | |
| information, the name of the organization. A template file ``ca.info``
 | |
| should be populated with the desired data to avoid having to deal with
 | |
| interactive prompts from certtool::
 | |
| 
 | |
|    # 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
 | |
| 
 | |
| The ``ca`` keyword in the template sets the v3 basic constraints
 | |
| extension to indicate this certificate is for a CA, while
 | |
| ``cert_signing_key`` sets the key usage extension to indicate this will
 | |
| be used for signing other keys. The generated ``ca-cert.pem`` file
 | |
| should be copied to all servers and clients wishing to utilize TLS
 | |
| support in the VNC server. The ``ca-key.pem`` must not be
 | |
| disclosed/copied anywhere except the host responsible for issuing
 | |
| certificates.
 | |
| 
 | |
| .. _tls_005fgenerate_005fserver:
 | |
| 
 | |
| 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 ``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 ``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.
 | |
| 
 | |
| ::
 | |
| 
 | |
|    # 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
 | |
| 
 | |
| The ``dns_name`` and ``ip_address`` fields in the template are setting
 | |
| the subject alt name extension data. The ``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 ``encryption_key`` and ``signing_key`` keyword is
 | |
| the key usage extension to indicate this certificate is intended for
 | |
| usage in the data session.
 | |
| 
 | |
| The ``server-hostNNN-key.pem`` and ``server-hostNNN-cert.pem`` files
 | |
| should now be securely copied to the server for which they were
 | |
| generated, and renamed to ``server-key.pem`` and ``server-cert.pem``
 | |
| when added to the ``/etc/pki/qemu`` directory on the target host. The
 | |
| ``server-key.pem`` file is security sensitive and should be kept
 | |
| protected with file mode 0600 to prevent disclosure.
 | |
| 
 | |
| .. _tls_005fgenerate_005fclient:
 | |
| 
 | |
| 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.
 | |
| 
 | |
| ::
 | |
| 
 | |
|    # 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
 | |
| 
 | |
| The subject alt name extension data is not required for clients, so the
 | |
| the ``dns_name`` and ``ip_address`` fields are not included. The
 | |
| ``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 ``encryption_key`` and ``signing_key`` keyword is the
 | |
| key usage extension to indicate this certificate is intended for usage
 | |
| in the data session.
 | |
| 
 | |
| The ``client-hostNNN-key.pem`` and ``client-hostNNN-cert.pem`` files
 | |
| should now be securely copied to the client for which they were
 | |
| generated, and renamed to ``client-key.pem`` and ``client-cert.pem``
 | |
| when added to the ``/etc/pki/qemu`` directory on the target host. The
 | |
| ``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.
 | |
| 
 | |
| ::
 | |
| 
 | |
|    # 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
 | |
| 
 | |
| When copying the PEM files to the target host, save them twice, once as
 | |
| ``server-cert.pem`` and ``server-key.pem``, and again as
 | |
| ``client-cert.pem`` and ``client-key.pem``.
 | |
| 
 | |
| .. _tls_005fcreds_005fsetup:
 | |
| 
 | |
| 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
 | |
| ``tls-creds-x509`` class name to the ``--object`` command line argument
 | |
| for the system emulators. Each set of credentials loaded should be given
 | |
| a unique string identifier via the ``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 ``dir`` parameters specifies which
 | |
| directory contains the credential files. This directory is expected to
 | |
| contain files with the names mentioned previously, ``ca-cert.pem``,
 | |
| ``server-key.pem``, ``server-cert.pem``, ``client-key.pem`` and
 | |
| ``client-cert.pem`` as appropriate. It is also possible to include a set
 | |
| of pre-generated Diffie-Hellman (DH) parameters in a file
 | |
| ``dh-params.pem``, which can be created using the
 | |
| ``certtool --generate-dh-params`` command. If omitted, QEMU will
 | |
| dynamically generate DH parameters when loading the credentials.
 | |
| 
 | |
| The ``endpoint`` parameter indicates whether the credentials will be
 | |
| used for a network client or server, and determines which PEM files are
 | |
| loaded.
 | |
| 
 | |
| The ``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
 | |
| 
 | |
| .. parsed-literal::
 | |
| 
 | |
|    |qemu_system| -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server
 | |
| 
 | |
| while to load client credentials use
 | |
| 
 | |
| .. parsed-literal::
 | |
| 
 | |
|    |qemu_system| -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=client
 | |
| 
 | |
| Network services which support TLS will all have a ``tls-creds``
 | |
| parameter which expects the ID of the TLS credentials object. For
 | |
| example with VNC:
 | |
| 
 | |
| .. parsed-literal::
 | |
| 
 | |
|    |qemu_system| -vnc 0.0.0.0:0,tls-creds=tls0
 | |
| 
 | |
| .. _tls_005fpsk:
 | |
| 
 | |
| 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 ``psktool`` program to generate a ``keys.psk`` file
 | |
| containing one or more usernames and random keys::
 | |
| 
 | |
|    mkdir -m 0700 /tmp/keys
 | |
|    psktool -u rich -p /tmp/keys/keys.psk
 | |
| 
 | |
| TLS-enabled servers such as ``qemu-nbd`` can use this directory like so::
 | |
| 
 | |
|    qemu-nbd \
 | |
|      -t -x / \
 | |
|      --object tls-creds-psk,id=tls0,endpoint=server,dir=/tmp/keys \
 | |
|      --tls-creds tls0 \
 | |
|      image.qcow2
 | |
| 
 | |
| When connecting from a qemu-based client you must specify the directory
 | |
| containing ``keys.psk`` and an optional username (defaults to "qemu")::
 | |
| 
 | |
|    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=/
 |