.\" -*- mode: troff; coding: utf-8 -*-
.\" Automatically generated by Podwrapper::Man 1.47.9 (Pod::Simple 3.47)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>.
.ie n \{\
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
.    if \nF \{\
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{\
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\"
.\" Required to disable full justification in groff 1.23.0.
.if n .ds AD l
.\" ========================================================================
.\"
.IX Title "nbdkit-tls 1"
.TH nbdkit-tls 1 2026-05-16 nbdkit-1.47.9 NBDKIT
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH NAME
nbdkit\-tls \- authentication and encryption of NBD connections
(sometimes called "SSL")
.SH SYNOPSIS
.IX Header "SYNOPSIS"
.Vb 5
\& nbdkit [\-\-tls=off|on|require]
\&        [\-\-tls\-certificates=/path/to/certificates]
\&        [\-\-tls\-psk=/path/to/pskfile]
\&        [\-\-tls\-verify\-peer]
\&        PLUGIN [...]
.Ve
.SH DESCRIPTION
.IX Header "DESCRIPTION"
TLS (authentication and encryption, sometimes incorrectly called
"SSL") is supported if nbdkit was compiled with GnuTLS.  This allows
the server to verify that the client is allowed access, and to encrypt
the contents of the protocol in transit over the network.
.PP
TLS can be disabled or enabled by specifying either \fI\-\-tls=off\fR or
\&\fI\-\-tls=on\fR.  With \fI\-\-tls=off\fR, if a client tries to use TLS to
connect, it will be rejected by the server (in other words, as if the
server doesn\*(Aqt support TLS).
.PP
\&\fI\-\-tls=on\fR means that the client may choose to connect either with or
without TLS.
.PP
\&\fI\-\-tls=require\fR enables TLS \fBand\fR rejects all non\-TLS connection
attempts.  This prevents downgrade attacks where a malicious proxy
pretends not to support TLS in order to force either the client or
server to communicate in plaintext.
.SS Example
.IX Subsection "Example"
If certificates have been set up correctly then you should be able to
start a TLS server by doing:
.PP
.Vb 1
\& nbdkit \-\-tls=require memory 1G
.Ve
.PP
and connect to it by doing:
.PP
.Vb 1
\& nbdinfo nbds://localhost
.Ve
.PP
If certificates are in a non\-standard directory and you have
libnbd\ ≥\ 1.10:
.PP
.Vb 2
\& nbdkit \-\-tls=require \-\-tls\-certificates=/certs memory 1G
\& nbdinfo nbds://localhost?tls\-certificates=/certs
.Ve
.SS "TLS with X.509 certificates"
.IX Subsection "TLS with X.509 certificates"
When nbdkit starts up, it loads TLS certificates from some built\-in
paths, or from the directory specified by the \fI\-\-tls\-certificates\fR
option.
.PP
In this directory, nbdkit expects to find several files:
.IP \fIca\-cert.pem\fR 4
.IX Item "ca-cert.pem"
The Certificate Authority certificate.
.IP \fIserver\-cert.pem\fR 4
.IX Item "server-cert.pem"
The server certificate.
.IP \fIserver\-cert\-N.pem\fR 4
.IX Item "server-cert-N.pem"
(Optional) Additional server certificates (where \f(CW\*(C`N\*(C'\fR is \f(CW0\fR, \f(CW1\fR,
\&...)
.IP \fIserver\-key.pem\fR 4
.IX Item "server-key.pem"
The server private key.
.IP \fIserver\-key\-N.pem\fR 4
.IX Item "server-key-N.pem"
(Optional) Additional server private keys (where \f(CW\*(C`N\*(C'\fR is \f(CW0\fR, \f(CW1\fR,
\&...)
.IP \fIca\-crl.pem\fR 4
.IX Item "ca-crl.pem"
(Optional) The certificate revocation list.
.PP
\fISetting up the Certificate Authority\fR
.IX Subsection "Setting up the Certificate Authority"
.PP
This step only needs to be done once per organization.  It may be that
your organization already has a CA.
.PP
.Vb 2
\& $ certtool \-\-generate\-privkey > ca\-key.pem
\& $ chmod 0600 ca\-key.pem
.Ve
.PP
The \fIca\-key.pem\fR file is the CA private key and is \fIextremely\fR
sensitive data.  With possession of this key, anyone can create
certificates pretending to be your organization!
.PP
To create the CA certificate file:
.PP
.Vb 9
\& $ cat > ca.info <<EOF
\& cn = Name of your organization
\& ca
\& cert_signing_key
\& EOF
\& $ certtool \-\-generate\-self\-signed \e
\&            \-\-load\-privkey ca\-key.pem \e
\&            \-\-template ca.info \e
\&            \-\-outfile ca\-cert.pem
.Ve
.PP
\fIIssuing a server certificate for the nbdkit server\fR
.IX Subsection "Issuing a server certificate for the nbdkit server"
.PP
Each nbdkit server (or host) needs a secret key and certificate.
.PP
.Vb 2
\& $ certtool \-\-generate\-privkey > server\-key.pem
\& $ chmod 0600 server\-key.pem
.Ve
.PP
The server key file is sensitive.  Setting the mode to \f(CW0600\fR helps
to prevent other users on the same machine from reading it.
.PP
The common name (\f(CW\*(C`cn\*(C'\fR below) field must be the fully qualified
hostname that the client connects to.  However most clients and
servers including nbdkit support the Subject Alternative Name
extension (RFC\ 2818) which uses the \f(CW\*(C`dns_name\*(C'\fR and \f(CW\*(C`ip_address\*(C'\fR
fields and deprecates \f(CW\*(C`cn\*(C'\fR.
.PP
.Vb 10
\& $ cat > server.info <<EOF
\& organization = Name of your organization
\& cn = nbd\-server.example.com
\& dns_name = nbd\-server
\& dns_name = nbd\-server.example.com
\& ip_address = 10.0.1.2
\& ip_address = 2001:24::92
\& tls_www_server
\& encryption_key
\& signing_key
\& EOF
\& $ certtool \-\-generate\-certificate \e
\&            \-\-load\-ca\-certificate ca\-cert.pem \e
\&            \-\-load\-ca\-privkey ca\-key.pem \e
\&            \-\-load\-privkey server\-key.pem \e
\&            \-\-template server.info \e
\&            \-\-outfile server\-cert.pem
.Ve
.PP
\fIIssuing and checking client certificates\fR
.IX Subsection "Issuing and checking client certificates"
.PP
\&\fBNote:\fR You don\*(Aqt need to create client certificates unless you want
to check and limit which clients can connect to nbdkit.  \fBnbdkit does
not check client certificates\fR unless you specify the
\&\fI\-\-tls\-verify\-peer\fR option on the command line.  There are other
methods for limiting access to nbdkit including
\&\fBnbdkit\-ip\-filter\fR\|(1).
.PP
For each client you should generate a private key and a client
certificate:
.PP
.Vb 2
\& $ certtool \-\-generate\-privkey > client\-key.pem
\& $ chmod 0600 client\-key.pem
.Ve
.PP
The client key file is sensitive.
.PP
The client DNS name (\f(CW\*(C`cn\*(C'\fR below) is the client\*(Aqs name for information
only.
.PP
.Vb 10
\& $ cat > client.info <<EOF
\& country = US
\& state = New York
\& locality = New York
\& organization = Name of your organization
\& cn = client.example.com
\& tls_www_client
\& encryption_key
\& signing_key
\& EOF
\& $ certtool \-\-generate\-certificate \e
\&            \-\-load\-ca\-certificate ca\-cert.pem \e
\&            \-\-load\-ca\-privkey ca\-key.pem \e
\&            \-\-load\-privkey client\-key.pem \e
\&            \-\-template client.info \e
\&            \-\-outfile client\-cert.pem
.Ve
.PP
Client certificates do \fInot\fR need to be present anywhere on the
nbdkit host.  You don\*(Aqt need to copy them into nbdkit\*(Aqs TLS
certificates directory.  The security comes from the fact that the
client must present a client certificate signed by the Certificate
Authority, and nbdkit can check this because it has the \fIca\-cert.pem\fR
file.
.PP
To enable checking of client certificates, specify the
\&\fI\-\-tls\-verify\-peer\fR option on the command line.  Clients which don\*(Aqt
present a valid certificate (eg. not signed, incorrect signature) are
denied.  Also denied are clients which present a valid certificate
signed by another CA.  Also denied are clients with certificates added
to the certificate revocation list (\fIca\-crl.pem\fR).
.SS "Connecting nbd\-client to nbdkit with TLS certificates"
.IX Subsection "Connecting nbd-client to nbdkit with TLS certificates"
With the TLS certificates files generated above in the current
directory (\f(CW\*(C`.\*(C'\fR) you can use:
.PP
.Vb 1
\& nbdkit \-\-tls=require \-\-tls\-certificates=. \-\-tls\-verify\-peer memory 1G
\&
\& nbd\-client /dev/nbd0 \e
\&           \-cacertfile ca\-cert.pem \e
\&           \-certfile client\-cert.pem \e
\&           \-keyfile client\-key.pem
.Ve
.PP
\&\fI\-\-tls\-verify\-peer\fR is only required if you want to check the client
certificate.  If you want to allow any client to connect then you can
omit it.
.SS "TLS with Pre\-Shared Keys (PSK)"
.IX Subsection "TLS with Pre-Shared Keys (PSK)"
As a simpler alternative to TLS certificates, you may use pre\-shared
keys to authenticate clients.
.PP
Create a PSK file containing one or more \f(CW\*(C`username:key\*(C'\fR pairs.  It is
easiest to use \fBpsktool\fR\|(1) for this:
.PP
.Vb 2
\& mkdir \-m 0700 /tmp/keys
\& psktool \-u alice \-p /tmp/keys/keys.psk
.Ve
.PP
The PSK file contains the hex\-encoded random keys in plaintext.  Any
client which can read this file will be able to connect to the server.
.PP
Use the nbdkit \fI\-\-tls\-psk\fR option to start the server:
.PP
.Vb 1
\& nbdkit \-\-tls=require \-\-tls\-psk=/tmp/keys/keys.psk file disk.img
.Ve
.PP
This option overrides X.509 certificate authentication.
.PP
Clients must supply one of the usernames in the PSK file and the
corresponding key in order to connect.
.PP
An example of connecting using \fBnbdinfo\fR\|(1) using an NBD URI is:
.PP
.Vb 1
\& nbdinfo \*(Aqnbds://alice@localhost?tls\-psk\-file=/tmp/keys/keys.psk\*(Aq
.Ve
.PP
An example of connecting using \fBqemu\-img\fR\|(1) is:
.PP
.Vb 4
\& qemu\-img info \e
\&   \-\-object tls\-creds\-psk,id=tls0,dir=/tmp/keys,username=alice,endpoint=client \e
\&   \-\-image\-opts \e
\&   file.driver=nbd,file.host=localhost,file.port=10809,file.tls\-creds=tls0,file.export=/
.Ve
.SS "Default TLS behaviour"
.IX Subsection "Default TLS behaviour"
If nbdkit was compiled without GnuTLS support, then TLS is disabled
and TLS connections will be rejected (as if \fI\-\-tls=off\fR was specified
on the command line).  Also it is impossible to turn on TLS in this
scenario.  You can tell if nbdkit was compiled without GnuTLS support
because \f(CW\*(C`nbdkit \-\-dump\-config\*(C'\fR will contain \f(CW\*(C`tls=no\*(C'\fR.
.PP
If TLS certificates cannot be loaded either from the built\-in path or
from the directory specified by \fI\-\-tls\-certificates\fR, then TLS
defaults to disabled.  Turning TLS on will give a warning
(\fI\-\-tls=on\fR) or error (\fI\-\-tls=require\fR) about the missing
certificates.
.PP
If TLS certificates can be loaded from the built\-in path or from the
\&\fI\-\-tls\-certificates\fR directory, then TLS will by default be enabled
(like \fI\-\-tls=on\fR), but it is not required.  Clients can choose
whether or not to use TLS and whether or not to present certificates.
.PP
TLS client certificates are \fInot\fR checked by default unless you
specify \fI\-\-tls\-verify\-peer\fR.
.PP
If the \fI\-\-tls\-psk\fR option is used then TLS is enabled (but \fInot\fR
required).  To ensure that all clients are authorized you must use
\&\fI\-\-tls=require\fR.
.PP
Each of these defaults is insecure to some extent (including
\&\fI\-\-tls=on\fR which could be subject to a downgrade attack).  If you
expect TLS then it is best to specify \fI\-\-tls=require\fR, and if you
want to check client certificates, additionally use the
\&\fI\-\-tls\-verify\-peer\fR option.
.SS "Controlling TLS fallback to plaintext"
.IX Subsection "Controlling TLS fallback to plaintext"
When \fI\-\-tls=on\fR is used, the connection can fall back to plaintext.
You can use \fBnbdkit\-tls\-fallback\-filter\fR\|(1) to provide safe fallback
content to plaintext connections.  With this filter the underlying
plugin content is only served on secure connections.
.PP
Alternatively a plugin may wish to serve different content depending
on whether the client is using TLS.  The function \fBnbdkit_is_tls\fR\|(3)
can be used during the \f(CW\*(C`.open\*(C'\fR callback for that purpose.
.SS "NBD URIs for TLS"
.IX Subsection "NBD URIs for TLS"
Tools such \fBnbdcopy\fR\|(1), \fBnbdinfo\fR\|(1) and \fBnbdsh\fR\|(1) (from
\&\fBlibnbd\fR\|(3)) allow you to use \f(CW\*(C`nbds://\*(C'\fR or \f(CW\*(C`nbds+unix://\*(C'\fR URIs to
connect to nbdkit servers using TLS.
.PP
The syntax is fully documented in the NBD URI specification:
https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md.
This section contains an outline.  You can also find further examples
in \fBnbd_connect_uri\fR\|(3).
.PP
Use the nbdkit \fI\-\-print\-uri\fR option to print the URI when nbdkit
starts up.
.IP \fBnbds://\fRexample.com 4
.IX Item "nbds://example.com"
Connect over TCP with TLS, to \f(CW\*(C`example.com\*(C'\fR port 10809.  If the
server does not support TLS then this will fail.
.IP \fBnbds+unix:///?socket=\fRSOCKET 4
.IX Item "nbds+unix:///?socket=SOCKET"
As above, but connect over a Unix domain socket called \fISOCKET\fR.
.IP \fBnbds+unix:///?socket=\fRSOCKET\fB&tls\-certificates=\fRDIR 4
.IX Item "nbds+unix:///?socket=SOCKET&tls-certificates=DIR"
As above, but specify the directory \fIDIR\fR containing TLS certificates
(used by the client to verify the server, and to present client
authentication to the server).  Note this requires libnbd\ ≥\ 1.10.
.IP \fBnbds+unix:///?socket=\fRSOCKET\fB&tls\-psk\-file=\fRFILENAME 4
.IX Item "nbds+unix:///?socket=SOCKET&tls-psk-file=FILENAME"
As above, but use TLS with Pre\-Shared Keys (PSK), stored in the
secrets file \fIFILENAME\fR.
.IP \fBnbds+unix://\fRalice\fB@/?socket=\fRSOCKET\fB&tls\-psk\-file=\fRFILENAME 4
.IX Item "nbds+unix://alice@/?socket=SOCKET&tls-psk-file=FILENAME"
As above, but use \f(CW\*(C`alice\*(C'\fR as the username.
.SS "Default location of certificates"
.IX Subsection "Default location of certificates"
Without \fI\-\-tls\-certificates\fR nbdkit and libnbd look in several
locations for certificates.
.PP
If nbdkit is started as a non\-root user (note this does not include
use of the \fI\-u\fR or \fI\-g\fR options), nbdkit looks in each of these
paths in turn:
.PP
.Vb 2
\& $HOME/.pki/nbdkit/
\& $HOME/.config/pki/nbdkit/
.Ve
.PP
If nbdkit is started as root:
.PP
.Vb 1
\& $sysconfdir/pki/nbdkit/
.Ve
.PP
where \f(CW$sysconfdir\fR is set when nbdkit is compiled, usually \fI/etc\fR.
(Use \f(CW\*(C`nbdkit \-\-dump\-config\*(C'\fR and look at the
\&\f(CW\*(C`root_tls_certificates_dir\*(C'\fR setting to get the actual directory built
into the binary.)
.PP
In libnbd the paths are different.  For non\-root:
.PP
.Vb 2
\& $HOME/.pki/libnbd/
\& $HOME/.config/pki/libnbd/
.Ve
.PP
For root:
.PP
.Vb 1
\& $sysconfdir/pki/libnbd/
.Ve
.PP
In nbdkit you can override these directories by using
\&\fI\-\-tls\-certificates=/path/to/certificates\fR.
.PP
In libnbd you can use \fBnbd_set_tls_certificates\fR\|(3).
In libnbd\ ≥\ 1.10 you can append
\&\f(CW\*(C`&tls\-certificates=/path/to/certificates\*(C'\fR to URIs.
.SS "Choice of TLS algorithms"
.IX Subsection "Choice of TLS algorithms"
TLS has a bewildering choice of algorithms that can be used.  These
are controlled by the TLS priority string, described in full in the
section "Priority strings" in the GnuTLS
manual
.PP
If not set anywhere, this defaults to \f(CW\*(C`NORMAL\*(C'\fR which, to quote the
GnuTLS documentation:
.Sp
.RS 4
"\f(CW\*(C`NORMAL\*(C'\fR means all \f(CW\*(C`secure\*(C'\fR ciphersuites.  The 256\-bit ciphers are
included as a fallback only.  The ciphers are sorted by security
margin."
.RE
.PP
The nbdkit default can also be set either at \f(CW\*(C`./configure\*(C'\fR time or at
run time.
.PP
You can set the TLS priority so that it can be read from a file:
.PP
.Vb 1
\& ./configure \-\-with\-tls\-priority=@SYSTEM
.Ve
.PP
which means use the policy from \fI/etc/crypto\-policies/config\fR, or
.PP
.Vb 1
\& ./configure \-\-with\-tls\-priority=@NBDKIT,SYSTEM
.Ve
.PP
which means use the policy from
\&\fI/etc/crypto\-policies/local.d/nbdkit.config\fR and fall back to
\&\fI/etc/crypto\-policies/config\fR if the first file does not exist.
.PP
At run time, the TLS priority string can be overridden using the
nbdkit \fI\-\-tls\-priority\fR option.
.SS "Debugging TLS connections"
.IX Subsection "Debugging TLS connections"
Encrypted connections makes snooping on network traffic with Wireshark
impossible, by design.
.PP
The TLS library used by nbdkit, called gnutls, supports the
\&\f(CW\*(C`SSLKEYLOGFILE\*(C'\fR standard:
https://web.archive.org/web/20200118013150/https://developer.mozilla.org/en\-US/docs/Mozilla/Projects/NSS/Key_Log_Format
.PP
Before running nbdkit set the environment variable to point to a log
file (note it will append to the file if it already exists):
.PP
.Vb 1
\& SSLKEYLOGFILE=/tmp/keylog nbdkit [...]
.Ve
.PP
In Wireshark go to Edit → Preferences → Protocols → TLS and set
(Pre)\-Master\-Secret\ log\ filename to the log file name.  Wireshark
should be able to see the unencrypted traffic.  For further
information read:
https://wiki.wireshark.org/TLS#using\-the\-pre\-master\-secret
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBnbdkit\fR\|(1),
\&\fBnbdkit\-luks\-filter\fR\|(1),
\&\fBnbdkit\-tls\-fallback\-filter\fR\|(1),
\&\fBnbdkit_is_tls\fR\|(3),
\&\fBnbdkit_peer_tls_dn\fR\|(3),
\&\fBnbdkit_peer_tls_issuer_dn\fR\|(3),
\&\fBnbdcopy\fR\|(1),
\&\fBnbdfuse\fR\|(1),
\&\fBnbdinfo\fR\|(1),
\&\fBnbdsh\fR\|(1),
\&\fBnbd_connect_uri\fR\|(3),
\&\fBnbd_set_tls\fR\|(3),
\&\fBnbd_set_tls_certificates\fR\|(3),
\&\fBpsktool\fR\|(1),
https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md,
https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md,
https://nbd.sourceforge.io/.
.SH AUTHORS
.IX Header "AUTHORS"
Eric Blake
.PP
Richard W.M. Jones
.PP
Pino Toscano
.SH COPYRIGHT
.IX Header "COPYRIGHT"
Copyright Red Hat
.SH LICENSE
.IX Header "LICENSE"
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
.IP \(bu 4
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
.IP \(bu 4
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
.IP \(bu 4
Neither the name of Red Hat nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
.PP
THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS \*(Aq\*(AqAS IS\*(Aq\*(Aq AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
