diff options
author | Christian Poessinger <christian@poessinger.com> | 2021-09-26 12:28:37 +0200 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2021-09-26 12:36:19 +0200 |
commit | e4812d266ea841f8baf5ad6c7cfae1c7eba664b6 (patch) | |
tree | 0e659ded033cf139f86be067874d6c2d47852e56 /python/vyos/ifconfig/interface.py | |
parent | bfe59076f8075083920143cfb4ae22617aa0c663 (diff) | |
download | vyos-1x-e4812d266ea841f8baf5ad6c7cfae1c7eba664b6.tar.gz vyos-1x-e4812d266ea841f8baf5ad6c7cfae1c7eba664b6.zip |
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)
Diffstat (limited to 'python/vyos/ifconfig/interface.py')
-rw-r--r-- | python/vyos/ifconfig/interface.py | 23 |
1 files changed, 16 insertions, 7 deletions
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 |