From 8777b73bb7bd2755e4e089f42b4994b32565e137 Mon Sep 17 00:00:00 2001 From: Baptiste Jonglez Date: Tue, 16 Jun 2020 10:56:21 +0200 Subject: [PATCH] lg: Change configuration of proxied hosts (not backward compatible) This simplifies and clarify the configuration, while making it more generic and getting rid of the "DOMAIN" variable. Proxied hosts can now be reached over HTTP or HTTPS, through any DNS name, and even through IP literals to avoid dependency on DNS. With the previous code, proxied hosts needed to be reachable with the fixed scheme `http://.:`, and this was a big limitation for some deployments. This is not backwards compatible, users will have to adapt their configuration. We rename the `PROXY` variable to `HOSTS` to make that extra-clear. --- lg.cfg | 41 ++++++++++++++++++++++-------------- lg.py | 49 +++++++++++++++++++------------------------ templates/layout.html | 2 +- 3 files changed, 48 insertions(+), 44 deletions(-) diff --git a/lg.cfg b/lg.cfg index 4d120ea..193ec7f 100644 --- a/lg.cfg +++ b/lg.cfg @@ -3,28 +3,36 @@ DEBUG = False LOG_FILE="/var/log/lg.log" LOG_LEVEL="WARNING" -DOMAIN = "tetaneutral.net" - # Used to optionally restrict access to lgproxy based on a shared secret. SHARED_SECRET="ThisTokenIsNotSecret" BIND_IP = "0.0.0.0" BIND_PORT = 5000 -PROXY = { - "gw": 5000, - "h3": 5000, - } - -# Used for bgpmap -ROUTER_IP = { - "gw" : [ "91.224.148.2", "2a01:6600:8000::175" ], - "h3" : [ "91.224.148.3", "2a01:6600:8000::131" ] -} - -AS_NUMBER = { - "gw" : "197422", - "h3" : "197422" +# List of hosts to query (each one is a lgproxy instances) +HOSTS = { + "r1": { + # Endpoint at which lgproxy can be queried + "endpoint": "http://r1.example.com:5000", + # ASN and Router IP are optional, they are used to make the bgpmap more pretty + "asn": "65551", + "routerip": ["198.51.100.99", "192.0.2.12", "2001:db8:42:cafe::175"], + }, + "r2": { + # Using a plain IP address as endpoint is possible + "endpoint": "http://203.0.113.42:5000", + # It is fine to provide no "routerip" or "asn" field + }, + "r3": { + # IPv6 litterals are supported too + "endpoint": "http://[2001:db8:ffff::42]:5000", + "asn": "65551", + }, + "r4": { + # Example with HTTPS + "endpoint": "https://r5.example.com", + "asn": "64498", + }, } #WHOIS_SERVER = "whois.foo.bar" @@ -32,4 +40,5 @@ AS_NUMBER = { # DNS zone to query for ASN -> name mapping ASN_ZONE = "asn.cymru.com" +# Change this to random data SESSION_KEY = '\xd77\xf9\xfa\xc2\xb5\xcd\x85)`+H\x9d\xeeW\\%\xbe/\xbaT\x89\xe8\xa7' diff --git a/lg.py b/lg.py index a827988..c4288b9 100644 --- a/lg.py +++ b/lg.py @@ -138,17 +138,14 @@ def bird_proxy(host, proto, service, query): elif proto == "ipv4": path = service - port = app.config["PROXY"].get(host, "") - - if not port: - return False, 'Host "%s" invalid' % host - elif not path: + if not path: return False, 'Proto "%s" invalid' % proto - url = "http://%s" % (host) - if "DOMAIN" in app.config: - url = "%s.%s" % (url, app.config["DOMAIN"]) - url = "%s:%d/%s?" % (url, port, path) + if host not in app.config["HOSTS"]: + return False, 'Host "%s" invalid' % host + + endpoint = app.config["HOSTS"][host]["endpoint"] + url = "%s/%s?" % (endpoint, path) if "SHARED_SECRET" in app.config: url = "%ssecret=%s&" % (url, app.config["SHARED_SECRET"]) url = "%sq=%s" % (url, quote(query)) @@ -158,7 +155,7 @@ def bird_proxy(host, proto, service, query): resultat = f.read() status = True # retreive remote status except IOError: - resultat = "Failed to retrieve URL for host %s" % host + resultat = "Failed to retrieve data from host %s" % host app.logger.warning("Failed to retrieve URL for host %s: %s", host, url) status = False @@ -188,12 +185,12 @@ def inject_commands(): @app.context_processor def inject_all_host(): - return dict(all_hosts="+".join(app.config["PROXY"].keys())) + return dict(all_hosts="+".join(app.config["HOSTS"].keys())) @app.route("/") def hello(): - return redirect("/summary/%s/ipv4" % "+".join(app.config["PROXY"].keys())) + return redirect("/summary/%s/ipv4" % "+".join(app.config["HOSTS"].keys())) def error_page(text): @@ -455,17 +452,16 @@ def show_bgpmap(): return edges[edge_tuple] for host, asmaps in data.iteritems(): - if "DOMAIN" in app.config: - add_node(host, label= "%s\r%s" % (host.upper(), app.config["DOMAIN"].upper()), shape="box", fillcolor="#F5A9A9") - else: - add_node(host, label= "%s" % (host.upper()), shape="box", fillcolor="#F5A9A9") + add_node(host, label= "%s" % (host.upper()), shape="box", fillcolor="#F5A9A9") - as_number = app.config["AS_NUMBER"].get(host, None) - if as_number: - node = add_node(as_number, fillcolor="#F5A9A9") - edge = add_edge(as_number, nodes[host]) - edge.set_color("red") - edge.set_style("bold") + host_config = app.config["HOSTS"].get(host) + if host_config: + as_number = host_config.get("asn") + if as_number: + node = add_node(as_number, fillcolor="#F5A9A9") + edge = add_edge(as_number, nodes[host]) + edge.set_color("red") + edge.set_style("bold") #colors = [ "#009e23", "#1a6ec1" , "#d05701", "#6f879f", "#939a0e", "#0e9a93", "#9a0e85", "#56d8e1" ] previous_as = None @@ -569,11 +565,10 @@ def build_as_tree_from_raw_bird_ouput(host, proto, text): peer_ip = expr2.group(2).strip() if expr2.group(4): peer_protocol_name = expr2.group(4).strip() - # Check if via line is a internal route - for rt_host, rt_ips in app.config["ROUTER_IP"].iteritems(): - # Special case for internal routing - if peer_ip in rt_ips: - path = [rt_host] + # Check if via line is an internal route (special case for internal routing) + for other_host in app.config["HOSTS"].keys(): + if peer_ip in app.config["HOSTS"][other_host].get("routerip", []): + path = [other_host] break else: # ugly hack for good printing diff --git a/templates/layout.html b/templates/layout.html index c0b7281..52169f7 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -24,7 +24,7 @@
  • all
  • - {% for host in config.PROXY %} + {% for host in config.HOSTS %}
  • {{host}}
  • {% endfor %}