Thoughts on flexible mesh-routing of NNCP packets

John Goerzen
2021-01-31T07:05:12Z

Hi,

So I've been thinking about the problem of getting NNCP packets
delivered in a dynamic topology. As they are source-routed, that
can be a bit of a challenge. I've got some ideas.

First I want to make sure I understand how the onion routing in
NNCP works, because I think it's somewhat different than Tor (not
trying to preserve the anonymity of the sender). Is this
description correct? (I originally posted this in comp.mail.uucp
and will correct it there if not)

In this example, node1 is wanting to send a packet to node5 via
intermediaries.

So what happens here is that node1 first generates an encrypted
packet to node5,
using node5's public key, and that packet is signed by node1.
Next, it takes
that whole thing, encryption and signature and all, and uses it as
input for an
encrypted packet to node4 -- that packet itself also signed by
node1. It
repeats this process until it generates the packet to node2.

Think of it like this:

node1$ gpg --sign -e -r node5 < datafile > node5.gpg
node1$ gpg --sign -e -r node4 < node5.gpg > node4.gpg
node1$ gpg --sign -e -r node3 < node4.gpg > node3.gpg
node1$ gpg --sign -e -r node2 < node3.gpg > outbound-to-node2.gpg
node1$ rm node[345.jpg]

Node2 receives the packet - encrypted only to it, and signed by
node1 -
and decrypts the payload. The payload is a command (send this on
to
node2) and an encrypted payload for THAT command - encrypted to
node2
and signed by node1. This process also continues until you get to
node5.
So, at node4, node4 receives its packet from node3 -- signed by
node1, encrypted
to node4. Node4 decrypts it and finds a payload for node5 --
again, signed by
node1, encrypted to node5. It places this in the queue for node5.
(Just like
with node2)

Node5 receives the packet. It verifies the signature from node1,
and it is the
only node that can decrypt it. nncp-toss finds the packet in the
rx queue from
node4, but it doesn't really pass this information on anywhere; it
knows from
the signature that the origin was node1 (doesn't much care how it
arrived) and
that single verified signature is what is used for all processing
(looking up
whether node1 is authorized to run a command, exposed as an
environment variable
to nncp-exec runners, used to determine the incoming directory for
nncp-file,
etc).

Node5 could sort of know that the packet arrived from node4, but
there is no
cryptographic guarantee of that (the ONLY signatures in this whole
chain come
from node1) so that information is basically discarded.

This is different from the UUCP model, in which node5 only really
knows about
its neighbor node4 and may have no idea whatever about node1's
existence.
Permissions in UUCP are based on what the neighbor can do, not
what the source
can do, if I remember correctly.

The other thing that follows from this is that if node3 were
compromised, the
worst it can do is fail to relay packets. It cannot modify packets
(signature
validation from node1 would fail), it cannot spoof node1 (lacking
its private
key), it can't inject fake packets claiming to have followed the
node1!node2!node3 path (again, lacking node1's private key), it
can't even see
what the ultimate destination is (it just knows the next hop is
node4 but since
it doesn't have node4's private key, it doesn't even know if node4
is the
ultimate hop or not).

Now then....

If that is correct, that would imply that it would be difficult
to, say, bypass node2 on the way to node5 -- though it would be
(theoretically) easy enough to send from node1 to node1.5 and then
on to node2.

So I've been thinking about this more expansively.

https://verbnetworks.com/research/store-forward-networks/ planted
the idea in my head: why not use Syncthing for this?

It would seem to make perfect sense, given nncp-xfer. There could
be a shared Syncthing folder which leaf sites could dump packets
into using nncp-xfer, and read other packets out (also using
nncp-xfer). Since Syncthing implements a Bittorrent-like
protocol, a leaf site can just dump packets into its local
Syncthing folder, letting Syncthing get them out via whatever path
it can. Once the files are properly received, the receiver
deletes them and this propagates out over the swarm as well.
Slick!

I had initially been thinking up some fancy scheme to send back a
"I've got this packet, delete your copy" back to the originator,
but then realized Syncthing basically already solved that.

- John