From a discussion on how to prevent MAC address spoofing, the need of edge authentication became evident. In fact, the REGISTER_SUPER type messages already have shown a so far unused `auth` field which gets used for the first time starting in the course of n2n version 2.9 development.
A very basic authentication scheme based on a uniqe identification number is put in place. This ID is randomly generated during edge start-up and remains unchanged until the edge terminates. With every REGISTER_SUPER, it is tranmitted to the supernode which remembers it from the first REGISTER_SUPER and can compare it to all the following ones. It is a verfication based on "showing the ID". The supernode accepts REGISTER_SUPER (and thus changed MAC address or internet socket) and UNREGISTER type messages only if verification passes.
This does not only prevent UNREGISTER attacks but also MAC spoofing even in case of several federated supernodes because each REGISTER_SUPER message is forwarded to all other supernodes. If a new edge (un)intentionally tries to claim a MAC address which already has been in use by another edge, this would be detected as unauthorized MAC change because the new edge presents a different authentication ID. The supernode which rejects it (based on a failed comparison) sends a REGISTER_SUPER_**NAK** type message to the new edge as well as the supernode through which the new edge tried to register. The REGISTER_SUPER_NAK will cause deletion of associated entries at the supernode and make a complying edge stop.
As opposed to the MAC address which is sent out with each packet also between edges, the ID remains between the edge and the supernode. Other edges do not become aware of it and thus are not able to spoof.
A somewhat hurdling network sniffing attack aimed at observing the authentication ID could break this scheme. Thus, further development towards a more sophisticated crypto-based authentication scheme is intended.
In case of edges unexpectedly shutting down with no opportunity for a clean exit, this auth scheme prevents re-connection to the supernode until it internally is removed from the list (after some 90 seconds or so). Although `-M` command line option at the supernode can disable authentication ID comparison to circumvent this situation, usage of user / password based authentication scheme is highly recommended instead.
A more advanced scheme relies on username and especially password. Public key cryptography, namely Curve25519, ensures safety. Basically, the password along with the mixed in user name, serve as private key. The corresponding public key is generated by the `tools/n2n-keygen` utility. The such generated public key gets depoisted at the supernode.
#### Supernode Preparation
To generate a public key for the user `logan` and her very secret password `007`, the `tools/n2n-keygen` utility would be called with username and password as command line parameter:
The generated output line of format `* <username> <public key>` needs to be copied to the supernode's community list file, e.g. to the exemplary `community.list` file.
```
#
# List of allowed communities
# ---------------------------
#
# these could either be fixed-name communities such as the following lines ...
# ... or regular expressions that a community name must fully match
# such as ntop[0-1][0-9] for communities from "ntop00" through "ntop19"
#
ntop[0-1][0-9]
...
```
This example also lists another user `sister` (with the same secret password `007`). The users become part of the preceding community name, `netleo` in this case. The public keys are cryptographically tied only to the user name, not to the community name. That way, to switch a user from one community to another, her line can easily be copied from one community section to another. By the way, do not forget to provide the `community.list` file to the supernode through the `-c community.list` parameter.
Current supernode behavior does not limit the simultanious usage of usernames, i.e. one username can be used from several edges at the same time. However, it is recommended to use a distinct username and password for each edge or computer. Your management port output will be much more meaningful then with the HINT column showing the related username. Also, the auto IP address feature, i.e. not using `-a <IP address>` at the edge, will more likely assign unique addresses as those depend on the username.
If a user chooses a new password or needs to be excluded from accessing the community (stolen edge scenario), the corresponding line of the `community.list` file can be replaced with a newly generated one or be deleted respectively. Restarting the supernode is required after performing changes because the supernode reads in this data only once at start-up.
With a view to the detailed explanations below, your supernode should have a non-default federation name given by the `-F <federation name>` command line parameter, e.g. `-F secretFed`. It is used to derive a priavte key on the supernode side and is only to be shared among supernodes. However, a federation-wide support for this feature, i.e. across several supernodes, is possible but not implemented yet.
#### Edge
The edge takes the username with the already present, identifying command line paramater `-I <username>`. The password goes into `-J <password>`. Continuing the given example, the edge is invoked by
Note that header encryption already is enabled automatically as this authentication scheme heavily relies on it. Also, currently only the stream ciphers work with this authentication scheme reliably in terms of security. So, `-A4` for ChaCha20 or `-A5` for SPECK along with a key `-k <key>` are required as additional parameters.
The edges need to know the public key of the supernode. By default, the edges assume the default federation name, or more specific, the corresponding public key. In case the supernode is given a custom federation name which is highly recommended, the supernode's public key is provided to the edges via command line parameter `-P <public key>. It can be generated from the federation name by using the `tools/n2n-keygen` utility as well:
In order to make this authentication scheme work, the existing header encryption scheme is split into using two keys: a _static_ and a _dynamic_ one. The static key remains unchanged and is the [classic header encryption key](https://github.com/ntop/n2n/blob/dev/doc/Crypto.md#header) derived from the community name. It only is applied to the very basic registration traffic between edge and supernode (REGISTER_SUPER, REGISTER_SUPER_ACK, REGISTER_SUPER_NAK). The dynamic key is derived (among others) from the federation name – keep it secret! – and appplied to all the other packets, especially the data packets (PAKET) and peer-to-peer building packets (REGISTER), but also the ping and peer information (QUERY_PEER, PEER_INFO). An edge not provided with a valid dynamic key is not able to participate in the further communication.
In regular header encryption mode, static key and dynamic key are equal. With activated user-password scheme, the supernode generates and transmits a dynamic key with the REGISTER_SUPER for further use. This happens in a secure way based on public key cryptography. A non-autheticated edge, i.e. without corresponding entry at the supernode or valid credentials, will not receive a valid dynmic key for communication beyond registration.
#### Possible Extensions
Tools for automizing [`.conf` file](https://github.com/ntop/n2n/blob/dev/doc/ConfigurationFiles.md) generation for deployment ot delivery to freshly registered and approved users could greatly enhance this ecosystem; a user would not have to mess around with command line parameters but just copy a `.conf` file into a specified directory.
Implementation of a federation-wide support for user-password authentication would allow much bigger networks using this feature. Still required steps are outlined [in some earlier post](https://github.com/ntop/n2n/issues/670#issuecomment-802119568).