¿Cómo recuperar las tablas de enrutamiento en formato JSON (linux)?

¿Cómo recuperar las tablas de enrutamiento en formato JSON (linux)?

El ipcomando puede devolver algunos de sus resultados en formato JSON, pero parece no poder formatear las tablas de enrutamiento.
Aquí hay algunos ejemplos de lo que quiero decir.

Lista de todas las direcciones:ip --json address show

[{ ... },{
    "ifindex": 2,
    "ifname": "eth0",
    "flags": ["BROADCAST","MULTICAST","UP","LOWER_UP"],
    "mtu": 1500,
    "qdisc": "fq_codel",
    "master": "lan0",
    "operstate": "UP",
    "group": "default",
    "txqlen": 1000,
    "link_type": "ether",
    "address": "44:89:3f:e9:a8:08",
    "broadcast": "ff:ff:ff:ff:ff:ff",
    "addr_info": []
},{ ... }]



Lista de interfaces:ip --json link show

[{ ... },{
    "ifindex": 2,
    "ifname": "eth0",
    "flags": ["BROADCAST","MULTICAST","UP","LOWER_UP"],
    "mtu": 1500,
    "qdisc": "fq_codel",
    "master": "lan0",
    "operstate": "UP",
    "linkmode": "DEFAULT",
    "group": "default",
    "txqlen": 1000,
    "link_type": "ether",
    "address": "44:89:3f:e9:a8:08",
    "broadcast": "ff:ff:ff:ff:ff:ff"
},{ ... }]



También esperaba recuperar la lista de rutas en JSON, pero solo pude recuperar su versión en texto sin formato:
Lista de rutas: ip --json route list(todavía está en texto sin formato)

1.1.1.2 via 192.168.255.11 dev lan0 table hopper src 192.168.254.1 metric 10
default via 10.19.1.4 dev wg0 metric 5
default via 192.168.255.11 dev lan0 metric 6
10.19.1.0/24 dev wg0 scope link
124.214.110.113 via 192.168.255.11 dev lan0 metric 4
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-fea43fdf31f1 proto kernel scope link src 172.18.0.1
172.19.0.0/16 dev br-6f9e681d15b0 proto kernel scope link src 172.19.0.1 linkdown
192.168.0.0/16 dev lan0 proto kernel scope link src 192.168.254.1
192.168.1.0/24 dev wan0 proto kernel scope link src 192.168.1.9
192.168.1.0/24 via 192.168.255.11 dev lan0 metric 3
broadcast 127.0.0.0 dev lo table local proto kernel scope link src 127.0.0.1
local 127.0.0.1 dev lo table local proto kernel scope host src 127.0.0.1
multicast 239.255.255.250/32 from 192.168.1.109/32 table default proto 17 unresolved

Como no pude encontrar una solución en ninguna parte, responderé mi propia pregunta y dejaré aquí lo que hice.
Quién sabe, tal vez algún día lo necesite nuevamente, ¡o tal vez alguien más tenga el mismo problema! :-)

Respuesta1

Entonces, esto es lo que hice.
Utilicé el comando jqpara analizar el resultado del ip route list table alluso de una expresión regular, transformando la salida a JSON.
Siéntete libre de jugar con jqyhaga clic aquí para utilizar una zona de pruebas en líneaya cargado con esta solución.
Este es el comando completo:

ip route list table all | jq --raw-input --slurp 'split("\n") | map(capture("^(?:(?<broadcast>broadcast) ?)?(?:(?<local>local) ?)?(?:(?<multicast>multicast) ?)?(?: ?(?<network>.*?) )(?:from (?<from>\\S+) ?)?(?:via (?<via>\\S+) ?)?(?:dev (?<dev>\\S+) ?)?(?:table (?<table>\\S+) ?)?(?:proto (?<proto>\\S+) ?)?(?:scope (?<scope>\\S+) ?)?(?:src (?<src>\\S+) ?)?(?:metric (?<metric>\\d+) ?)?(?<linkdown>linkdown)?(?<unresolved>unresolved)?"; "g"))'

Y este es el resultado:

