Files
server/usr/share/doc/qemu-system-common/system/tls.html
2026-01-07 20:52:11 +01:00

444 lines
38 KiB
HTML

<!DOCTYPE html>
<html class="writer-html5" lang="en" data-content_root="../">
<head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TLS setup for network services &mdash; QEMU Debian 1:8.2.2+ds-0ubuntu1.11 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=86f27845" />
<link rel="stylesheet" type="text/css" href="../_static/theme_overrides.css?v=08e6c168" />
<link rel="shortcut icon" href="../_static/qemu_32x32.png"/>
<script src="../_static/jquery.js?v=8dae8fb0"></script>
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="../_static/documentation_options.js?v=802af9f6"></script>
<script src="../_static/doctools.js?v=888ff710"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="../_static/custom.js?v=2ab9f71d"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Providing secret data to QEMU" href="secrets.html" />
<link rel="prev" title="VNC security" href="vnc-security.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" style="background: #802400" >
<a href="../index.html" class="icon icon-home">
QEMU
<img src="../_static/qemu_128x128.png" class="logo" alt="Logo"/>
</a>
<div class="version">
8.2.2
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../about/index.html">About QEMU</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">System Emulation</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="introduction.html">Introduction</a></li>
<li class="toctree-l2"><a class="reference internal" href="invocation.html">Invocation</a></li>
<li class="toctree-l2"><a class="reference internal" href="device-emulation.html">Device Emulation</a></li>
<li class="toctree-l2"><a class="reference internal" href="keys.html">Keys in the graphical frontends</a></li>
<li class="toctree-l2"><a class="reference internal" href="mux-chardev.html">Keys in the character backend multiplexer</a></li>
<li class="toctree-l2"><a class="reference internal" href="monitor.html">QEMU Monitor</a></li>
<li class="toctree-l2"><a class="reference internal" href="images.html">Disk Images</a></li>
<li class="toctree-l2"><a class="reference internal" href="virtio-net-failover.html">QEMU virtio-net standby (net_failover)</a></li>
<li class="toctree-l2"><a class="reference internal" href="linuxboot.html">Direct Linux Boot</a></li>
<li class="toctree-l2"><a class="reference internal" href="generic-loader.html">Generic Loader</a></li>
<li class="toctree-l2"><a class="reference internal" href="guest-loader.html">Guest Loader</a></li>
<li class="toctree-l2"><a class="reference internal" href="barrier.html">QEMU Barrier Client</a></li>
<li class="toctree-l2"><a class="reference internal" href="vnc-security.html">VNC security</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">TLS setup for network services</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#setup-the-certificate-authority">Setup the Certificate Authority</a></li>
<li class="toctree-l3"><a class="reference internal" href="#issuing-server-certificates">Issuing server certificates</a></li>
<li class="toctree-l3"><a class="reference internal" href="#issuing-client-certificates">Issuing client certificates</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tls-x509-credential-configuration">TLS x509 credential configuration</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tls-pre-shared-keys-psk">TLS Pre-Shared Keys (PSK)</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="secrets.html">Providing secret data to QEMU</a></li>
<li class="toctree-l2"><a class="reference internal" href="authz.html">Client authorization</a></li>
<li class="toctree-l2"><a class="reference internal" href="gdb.html">GDB usage</a></li>
<li class="toctree-l2"><a class="reference internal" href="replay.html">Record/replay</a></li>
<li class="toctree-l2"><a class="reference internal" href="managed-startup.html">Managed start up options</a></li>
<li class="toctree-l2"><a class="reference internal" href="bootindex.html">Managing device boot order with bootindex properties</a></li>
<li class="toctree-l2"><a class="reference internal" href="cpu-hotplug.html">Virtual CPU hotplug</a></li>
<li class="toctree-l2"><a class="reference internal" href="pr-manager.html">Persistent reservation managers</a></li>
<li class="toctree-l2"><a class="reference internal" href="targets.html">QEMU System Emulator Targets</a></li>
<li class="toctree-l2"><a class="reference internal" href="security.html">Security</a></li>
<li class="toctree-l2"><a class="reference internal" href="multi-process.html">Multi-process QEMU</a></li>
<li class="toctree-l2"><a class="reference internal" href="confidential-guest-support.html">Confidential Guest Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="vm-templating.html">QEMU VM templating</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../user/index.html">User Mode Emulation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../tools/index.html">Tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../interop/index.html">System Emulation Management and Interoperability</a></li>
<li class="toctree-l1"><a class="reference internal" href="../specs/index.html">System Emulation Guest Hardware Specifications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../devel/index.html">Developer Information</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" style="background: #802400" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">QEMU</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="index.html">System Emulation</a></li>
<li class="breadcrumb-item active">TLS setup for network services</li>
<li class="wy-breadcrumbs-aside">
<a href="https://gitlab.com/qemu-project/qemu/blob/master/docs/system/tls.rst" class="fa fa-gitlab"> Edit on GitLab</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="tls-setup-for-network-services">
<span id="network-005ftls"></span><h1>TLS setup for network services<a class="headerlink" href="#tls-setup-for-network-services" title="Link to this heading"></a></h1>
<p>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.</p>
<p>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.</p>
<p>The GnuTLS package includes a command called <code class="docutils literal notranslate"><span class="pre">certtool</span></code> 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.</p>
<p>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.</p>
<p>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.</p>
<p>The recommendation is for the server to keep its certificates in either
<code class="docutils literal notranslate"><span class="pre">/etc/pki/qemu</span></code> or for unprivileged users in <code class="docutils literal notranslate"><span class="pre">$HOME/.pki/qemu</span></code>.</p>
<section id="setup-the-certificate-authority">
<span id="tls-005fgenerate-005fca"></span><h2>Setup the Certificate Authority<a class="headerlink" href="#setup-the-certificate-authority" title="Link to this heading"></a></h2>
<p>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.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># certtool --generate-privkey &gt; ca-key.pem</span>
</pre></div>
</div>
<p>To generate a self-signed certificate requires one core piece of
information, the name of the organization. A template file <code class="docutils literal notranslate"><span class="pre">ca.info</span></code>
should be populated with the desired data to avoid having to deal with
interactive prompts from certtool:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cat &gt; ca.info &lt;&lt;EOF</span>
<span class="n">cn</span> <span class="o">=</span> <span class="n">Name</span> <span class="n">of</span> <span class="n">your</span> <span class="n">organization</span>
<span class="n">ca</span>
<span class="n">cert_signing_key</span>
<span class="n">EOF</span>
<span class="c1"># certtool --generate-self-signed \</span>
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">privkey</span> <span class="n">ca</span><span class="o">-</span><span class="n">key</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">template</span> <span class="n">ca</span><span class="o">.</span><span class="n">info</span> \
<span class="o">--</span><span class="n">outfile</span> <span class="n">ca</span><span class="o">-</span><span class="n">cert</span><span class="o">.</span><span class="n">pem</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">ca</span></code> keyword in the template sets the v3 basic constraints
extension to indicate this certificate is for a CA, while
<code class="docutils literal notranslate"><span class="pre">cert_signing_key</span></code> sets the key usage extension to indicate this will
be used for signing other keys. The generated <code class="docutils literal notranslate"><span class="pre">ca-cert.pem</span></code> file
should be copied to all servers and clients wishing to utilize TLS
support in the VNC server. The <code class="docutils literal notranslate"><span class="pre">ca-key.pem</span></code> must not be
disclosed/copied anywhere except the host responsible for issuing
certificates.</p>
</section>
<section id="issuing-server-certificates">
<span id="tls-005fgenerate-005fserver"></span><h2>Issuing server certificates<a class="headerlink" href="#issuing-server-certificates" title="Link to this heading"></a></h2>
<p>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.</p>
<p>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 class="docutils literal notranslate"><span class="pre">CN</span></code> 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 class="docutils literal notranslate"><span class="pre">CN</span></code> field may be
discontinued entirely, so providing SAN extension data is strongly
recommended.</p>
<p>On the host holding the CA, create template files containing the
information for each server, and use it to issue server certificates.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cat &gt; server-hostNNN.info &lt;&lt;EOF</span>
<span class="n">organization</span> <span class="o">=</span> <span class="n">Name</span> <span class="n">of</span> <span class="n">your</span> <span class="n">organization</span>
<span class="n">cn</span> <span class="o">=</span> <span class="n">hostNNN</span><span class="o">.</span><span class="n">foo</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="n">dns_name</span> <span class="o">=</span> <span class="n">hostNNN</span>
<span class="n">dns_name</span> <span class="o">=</span> <span class="n">hostNNN</span><span class="o">.</span><span class="n">foo</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="n">ip_address</span> <span class="o">=</span> <span class="mf">10.0.1.87</span>
<span class="n">ip_address</span> <span class="o">=</span> <span class="mf">192.8.0.92</span>
<span class="n">ip_address</span> <span class="o">=</span> <span class="mi">2620</span><span class="p">:</span><span class="mi">0</span><span class="p">:</span><span class="n">cafe</span><span class="p">::</span><span class="mi">87</span>
<span class="n">ip_address</span> <span class="o">=</span> <span class="mi">2001</span><span class="p">:</span><span class="mi">24</span><span class="p">::</span><span class="mi">92</span>
<span class="n">tls_www_server</span>
<span class="n">encryption_key</span>
<span class="n">signing_key</span>
<span class="n">EOF</span>
<span class="c1"># certtool --generate-privkey &gt; server-hostNNN-key.pem</span>
<span class="c1"># certtool --generate-certificate \</span>
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">ca</span><span class="o">-</span><span class="n">certificate</span> <span class="n">ca</span><span class="o">-</span><span class="n">cert</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">ca</span><span class="o">-</span><span class="n">privkey</span> <span class="n">ca</span><span class="o">-</span><span class="n">key</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">privkey</span> <span class="n">server</span><span class="o">-</span><span class="n">hostNNN</span><span class="o">-</span><span class="n">key</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">template</span> <span class="n">server</span><span class="o">-</span><span class="n">hostNNN</span><span class="o">.</span><span class="n">info</span> \
<span class="o">--</span><span class="n">outfile</span> <span class="n">server</span><span class="o">-</span><span class="n">hostNNN</span><span class="o">-</span><span class="n">cert</span><span class="o">.</span><span class="n">pem</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">dns_name</span></code> and <code class="docutils literal notranslate"><span class="pre">ip_address</span></code> fields in the template are setting
the subject alt name extension data. The <code class="docutils literal notranslate"><span class="pre">tls_www_server</span></code> 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 class="docutils literal notranslate"><span class="pre">encryption_key</span></code> and <code class="docutils literal notranslate"><span class="pre">signing_key</span></code> keyword is
the key usage extension to indicate this certificate is intended for
usage in the data session.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">server-hostNNN-key.pem</span></code> and <code class="docutils literal notranslate"><span class="pre">server-hostNNN-cert.pem</span></code> files
should now be securely copied to the server for which they were
generated, and renamed to <code class="docutils literal notranslate"><span class="pre">server-key.pem</span></code> and <code class="docutils literal notranslate"><span class="pre">server-cert.pem</span></code>
when added to the <code class="docutils literal notranslate"><span class="pre">/etc/pki/qemu</span></code> directory on the target host. The
<code class="docutils literal notranslate"><span class="pre">server-key.pem</span></code> file is security sensitive and should be kept
protected with file mode 0600 to prevent disclosure.</p>
</section>
<section id="issuing-client-certificates">
<span id="tls-005fgenerate-005fclient"></span><h2>Issuing client certificates<a class="headerlink" href="#issuing-client-certificates" title="Link to this heading"></a></h2>
<p>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.</p>
<p>Once again on the host holding the CA, create template files containing
the information for each client, and use it to issue client
certificates.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cat &gt; client-hostNNN.info &lt;&lt;EOF</span>
<span class="n">country</span> <span class="o">=</span> <span class="n">GB</span>
<span class="n">state</span> <span class="o">=</span> <span class="n">London</span>
<span class="n">locality</span> <span class="o">=</span> <span class="n">City</span> <span class="n">Of</span> <span class="n">London</span>
<span class="n">organization</span> <span class="o">=</span> <span class="n">Name</span> <span class="n">of</span> <span class="n">your</span> <span class="n">organization</span>
<span class="n">cn</span> <span class="o">=</span> <span class="n">hostNNN</span><span class="o">.</span><span class="n">foo</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="n">tls_www_client</span>
<span class="n">encryption_key</span>
<span class="n">signing_key</span>
<span class="n">EOF</span>
<span class="c1"># certtool --generate-privkey &gt; client-hostNNN-key.pem</span>
<span class="c1"># certtool --generate-certificate \</span>
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">ca</span><span class="o">-</span><span class="n">certificate</span> <span class="n">ca</span><span class="o">-</span><span class="n">cert</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">ca</span><span class="o">-</span><span class="n">privkey</span> <span class="n">ca</span><span class="o">-</span><span class="n">key</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">privkey</span> <span class="n">client</span><span class="o">-</span><span class="n">hostNNN</span><span class="o">-</span><span class="n">key</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">template</span> <span class="n">client</span><span class="o">-</span><span class="n">hostNNN</span><span class="o">.</span><span class="n">info</span> \
<span class="o">--</span><span class="n">outfile</span> <span class="n">client</span><span class="o">-</span><span class="n">hostNNN</span><span class="o">-</span><span class="n">cert</span><span class="o">.</span><span class="n">pem</span>
</pre></div>
</div>
<p>The subject alt name extension data is not required for clients, so
the <code class="docutils literal notranslate"><span class="pre">dns_name</span></code> and <code class="docutils literal notranslate"><span class="pre">ip_address</span></code> fields are not included. The
<code class="docutils literal notranslate"><span class="pre">tls_www_client</span></code> 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 class="docutils literal notranslate"><span class="pre">encryption_key</span></code> and <code class="docutils literal notranslate"><span class="pre">signing_key</span></code> keyword is the
key usage extension to indicate this certificate is intended for usage
in the data session.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">client-hostNNN-key.pem</span></code> and <code class="docutils literal notranslate"><span class="pre">client-hostNNN-cert.pem</span></code> files
should now be securely copied to the client for which they were
generated, and renamed to <code class="docutils literal notranslate"><span class="pre">client-key.pem</span></code> and <code class="docutils literal notranslate"><span class="pre">client-cert.pem</span></code>
when added to the <code class="docutils literal notranslate"><span class="pre">/etc/pki/qemu</span></code> directory on the target host. The
<code class="docutils literal notranslate"><span class="pre">client-key.pem</span></code> file is security sensitive and should be kept
protected with file mode 0600 to prevent disclosure.</p>
<p>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.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cat &gt; both-hostNNN.info &lt;&lt;EOF</span>
<span class="n">country</span> <span class="o">=</span> <span class="n">GB</span>
<span class="n">state</span> <span class="o">=</span> <span class="n">London</span>
<span class="n">locality</span> <span class="o">=</span> <span class="n">City</span> <span class="n">Of</span> <span class="n">London</span>
<span class="n">organization</span> <span class="o">=</span> <span class="n">Name</span> <span class="n">of</span> <span class="n">your</span> <span class="n">organization</span>
<span class="n">cn</span> <span class="o">=</span> <span class="n">hostNNN</span><span class="o">.</span><span class="n">foo</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="n">dns_name</span> <span class="o">=</span> <span class="n">hostNNN</span>
<span class="n">dns_name</span> <span class="o">=</span> <span class="n">hostNNN</span><span class="o">.</span><span class="n">foo</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="n">ip_address</span> <span class="o">=</span> <span class="mf">10.0.1.87</span>
<span class="n">ip_address</span> <span class="o">=</span> <span class="mf">192.8.0.92</span>
<span class="n">ip_address</span> <span class="o">=</span> <span class="mi">2620</span><span class="p">:</span><span class="mi">0</span><span class="p">:</span><span class="n">cafe</span><span class="p">::</span><span class="mi">87</span>
<span class="n">ip_address</span> <span class="o">=</span> <span class="mi">2001</span><span class="p">:</span><span class="mi">24</span><span class="p">::</span><span class="mi">92</span>
<span class="n">tls_www_server</span>
<span class="n">tls_www_client</span>
<span class="n">encryption_key</span>
<span class="n">signing_key</span>
<span class="n">EOF</span>
<span class="c1"># certtool --generate-privkey &gt; both-hostNNN-key.pem</span>
<span class="c1"># certtool --generate-certificate \</span>
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">ca</span><span class="o">-</span><span class="n">certificate</span> <span class="n">ca</span><span class="o">-</span><span class="n">cert</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">ca</span><span class="o">-</span><span class="n">privkey</span> <span class="n">ca</span><span class="o">-</span><span class="n">key</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">load</span><span class="o">-</span><span class="n">privkey</span> <span class="n">both</span><span class="o">-</span><span class="n">hostNNN</span><span class="o">-</span><span class="n">key</span><span class="o">.</span><span class="n">pem</span> \
<span class="o">--</span><span class="n">template</span> <span class="n">both</span><span class="o">-</span><span class="n">hostNNN</span><span class="o">.</span><span class="n">info</span> \
<span class="o">--</span><span class="n">outfile</span> <span class="n">both</span><span class="o">-</span><span class="n">hostNNN</span><span class="o">-</span><span class="n">cert</span><span class="o">.</span><span class="n">pem</span>
</pre></div>
</div>
<p>When copying the PEM files to the target host, save them twice, once as
<code class="docutils literal notranslate"><span class="pre">server-cert.pem</span></code> and <code class="docutils literal notranslate"><span class="pre">server-key.pem</span></code>, and again as
<code class="docutils literal notranslate"><span class="pre">client-cert.pem</span></code> and <code class="docutils literal notranslate"><span class="pre">client-key.pem</span></code>.</p>
</section>
<section id="tls-x509-credential-configuration">
<span id="tls-005fcreds-005fsetup"></span><h2>TLS x509 credential configuration<a class="headerlink" href="#tls-x509-credential-configuration" title="Link to this heading"></a></h2>
<p>QEMU has a standard mechanism for loading x509 credentials that will be
used for network services and clients. It requires specifying the
<code class="docutils literal notranslate"><span class="pre">tls-creds-x509</span></code> class name to the <code class="docutils literal notranslate"><span class="pre">--object</span></code> command line argument
for the system emulators. Each set of credentials loaded should be given
a unique string identifier via the <code class="docutils literal notranslate"><span class="pre">id</span></code> 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.</p>
<p>When specifying the object, the <code class="docutils literal notranslate"><span class="pre">dir</span></code> parameters specifies which
directory contains the credential files. This directory is expected to
contain files with the names mentioned previously, <code class="docutils literal notranslate"><span class="pre">ca-cert.pem</span></code>,
<code class="docutils literal notranslate"><span class="pre">server-key.pem</span></code>, <code class="docutils literal notranslate"><span class="pre">server-cert.pem</span></code>, <code class="docutils literal notranslate"><span class="pre">client-key.pem</span></code> and
<code class="docutils literal notranslate"><span class="pre">client-cert.pem</span></code> as appropriate. It is also possible to include a set
of pre-generated Diffie-Hellman (DH) parameters in a file
<code class="docutils literal notranslate"><span class="pre">dh-params.pem</span></code>, which can be created using the
<code class="docutils literal notranslate"><span class="pre">certtool</span> <span class="pre">--generate-dh-params</span></code> command. If omitted, QEMU will
dynamically generate DH parameters when loading the credentials.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">endpoint</span></code> parameter indicates whether the credentials will be
used for a network client or server, and determines which PEM files are
loaded.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">verify</span></code> 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.</p>
<p>To load server credentials with client certificate validation enabled</p>
<pre class="literal-block">qemu-system-x86_64 -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server</pre>
<p>while to load client credentials use</p>
<pre class="literal-block">qemu-system-x86_64 -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=client</pre>
<p>Network services which support TLS will all have a <code class="docutils literal notranslate"><span class="pre">tls-creds</span></code>
parameter which expects the ID of the TLS credentials object. For
example with VNC:</p>
<pre class="literal-block">qemu-system-x86_64 -vnc 0.0.0.0:0,tls-creds=tls0</pre>
</section>
<section id="tls-pre-shared-keys-psk">
<span id="tls-005fpsk"></span><h2>TLS Pre-Shared Keys (PSK)<a class="headerlink" href="#tls-pre-shared-keys-psk" title="Link to this heading"></a></h2>
<p>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.</p>
<p>Use the GnuTLS <code class="docutils literal notranslate"><span class="pre">psktool</span></code> program to generate a <code class="docutils literal notranslate"><span class="pre">keys.psk</span></code> file
containing one or more usernames and random keys:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">mkdir</span> <span class="o">-</span><span class="n">m</span> <span class="mi">0700</span> <span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">keys</span>
<span class="n">psktool</span> <span class="o">-</span><span class="n">u</span> <span class="n">rich</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">keys</span><span class="o">/</span><span class="n">keys</span><span class="o">.</span><span class="n">psk</span>
</pre></div>
</div>
<p>TLS-enabled servers such as <code class="docutils literal notranslate"><span class="pre">qemu-nbd</span></code> can use this directory like so:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">qemu</span><span class="o">-</span><span class="n">nbd</span> \
<span class="o">-</span><span class="n">t</span> <span class="o">-</span><span class="n">x</span> <span class="o">/</span> \
<span class="o">--</span><span class="nb">object</span> <span class="n">tls</span><span class="o">-</span><span class="n">creds</span><span class="o">-</span><span class="n">psk</span><span class="p">,</span><span class="nb">id</span><span class="o">=</span><span class="n">tls0</span><span class="p">,</span><span class="n">endpoint</span><span class="o">=</span><span class="n">server</span><span class="p">,</span><span class="nb">dir</span><span class="o">=/</span><span class="n">tmp</span><span class="o">/</span><span class="n">keys</span> \
<span class="o">--</span><span class="n">tls</span><span class="o">-</span><span class="n">creds</span> <span class="n">tls0</span> \
<span class="n">image</span><span class="o">.</span><span class="n">qcow2</span>
</pre></div>
</div>
<p>When connecting from a qemu-based client you must specify the directory
containing <code class="docutils literal notranslate"><span class="pre">keys.psk</span></code> and an optional username (defaults to “qemu”):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">qemu</span><span class="o">-</span><span class="n">img</span> <span class="n">info</span> \
<span class="o">--</span><span class="nb">object</span> <span class="n">tls</span><span class="o">-</span><span class="n">creds</span><span class="o">-</span><span class="n">psk</span><span class="p">,</span><span class="nb">id</span><span class="o">=</span><span class="n">tls0</span><span class="p">,</span><span class="nb">dir</span><span class="o">=/</span><span class="n">tmp</span><span class="o">/</span><span class="n">keys</span><span class="p">,</span><span class="n">username</span><span class="o">=</span><span class="n">rich</span><span class="p">,</span><span class="n">endpoint</span><span class="o">=</span><span class="n">client</span> \
<span class="o">--</span><span class="n">image</span><span class="o">-</span><span class="n">opts</span> \
<span class="n">file</span><span class="o">.</span><span class="n">driver</span><span class="o">=</span><span class="n">nbd</span><span class="p">,</span><span class="n">file</span><span class="o">.</span><span class="n">host</span><span class="o">=</span><span class="n">localhost</span><span class="p">,</span><span class="n">file</span><span class="o">.</span><span class="n">port</span><span class="o">=</span><span class="mi">10809</span><span class="p">,</span><span class="n">file</span><span class="o">.</span><span class="n">tls</span><span class="o">-</span><span class="n">creds</span><span class="o">=</span><span class="n">tls0</span><span class="p">,</span><span class="n">file</span><span class="o">.</span><span class="n">export</span><span class="o">=/</span>
</pre></div>
</div>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="vnc-security.html" class="btn btn-neutral float-left" title="VNC security" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="secrets.html" class="btn btn-neutral float-right" title="Providing secret data to QEMU" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2025, The QEMU Project Developers.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
<!-- Empty para to force a blank line after "Built with Sphinx ..." -->
<p></p>
<p>This documentation is for QEMU version 8.2.2.</p>
<p><a href="../about/license.html">QEMU and this manual are released under the
GNU General Public License, version 2.</a></p>
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>