Fertige Lösung: Nodes einer Stadt ermitteln / Tool für Domain-Split

Nachdem ich von @PetaByteBoy darauf aufmerksam gemacht wurde, dass es für den einen oder anderen in Zukunft interessant sein könnte, alle Nodes einer Stadt zu ermitteln, falls ein Domain Split durchgeführt werden soll, möchte ich gerne die Lösung mit den Interessierten teilen.
Dadurch könnt Ihr die IPv6 Adressen der gesuchten Router rausfiltern, um dann die Server für Firmware Updates umzubiegen.
Die Basis hierfür ist Elasticsearch (ES) und die Geokoordinaten einer Stadt als Polygon (GeoJSON Utilities - Anzeige, Auswahl und Export von Verwaltungsgebieten in Deutschland)
Ablauf in Kürze:

  1. ES installieren
  2. Anlegen eines Index in ES
  3. Erstellen eines Mapping für den Index (muss geschehen, bevor die die Daten reingepumpt werden)
  4. nodes.json in Elasticsearch reinpumpen
  5. query mit dem Polygon deiner Stadt durchführen
  6. Glücklich sein :wink:
    Hinweis1: Das Python Script und das Mapping stammen aus einem anderen ES Test und ich war zu faul, es für diesen Zweck zu optimieren (wir könnten auch die nodes.json direkt per curl in ES reinschaufeln), aber dann hätte ich eventuell das Mapping anpassen müssen).

1. ES installieren
Quelle und Dokumentation für ES: Download Elasticsearch Free • Get Started Now | Elastic
2. Index erstellen

curl -XPUT 'http://localhost:9200/freifunk-bg'

3. Mapping erstellen

curl -XPUT 'http://localhost:9200/freifunk-bg/_mapping/nodes' -d '{
    "nodes" : {
        "properties" : {
            "nodeinfo" : {
                "properties" : {
                    "node_id" : { "type" : "string",  "index" : "not_analyzed" },
                    "location" : { "type" : "geo_point" },
                    "hostname" : { "type" : "string",  "index" : "not_analyzed" },
                    "software" : {
                        "properties" : {
                            "firmware" : {
                                "properties" : {
                                    "base" : { "type" : "string", "index" : "not_analyzed" },
                                    "release" : { "type" : "string", "index" : "not_analyzed" }
                                    }
                                }
                            },
                            "fastd" : {
                                "properties" : {
                                    "version" : { "type" : "string", "index" : "not_analyzed" }
                                }
                            },
                            "batman-adv" : {
                                "properties" : {
                                    "version" : { "type" : "string", "index" : "not_analyzed" }
                                }
                            },
                            "hardware" : {
                                "properties" : {
                                    "model" : { "type" : "string",  "index" : "not_analyzed" }
                                }
                            }
                       }       
                    }       
                }           
            }                   
        }                           
    }                           
}' 

4. Pyhon3 (Python 2.x nicht getestet) Script für den Download der nodes.json und den Upload in ES

import sys, datetime, requests, json, elasticsearch
from elasticsearch import Elasticsearch
JSONURL = "http://map.ff.petabyteboy.de/data/nodes.json"
INDEX = "freifunk-bg"
DOC = "nodes"

JSONGET = requests.get(JSONURL)
APS = json.loads(JSONGET.text)

es = Elasticsearch([{'host': 'localhost', 'port': 9200}])

for AP in APS['nodes']:
    if 'location' in APS['nodes'][AP]['nodeinfo']:
        if 'latitude' in APS['nodes'][AP]['nodeinfo']['location']:
            APS['nodes'][AP]['nodeinfo']['location']['lat'] = APS['nodes'][AP]['nodeinfo']['location']['latitude']
            del APS['nodes'][AP]['nodeinfo']['location']['latitude']
            APS['nodes'][AP]['nodeinfo']['location']['lon'] = APS['nodes'][AP]['nodeinfo']['location']['longitude']
            del APS['nodes'][AP]['nodeinfo']['location']['longitude']
        if 'altitude' in APS['nodes'][AP]['nodeinfo']['location']:
            del APS['nodes'][AP]['nodeinfo']['location']['altitude']
    APS['nodes'][AP]['timestamp'] = APS['timestamp']
    res = es.index(index=INDEX, doc_type=DOC, body=APS['nodes'][AP])

den Python Aufruf hinter curl kann man auch weglassen…
5. Polygon in ES abfragen

curl -XGET http://localhost:9200/freifunk-bg/_search -d @bg.json | python -m json.tool
Inhalt der bg.json, wo ihr die Geokoordinaten einfügt, sollte direkt ersichtlich sein...
{ "query" : {
    "filtered" : {
        "query" : {
            "match_all" : {}
        },

"filter" : {
    "geo_polygon" : {
        "nodeinfo.location" : {
              "points" :
[[7.080716373054297,51.0262244485241], ……,[7.080716373054297,51.0262244485241]]
       }    
    }       
}           
}       
}           
}

6. Glücklich sein

HINWEIS2: OPnotDEV: Verbesserungsvorschläge sind Willkommen! Das war jetzt eine Quick&Dirty Lösung
HINWEIS3: Ich hoffe, dass ich nichts vergessen habe :wink:

Ich möchte mich bei den folgenden Personen bedanken:
@Michael1 : Für die Bereitstellung von Infrastuktur
@nomaster : Für die Anregung mit ES
@PetaByteBoy: Betatester

6 Likes

Das ist sehr, sehr fein, was du da gebastelt hast. :slight_smile:

Bei reinen MeshkKnoten ohne Koordinaten könnte man noch evtl. Meshverbindungen abfragen, um sie zuzuordnen.

Danke für das Tool!

Grüße
MPW

Falls die Daten in der JSON Datei vorhanden sind, dann kannst du das auch filtern.

@MPW Wenn du mir ein Beispiel nennen kannst, werde ich das gerne mal testen.

Bin verwirrt, Beispiel wofür? Reiner Meshknoten ohne Koordinaten? Schmeiß Gluon-x86 in eine VM und mach WAN-Mesh zu deinem FF-Router.

Da hast du auch wieder recht, ich flash bei Gelegenheit einen Unifi AP um zum Testen.

In der json Datei steht die Info zu den gemeshten Knoten anscheinend nicht drin. Die Daten dazu werden wahrscheinlich aus batman direkt ausgelesen.