@@ -22,8 +22,36 @@ import (
22
22
"github.com/vishvananda/netlink"
23
23
)
24
24
25
+ /*
26
+ Encrypted overlay networks use IPsec in transport mode to encrypt and
27
+ authenticate the VXLAN UDP datagrams. This driver implements a bespoke control
28
+ plane which negotiates the security parameters for each peer-to-peer tunnel.
29
+
30
+ IPsec Terminology
31
+
32
+ - ESP: IPSec Encapsulating Security Payload
33
+ - SPI: Security Parameter Index
34
+ - ICV: Integrity Check Value
35
+ - SA: Security Association https://en.wikipedia.org/wiki/IPsec#Security_association
36
+
37
+
38
+ Developer documentation for Linux IPsec is rather sparse online. The following
39
+ slide deck provides a decent overview.
40
+ https://libreswan.org/wiki/images/e/e0/Netdev-0x12-ipsec-flow.pdf
41
+
42
+ The Linux IPsec stack is part of XFRM, the netlink packet transformation
43
+ interface.
44
+ https://man7.org/linux/man-pages/man8/ip-xfrm.8.html
45
+ */
46
+
25
47
const (
26
- r = 0xD0C4E3
48
+ // Value used to mark outgoing packets which should have our IPsec
49
+ // processing applied. It is also used as a label to identify XFRM
50
+ // states (Security Associations) and policies (Security Policies)
51
+ // programmed by us so we know which ones we can clean up without
52
+ // disrupting other VPN connections on the system.
53
+ mark = 0xD0C4E3
54
+
27
55
pktExpansion = 26 // SPI(4) + SeqN(4) + IV(8) + PadLength(1) + NextHeader(1) + ICV(8)
28
56
)
29
57
@@ -33,7 +61,9 @@ const (
33
61
bidir
34
62
)
35
63
36
- var spMark = netlink.XfrmMark {Value : uint32 (r ), Mask : 0xffffffff }
64
+ // Mark value for matching packets which should have our IPsec security policy
65
+ // applied.
66
+ var spMark = netlink.XfrmMark {Value : mark , Mask : 0xffffffff }
37
67
38
68
type key struct {
39
69
value []byte
@@ -47,6 +77,9 @@ func (k *key) String() string {
47
77
return ""
48
78
}
49
79
80
+ // Security Parameter Indices for the IPsec flows between local node and a
81
+ // remote peer, which identify the Security Associations (XFRM states) to be
82
+ // applied when encrypting and decrypting packets.
50
83
type spi struct {
51
84
forward int
52
85
reverse int
@@ -204,7 +237,7 @@ func programMangle(vni uint32, add bool) (err error) {
204
237
var (
205
238
p = strconv .FormatUint (uint64 (overlayutils .VXLANUDPPort ()), 10 )
206
239
c = fmt .Sprintf ("0>>22&0x3C@12&0xFFFFFF00=%d" , int (vni )<< 8 )
207
- m = strconv .FormatUint (uint64 ( r ) , 10 )
240
+ m = strconv .FormatUint (mark , 10 )
208
241
chain = "OUTPUT"
209
242
rule = []string {"-p" , "udp" , "--dport" , p , "-m" , "u32" , "--u32" , c , "-j" , "MARK" , "--set-mark" , m }
210
243
a = "-A"
@@ -251,10 +284,12 @@ func programInput(vni uint32, add bool) (err error) {
251
284
msg = "remove"
252
285
}
253
286
287
+ // Accept incoming VXLAN datagrams for the VNI which were subjected to IPSec processing.
254
288
if err := iptable .ProgramRule (iptables .Filter , chain , action , accept ); err != nil {
255
289
logrus .Errorf ("could not %s input rule: %v. Please do it manually." , msg , err )
256
290
}
257
291
292
+ // Drop incoming VXLAN datagrams for the VNI which were received in cleartext.
258
293
if err := iptable .ProgramRule (iptables .Filter , chain , action , block ); err != nil {
259
294
logrus .Errorf ("could not %s input rule: %v. Please do it manually." , msg , err )
260
295
}
@@ -280,7 +315,7 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f
280
315
Proto : netlink .XFRM_PROTO_ESP ,
281
316
Spi : spi .reverse ,
282
317
Mode : netlink .XFRM_MODE_TRANSPORT ,
283
- Reqid : r ,
318
+ Reqid : mark ,
284
319
}
285
320
if add {
286
321
rSA .Aead = buildAeadAlgo (k , spi .reverse )
@@ -306,7 +341,7 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f
306
341
Proto : netlink .XFRM_PROTO_ESP ,
307
342
Spi : spi .forward ,
308
343
Mode : netlink .XFRM_MODE_TRANSPORT ,
309
- Reqid : r ,
344
+ Reqid : mark ,
310
345
}
311
346
if add {
312
347
fSA .Aead = buildAeadAlgo (k , spi .forward )
@@ -355,7 +390,7 @@ func programSP(fSA *netlink.XfrmState, rSA *netlink.XfrmState, add bool) error {
355
390
Proto : netlink .XFRM_PROTO_ESP ,
356
391
Mode : netlink .XFRM_MODE_TRANSPORT ,
357
392
Spi : fSA .Spi ,
358
- Reqid : r ,
393
+ Reqid : mark ,
359
394
},
360
395
},
361
396
}
@@ -569,7 +604,7 @@ func updateNodeKey(lIP, aIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, pr
569
604
Proto : netlink .XFRM_PROTO_ESP ,
570
605
Mode : netlink .XFRM_MODE_TRANSPORT ,
571
606
Spi : fSA2 .Spi ,
572
- Reqid : r ,
607
+ Reqid : mark ,
573
608
},
574
609
},
575
610
}
@@ -638,7 +673,7 @@ func clearEncryptionStates() {
638
673
}
639
674
for _ , sa := range saList {
640
675
sa := sa
641
- if sa .Reqid == r {
676
+ if sa .Reqid == mark {
642
677
if err := nlh .XfrmStateDel (& sa ); err != nil {
643
678
logrus .Warnf ("Failed to delete stale SA %s: %v" , sa , err )
644
679
continue
0 commit comments