Detect and fix port forwarding collisions

This commit is contained in:
Dominik Moritz Roth 2024-05-21 17:17:27 +02:00
parent dbdf320b5b
commit 60ce64c1f3

21
main.py
View File

@ -71,7 +71,7 @@ def readMyIP():
s.connect(("8.8.8.8", 80)) s.connect(("8.8.8.8", 80))
return s.getsockname()[0] return s.getsockname()[0]
def addPortMapping(fc, extPort, intPort, name=None, protocol='TCP', active=True): def upsertPortMapping(fc, extPort, intPort, name=None, protocol='TCP', active=True):
mapping = { mapping = {
'NewRemoteHost': '0.0.0.0', 'NewRemoteHost': '0.0.0.0',
'NewExternalPort': extPort, 'NewExternalPort': extPort,
@ -87,9 +87,6 @@ def addPortMapping(fc, extPort, intPort, name=None, protocol='TCP', active=True)
return return
fc.call_action("WANPPPConnection1", "AddPortMapping", **mapping ) fc.call_action("WANPPPConnection1", "AddPortMapping", **mapping )
def deletePortMapping(fc, extPort, intPort, protocol='TCP', name=None):
addPortMapping(fc, extPort, intPort, name=name, protocol=protocol, active=False)
def load_config(): def load_config():
with open('config.yaml', 'r') as f: with open('config.yaml', 'r') as f:
conf = yaml.safe_load(f) conf = yaml.safe_load(f)
@ -166,19 +163,19 @@ def read_paths(conf, fc):
ms = readPortmappings(fc) ms = readPortmappings(fc)
path_indices = {} path_indices = {}
for route in conf['routes']: for route in conf['routes']:
found_map = False
for path in route['paths']: for path in route['paths']:
# Lets see if we have such a path active # Lets see if we have such a path active
fstFwd = path['forwards'][0] fstFwd = path['forwards'][0]
found_map = False
for m in ms: for m in ms:
if m['NewEnabled'] and m['NewInternalClient'] == path['ip'] and m['NewPortMappingDescription'] == fstFwd['name'] and m['NewExternalPort'] == fstFwd['external'] and m['NewInternalPort'] == fstFwd['internal'] and m['NewProtocol'] == fstFwd['protocol'].upper(): if m['NewEnabled'] and m['NewInternalClient'] == path['ip'] and m['NewPortMappingDescription'] == fstFwd['name'] and m['NewExternalPort'] == fstFwd['external'] and m['NewInternalPort'] == fstFwd['internal'] and m['NewProtocol'] == fstFwd['protocol'].upper():
# This path is (at least partially) active # This path is (at least partially) active
path_indices[route['name']] = path['name'] if found_map: # Collision!!!
found_map = True path_indices[route['name']] = 'COLLISION'
break else:
if found_map: path_indices[route['name']] = path['name']
break found_map = True
else: if not found_map:
# All paths are down # All paths are down
path_indices[route['name']] = None path_indices[route['name']] = None
alert('We found no active path for route {route["name"]}.') alert('We found no active path for route {route["name"]}.')
@ -203,7 +200,7 @@ def flush_paths(conf, fc, active_paths):
def flush_forwards(path, make_active, fc): def flush_forwards(path, make_active, fc):
for forward in path['forwards']: for forward in path['forwards']:
addPortMapping(fc, forward['external'], forward['internal'], name=forward['name'], protocol=forward['protocol'], active=make_active) upsertPortMapping(fc, forward['external'], forward['internal'], name=forward['name'], protocol=forward['protocol'], active=make_active)
def check_avail(path): def check_avail(path):
ip = path['ip'] ip = path['ip']