From 4523e9c897b3fa8d12c1b16c830c01820fee5583 Mon Sep 17 00:00:00 2001 From: zsdc Date: Thu, 26 Aug 2021 18:15:36 +0300 Subject: wireguard: T3763: Added check for listening port availability Each wireguard interface requires a unique port for in and out connections. This commit adds the new `vyos.util` function - `check_port_availability`, and uses it to be sure that a port that is planned to be used for wireguard interface is truly available and not used by any other services (not only other wireguard interfaces). --- src/conf_mode/interfaces-wireguard.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/conf_mode/interfaces-wireguard.py') diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index 4c566a5ad..ad3ddcba2 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -30,6 +30,7 @@ from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 from vyos.ifconfig import WireGuardIf from vyos.util import check_kmod +from vyos.util import check_port_availability from vyos import ConfigError from vyos import airbag airbag.enable() @@ -73,6 +74,10 @@ def verify(wireguard): if 'peer' not in wireguard: raise ConfigError('At least one Wireguard peer is required!') + if 'port' in wireguard and check_port_availability( + '0.0.0.0', int(wireguard['port']), 'udp') is not True: + raise ConfigError('The port cannot be used for the interface') + # run checks on individual configured WireGuard peer for tmp in wireguard['peer']: peer = wireguard['peer'][tmp] -- cgit v1.2.3 From eb11d4b688d883d0c1d150b00eee40b54df42b32 Mon Sep 17 00:00:00 2001 From: zsdc Date: Thu, 26 Aug 2021 23:18:29 +0300 Subject: vyos.util: T3763: Optimized the check_port_availability function `print` was removed or replaced to `ValueError`, where possible. --- python/vyos/util.py | 12 +++--------- src/conf_mode/interfaces-wireguard.py | 9 ++++++--- 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'src/conf_mode/interfaces-wireguard.py') diff --git a/python/vyos/util.py b/python/vyos/util.py index fc2834a97..93a2f6640 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -834,16 +834,13 @@ def check_port_availability(ipaddress, port, protocol): try: ipaddress = ip_address(ipaddress).compressed except: - print(f'The {ipaddress} is not a valid IPv4 or IPv6 address') - return + raise ValueError(f'The {ipaddress} is not a valid IPv4 or IPv6 address') if port not in range(1, 65536): - print(f'The port number {port} is not in the 1-65535 range') - return + raise ValueError(f'The port number {port} is not in the 1-65535 range') if protocol not in ['tcp', 'udp']: - print( + raise ValueError( f'The protocol {protocol} is not supported. Only tcp and udp are allowed' ) - return # check port availability try: @@ -854,7 +851,4 @@ def check_port_availability(ipaddress, port, protocol): server.server_close() return True except: - print( - f'The {protocol} port {port} on the {ipaddress} is busy or unavailable' - ) return False diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index ad3ddcba2..68181465e 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -74,9 +74,12 @@ def verify(wireguard): if 'peer' not in wireguard: raise ConfigError('At least one Wireguard peer is required!') - if 'port' in wireguard and check_port_availability( - '0.0.0.0', int(wireguard['port']), 'udp') is not True: - raise ConfigError('The port cannot be used for the interface') + listen_port = int(wireguard['port']) + if 'port' in wireguard and check_port_availability('0.0.0.0', listen_port, + 'udp') is not True: + raise ConfigError( + f'The UDP port {listen_port} is busy or unavailable and cannot be used for the interface' + ) # run checks on individual configured WireGuard peer for tmp in wireguard['peer']: -- cgit v1.2.3 From c78daaf0f93937a7ecac139c45c5c81f7fcee81f Mon Sep 17 00:00:00 2001 From: zsdc Date: Sun, 29 Aug 2021 15:50:24 +0300 Subject: wireguard: T3763: Fixed uninitialized port issue The commit fixes the problem, when port availability check is triggered even if a port for WireGuard interface is not defined (randomized port, default behavior). --- src/conf_mode/interfaces-wireguard.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/conf_mode/interfaces-wireguard.py') diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index 68181465e..9baf5b6e9 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -74,12 +74,12 @@ def verify(wireguard): if 'peer' not in wireguard: raise ConfigError('At least one Wireguard peer is required!') - listen_port = int(wireguard['port']) - if 'port' in wireguard and check_port_availability('0.0.0.0', listen_port, - 'udp') is not True: - raise ConfigError( - f'The UDP port {listen_port} is busy or unavailable and cannot be used for the interface' - ) + if 'port' in wireguard: + listen_port = int(wireguard['port']) + if check_port_availability('0.0.0.0', listen_port, 'udp') is not True: + raise ConfigError( + f'The UDP port {listen_port} is busy or unavailable and cannot be used for the interface' + ) # run checks on individual configured WireGuard peer for tmp in wireguard['peer']: -- cgit v1.2.3 From 8d0207f87cf692458b688527022c8d841ec72904 Mon Sep 17 00:00:00 2001 From: zsdc Date: Sun, 29 Aug 2021 16:13:45 +0300 Subject: wireguard: T3763: The port availability check fix Check a port availability only if it was changed in current commit. This should protect from fail-positive errors when other parameters change for an interface. --- src/conf_mode/interfaces-wireguard.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/conf_mode/interfaces-wireguard.py') diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index 9baf5b6e9..da64dd076 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -47,6 +47,9 @@ def get_config(config=None): base = ['interfaces', 'wireguard'] wireguard = get_interface_dict(conf, base) + # Check if a port was changed + wireguard['port_changed'] = leaf_node_changed(conf, ['port']) + # Determine which Wireguard peer has been removed. # Peers can only be removed with their public key! dict = {} @@ -74,7 +77,7 @@ def verify(wireguard): if 'peer' not in wireguard: raise ConfigError('At least one Wireguard peer is required!') - if 'port' in wireguard: + if 'port' in wireguard and wireguard['port_changed']: listen_port = int(wireguard['port']) if check_port_availability('0.0.0.0', listen_port, 'udp') is not True: raise ConfigError( -- cgit v1.2.3