From dfdf1b8fb56d34a843427ef10f26116001685ec7 Mon Sep 17 00:00:00 2001 From: Chukwuleta Tobechi <47084273+TChukwuleta@users.noreply.github.com> Date: Thu, 7 Dec 2023 07:27:25 +0100 Subject: [PATCH 1/2] move IP generators into an abstract base class --- src/warnet/ip_generator.py | 49 ++++++++++++++++++++++++++++++++++++++ src/warnet/lnnode.py | 6 ++--- src/warnet/tank.py | 6 ++--- src/warnet/utils.py | 42 -------------------------------- 4 files changed, 55 insertions(+), 48 deletions(-) create mode 100644 src/warnet/ip_generator.py diff --git a/src/warnet/ip_generator.py b/src/warnet/ip_generator.py new file mode 100644 index 000000000..2cc46fedc --- /dev/null +++ b/src/warnet/ip_generator.py @@ -0,0 +1,49 @@ +from abc import ABC, abstractmethod +import ipaddress +import random + +class IPV4AddressGenerator(ABC): + @abstractmethod + def get_ip(self): + pass + + def generate_ipv4_addr(self, subnet): + """ + Generate a valid random IPv4 address within the given subnet. + + :param subnet: Subnet in CIDR notation (e.g., '100.0.0.0/8') + :return: Random IP address within the subnet + """ + reserved_ips = [ + "0.0.0.0/8", + "10.0.0.0/8", + "100.64.0.0/10", + "127.0.0.0/8", + "169.254.0.0/16", + "172.16.0.0/12", + "192.0.0.0/24", + "192.0.2.0/24", + "192.88.99.0/24", + "192.168.0.0/16", + "198.18.0.0/15", + "198.51.100.0/24", + "203.0.113.0/24", + "224.0.0.0/4", + ] + + def is_public(ip): + for reserved in reserved_ips: + if ipaddress.ip_address(ip) in ipaddress.ip_network(reserved, strict=False): + return False + return True + + network = ipaddress.ip_network(subnet, strict=False) + + # Generate a random IP within the subnet range + while True: + ip_int = random.randint( + int(network.network_address), int(network.broadcast_address) + ) + ip_str = str(ipaddress.ip_address(ip_int)) + if is_public(ip_str): + return ip_str \ No newline at end of file diff --git a/src/warnet/lnnode.py b/src/warnet/lnnode.py index 3784f1277..ce7028fc7 100644 --- a/src/warnet/lnnode.py +++ b/src/warnet/lnnode.py @@ -1,21 +1,21 @@ import json import os +from warnet.ip_generator import IPV4AddressGenerator from warnet.utils import ( exponential_backoff, - generate_ipv4_addr ) from backends import BackendInterface, ServiceType from .status import RunningStatus -class LNNode: +class LNNode(IPV4AddressGenerator): def __init__(self, warnet, tank, impl, backend: BackendInterface): self.warnet = warnet self.tank = tank assert impl == "lnd" self.impl = impl self.backend = backend - self.ipv4 = generate_ipv4_addr(self.warnet.subnet) + self.ipv4 = super().generate_ipv4_addr(self.warnet.subnet) self.rpc_port = 10009 @property diff --git a/src/warnet/tank.py b/src/warnet/tank.py index 1c1fe8678..293939916 100644 --- a/src/warnet/tank.py +++ b/src/warnet/tank.py @@ -6,9 +6,9 @@ from pathlib import Path from warnet.lnnode import LNNode +from warnet.ip_generator import IPV4AddressGenerator from warnet.utils import ( exponential_backoff, - generate_ipv4_addr, sanitize_tc_netem_command, SUPPORTED_TAGS, ) @@ -22,7 +22,7 @@ logger = logging.getLogger("tank") -class Tank: +class Tank(IPV4AddressGenerator): DEFAULT_BUILD_ARGS = "--disable-tests --with-incompatible-bdb --without-gui --disable-bench --disable-fuzz-binary --enable-suppress-external-warnings --enable-debug " def __init__(self, index:int, config_dir: Path, warnet): @@ -97,7 +97,7 @@ def suffix(self): @property def ipv4(self): if self._ipv4 is None: - self._ipv4 = generate_ipv4_addr(self.warnet.subnet) + self._ipv4 = self.generate_ipv4_addr(self.warnet.subnet) return self._ipv4 @property diff --git a/src/warnet/utils.py b/src/warnet/utils.py index b5ca01d16..5336e932a 100644 --- a/src/warnet/utils.py +++ b/src/warnet/utils.py @@ -78,48 +78,6 @@ def get_architecture(): return arch -def generate_ipv4_addr(subnet): - """ - Generate a valid random IPv4 address within the given subnet. - - :param subnet: Subnet in CIDR notation (e.g., '100.0.0.0/8') - :return: Random IP address within the subnet - """ - reserved_ips = [ - "0.0.0.0/8", - "10.0.0.0/8", - "100.64.0.0/10", - "127.0.0.0/8", - "169.254.0.0/16", - "172.16.0.0/12", - "192.0.0.0/24", - "192.0.2.0/24", - "192.88.99.0/24", - "192.168.0.0/16", - "198.18.0.0/15", - "198.51.100.0/24", - "203.0.113.0/24", - "224.0.0.0/4", - ] - - def is_public(ip): - for reserved in reserved_ips: - if ipaddress.ip_address(ip) in ipaddress.ip_network(reserved, strict=False): - return False - return True - - network = ipaddress.ip_network(subnet, strict=False) - - # Generate a random IP within the subnet range - while True: - ip_int = random.randint( - int(network.network_address), int(network.broadcast_address) - ) - ip_str = str(ipaddress.ip_address(ip_int)) - if is_public(ip_str): - return ip_str - - def sanitize_tc_netem_command(command: str) -> bool: """ Sanitize the tc-netem command to ensure it's valid and safe to execute, as we run it as root on a container. From 1085195a0d15a0f16f3b8829bfd0e9169269dafd Mon Sep 17 00:00:00 2001 From: Chukwuleta Tobechi <47084273+TChukwuleta@users.noreply.github.com> Date: Thu, 7 Dec 2023 07:42:17 +0100 Subject: [PATCH 2/2] remove abstract method --- src/warnet/ip_generator.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/warnet/ip_generator.py b/src/warnet/ip_generator.py index 2cc46fedc..4adb175cf 100644 --- a/src/warnet/ip_generator.py +++ b/src/warnet/ip_generator.py @@ -3,10 +3,6 @@ import random class IPV4AddressGenerator(ABC): - @abstractmethod - def get_ip(self): - pass - def generate_ipv4_addr(self, subnet): """ Generate a valid random IPv4 address within the given subnet. @@ -46,4 +42,4 @@ def is_public(ip): ) ip_str = str(ipaddress.ip_address(ip_int)) if is_public(ip_str): - return ip_str \ No newline at end of file + return ip_str