mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
The overlay driver's checkEncryption function configures the IPSec parameters for the VXLAN tunnels to peer nodes. When called with isLocal=true, it configures encryption for all peer nodes with at least one peerDB entry. Since the local peers are also included in the peerDB, it needs to filter those entries out. It does so by filtering out any peer entries whose VTEP address is equal to the current local advertise address. Trouble is, the local advertise address is not necessarily constant. The driver tries to handle this case by calling peerDBUpdateSelf() when the advertise address changes. This function iterates through the peerDB and tries to update the VTEP address for all local peer entries, but it does not actually do anything: it mutates a temporary copy of the entry which is not persisted back into the peerDB. (It used to be functional, but was broken when the peerDB was extended to use SetMatrix.) So there may be cases where local peer entries are not filtered out properly, resulting in spurious encryption parameters being programmed into the kernel. Filter out local peers when walking the peerDB by filtering on whether the entry has the isLocal flag set. Remove the no-op code which attempts to update local entries in the peerDB. No other code takes any interest in the VTEP value for isLocal peer entries. Signed-off-by: Cory Snider <csnider@mirantis.com>
162 lines
4.2 KiB
Go
162 lines
4.2 KiB
Go
//go:build linux
|
|
|
|
package overlay
|
|
|
|
//go:generate protoc -I=. -I=../../../vendor/ --gogofaster_out=import_path=github.com/docker/docker/libnetwork/drivers/overlay:. overlay.proto
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/netip"
|
|
"sync"
|
|
|
|
"github.com/containerd/log"
|
|
"github.com/docker/docker/libnetwork/discoverapi"
|
|
"github.com/docker/docker/libnetwork/driverapi"
|
|
"github.com/docker/docker/libnetwork/scope"
|
|
)
|
|
|
|
const (
|
|
NetworkType = "overlay"
|
|
vethPrefix = "veth"
|
|
vethLen = len(vethPrefix) + 7
|
|
vxlanEncap = 50
|
|
secureOption = "encrypted"
|
|
)
|
|
|
|
// overlay driver must implement the discover-API.
|
|
var _ discoverapi.Discover = (*driver)(nil)
|
|
|
|
type driver struct {
|
|
bindAddress, advertiseAddress netip.Addr
|
|
|
|
config map[string]interface{}
|
|
peerDb peerNetworkMap
|
|
secMap *encrMap
|
|
networks networkTable
|
|
initOS sync.Once
|
|
keys []*key
|
|
peerOpMu sync.Mutex
|
|
sync.Mutex
|
|
}
|
|
|
|
// Register registers a new instance of the overlay driver.
|
|
func Register(r driverapi.Registerer, config map[string]interface{}) error {
|
|
d := &driver{
|
|
networks: networkTable{},
|
|
peerDb: peerNetworkMap{
|
|
mp: map[string]*peerMap{},
|
|
},
|
|
secMap: &encrMap{nodes: map[netip.Addr][]*spi{}},
|
|
config: config,
|
|
}
|
|
return r.RegisterDriver(NetworkType, d, driverapi.Capability{
|
|
DataScope: scope.Global,
|
|
ConnectivityScope: scope.Global,
|
|
})
|
|
}
|
|
|
|
func (d *driver) configure() error {
|
|
// Apply OS specific kernel configs if needed
|
|
d.initOS.Do(applyOStweaks)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *driver) Type() string {
|
|
return NetworkType
|
|
}
|
|
|
|
func (d *driver) IsBuiltIn() bool {
|
|
return true
|
|
}
|
|
|
|
// isIPv6Transport reports whether the outer Layer-3 transport for VXLAN datagrams is IPv6.
|
|
func (d *driver) isIPv6Transport() (bool, error) {
|
|
// Infer whether remote peers' virtual tunnel endpoints will be IPv4 or IPv6
|
|
// from the address family of our own advertise address. This is a
|
|
// reasonable inference to make as Linux VXLAN links do not support
|
|
// mixed-address-family remote peers.
|
|
if !d.advertiseAddress.IsValid() {
|
|
return false, fmt.Errorf("overlay: cannot determine address family of transport: the local data-plane address is not currently known")
|
|
}
|
|
return d.advertiseAddress.Is6(), nil
|
|
}
|
|
|
|
func (d *driver) nodeJoin(data discoverapi.NodeDiscoveryData) error {
|
|
if data.Self {
|
|
advAddr, _ := netip.ParseAddr(data.Address)
|
|
bindAddr, _ := netip.ParseAddr(data.BindAddress)
|
|
if !advAddr.IsValid() {
|
|
return fmt.Errorf("invalid discovery data")
|
|
}
|
|
d.Lock()
|
|
d.advertiseAddress = advAddr
|
|
d.bindAddress = bindAddr
|
|
d.Unlock()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
|
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
switch dType {
|
|
case discoverapi.NodeDiscovery:
|
|
nodeData, ok := data.(discoverapi.NodeDiscoveryData)
|
|
if !ok {
|
|
return fmt.Errorf("invalid discovery data type: %T", data)
|
|
}
|
|
return d.nodeJoin(nodeData)
|
|
case discoverapi.EncryptionKeysConfig:
|
|
encrData, ok := data.(discoverapi.DriverEncryptionConfig)
|
|
if !ok {
|
|
return fmt.Errorf("invalid encryption key notification data")
|
|
}
|
|
keys := make([]*key, 0, len(encrData.Keys))
|
|
for i := 0; i < len(encrData.Keys); i++ {
|
|
k := &key{
|
|
value: encrData.Keys[i],
|
|
tag: uint32(encrData.Tags[i]),
|
|
}
|
|
keys = append(keys, k)
|
|
}
|
|
if err := d.setKeys(keys); err != nil {
|
|
log.G(context.TODO()).Warn(err)
|
|
}
|
|
case discoverapi.EncryptionKeysUpdate:
|
|
var newKey, delKey, priKey *key
|
|
encrData, ok := data.(discoverapi.DriverEncryptionUpdate)
|
|
if !ok {
|
|
return fmt.Errorf("invalid encryption key notification data")
|
|
}
|
|
if encrData.Key != nil {
|
|
newKey = &key{
|
|
value: encrData.Key,
|
|
tag: uint32(encrData.Tag),
|
|
}
|
|
}
|
|
if encrData.Primary != nil {
|
|
priKey = &key{
|
|
value: encrData.Primary,
|
|
tag: uint32(encrData.PrimaryTag),
|
|
}
|
|
}
|
|
if encrData.Prune != nil {
|
|
delKey = &key{
|
|
value: encrData.Prune,
|
|
tag: uint32(encrData.PruneTag),
|
|
}
|
|
}
|
|
if err := d.updateKeys(newKey, priKey, delKey); err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
|
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
return nil
|
|
}
|