Skip to content

Commit eda38ad

Browse files
committed
docs: add howto to setup TLS connections
There are couple of step necessary to get TLS working nicely. Document it how this is done. Signed-off-by: Daniel Wagner <wagi@kernel.org>
1 parent 39b1db8 commit eda38ad

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed

TLS.md

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# How to Set Up TLS for NVMe-TCP
2+
3+
Enabling TLS for the NVMe-TCP feature requires a few configuration steps for both the kernel and userland.
4+
5+
## Kernel Configuration
6+
7+
To support TCP authentication and TLS encryption, enable the following kernel options:
8+
9+
- For DHCHAP authentication:
10+
`CONFIG_NVME_HOST_AUTH`
11+
12+
- For TLS transport encryption:
13+
`CONFIG_NVME_TCP_TLS`
14+
15+
## Setting Up `tlshd`
16+
17+
For TLS protocol support, which handles authentication and encryption, the kernel handles data encryption only, so userland support is required for the TLS handshake. The `tlshd` daemon implements the handshake process.
18+
19+
### Requirements
20+
21+
Ensure `tlshd` includes the commit `311d9438b984` ("tlshd: always link .nvme default keyring into the session") - likely in `ktls-utils` version 0.12. Alternatively, you can set the keyring manually in `/etc/tlshd.conf`:
22+
23+
```ini
24+
[authenticate]
25+
keyrings = .nvme
26+
```
27+
28+
No additional configuration is necessary for `tlshd`; simply start it as a daemon:
29+
30+
```bash
31+
systemctl enable --now tlshd
32+
```
33+
34+
## Loading Keys on Boot or Module Load
35+
36+
The NVMe subsystem loading keys from the kernel keystore, which means these keys must be available in the keystore before establishing a connection.
37+
38+
### Creating a New Key
39+
40+
```bash
41+
nvme gen-tls-key \
42+
--hostnqn nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36 \
43+
--subsysnqn nqn.io-1 --hmac 1 --identity 1 --insert --keyfile /etc/nvme/tls-keys
44+
```
45+
46+
This command creates a new host key, inserts it into the kernel keyring, and appends the derived TLS PSK to the keyfile (`/etc/nvme/tls-keys`).
47+
48+
### Inserting an Existing Key
49+
50+
```bash
51+
nvme check-tls-key \
52+
--hostnqn nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36 \
53+
--subsysnqn nqn.io-1 --identity 1 \
54+
--keydata NVMeTLSkey-1:01:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACtVQoZ: \
55+
--insert --keyfile /etc/nvme/tls-keys
56+
```
57+
58+
This command inserts the configured key (`--keydata`) into the kernel keyring and appends the derived TLS PSK to the keyfile.
59+
60+
### Loading Keys on Boot or Module Load
61+
62+
The kernel keyring does not persist keys, so userland must import keys into the keyring upon each boot or module load (for NVMe-TCP). To load keys:
63+
64+
```bash
65+
nvme tls --import /etc/nvme/tls-keys
66+
```
67+
68+
The `70-nvmf-keys.rules` udev rule ([source](https://github.com/linux-nvme/nvme-cli/blob/master/nvmf-autoconnect/udev-rules/70-nvmf-keys.rules.in)) will load keys from `/etc/nvme/tls-keys` automatically.
69+
70+
### Recommendation for Handling TLS Keys
71+
72+
The `nvme connect` command also allows passing a TLS key directly via the command line or a JSON config file. Avoid this method in production environments, as it may expose keys.
73+
74+
## Establishing a Connection
75+
76+
Once the keys are in the keystore, add the `--tls` option to establish a secure connection:
77+
78+
```bash
79+
nvme connect --transport tcp --traddr 192.168.154.148 --trsvcid 4420 \
80+
--hostnqn nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36 \
81+
--hostid befdec4c-2234-11b2-a85c-ca77c773af36 \
82+
--nqn nqn.io-1 --tls --dump-config --output-format json
83+
```
84+
85+
The resulting JSON output can be saved to simplify future connections:
86+
87+
```json
88+
[
89+
{
90+
"hostnqn": "nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36",
91+
"hostid": "befdec4c-2234-11b2-a85c-ca77c773af36",
92+
"subsystems": [
93+
{
94+
"nqn": "nqn.io-1",
95+
"ports": [
96+
{
97+
"transport": "tcp",
98+
"traddr": "192.168.154.148",
99+
"trsvcid": "4420",
100+
"dhchap_key": "none",
101+
"tls": true
102+
}
103+
]
104+
}
105+
]
106+
}
107+
]
108+
```
109+
110+
Using this JSON file, you can connect with:
111+
112+
```bash
113+
nvme connect --config config.json
114+
```
115+
116+
## Setting Up the Target
117+
118+
The same steps for creating keys and importing/exporting keys to/from the kernel are necessary for the target as they are for the host (see above).
119+
120+
For the above example, you can use the `nvmetcli` config:
121+
122+
```json
123+
{
124+
"hosts": [
125+
{
126+
"nqn": "nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36"
127+
}
128+
],
129+
"ports": [
130+
{
131+
"addr": {
132+
"adrfam": "ipv4",
133+
"traddr": "0.0.0.0",
134+
"treq": "not specified",
135+
"trsvcid": "4420",
136+
"trtype": "tcp",
137+
"tsas": "tls1.3"
138+
},
139+
"ana_groups": [
140+
{
141+
"ana": {
142+
"state": "optimized"
143+
},
144+
"grpid": 1
145+
}
146+
],
147+
"param": {
148+
"inline_data_size": "16384",
149+
"pi_enable": "0"
150+
},
151+
"portid": 0,
152+
"referrals": [],
153+
"subsystems": [
154+
"nqn.io-1"
155+
]
156+
}
157+
],
158+
"subsystems": [
159+
{
160+
"allowed_hosts": [
161+
"nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36"
162+
],
163+
"attr": {
164+
"allow_any_host": "0",
165+
"cntlid_max": "65519",
166+
"cntlid_min": "1",
167+
"firmware": "6.8.0-rc",
168+
"ieee_oui": "0x000000",
169+
"model": "Linux",
170+
"pi_enable": "0",
171+
"qid_max": "128",
172+
"serial": "0c74361069d9db6c65ef",
173+
"version": "1.3"
174+
},
175+
"namespaces": [
176+
{
177+
"ana": {
178+
"grpid": "1"
179+
},
180+
"ana_grpid": 1,
181+
"device": {
182+
"nguid": "00000000-0000-0000-0000-000000000000",
183+
"path": "/dev/vdb",
184+
"uuid": "91fdba0d-f87b-4c25-b80f-db7be1418b9e"
185+
},
186+
"enable": 1,
187+
"nsid": 1
188+
}
189+
],
190+
"nqn": "nqn.io-1"
191+
}
192+
]
193+
}
194+
```

0 commit comments

Comments
 (0)