From 6e2f25c796d984a53e10c9182d57866aa61597a2 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 23 Dec 2020 11:40:05 +0000 Subject: [PATCH] Assign a random MAC address to the bridge If we don't do this it will adopt the lowest address of an attached device, hence change over time. Remove the previous work-around of getting and setting the random MAC that Linux assigned, also getting and setting the TUN address since that doesn't change if you set the bridge address. --- pkg/container/network.go | 53 +++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/pkg/container/network.go b/pkg/container/network.go index 9f18c15ca..03393c0a8 100644 --- a/pkg/container/network.go +++ b/pkg/container/network.go @@ -1,6 +1,7 @@ package container import ( + "crypto/rand" "fmt" "net" "time" @@ -224,6 +225,14 @@ func createBridge(bridgeName string) (*netlink.Bridge, error) { la := netlink.NewLinkAttrs() la.Name = bridgeName + // Assign a specific mac to the bridge - if we don't do this it will adopt + // the lowest address of an attached device, hence change over time. + mac, err := randomMAC() + if err != nil { + return nil, err + } + la.HardwareAddr = mac + // Disable MAC address age tracking. This causes issues in the container, // the bridge is unable to resolve MACs from outside resulting in it never // establishing the internal routes. This "optimization" is only really useful @@ -243,45 +252,29 @@ func addLink(link netlink.Link) (err error) { return } -// This is a MAC address persistence workaround, netlink.LinkSetMaster{,ByIndex}() -// has a bug that arbitrarily changes the MAC addresses of the bridge and virtual -// device to be bound to it. TODO: Remove when fixed upstream -func setMaster(master netlink.Link, links ...netlink.Link) error { - masterIndex := master.Attrs().Index - masterMAC, err := getMAC(master) - if err != nil { - return err +func randomMAC() (net.HardwareAddr, error) { + mac := make([]byte, 6) + if _, err := rand.Read(mac); err != nil { + return nil, err } - for _, link := range links { - mac, err := getMAC(link) - if err != nil { - return err - } + // In the first byte of the MAC, the 'multicast' bit should be + // clear and 'locally administered' bit should be set. + mac[0] = (mac[0] & 0xFE) | 0x02 - if err = netlink.LinkSetMasterByIndex(link, masterIndex); err != nil { - return err + return net.HardwareAddr(mac), nil } - if err = netlink.LinkSetHardwareAddr(link, mac); err != nil { +func setMaster(master netlink.Link, links ...netlink.Link) error { + masterIndex := master.Attrs().Index + + for _, link := range links { + if err := netlink.LinkSetMasterByIndex(link, masterIndex); err != nil { return err } } - return netlink.LinkSetHardwareAddr(master, masterMAC) -} - -// getMAC fetches the generated MAC address for the given link -func getMAC(link netlink.Link) (addr net.HardwareAddr, err error) { - // The attributes of the netlink.Link passed to this function do not contain HardwareAddr - // as it is expected to be generated by the networking subsystem. Thus, "reload" the Link - // by querying it to retrieve the generated attributes after the link has been created. - if link, err = netlink.LinkByIndex(link.Attrs().Index); err != nil { - return - } - - addr = link.Attrs().HardwareAddr - return + return nil } func maskString(mask net.IPMask) string {