Skip to content

Commit 539a625

Browse files
authored
Add initial guide to upgrading to cert-v2 and IPv6 (#223)
1 parent 3e55dfa commit 539a625

File tree

2 files changed

+268
-0
lines changed

2 files changed

+268
-0
lines changed
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
---
2+
title: Upgrading a Nebula network to IPv6 overlay addresses
3+
summary:
4+
This guide describes how to upgrade an existing nebula network to the v2 certificate format and enable IPv6 addresses.
5+
---
6+
7+
# Upgrading a Nebula network to IPv6 overlay addresses
8+
9+
The upcoming release of Nebula (tenatively v1.10) will add support for IPv6-addressed Nebula hosts. To support the
10+
feature, Nebula has upgraded to a v2 certificate format. While v1 certificates support only a single IPv4 address for a
11+
given host, the v2 format allows multiple IPv4 and/or IPv6 addresses. In this guide we will describe how to upgrade a
12+
network to the v2 certificate format with IPv6 support.
13+
14+
Since Nebula v1.10 has yet to be released, we will first need to update every host on the network with a nightly build
15+
of Nebula. Next, we will issue backwards-compatible v1+v2 certificate bundles to each host. After updating each host's
16+
config with the new certificate bundle we will take a careful approach to switching over to the v2 certificate.
17+
18+
The basic steps are:
19+
20+
import TOCInline from '@theme/TOCInline';
21+
22+
<TOCInline toc={toc} />
23+
24+
## Upgrade Nebula
25+
26+
First, update each host in your network to a nightly build of Nebula with support for v2 certificates.
27+
28+
- [https://github.com/NebulaOSS/nebula-nightly/releases](https://github.com/NebulaOSS/nebula-nightly/releases)
29+
- [https://hub.docker.com/r/nebulaoss/nebula-nightly](https://hub.docker.com/r/nebulaoss/nebula-nightly)
30+
31+
## Create a v2 Certificate Authority
32+
33+
Next, create a v2 Certificate Authority and add it to the trust bundle of every host on the network. Creating a new CA
34+
with the nightly version of Nebula will create a v2 CA by default. v2 CAs support creating and signing both v1 and v2
35+
certificates.
36+
37+
```bash
38+
❯ nebula-cert ca -name "My Nebula CA" -encrypt
39+
Enter passphrase:
40+
```
41+
42+
Using `nebula-cert print` we can see that this is a v2 certificate authority.
43+
44+
```bash
45+
❯ nebula-cert print -path ./ca.crt
46+
{
47+
"curve": "CURVE25519",
48+
"details": {
49+
"groups": null,
50+
"isCa": true,
51+
"issuer": "",
52+
"name": "My Nebula CA",
53+
"networks": null,
54+
"notAfter": "2026-04-01T17:02:36-04:00",
55+
"notBefore": "2025-04-01T17:02:36-04:00",
56+
"unsafeNetworks": null
57+
},
58+
"fingerprint": "62aabc872783f1036c7075fa49302c306baa1efb2afe9966f08401f157b6ae75",
59+
"publicKey": "08edff75a4c83418ecac57f3c6f4c54d7a379c095c6fed161e947b471c5d63d8",
60+
"signature": "6b5cf89afca09f5136f1fd6dd8edea9bf0a92f369e03fa54ec3b9ac75292aa367fdd7940d220f0ceae545e00ff93ccbac7dacf1c642c017c72f7ea4b38723205",
61+
"version": 2
62+
}
63+
```
64+
65+
Append the new CA certificate to the [`pki.ca` trust bundle](https://nebula.defined.net/docs/config/pki/#pkica) in the
66+
config of every Nebula host and reload Nebula.
67+
68+
## Issue v1+v2 certificates bundles
69+
70+
Once the trust bundle of all hosts has been updated, we will issue v1+v2 certificate bundles using the new CA. We'll
71+
configure hosts with both certificates, but continue to use the v1 certificate for now.
72+
73+
By default, nebula-cert will create both v1 and v2 versions of the certificate when creating and signing a certificate.
74+
75+
```bash
76+
❯ nebula-cert sign -name "host-1" -networks "192.168.1.1/24"
77+
Enter passphrase:
78+
# Entered my passphrase
79+
```
80+
81+
Using `nebula-cert print` we can see that the file contains both versions of the certificate:
82+
83+
```bash
84+
❯ nebula-cert print -path nebula.crt
85+
{
86+
"details": {
87+
"curve": "CURVE25519",
88+
"groups": [],
89+
"isCa": false,
90+
"issuer": "62aabc872783f1036c7075fa49302c306baa1efb2afe9966f08401f157b6ae75",
91+
"name": "host-1",
92+
"networks": [
93+
"192.168.1.1/24"
94+
],
95+
"notAfter": "2026-04-01T17:02:35-04:00",
96+
"notBefore": "2025-04-01T17:08:37-04:00",
97+
"publicKey": "d368c3db5290f603c1f8456278b36d7854d49abfa183fb0d0e75b067c1b65d18",
98+
"unsafeNetworks": []
99+
},
100+
"fingerprint": "e8b9a645bd09a472ddb66efa01ce871b40008f4299b1c82d78d5c0a806c5272a",
101+
"signature": "6530d35de280f80a7d5c12657c6a31438d984588d0a107e053be86812da3dacdf6e4f83106dc3ecdd4cb1a6a325cefb4ae8dac61b5c95af85bd41d5574996b08",
102+
"version": 1
103+
}
104+
{
105+
"curve": "CURVE25519",
106+
"details": {
107+
"groups": null,
108+
"isCa": false,
109+
"issuer": "62aabc872783f1036c7075fa49302c306baa1efb2afe9966f08401f157b6ae75",
110+
"name": "host-1",
111+
"networks": [
112+
"192.168.1.1/24"
113+
],
114+
"notAfter": "2026-04-01T17:02:35-04:00",
115+
"notBefore": "2025-04-01T17:08:37-04:00",
116+
"unsafeNetworks": null
117+
},
118+
"fingerprint": "e93af78e6c24340d260fcf8127b3138f45c93963572423d1931faca11bf68b85",
119+
"publicKey": "d368c3db5290f603c1f8456278b36d7854d49abfa183fb0d0e75b067c1b65d18",
120+
"signature": "21863ad3d8b62779f80ea3ef9ae4d85bf6a8f557c6c272eefda0962cd856a3625a088e08e209d200f2fae0087ff095377622b3ac09bba5d9c7a2c1d03baef00b",
121+
"version": 2
122+
}
123+
```
124+
125+
Update the corresponding [`pki.cert` field](https://nebula.defined.net/docs/config/pki/#pkicert) with the contents of
126+
the entire file, and **restart** Nebula. Nebula will continue to use the v1 certificate when initiating tunnels until we
127+
update the `pki.initiating_version` config option. When another host initiates a tunnel, Nebula will respond with the
128+
same certificate version it was presented.
129+
130+
:::note
131+
132+
When adding or removing either a v1 or v2 certificate from the `pki.cert` field, Nebula must be restarted. A reload is
133+
insufficient for this change.
134+
135+
:::
136+
137+
## Start handshaking with v2 certificates
138+
139+
Once all hosts are configured with a v1+v2 certificate bundle, we can switch over to handshaking with the v2
140+
certificate. To do this, we set the `pki.initiating_version` config option to 2.
141+
142+
We recommend slow rolling this change by starting with a small subset of hosts and verifying the change before rolling
143+
it out widely. After updating the config option, reloading Nebula, and establishing a tunnel you can verify the v2
144+
certificate is in use via the `print-tunnel` command from [debug SSH server](/docs/guides/debug-ssh-commands/).
145+
146+
In this example we've updated host-1 (192.168.1.1) with `pki.initiating_version` set to 2 and restarted Nebula. Since
147+
its default version is set to 2, it'll use the v2 certificate when handshaking with the Lighthouse. Because the
148+
Lighthouse has a v1+v2 bundle configured it is able to complete the connection, even though its `pki.initiating_version`
149+
is still set to 1.
150+
151+
:::note
152+
153+
If the Lighthouse were configured with only a v1 certificate, host-1 would not be able to connect, even though it has a
154+
v1+v2 certificate bundle configured. This is because `pki.initiating_version` indicates the certificate version that
155+
should be used in outgoing handshakes. If the receiving end does not support v2 certificates, the initiator will not
156+
fallback on a v1 certificate.
157+
158+
:::
159+
160+
```bash
161+
steve@nebula > print-tunnel 192.168.1.2
162+
{
163+
"vpnAddrs": [
164+
"192.168.1.2"
165+
],
166+
"localIndex": 2965094606,
167+
"remoteIndex": 1285130098,
168+
"remoteAddrs": [
169+
"172.17.0.3:4242"
170+
],
171+
"cert": {
172+
"details": {
173+
"curve": "CURVE25519",
174+
"groups": [],
175+
"isCa": false,
176+
"issuer": "a95ed86f7754fc5b0fcaf38473504403748d6dc422b16bc3e29fcae32af9a73c",
177+
"name": "lighthouse1",
178+
"networks": [
179+
"192.168.1.2/24"
180+
],
181+
"notAfter": "2026-03-11T17:26:18Z",
182+
"notBefore": "2025-03-18T17:14:43Z",
183+
"publicKey": "c455bc023b1b3918538edf5f230169df12603703639db158c76da747e0eccc47",
184+
"unsafeNetworks": []
185+
},
186+
"fingerprint": "84cf960de2e49f7560a5c7f876857528f02ab201c906f5a094d0d3294732b655",
187+
"signature": "6b9e98e398fb4c6a89f8e71e6a1378cecb85c500966443673a3ebe8f9d46702d0213dbd4c5028644104eeae49c06a4906058b53cd809e07dec76fcec60a4370d",
188+
"version": 2
189+
},
190+
"messageCounter": 3,
191+
"currentRemote": "172.17.0.3:4242",
192+
"currentRelaysToMe": [],
193+
"currentRelaysThroughMe": []
194+
}
195+
```
196+
197+
You may also look in the host logs for the `certVersion` field in handshakes, ex:
198+
199+
```bash
200+
time="2025-03-27T16:50:26-05:00" level=info msg="Handshake message received" certName=lighthouse1 certVersion=2 durationNs=63460958 fingerprint=84cf960de2e49f7560a5c7f876857528f02ab201c906f5a094d0d3294732b655 handshake="map[stage:2 style:ix_psk0]" initiatorIndex=530355834 issuer=a95ed86f7754fc5b0fcaf38473504403748d6dc422b16bc3e29fcae32af9a73c remoteIndex=530355834 responderIndex=3163624101 sentCachedPackets=1 udpAddr="172.17.0.3:4242" vpnAddrs="[192.168.1.2]"
201+
```
202+
203+
## Remove v1 certificates from hosts
204+
205+
Now that every host on the network is communicating via v2 certificates, you can remove the v1 certificates by reissuing
206+
the certificates. Pass `-version 2` to only create certificates in the v2 certificate format.
207+
208+
```bash
209+
❯ nebula-cert sign -name "host-1" -networks "192.168.1.1/24" -version 2
210+
```
211+
212+
```bash
213+
❯ nebula-cert print -path host-1.crt
214+
{
215+
"curve": "CURVE25519",
216+
"details": {
217+
"groups": null,
218+
"isCa": false,
219+
"issuer": "62aabc872783f1036c7075fa49302c306baa1efb2afe9966f08401f157b6ae75",
220+
"name": "host-1",
221+
"networks": [
222+
"192.168.1.1/24"
223+
],
224+
"notAfter": "2026-04-01T17:02:35-04:00",
225+
"notBefore": "2025-04-01T20:40:00-04:00",
226+
"unsafeNetworks": null
227+
},
228+
"fingerprint": "05930841ba198874b932504de1cceb26e8d84b931ea29c673e22e0be06fb75f0",
229+
"publicKey": "501410109bd531fc5af3c75019cd2ed8349abfb56e3299a30ff72773300d1a4a",
230+
"signature": "fa1db2751fcbd6db73133364075f1577e17c3db4009bb84a7d82f159aaa4e17bb3b43636295567abda3ba9c9ad4cd5ed6357fffb8c93ebc299f3f8809e3aeb0e",
231+
"version": 2
232+
}
233+
```
234+
235+
At this point, you may wish to assign an IPv6 address:
236+
237+
```bash
238+
❯ nebula-cert sign -name "host-1" -networks "192.168.1.1/24,fdc8:d0db:a315:cb00::1/64" -version 2
239+
```
240+
241+
```bash
242+
❯ nebula-cert print -path host-1.crt
243+
{
244+
"curve": "CURVE25519",
245+
"details": {
246+
"groups": null,
247+
"isCa": false,
248+
"issuer": "62aabc872783f1036c7075fa49302c306baa1efb2afe9966f08401f157b6ae75",
249+
"name": "host-1",
250+
"networks": [
251+
"192.168.1.1/24",
252+
"fdc8:d0db:a315:cb00::1/64"
253+
],
254+
"notAfter": "2026-04-01T17:02:35-04:00",
255+
"notBefore": "2025-04-01T20:38:21-04:00",
256+
"unsafeNetworks": null
257+
},
258+
"fingerprint": "2eda0f2dc5c5f8b097a09027fc896c9b6ba78d8fdac1559878caccd4c947e3ff",
259+
"publicKey": "d8ebf7a93e62044eee4bc504aa2e82e80d79db11cfee37c75b3769df261d343b",
260+
"signature": "5a5987e2e7e0e8619b0b111d951b3297f2c704387a032f84876172a3f1864e7fb2a5bf2ce48f3fa48ff6f60d39749ba3444b073485f6a9d41c6d3c9d7856f104",
261+
"version": 2
262+
}
263+
```
264+
265+
Once you switch services over to use the new IPv6 addresses, you can decide to deprecate the IPv4 addresses or continue
266+
to run your overlay network with both IPv4 and IPv6 subnets. If you decide to switch to IPv6-only, don't forget to
267+
update your `static_host_map`.

docusaurus.config.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ const config = {
149149
prism: {
150150
theme: lightCodeTheme,
151151
darkTheme: darkCodeTheme,
152+
additionalLanguages: ['bash'],
152153
},
153154
},
154155
};

0 commit comments

Comments
 (0)