From 890ec39113360eee66031fc8dc652836ed565c41 Mon Sep 17 00:00:00 2001 From: Aaron Guise Date: Wed, 15 Feb 2023 20:22:07 +1300 Subject: [PATCH] Initial Project Import --- .gitignore | 2 ++ .vscode/settings.json | 3 ++ Dockerfile | 16 +++++++++++ src/app.py | 66 +++++++++++++++++++++++++++++++++++++++++++ src/requirements.txt | 2 ++ 5 files changed, 89 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Dockerfile create mode 100644 src/app.py create mode 100644 src/requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db1a302 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +.venv \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..de288e1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.formatting.provider": "black" +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..13231a2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3-slim AS build + +COPY src/ /app + +WORKDIR /app + +RUN python3 -m pip install -r requirements.txt + + +VOLUME /app/data + +ENV NOIP_HOST="127.0.0.1" +ENV NOIP_USERNAME="" +ENV NOIP_PASSWORD="" + +CMD ["python3", "app.py"] \ No newline at end of file diff --git a/src/app.py b/src/app.py new file mode 100644 index 0000000..e007fe7 --- /dev/null +++ b/src/app.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +import paramiko +import click +import re + + +def return_ip_and_prefix(lines :str, scheme :str ="ipv6" ) -> str: + """ Lookup and return IP Address and a suffix. + Supports both IPv6 and IPv4 + + Args: + lines (str): The lines of text to check. e.g. output from Paramiko + scheme (str, optional): The IP scheme (IPv4 or IPv6). Defaults to "ipv6". + + Returns: + str: An IP with prefix/CIDR + """ + if scheme == "ipv6": + m = re.search(r"inet6 ([\d\w:/]+).+prefixlen (56|64)$", lines) + ip_split = ":".join(m.group(1).split(":", 4)[:4]) + return ip_split + "::1/" + m.group(2) + elif scheme == "ipv4": + m = re.search(r"inet ([\d./]+)", lines) + return m.group(1) + "/32" + + +@click.command() +@click.option("--host", required=True, help="The hostname/ip to connect to.") +@click.option("--port", default=22, help="The SSH port to connect on.") +@click.option("--username", required=True, help="The username you wish to use.") +@click.option("--password", required=True, help="The Password/Secret for this user.") +def main(host: str, port: int, username: str, password: str) -> None: + """ This application will connect to an OpnSense firewall. The aim is to retrieve + the IPv6 Segment and Prefix along with the IPv4 address for the WAN. + """ + click.echo("Checking for IPv6 Prefix") + + command = "8;ifconfig vtnet1 | grep -E 'prefixlen [0-9]{2}$'" + ipv4_command = "ifconfig vtnet0 | grep -E 'inet.+ netmask'" + logout_command = "exit; 0\n" + + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(host, port, username, password) + + _, stdout, _ = ssh.exec_command(command) + output = stdout.read().decode() + + f = open("data/gallow.txt", "w") + f.write(return_ip_and_prefix(output, "ipv6") + "\n") + + click.echo("Fetched IPv6 Prefix") + + click.echo("Checking for IPv4 Address on WAN") + _, stdout, _ = ssh.exec_command(ipv4_command) + output = stdout.read().decode() + f.write(return_ip_and_prefix(output, "ipv4") + "\n") + click.echo("Retrieved IPv4 Address from WAN") + f.close() + + ssh.exec_command(logout_command) + ssh.close() + + +if __name__ == "__main__": + main(auto_envvar_prefix="NOIP") diff --git a/src/requirements.txt b/src/requirements.txt new file mode 100644 index 0000000..2d4f73b --- /dev/null +++ b/src/requirements.txt @@ -0,0 +1,2 @@ +paramiko==3.0.0 +click==8.1.3 \ No newline at end of file