代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/firewalld 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From a5291bcee84b56b30aac38544d85fb601fe6a25a Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Tue, 17 Mar 2020 13:51:43 -0400
Subject: [PATCH] improvement: port: allow coalescing and breaking of ranges
---
src/firewall/core/fw_zone.py | 106 +++++++++++++++++++++++++++----------
src/firewall/functions.py | 85 +++++++++++++++++++++++++++++
src/firewall/server/config_zone.py | 55 ++++++++++++++-----
3 files changed, 204 insertions(+), 42 deletions(-)
diff --git a/src/firewall/core/fw_zone.py b/src/firewall/core/fw_zone.py
index 2bc94e3..d32d7a8 100644
--- a/src/firewall/core/fw_zone.py
+++ b/src/firewall/core/fw_zone.py
@@ -25,7 +25,7 @@ from firewall.core.base import SHORTCUTS, DEFAULT_ZONE_TARGET, \
from firewall.core.logger import log
from firewall.functions import portStr, checkIPnMask, checkIP6nMask, \
checkProtocol, enable_ip_forwarding, check_single_address, check_mac, \
- portInPortRange, get_nf_conntrack_short_name
+ portInPortRange, get_nf_conntrack_short_name, coalescePortRange, breakPortRange
from firewall.core.rich import Rich_Rule, Rich_Accept, \
Rich_Mark, Rich_Service, Rich_Port, Rich_Protocol, \
Rich_Masquerade, Rich_ForwardPort, Rich_SourcePort, Rich_IcmpBlock, \
@@ -857,11 +857,13 @@ class FirewallZone(object):
self._fw.check_panic()
_obj = self._zones[_zone]
- port_id = self.__port_id(port, protocol)
- if port_id in _obj.settings["ports"]:
- raise FirewallError(errors.ALREADY_ENABLED,
- "'%s:%s' already in '%s'" % (port, protocol,
- _zone))
+ existing_port_ids = list(filter(lambda x: x[1] == protocol, _obj.settings["ports"]))
+ for port_id in existing_port_ids:
+ if portInPortRange(port, port_id[0]):
+ raise FirewallError(errors.ALREADY_ENABLED,
+ "'%s:%s' already in '%s'" % (port, protocol, _zone))
+
+ added_ranges, removed_ranges = coalescePortRange(port, [_port for (_port, _protocol) in existing_port_ids])
if use_transaction is None:
transaction = self.new_transaction()
@@ -869,10 +871,18 @@ class FirewallZone(object):
transaction = use_transaction
if _obj.applied:
- self._port(True, _zone, port, protocol, transaction)
-
- self.__register_port(_obj, port_id, timeout, sender)
- transaction.add_fail(self.__unregister_port, _obj, port_id)
+ for range in added_ranges:
+ self._port(True, _zone, portStr(range, "-"), protocol, transaction)
+ for range in removed_ranges:
+ self._port(False, _zone, portStr(range, "-"), protocol, transaction)
+
+ for range in added_ranges:
+ port_id = self.__port_id(range, protocol)
+ self.__register_port(_obj, port_id, timeout, sender)
+ transaction.add_fail(self.__unregister_port, _obj, port_id)
+ for range in removed_ranges:
+ port_id = self.__port_id(range, protocol)
+ transaction.add_post(self.__unregister_port, _obj, port_id)
if use_transaction is None:
transaction.execute(True)
@@ -889,20 +899,34 @@ class FirewallZone(object):
self._fw.check_panic()
_obj = self._zones[_zone]
- port_id = self.__port_id(port, protocol)
- if port_id not in _obj.settings["ports"]:
+ existing_port_ids = list(filter(lambda x: x[1] == protocol, _obj.settings["ports"]))
+ for port_id in existing_port_ids:
+ if portInPortRange(port, port_id[0]):
+ break
+ else:
raise FirewallError(errors.NOT_ENABLED,
"'%s:%s' not in '%s'" % (port, protocol, _zone))
+ added_ranges, removed_ranges = breakPortRange(port, [_port for (_port, _protocol) in existing_port_ids])
+
if use_transaction is None:
transaction = self.new_transaction()
else:
transaction = use_transaction
if _obj.applied:
- self._port(False, _zone, port, protocol, transaction)
-
- transaction.add_post(self.__unregister_port, _obj, port_id)
+ for range in added_ranges:
+ self._port(True, _zone, portStr(range, "-"), protocol, transaction)
+ for range in removed_ranges:
+ self._port(False, _zone, portStr(range, "-"), protocol, transaction)
+
+ for range in added_ranges:
+ port_id = self.__port_id(range, protocol)
+ self.__register_port(_obj, port_id, 0, None)
+ transaction.add_fail(self.__unregister_port, _obj, port_id)
+ for range in removed_ranges:
+ port_id = self.__port_id(range, protocol)
+ transaction.add_post(self.__unregister_port, _obj, port_id)
if use_transaction is None:
transaction.execute(True)
@@ -1015,11 +1039,13 @@ class FirewallZone(object):
self._fw.check_panic()
_obj = self._zones[_zone]
- port_id = self.__source_port_id(port, protocol)
- if port_id in _obj.settings["source_ports"]:
- raise FirewallError(errors.ALREADY_ENABLED,
- "'%s:%s' already in '%s'" % (port, protocol,
- _zone))
+ existing_port_ids = list(filter(lambda x: x[1] == protocol, _obj.settings["source_ports"]))
+ for port_id in existing_port_ids:
+ if portInPortRange(port, port_id[0]):
+ raise FirewallError(errors.ALREADY_ENABLED,
+ "'%s:%s' already in '%s'" % (port, protocol, _zone))
+
+ added_ranges, removed_ranges = coalescePortRange(port, [_port for (_port, _protocol) in existing_port_ids])
if use_transaction is None:
transaction = self.new_transaction()
@@ -1027,10 +1053,18 @@ class FirewallZone(object):
transaction = use_transaction
if _obj.applied:
- self._source_port(True, _zone, port, protocol, transaction)
-
- self.__register_source_port(_obj, port_id, timeout, sender)
- transaction.add_fail(self.__unregister_source_port, _obj, port_id)
+ for range in added_ranges:
+ self._source_port(True, _zone, portStr(range, "-"), protocol, transaction)
+ for range in removed_ranges:
+ self._source_port(False, _zone, portStr(range, "-"), protocol, transaction)
+
+ for range in added_ranges:
+ port_id = self.__source_port_id(range, protocol)
+ self.__register_source_port(_obj, port_id, timeout, sender)
+ transaction.add_fail(self.__unregister_source_port, _obj, port_id)
+ for range in removed_ranges:
+ port_id = self.__source_port_id(range, protocol)
+ transaction.add_post(self.__unregister_source_port, _obj, port_id)
if use_transaction is None:
transaction.execute(True)
@@ -1047,20 +1081,34 @@ class FirewallZone(object):
self._fw.check_panic()
_obj = self._zones[_zone]
- port_id = self.__source_port_id(port, protocol)
- if port_id not in _obj.settings["source_ports"]:
+ existing_port_ids = list(filter(lambda x: x[1] == protocol, _obj.settings["source_ports"]))
+ for port_id in existing_port_ids:
+ if portInPortRange(port, port_id[0]):
+ break
+ else:
raise FirewallError(errors.NOT_ENABLED,
"'%s:%s' not in '%s'" % (port, protocol, _zone))
+ added_ranges, removed_ranges = breakPortRange(port, [_port for (_port, _protocol) in existing_port_ids])
+
if use_transaction is None:
transaction = self.new_transaction()
else:
transaction = use_transaction
if _obj.applied:
- self._source_port(False, _zone, port, protocol, transaction)
-
- transaction.add_post(self.__unregister_source_port, _obj, port_id)
+ for range in added_ranges:
+ self._source_port(True, _zone, portStr(range, "-"), protocol, transaction)
+ for range in removed_ranges:
+ self._source_port(False, _zone, portStr(range, "-"), protocol, transaction)
+
+ for range in added_ranges:
+ port_id = self.__source_port_id(range, protocol)
+ self.__register_source_port(_obj, port_id, 0, None)
+ transaction.add_fail(self.__unregister_source_port, _obj, port_id)
+ for range in removed_ranges:
+ port_id = self.__source_port_id(range, protocol)
+ transaction.add_post(self.__unregister_source_port, _obj, port_id)
if use_transaction is None:
transaction.execute(True)
diff --git a/src/firewall/functions.py b/src/firewall/functions.py
index 6af2206..6bc52d9 100644
--- a/src/firewall/functions.py
+++ b/src/firewall/functions.py
@@ -72,6 +72,10 @@ def getPortRange(ports):
@return Array containing start and end port id for a valid range or -1 if port can not be found and -2 if port is too big for integer input or -1 for invalid ranges or None if the range is ambiguous.
"""
+ # (port, port) or [port, port] case
+ if isinstance(ports, tuple) or isinstance(ports, list):
+ return ports
+
# "<port-id>" case
if isinstance(ports, int) or ports.isdigit():
id1 = getPortID(ports)
@@ -155,6 +159,87 @@ def portInPortRange(port, range):
return False
+def coalescePortRange(new_range, ranges):
+ """ Coalesce a port range with existing list of port ranges
+
+ @param new_range tuple/list/string
+ @param ranges list of tuple/list/string
+ @return tuple of (list of ranges added after coalescing, list of removed original ranges)
+ """
+
+ coalesced_range = getPortRange(new_range)
+ # normalize singleton ranges, e.g. (x,) --> (x,x)
+ if len(coalesced_range) == 1:
+ coalesced_range = (coalesced_range[0], coalesced_range[0])
+ _ranges = map(getPortRange, ranges)
+ _ranges = sorted(map(lambda x: (x[0],x[0]) if len(x) == 1 else x, _ranges), key=lambda x: x[0])
+
+ removed_ranges = []
+ for range in _ranges:
+ if coalesced_range[0] <= range[0] and coalesced_range[1] >= range[1]:
+ # new range covers this
+ removed_ranges.append(range)
+ elif coalesced_range[0] <= range[0] and coalesced_range[1] < range[1] and \
+ coalesced_range[1] >= range[0]:
+ # expand beginning of range
+ removed_ranges.append(range)
+ coalesced_range = (coalesced_range[0], range[1])
+ elif coalesced_range[0] > range[0] and coalesced_range[1] >= range[1] and \
+ coalesced_range[0] <= range[1]:
+ # expand end of range
+ removed_ranges.append(range)
+ coalesced_range = (range[0], coalesced_range[1])
+
+ # normalize singleton ranges, e.g. (x,x) --> (x,)
+ removed_ranges = list(map(lambda x: (x[0],) if x[0] == x[1] else x, removed_ranges))
+ if coalesced_range[0] == coalesced_range[1]:
+ coalesced_range = (coalesced_range[0],)
+
+ return ([coalesced_range], removed_ranges)
+
+def breakPortRange(remove_range, ranges):
+ """ break a port range from existing list of port ranges
+
+ @param remove_range tuple/list/string
+ @param ranges list of tuple/list/string
+ @return tuple of (list of ranges added after breaking up, list of removed original ranges)
+ """
+
+ remove_range = getPortRange(remove_range)
+ # normalize singleton ranges, e.g. (x,) --> (x,x)
+ if len(remove_range) == 1:
+ remove_range = (remove_range[0], remove_range[0])
+ _ranges = map(getPortRange, ranges)
+ _ranges = sorted(map(lambda x: (x[0],x[0]) if len(x) == 1 else x, _ranges), key=lambda x: x[0])
+
+ removed_ranges = []
+ added_ranges = []
+ for range in _ranges:
+ if remove_range[0] <= range[0] and remove_range[1] >= range[1]:
+ # remove entire range
+ removed_ranges.append(range)
+ elif remove_range[0] <= range[0] and remove_range[1] < range[1] and \
+ remove_range[1] >= range[0]:
+ # remove from beginning of range
+ removed_ranges.append(range)
+ added_ranges.append((remove_range[1] + 1, range[1]))
+ elif remove_range[0] > range[0] and remove_range[1] >= range[1] and \
+ remove_range[0] <= range[1]:
+ # remove from end of range
+ removed_ranges.append(range)
+ added_ranges.append((range[0], remove_range[0] - 1))
+ elif remove_range[0] > range[0] and remove_range[1] < range[1]:
+ # remove inside range
+ removed_ranges.append(range)
+ added_ranges.append((range[0], remove_range[0] - 1))
+ added_ranges.append((remove_range[1] + 1, range[1]))
+
+ # normalize singleton ranges, e.g. (x,x) --> (x,)
+ removed_ranges = list(map(lambda x: (x[0],) if x[0] == x[1] else x, removed_ranges))
+ added_ranges = list(map(lambda x: (x[0],) if x[0] == x[1] else x, added_ranges))
+
+ return (added_ranges, removed_ranges)
+
def getServiceName(port, proto):
""" Check and Get service name from port and proto string combination using socket.getservbyport
diff --git a/src/firewall/server/config_zone.py b/src/firewall/server/config_zone.py
index 1ae20ce..1c05318 100644
--- a/src/firewall/server/config_zone.py
+++ b/src/firewall/server/config_zone.py
@@ -41,7 +41,8 @@ from firewall.server.decorators import handle_exceptions, \
dbus_handle_exceptions, dbus_service_method
from firewall import errors
from firewall.errors import FirewallError
-from firewall.functions import portInPortRange
+from firewall.functions import portStr, portInPortRange, coalescePortRange, \
+ breakPortRange
############################################################################
#
@@ -455,10 +456,16 @@ class FirewallDConfigZone(slip.dbus.service.Object):
protocol)
self.parent.accessCheck(sender)
settings = list(self.getSettings())
- if (port,protocol) in settings[6]:
- raise FirewallError(errors.ALREADY_ENABLED,
- "%s:%s" % (port, protocol))
- settings[6].append((port,protocol))
+ existing_port_ids = list(filter(lambda x: x[1] == protocol, settings[6]))
+ for port_id in existing_port_ids:
+ if portInPortRange(port, port_id[0]):
+ raise FirewallError(errors.ALREADY_ENABLED,
+ "%s:%s" % (port, protocol))
+ added_ranges, removed_ranges = coalescePortRange(port, [_port for (_port, _protocol) in existing_port_ids])
+ for range in removed_ranges:
+ settings[6].remove((portStr(range, "-"), protocol))
+ for range in added_ranges:
+ settings[6].append((portStr(range, "-"), protocol))
self.update(settings)
@dbus_service_method(config.dbus.DBUS_INTERFACE_CONFIG_ZONE,
@@ -471,9 +478,17 @@ class FirewallDConfigZone(slip.dbus.service.Object):
protocol)
self.parent.accessCheck(sender)
settings = list(self.getSettings())
- if (port,protocol) not in settings[6]:
+ existing_port_ids = list(filter(lambda x: x[1] == protocol, settings[6]))
+ for port_id in existing_port_ids:
+ if portInPortRange(port, port_id[0]):
+ break
+ else:
raise FirewallError(errors.NOT_ENABLED, "%s:%s" % (port, protocol))
- settings[6].remove((port,protocol))
+ added_ranges, removed_ranges = breakPortRange(port, [_port for (_port, _protocol) in existing_port_ids])
+ for range in removed_ranges:
+ settings[6].remove((portStr(range, "-"), protocol))
+ for range in added_ranges:
+ settings[6].append((portStr(range, "-"), protocol))
self.update(settings)
@dbus_service_method(config.dbus.DBUS_INTERFACE_CONFIG_ZONE,
@@ -583,10 +598,16 @@ class FirewallDConfigZone(slip.dbus.service.Object):
protocol)
self.parent.accessCheck(sender)
settings = list(self.getSettings())
- if (port,protocol) in settings[14]:
- raise FirewallError(errors.ALREADY_ENABLED,
- "%s:%s" % (port, protocol))
- settings[14].append((port,protocol))
+ existing_port_ids = list(filter(lambda x: x[1] == protocol, settings[14]))
+ for port_id in existing_port_ids:
+ if portInPortRange(port, port_id[0]):
+ raise FirewallError(errors.ALREADY_ENABLED,
+ "%s:%s" % (port, protocol))
+ added_ranges, removed_ranges = coalescePortRange(port, [_port for (_port, _protocol) in existing_port_ids])
+ for range in removed_ranges:
+ settings[14].remove((portStr(range, "-"), protocol))
+ for range in added_ranges:
+ settings[14].append((portStr(range, "-"), protocol))
self.update(settings)
@dbus_service_method(config.dbus.DBUS_INTERFACE_CONFIG_ZONE,
@@ -599,9 +620,17 @@ class FirewallDConfigZone(slip.dbus.service.Object):
protocol)
self.parent.accessCheck(sender)
settings = list(self.getSettings())
- if (port,protocol) not in settings[14]:
+ existing_port_ids = list(filter(lambda x: x[1] == protocol, settings[14]))
+ for port_id in existing_port_ids:
+ if portInPortRange(port, port_id[0]):
+ break
+ else:
raise FirewallError(errors.NOT_ENABLED, "%s:%s" % (port, protocol))
- settings[14].remove((port,protocol))
+ added_ranges, removed_ranges = breakPortRange(port, [_port for (_port, _protocol) in existing_port_ids])
+ for range in removed_ranges:
+ settings[14].remove((portStr(range, "-"), protocol))
+ for range in added_ranges:
+ settings[14].append((portStr(range, "-"), protocol))
self.update(settings)
@dbus_service_method(config.dbus.DBUS_INTERFACE_CONFIG_ZONE,
--
1.8.3.1
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。