IPRoute2 App

Code


├── Dockerfile
├── api
│   └── v1
│       ├── index.php
│       └── util.php
├── docker-compose.yml
└── public
    ├── index.html
    ├── js
    │   ├── index.js
    │   └── link.js
    └── link.html

docker-compose.yml:

version: "3"

services:
  web:
    container_name: web
    image: ifpb/php:7.3-apache-iproute2
    build: .
    ports:
      - 8080:80
    volumes:
      - ./:/var/www/html/

Dockerfile:

FROM php:7.3-apache

RUN apt -y update && \
  apt install -y \
  iproute2

Back-end side


IPRoute2 API

└── api
    └── v1
        ├── index.php
        └── util.php

Front-end side


└── public
    ├── index.html
    ├── js
    │   ├── index.js
    │   └── link.js
    └── link.html

public/index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
      integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
      crossorigin="anonymous"
    />
    <title>Interfaces</title>
  </head>
  <body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
      <a class="navbar-brand" href="#">Network Manager</a>
      <button
        class="navbar-toggler"
        type="button"
        data-toggle="collapse"
        data-target="#navbarSupportedContent"
        aria-controls="navbarSupportedContent"
        aria-expanded="false"
        aria-label="Toggle navigation"
      >
        <span class="navbar-toggler-icon"></span>
      </button>
    </nav>
    <div class="container">
      <h1 class="text-center mt-5">Interfaces</h1>
      <table class="table mt-4">
        <thead>
          <th>#</th>
          <th>Name</th>
          <th>MTU</th>
          <th>State</th>
          <th>MAC</th>
          <th>IP</th>
        </thead>
        <tbody></tbody>
      </table>
    </div>
    <script
      src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
      integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
      integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
      integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
      crossorigin="anonymous"
    ></script>
    <script src="js/index.js"></script>
  </body>
</html>

public/js/index.js:

const table = document.querySelector("table tbody");

function loadInterfaces() {
  fetch("/api/v1/")
    .then(res => res.json())
    .then(json => showInterfaces(json));
}

function showInterfaces(interfaces) {
  let rows = "";
  for (const interface of interfaces) {
    const mask = interface.ipmask ? "/" + interface.ipmask : "";
    const link = interface.name.split("@")[0];
    rows += `<tr>
      <td>${interface.id}</td>
      <td>
        <a href="link.html?info=link&link=${link}" target="_blank">${
      interface.name
    }</a>
      </td>
      <td>${interface.mtu}</td>
      <td>${interface.state}</td>
      <td>${interface.mac}</td>
      <td>${interface.ip || "-"}${mask}</td>
    </tr>`;
  }
  table.innerHTML = rows;
}

loadInterfaces();

public/link.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
      integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
      crossorigin="anonymous"
    />
    <title>Interface</title>
  </head>
  <body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
      <a class="navbar-brand" href="#">Network Manager</a>
      <button
        class="navbar-toggler"
        type="button"
        data-toggle="collapse"
        data-target="#navbarSupportedContent"
        aria-controls="navbarSupportedContent"
        aria-expanded="false"
        aria-label="Toggle navigation"
      >
        <span class="navbar-toggler-icon"></span>
      </button>
    </nav>
    <div class="container">
      <h1 class="text-center mt-5">Interface X</h1>
      <table class="table mt-4">
        <thead>
          <th>#</th>
          <th>bytes</th>
          <th>packets</th>
          <th>errors</th>
          <th>dropped</th>
        </thead>
        <tbody></tbody>
      </table>
    </div>
    <script
      src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
      integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
      integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
      integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
      crossorigin="anonymous"
    ></script>
    <script src="js/link.js"></script>
  </body>
</html>

public/js/link.js:

const url = new URL(location);
const link = url.searchParams.get("link");
const title = document.querySelector("h1");
const table = document.querySelector("table tbody");

function loadInterface() {
  title.innerHTML = `Interface ${link}`;
  fetch(`/api/v1/?a=link&link=${link}`)
    .then(res => res.json())
    .then(json => showInterface(json));
}

function showInterface(interface) {
  let rows = "";
  for (const kind of ["rx", "tx"]) {
    rows += `<tr>
    <th>${kind.toUpperCase()}</th>
    <td>${interface.stats[kind].bytes}</td>
    <td>${interface.stats[kind].packets}</td>
    <td>${interface.stats[kind].errors}</td>
    <td>${interface.stats[kind].dropped}</td>
  </tr>`;
  }
  table.innerHTML = rows;
  setTimeout("loadInterface()", 2000);
}

loadInterface();