ntop / n2n

Peer-to-peer VPN
GNU General Public License v3.0
6.26k stars 940 forks source link

Implement supernode management capability #17

Open lucaderi opened 6 years ago

lucaderi commented 6 years ago

Currently the supernode does not report any info about connected peers and activities. It would be nice to add a web GUI or at least a way to query it in order to understand the ongoing registrations etc.

enira commented 6 years ago

EDIT: Made a small web GUI with python. It's a quick 30 min job but if anyone want me to expand this, just ask.

Although interested to see which commands the management interface has to offer. And what does 'fwd', 'broadcast', 'last fwd', 'reg_nak' and 'reg_sup' means?

from __future__ import print_function

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import threading

import socket
import time

from threading import Thread

page = """
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Simple Supernode Status Page</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <meta http-equiv="Cache-control" content="no-cache" />

    <style type="text/css">
                #status {
                        font-family: Calibri;
                }
                #status h2 {
                        font-size: 1em;
                }

                table.status {
                        width: 100%;
                        border-collapse: collapse;
                        text-align: left;
                        color: #606060;
                }

                table.status td {
                        vertical-align: middle;
                        padding: 0.5em;
                }

                table.status thead tr td {
                        background-color: White;
                        vertical-align: middle;
                        padding: 0.6em;
                        font-size: 0.8em;
                }

                table.status thead tr th,
                table.status tbody tr.separator {
                        padding: 0.5em;
                        background-color: #909090;
                        background: -webkit-gradient(linear, left top, left bottom, from(#909090), to(#ababab));
                        background: -moz-linear-gradient(top, #909090, #ababab);
                        color: #efefef;
                }

                table.status tbody tr:nth-child(odd) {
                        background-color: #fafafa;
                }

                table.status tbody tr:nth-child(even) {
                        background-color: #efefef;
                }

                table.status tbody tr:last-child {
                        border-bottom: solid 1px #404040;
                }

                table.status tbody tr:hover {
                        cursor: pointer;
                        background-color: #909090;
                        background: -webkit-gradient(linear, left top, left bottom, from(#909090), to(#ababab));
                        background: -moz-linear-gradient(top, #909090, #ababab);
                        color: #dadada;
                }

                table.status tfoot {
                        text-align: center;
                        color: #303030;
                        text-shadow: 0 1px 1px rgba(255,255,255,0.3);
                }
    </style>
</head>
<body>
    <div id="status">
        <h2>Simple Supernode Status Page</h2>
        <table class="status">
            <thead>
                <tr>
                    <th>Description</th>
                    <th>Value</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Uptime</td>
                    <td>$UPTIME</td>
                </tr>
                <tr>
                    <td>Connected Edges</td>
                    <td>$EDGES</td>
                </tr>
                <tr>
                    <td>Errors</td>
                    <td>$ERRORS</td>
                </tr>
                <tr>
                    <td>reg_sup</td>
                    <td>$REG_SUP</td>
                </tr>
                <tr>
                    <td>reg_nak</td>
                    <td>$REG_NAK</td>
                </tr>
                <tr>
                    <td>fwd</td>
                    <td>$FWD</td>
                </tr>
                <tr>
                    <td>broadcast</td>
                    <td>$BROADCAST</td>
                </tr>
                <tr>
                    <td>last fwd</td>
                    <td>$LAST_FWD</td>
                </tr>
                <tr>
                    <td>Last node registered</td>
                    <td>$LAST_REG seconds ago</td>
                </tr>
            </tbody>
        </table>
    </div>
</body>
</html>
"""

class Handler(BaseHTTPRequestHandler):

    def do_GET(self):
        self.send_response(200)
        self.end_headers()

        result = page
        result = result.replace("$UPTIME", status["uptime"])
        result = result.replace("$ERRORS", status["errors"])
        result = result.replace("$EDGES", status["edges"])
        result = result.replace("$REG_NAK", status["reg_nak"])
        result = result.replace("$FWD", status["fwd"])
        result = result.replace("$BROADCAST", status["broadcast"])
        result = result.replace("$LAST_REG", status["last reg"])
        result = result.replace("$LAST_FWD", status["last fwd"])
        result = result.replace("$REG_SUP", status["reg_sup"])

        self.wfile.write(result)

        return

    def log_message(self, format, *args):
        return

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""

def gather(port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto("?", ("localhost", port))
    sock.settimeout(2.0)
    data, addr = sock.recvfrom(2048)

    for line in data.split('\n'):
        if line[10:]:
            status[line[:10].strip()] = line[10:]

    time.sleep(10)
    thread = Thread(target=gather, args=(port,))
    thread.start()

status = {}

if __name__ == '__main__':
    thread = Thread(target=gather, args=(5645,))
    thread.start()

    server = ThreadedHTTPServer(('0.0.0.0', 8080), Handler)
    print('Starting server, use <Ctrl-C> to stop')
    server.serve_forever()
kbmorris commented 4 years ago

And what does 'fwd', 'broadcast', 'last fwd', 'reg_nak' and 'reg_sup' means?

struct sn_stats { size_t errors; / Number of errors encountered. / size_t reg_super; / Number of REGISTER_SUPER requests received. / size_t reg_super_nak; / Number of REGISTER_SUPER requests declined. / size_t fwd; / Number of messages forwarded. / size_t broadcast; / Number of messages broadcast to a community. / time_t last_fwd; / Time when last message was forwarded. / time_t last_reg_super; / Time when last REGISTER_SUPER was received. / }