From e4812d266ea841f8baf5ad6c7cfae1c7eba664b6 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 26 Sep 2021 12:28:37 +0200 Subject: vyos.ifconfig: T3860: bugfix in get_mac_synthetic() Commit 081e23996f (vyos.ifconfig: get_mac_synthetic() must generate a stable "MAC") calculated a "stable" synthetic MAC address per the interface based on UUID and the interface name. The problem is that this calculation is too stable when run on multiple instances of VyOS on different hosts/hypervisors. Having R1 and R2 setup a connection both via "tun10" interface will become the same "synthetic" MAC address manifesting in the same link-local IPv6 address. This e.g. breaks OSPFv3 badly as both neighbors communicate using the same link-local address. As workaround one can: set interfaces tunnel tun1337 address 'fe80::1:1337/64' set interfaces tunnel tun1337 ipv6 address no-default-link-local This commit changes the way in how the synthetic MAC address is generated. It's based on the first 48 bits of a sha256 sum build from a CPU ID retrieved via DMI, the MAC address of eth0 and the interface name as used before. This should add enough entropy to get a stable pseudo MAC address. (cherry picked from commit 8d6861290f39298701b0a89bd358545763cee14b) --- python/vyos/ifconfig/interface.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'python/vyos/ifconfig') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 76f1e158a..709c70b65 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -27,8 +27,6 @@ from netifaces import ifaddresses # this is not the same as socket.AF_INET/INET6 from netifaces import AF_INET from netifaces import AF_INET6 -from uuid import uuid3 -from uuid import NAMESPACE_DNS from vyos import ConfigError from vyos.configdict import list_diff @@ -439,11 +437,22 @@ class Interface(Control): >>> Interface('eth0').get_mac() '00:50:ab:cd:ef:00' """ - # calculate a UUID based on the interface name - this is as predictable - # as an interface MAC address and thus can be used in the same way - tmp = uuid3(NAMESPACE_DNS, self.ifname) - # take the last 48 bits from the UUID string - tmp = str(tmp).split('-')[-1] + from hashlib import sha256 + + # Get processor ID number + cpu_id = self._cmd('sudo dmidecode -t 4 | grep ID | head -n1 | sed "s/.*ID://;s/ //g"') + # Get system eth0 base MAC address - every system has eth0 + eth0_mac = Interface('eth0').get_mac() + + sha = sha256() + # Calculate SHA256 sum based on the CPU ID number, eth0 mac address and + # this interface identifier - this is as predictable as an interface + # MAC address and thus can be used in the same way + sha.update(cpu_id.encode()) + sha.update(eth0_mac.encode()) + sha.update(self.ifname.encode()) + # take the most significant 48 bits from the SHA256 string + tmp = sha.hexdigest()[:12] # Convert pseudo random string into EUI format which now represents a # MAC address tmp = EUI(tmp).value -- cgit v1.2.3