xref: /openbmc/qemu/docs/system/tls.rst (revision 072470dfae125f5622e2250ebd1daf626d4023b7)
1.. _network_005ftls:
2
3TLS setup for network services
4------------------------------
5
6Almost all network services in QEMU have the ability to use TLS for
7session data encryption, along with x509 certificates for simple client
8authentication. What follows is a description of how to generate
9certificates suitable for usage with QEMU, and applies to the VNC
10server, character devices with the TCP backend, NBD server and client,
11and migration server and client.
12
13At a high level, QEMU requires certificates and private keys to be
14provided in PEM format. Aside from the core fields, the certificates
15should include various extension data sets, including v3 basic
16constraints data, key purpose, key usage and subject alt name.
17
18The GnuTLS package includes a command called ``certtool`` which can be
19used to easily generate certificates and keys in the required format
20with expected data present. Alternatively a certificate management
21service may be used.
22
23At a minimum it is necessary to setup a certificate authority, and issue
24certificates to each server. If using x509 certificates for
25authentication, then each client will also need to be issued a
26certificate.
27
28Assuming that the QEMU network services will only ever be exposed to
29clients on a private intranet, there is no need to use a commercial
30certificate authority to create certificates. A self-signed CA is
31sufficient, and in fact likely to be more secure since it removes the
32ability of malicious 3rd parties to trick the CA into mis-issuing certs
33for impersonating your services. The only likely exception where a
34commercial CA might be desirable is if enabling the VNC websockets
35server and exposing it directly to remote browser clients. In such a
36case it might be useful to use a commercial CA to avoid needing to
37install custom CA certs in the web browsers.
38
39The recommendation is for the server to keep its certificates in either
40``/etc/pki/qemu`` or for unprivileged users in ``$HOME/.pki/qemu``.
41
42.. _tls_005fgenerate_005fca:
43
44Setup the Certificate Authority
45~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46
47This step only needs to be performed once per organization /
48organizational unit. First the CA needs a private key. This key must be
49kept VERY secret and secure. If this key is compromised the entire trust
50chain of the certificates issued with it is lost.
51
52::
53
54   # certtool --generate-privkey > ca-key.pem
55
56To generate a self-signed certificate requires one core piece of
57information, the name of the organization. A template file ``ca.info``
58should be populated with the desired data to avoid having to deal with
59interactive prompts from certtool::
60
61   # cat > ca.info <<EOF
62   cn = Name of your organization
63   ca
64   cert_signing_key
65   EOF
66   # certtool --generate-self-signed \
67              --load-privkey ca-key.pem \
68              --template ca.info \
69              --outfile ca-cert.pem
70
71The ``ca`` keyword in the template sets the v3 basic constraints
72extension to indicate this certificate is for a CA, while
73``cert_signing_key`` sets the key usage extension to indicate this will
74be used for signing other keys. The generated ``ca-cert.pem`` file
75should be copied to all servers and clients wishing to utilize TLS
76support in the VNC server. The ``ca-key.pem`` must not be
77disclosed/copied anywhere except the host responsible for issuing
78certificates.
79
80.. _tls_005fgenerate_005fserver:
81
82Issuing server certificates
83~~~~~~~~~~~~~~~~~~~~~~~~~~~
84
85Each server (or host) needs to be issued with a key and certificate.
86When connecting the certificate is sent to the client which validates it
87against the CA certificate. The core pieces of information for a server
88certificate are the hostnames and/or IP addresses that will be used by
89clients when connecting. The hostname / IP address that the client
90specifies when connecting will be validated against the hostname(s) and
91IP address(es) recorded in the server certificate, and if no match is
92found the client will close the connection.
93
94Thus it is recommended that the server certificate include both the
95fully qualified and unqualified hostnames. If the server will have
96permanently assigned IP address(es), and clients are likely to use them
97when connecting, they may also be included in the certificate. Both IPv4
98and IPv6 addresses are supported. Historically certificates only
99included 1 hostname in the ``CN`` field, however, usage of this field
100for validation is now deprecated. Instead modern TLS clients will
101validate against the Subject Alt Name extension data, which allows for
102multiple entries. In the future usage of the ``CN`` field may be
103discontinued entirely, so providing SAN extension data is strongly
104recommended.
105
106On the host holding the CA, create template files containing the
107information for each server, and use it to issue server certificates.
108
109::
110
111   # cat > server-hostNNN.info <<EOF
112   organization = Name  of your organization
113   cn = hostNNN.foo.example.com
114   dns_name = hostNNN
115   dns_name = hostNNN.foo.example.com
116   ip_address = 10.0.1.87
117   ip_address = 192.8.0.92
118   ip_address = 2620:0:cafe::87
119   ip_address = 2001:24::92
120   tls_www_server
121   signing_key
122   EOF
123   # certtool --generate-privkey > server-hostNNN-key.pem
124   # certtool --generate-certificate \
125              --load-ca-certificate ca-cert.pem \
126              --load-ca-privkey ca-key.pem \
127              --load-privkey server-hostNNN-key.pem \
128              --template server-hostNNN.info \
129              --outfile server-hostNNN-cert.pem
130
131The ``dns_name`` and ``ip_address`` fields in the template are setting
132the subject alt name extension data. The ``tls_www_server`` keyword is
133the key purpose extension to indicate this certificate is intended for
134usage in a web server. Although QEMU network services are not in fact
135HTTP servers (except for VNC websockets), setting this key purpose is
136still recommended. The ``signing_key`` keyword is the key usage extension
137to indicate this certificate is intended for usage in the data session.
138
139The ``server-hostNNN-key.pem`` and ``server-hostNNN-cert.pem`` files
140should now be securely copied to the server for which they were
141generated, and renamed to ``server-key.pem`` and ``server-cert.pem``
142when added to the ``/etc/pki/qemu`` directory on the target host. The
143``server-key.pem`` file is security sensitive and should be kept
144protected with file mode 0600 to prevent disclosure.
145
146.. _tls_005fgenerate_005fclient:
147
148Issuing client certificates
149~~~~~~~~~~~~~~~~~~~~~~~~~~~
150
151The QEMU x509 TLS credential setup defaults to enabling client
152verification using certificates, providing a simple authentication
153mechanism. If this default is used, each client also needs to be issued
154a certificate. The client certificate contains enough metadata to
155uniquely identify the client with the scope of the certificate
156authority. The client certificate would typically include fields for
157organization, state, city, building, etc.
158
159Once again on the host holding the CA, create template files containing
160the information for each client, and use it to issue client
161certificates.
162
163::
164
165   # cat > client-hostNNN.info <<EOF
166   country = GB
167   state = London
168   locality = City Of London
169   organization = Name of your organization
170   cn = hostNNN.foo.example.com
171   tls_www_client
172   signing_key
173   EOF
174   # certtool --generate-privkey > client-hostNNN-key.pem
175   # certtool --generate-certificate \
176              --load-ca-certificate ca-cert.pem \
177              --load-ca-privkey ca-key.pem \
178              --load-privkey client-hostNNN-key.pem \
179              --template client-hostNNN.info \
180              --outfile client-hostNNN-cert.pem
181
182The subject alt name extension data is not required for clients, so
183the ``dns_name`` and ``ip_address`` fields are not included. The
184``tls_www_client`` keyword is the key purpose extension to indicate this
185certificate is intended for usage in a web client. Although QEMU network
186clients are not in fact HTTP clients, setting this key purpose is still
187recommended. The ``signing_key`` keyword is the key usage extension to
188indicate this certificate is intended for usage in the data session.
189
190The ``client-hostNNN-key.pem`` and ``client-hostNNN-cert.pem`` files
191should now be securely copied to the client for which they were
192generated, and renamed to ``client-key.pem`` and ``client-cert.pem``
193when added to the ``/etc/pki/qemu`` directory on the target host. The
194``client-key.pem`` file is security sensitive and should be kept
195protected with file mode 0600 to prevent disclosure.
196
197If a single host is going to be using TLS in both a client and server
198role, it is possible to create a single certificate to cover both roles.
199This would be quite common for the migration and NBD services, where a
200QEMU process will be started by accepting a TLS protected incoming
201migration, and later itself be migrated out to another host. To generate
202a single certificate, simply include the template data from both the
203client and server instructions in one.
204
205::
206
207   # cat > both-hostNNN.info <<EOF
208   country = GB
209   state = London
210   locality = City Of London
211   organization = Name of your organization
212   cn = hostNNN.foo.example.com
213   dns_name = hostNNN
214   dns_name = hostNNN.foo.example.com
215   ip_address = 10.0.1.87
216   ip_address = 192.8.0.92
217   ip_address = 2620:0:cafe::87
218   ip_address = 2001:24::92
219   tls_www_server
220   tls_www_client
221   signing_key
222   EOF
223   # certtool --generate-privkey > both-hostNNN-key.pem
224   # certtool --generate-certificate \
225              --load-ca-certificate ca-cert.pem \
226              --load-ca-privkey ca-key.pem \
227              --load-privkey both-hostNNN-key.pem \
228              --template both-hostNNN.info \
229              --outfile both-hostNNN-cert.pem
230
231When copying the PEM files to the target host, save them twice, once as
232``server-cert.pem`` and ``server-key.pem``, and again as
233``client-cert.pem`` and ``client-key.pem``.
234
235.. _tls_005fcreds_005fsetup:
236
237TLS x509 credential configuration
238~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
239
240QEMU has a standard mechanism for loading x509 credentials that will be
241used for network services and clients. It requires specifying the
242``tls-creds-x509`` class name to the ``--object`` command line argument
243for the system emulators. Each set of credentials loaded should be given
244a unique string identifier via the ``id`` parameter. A single set of TLS
245credentials can be used for multiple network backends, so VNC,
246migration, NBD, character devices can all share the same credentials.
247Note, however, that credentials for use in a client endpoint must be
248loaded separately from those used in a server endpoint.
249
250When specifying the object, the ``dir`` parameters specifies which
251directory contains the credential files. This directory is expected to
252contain files with the names mentioned previously, ``ca-cert.pem``,
253``server-key.pem``, ``server-cert.pem``, ``client-key.pem`` and
254``client-cert.pem`` as appropriate. It is also possible to include a set
255of pre-generated Diffie-Hellman (DH) parameters in a file
256``dh-params.pem``, which can be created using the
257``certtool --generate-dh-params`` command. If omitted, QEMU will
258dynamically generate DH parameters when loading the credentials.
259
260The ``endpoint`` parameter indicates whether the credentials will be
261used for a network client or server, and determines which PEM files are
262loaded.
263
264The ``verify`` parameter determines whether x509 certificate validation
265should be performed. This defaults to enabled, meaning clients will
266always validate the server hostname against the certificate subject alt
267name fields and/or CN field. It also means that servers will request
268that clients provide a certificate and validate them. Verification
269should never be turned off for client endpoints, however, it may be
270turned off for server endpoints if an alternative mechanism is used to
271authenticate clients. For example, the VNC server can use SASL to
272authenticate clients instead.
273
274To load server credentials with client certificate validation enabled
275
276.. parsed-literal::
277
278   |qemu_system| -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server
279
280while to load client credentials use
281
282.. parsed-literal::
283
284   |qemu_system| -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=client
285
286Network services which support TLS will all have a ``tls-creds``
287parameter which expects the ID of the TLS credentials object. For
288example with VNC:
289
290.. parsed-literal::
291
292   |qemu_system| -vnc 0.0.0.0:0,tls-creds=tls0
293
294.. _tls_005fpsk:
295
296TLS Pre-Shared Keys (PSK)
297~~~~~~~~~~~~~~~~~~~~~~~~~
298
299Instead of using certificates, you may also use TLS Pre-Shared Keys
300(TLS-PSK). This can be simpler to set up than certificates but is less
301scalable.
302
303Use the GnuTLS ``psktool`` program to generate a ``keys.psk`` file
304containing one or more usernames and random keys::
305
306   mkdir -m 0700 /tmp/keys
307   psktool -u rich -p /tmp/keys/keys.psk
308
309TLS-enabled servers such as ``qemu-nbd`` can use this directory like so::
310
311   qemu-nbd \
312     -t -x / \
313     --object tls-creds-psk,id=tls0,endpoint=server,dir=/tmp/keys \
314     --tls-creds tls0 \
315     image.qcow2
316
317When connecting from a qemu-based client you must specify the directory
318containing ``keys.psk`` and an optional username (defaults to "qemu")::
319
320   qemu-img info \
321     --object tls-creds-psk,id=tls0,dir=/tmp/keys,username=rich,endpoint=client \
322     --image-opts \
323     file.driver=nbd,file.host=localhost,file.port=10809,file.tls-creds=tls0,file.export=/
324