]> git.proxmox.com Git - mirror_ifupdown2.git/commitdiff
add support for new address policy: 'ip_blacklist'
authorJulien Fortin <jfortin@nvidia.com>
Fri, 9 Apr 2021 00:59:46 +0000 (02:59 +0200)
committerJulien Fortin <jfortin@nvidia.com>
Tue, 18 May 2021 15:19:25 +0000 (17:19 +0200)
context:
The IP address 169.254.0.1 is used by BGP unnumbered as an onlink
next-hop for IPv4 prefixes. When this is configured on the box, it
causes major issues which are very difficult to diagnose a debug.
It would be great if ifupdown2 could block this from being installed
on any interface as an address or address-virtual.

Signed-off-by: Julien Fortin <jfortin@nvidia.com>
ifupdown2/addons/address.py
ifupdown2/addons/addressvirtual.py
ifupdown2/lib/addon.py

index a4e2f8c71f587384b74ba1d3d24ca806b53ca05c..a567e2d85ccd9c7cf4e84095b6922501e6a3c535 100644 (file)
@@ -7,7 +7,7 @@
 import socket
 
 try:
-    from ifupdown2.lib.addon import Addon
+    from ifupdown2.lib.addon import AddonWithIpBlackList
     from ifupdown2.nlmanager.nlmanager import Link
 
     from ifupdown2.ifupdown.iface import *
@@ -23,7 +23,7 @@ try:
     import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
     import ifupdown2.ifupdown.ifupdownconfig as ifupdownconfig
 except (ImportError, ModuleNotFoundError):
-    from lib.addon import Addon
+    from lib.addon import AddonWithIpBlackList
     from nlmanager.nlmanager import Link
 
     from ifupdown.iface import *
@@ -40,7 +40,7 @@ except (ImportError, ModuleNotFoundError):
     import ifupdown.ifupdownconfig as ifupdownconfig
 
 
-class address(Addon, moduleBase):
+class address(AddonWithIpBlackList, moduleBase):
     """  ifupdown2 addon module to configure address, mtu, hwaddress, alias
     (description) on an interface """
 
@@ -175,7 +175,7 @@ class address(Addon, moduleBase):
     DEFAULT_MTU_STRING = "1500"
 
     def __init__(self, *args, **kargs):
-        Addon.__init__(self)
+        AddonWithIpBlackList.__init__(self)
         moduleBase.__init__(self, *args, **kargs)
         self._bridge_fdb_query_cache = {}
         self.ipforward = policymanager.policymanager_api.get_attr_default(module_name=self.__class__.__name__, attr='ip-forward')
@@ -474,6 +474,9 @@ class address(Addon, moduleBase):
                         # enable ipv6
                         self.write_file(proc_path, "0")
 
+                # check if ip is not blacklisted
+                self.ip_blacklist_check(ifname, ip)
+
                 if attributes:
                     self.netlink.addr_add(
                         ifname, ip,
index 1c85b7db4fd369aab3a92853f15ced834bf17298..55d3f5173f329b285721e5ee0d080b10d72d5388 100644 (file)
@@ -12,7 +12,7 @@ import subprocess
 from collections import deque
 
 try:
-    from ifupdown2.lib.addon import Addon
+    from ifupdown2.lib.addon import AddonWithIpBlackList
     from ifupdown2.ifupdown.iface import *
     from ifupdown2.ifupdown.utils import utils
 
@@ -27,7 +27,7 @@ try:
     import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
     import ifupdown2.ifupdown.ifupdownconfig as ifupdownconfig
 except (ImportError, ModuleNotFoundError):
-    from lib.addon import Addon
+    from lib.addon import AddonWithIpBlackList
     from ifupdown.iface import *
     from ifupdown.utils import utils
 
@@ -43,7 +43,7 @@ except (ImportError, ModuleNotFoundError):
     import ifupdown.ifupdownconfig as ifupdownconfig
 
 
-class addressvirtual(Addon, moduleBase):
+class addressvirtual(AddonWithIpBlackList, moduleBase):
     """  ifupdown2 addon module to configure virtual addresses """
 
     _modinfo = {
@@ -80,7 +80,7 @@ class addressvirtual(Addon, moduleBase):
     ADDR_METRIC_SUPPORT = None
 
     def __init__(self, *args, **kargs):
-        Addon.__init__(self)
+        AddonWithIpBlackList.__init__(self)
         moduleBase.__init__(self, *args, **kargs)
         self._bridge_fdb_query_cache = {}
         self.addressvirtual_with_route_metric = utils.get_boolean_from_string(
@@ -437,6 +437,9 @@ class addressvirtual(Addon, moduleBase):
             macvlan_mode = intf_config_dict.get("mode")
             ips = intf_config_dict.get("ips")
 
+            for ip in ips:
+                self.ip_blacklist_check(ifname, ip)
+
             if not self.cache.link_exists(macvlan_ifname):
                 # When creating VRRP macvlan with bridge mode, the kernel
                 # return an error: 'Invalid argument' (22)
index 4075a02fb4cb2fee387bb5fb218aa45d3b048940..1e463f9b4c358915866ed48e76cb15fd24f77033 100644 (file)
@@ -31,12 +31,18 @@ try:
     from ifupdown2.lib.sysfs import Sysfs
     from ifupdown2.lib.iproute2 import IPRoute2
     from ifupdown2.lib.base_objects import Netlink, Cache, Requirements
+
+    import ifupdown2.ifupdown.policymanager as policymanager
+    import ifupdown2.nlmanager.ipnetwork as ipnetwork
 except (ImportError, ModuleNotFoundError):
     from lib.io import IO
     from lib.sysfs import Sysfs
     from lib.iproute2 import IPRoute2
     from lib.base_objects import Netlink, Cache, Requirements
 
+    import ifupdown.policymanager as policymanager
+    import nlmanager.ipnetwork as ipnetwork
+
 
 class Addon(Netlink, Cache):
     """
@@ -88,3 +94,37 @@ class Bridge(Addon):
 
     def __init__(self):
         super(Bridge, self).__init__()
+
+
+class AddonWithIpBlackList(Addon):
+    try:
+        ip_blacklist = [ipnetwork.IPNetwork(ip).ip for ip in policymanager.policymanager_api.get_module_globals(
+            module_name="address",
+            attr="ip_blacklist"
+        ) or []]
+        __ip_blacklist_exception = None
+    except Exception as e:
+        __ip_blacklist_exception = e
+        ip_blacklist = []
+
+    def __init__(self):
+        """
+        If an exception occurred during the ip blacklist parsing we need to display it (once)
+        Also we keep this as a class variable to share it between the address and addressvirtual module
+        """
+        super(AddonWithIpBlackList, self).__init__()
+
+        if AddonWithIpBlackList.__ip_blacklist_exception:
+            self.logger.warning("policy.d: address: 'ip_blacklist': %s" % AddonWithIpBlackList.__ip_blacklist_exception)
+            AddonWithIpBlackList.__ip_blacklist_exception = None
+
+    def ip_blacklist_check(self, ifname, ip):
+        """
+        Check if the ip address is not blacklisted (in ip_blacklist)
+
+        :param ifname:
+        :param ip:
+        :return:
+        """
+        if ip.ip in AddonWithIpBlackList.ip_blacklist:
+            raise Exception("%s: blacklisted ip address in use: %s" % (ifname, ip.ip))