[
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "1.1.1.2",
    "from": null,
    "via": "192.168.255.11",
    "dev": "lan0",
    "table": "hopper",
    "proto": null,
    "scope": null,
    "src": "192.168.254.1",
    "metric": "10",
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "default",
    "from": null,
    "via": "10.19.1.4",
    "dev": "wg0",
    "table": null,
    "proto": null,
    "scope": null,
    "src": null,
    "metric": "5",
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "default",
    "from": null,
    "via": "192.168.255.11",
    "dev": "lan0",
    "table": null,
    "proto": null,
    "scope": null,
    "src": null,
    "metric": "6",
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "10.19.1.0/24",
    "from": null,
    "via": null,
    "dev": "wg0",
    "table": null,
    "proto": null,
    "scope": "link",
    "src": null,
    "metric": null,
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "124.214.110.113",
    "from": null,
    "via": "192.168.255.11",
    "dev": "lan0",
    "table": null,
    "proto": null,
    "scope": null,
    "src": null,
    "metric": "4",
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "172.17.0.0/16",
    "from": null,
    "via": null,
    "dev": "docker0",
    "table": null,
    "proto": "kernel",
    "scope": "link",
    "src": "172.17.0.1",
    "metric": null,
    "linkdown": "linkdown",
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "172.18.0.0/16",
    "from": null,
    "via": null,
    "dev": "br-fea43fdf31f1",
    "table": null,
    "proto": "kernel",
    "scope": "link",
    "src": "172.18.0.1",
    "metric": null,
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "172.19.0.0/16",
    "from": null,
    "via": null,
    "dev": "br-6f9e681d15b0",
    "table": null,
    "proto": "kernel",
    "scope": "link",
    "src": "172.19.0.1",
    "metric": null,
    "linkdown": "linkdown",
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "192.168.0.0/16",
    "from": null,
    "via": null,
    "dev": "lan0",
    "table": null,
    "proto": "kernel",
    "scope": "link",
    "src": "192.168.254.1",
    "metric": null,
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "192.168.1.0/24",
    "from": null,
    "via": null,
    "dev": "wan0",
    "table": null,
    "proto": "kernel",
    "scope": "link",
    "src": "192.168.1.9",
    "metric": null,
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": null,
    "network": "192.168.1.0/24",
    "from": null,
    "via": "192.168.255.11",
    "dev": "lan0",
    "table": null,
    "proto": null,
    "scope": null,
    "src": null,
    "metric": "3",
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": "broadcast",
    "local": null,
    "multicast": null,
    "network": "127.0.0.0",
    "from": null,
    "via": null,
    "dev": "lo",
    "table": "local",
    "proto": "kernel",
    "scope": "link",
    "src": "127.0.0.1",
    "metric": null,
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": "local",
    "multicast": null,
    "network": "127.0.0.1",
    "from": null,
    "via": null,
    "dev": "lo",
    "table": "local",
    "proto": "kernel",
    "scope": "host",
    "src": "127.0.0.1",
    "metric": null,
    "linkdown": null,
    "unresolved": null
  },
  {
    "broadcast": null,
    "local": null,
    "multicast": "multicast",
    "network": "239.255.255.250/32",
    "from": "192.168.1.109/32",
    "via": null,
    "dev": null,
    "table": "default",
    "proto": "17",
    "scope": null,
    "src": null,
    "metric": null,
    "linkdown": null,
    "unresolved": "unresolved"
  }
]

Eso ya es suficiente para lo que necesitaba pero, si tienes algo de tiempo de sobra, todavía hay margen de mejora: todos los valores nulos podrían eliminarse, los valores "métricos" podrían transformarse en números y "transmitirse", "local". , "multicast", "linkdown" y "unresolved" podrían ser valores booleanos.

Respuesta2

Escribí una herramienta cli llamada jcque convertirá netstat -ry routeordenará la salida a JSON.

$ jc netstat -rn | jq
[
  {
    "destination": "0.0.0.0",
    "gateway": "192.168.71.2",
    "genmask": "0.0.0.0",
    "route_flags": "UG",
    "mss": 0,
    "window": 0,
    "irtt": 0,
    "iface": "ens33",
    "kind": "route",
    "route_flags_pretty": [
      "UP",
      "GATEWAY"
    ]
  },
  {
    "destination": "172.17.0.0",
    "gateway": "0.0.0.0",
    "genmask": "255.255.0.0",
    "route_flags": "U",
    "mss": 0,
    "window": 0,
    "irtt": 0,
    "iface": "docker0",
    "kind": "route",
    "route_flags_pretty": [
      "UP"
    ]
  },
  {
    "destination": "192.168.71.0",
    "gateway": "0.0.0.0",
    "genmask": "255.255.255.0",
    "route_flags": "U",
    "mss": 0,
    "window": 0,
    "irtt": 0,
    "iface": "ens33",
    "kind": "route",
    "route_flags_pretty": [
      "UP"
    ]
  }
]
$ jc route | jq
[
  {
    "destination": "default",
    "gateway": "gateway",
    "genmask": "0.0.0.0",
    "flags": "UG",
    "metric": 100,
    "ref": 0,
    "use": 0,
    "iface": "ens33",
    "flags_pretty": [
      "UP",
      "GATEWAY"
    ]
  },
  {
    "destination": "172.17.0.0",
    "gateway": "0.0.0.0",
    "genmask": "255.255.0.0",
    "flags": "U",
    "metric": 0,
    "ref": 0,
    "use": 0,
    "iface": "docker0",
    "flags_pretty": [
      "UP"
    ]
  },
  {
    "destination": "192.168.71.0",
    "gateway": "0.0.0.0",
    "genmask": "255.255.255.0",
    "flags": "U",
    "metric": 100,
    "ref": 0,
    "use": 0,
    "iface": "ens33",
    "flags_pretty": [
      "UP"
    ]
  }
]

También se admiten docenas de otros comandos.

https://github.com/kellyjonbrazil/jc

Respuesta3

De forma predeterminada, la utilidad iproute2 admite la opción --json como

ip --json address show
ip --json link show

etc..

Enumera toda la configuración/estadísticas en formato JSON.

Pero en algunos casos, como la ruta, solo enumera la tabla de rutas particular. Para enumerar todas las tablas, puede utilizar explícitamente el comando:

ip --json route show table all

También puedes obtener la tabla particular usando sus nombres como:

ip --json route show table default

[No sé si ya obtuviste la respuesta o no. Si no, espero que esto te sea útil... Adiós :)]

información relacionada