nix-files/pkgs/additional/sane-scripts/src/sane-ip-check

74 lines
2.3 KiB
Python
Executable File

#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.requests ps.sane-lib.ssdp ])" -p miniupnpc
# vim: set filetype=python :
"""
sane-ip-check: query the IP address of this machine as seen by an external Internet host.
"""
# best to run this with an external timeout. e.g.
# - `timeout 60 sane-ip-check`
import argparse
import json
import logging
import requests
import subprocess
import sys
from sane_ssdp import get_any_wan
logger = logging.getLogger(__name__)
def get_wan_fallback():
"untrusted method in which to get the WAN IP"
r = requests.get("https://ipinfo.io/ip")
ip = r.text.strip()
if any(c not in "0123456789." for c in ip):
logging.warn("invalid IP from ipinfo.ip", ip)
return ""
else:
return ip
def main(format: str, try_upnp: bool, expect: str|None) -> None:
upnp_details = get_any_wan() if try_upnp else None
if upnp_details:
root_dev, _lan_ip, wan_ip = upnp_details
else:
root_dev, wan_ip = "", get_wan_fallback()
if expect:
assert wan_ip == expect, f"actual IP {wan_ip} != expected IP {expect}"
if format == "plaintext":
print(wan_ip)
elif format == "json":
print(json.dumps(dict(
wan=wan_ip,
upnp=root_dev,
)))
if __name__ == '__main__':
logging.basicConfig()
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("-v", action="store_true", help="be verbose")
parser.add_argument("-vv", action="store_true", help="be more verbose")
parser.add_argument("--json", action="store_true", help="output results in json format")
parser.add_argument("--no-upnp", action="store_true", help="instead of asking the gateway for its IP address, discover my IP by querying a third-party public service")
parser.add_argument("--expect", default=None, help="exit with error if IP address isn't as specified")
format = "plaintext"
try_upnp = True
args = parser.parse_args()
if args.v:
logging.getLogger().setLevel(logging.INFO)
if args.vv:
logging.getLogger().setLevel(logging.DEBUG)
if args.json:
format = "json"
if args.no_upnp:
try_upnp = False
main(format=format, try_upnp=try_upnp, expect=args.expect)