diff --git a/config.example.yaml b/config.example.yaml index a3fb5e3..b542325 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -1,3 +1,14 @@ +# Forwarded port should be declared as : +# service-name: +# internal_port: XXXX +# external_port: YYYY +# protocol: 'ZZZ' +# +# With XXXX the internal port, YYYY the external port and ZZZ the protocol (TCP or UDP) +# Additional fields can be set: +# description: "A description to help understand the port forwarding" + + wireguard: description: "Wireguard port" internal_port: 51820 diff --git a/grep b/grep new file mode 100644 index 0000000..30b5e53 --- /dev/null +++ b/grep @@ -0,0 +1,4 @@ +upnpc : miniupnpc library test client, version 2.2.3. + (c) 2005-2021 Thomas Bernard. +Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ +for more information. diff --git a/port-forwarder.py b/port-forwarder.py index 4ebd0bf..b70c108 100644 --- a/port-forwarder.py +++ b/port-forwarder.py @@ -1,6 +1,42 @@ #!/usr/bin/python3 import miniupnpc +import os import sys +import yaml + +try: + from yaml import CLoader as Loader, CDumper as Dumper +except ImportError: + from yaml import Loader, Dumper + +# Arguments +verbose = True +action = "open" # open, close, status + +# If no config exists we create one +if not os.path.exists("config.yaml"): + print("No config file detected, populating one") + dummy_config = """dummy-service: + description: "Dummy service to change" + external_port: 12000 + internal_port: 12000 + protocol: 'TCP'""" + +config_data = "" + +if verbose: + print("Reading the config") +with open("config.yaml", "r", encoding="utf8") as config_file: + config_data = config_file.read() + +if not config_data: + print("Could not read config file !") + sys.exit(1) + +config_data = yaml.load(config_data, Loader=Loader) + +if verbose: + print("Config read and in memory, executing miniUPnP") u = miniupnpc.UPnP(None, None, 200, 0) u.lanaddr @@ -17,4 +53,22 @@ print('external ip address :', u.externalipaddress()) print( u.statusinfo(), u.connectiontype()) +for service_name in config_data: + data = config_data[service_name] + if verbose: + print(f"{service_name} | data : {data}") + if {"internal_port", "external_port", "protocol"}.issubset(set(data.keys())): + internal_port = data["internal_port"] + external_port = data["external_port"] + protocol = data["protocol"] + else: + print(f"Error: {service_name}, missing one of the required keys internal_port, external_port or protocol, skipping the service.") + if "description" in data.keys(): + if verbose: + print(f"A description was provided for {service_name}.") + description = data["description"] + else: + description = "" + + u.addportmapping(external_port, protocol, u.lanaddr, internal_port, description, '')