From: Sergey Matveev Date: Mon, 9 Jan 2017 08:44:02 +0000 (+0300) Subject: Documentation updates X-Git-Tag: 0.1~5 X-Git-Url: http://www.git.cypherpunks.ru/?p=nncp.git;a=commitdiff_plain;h=4a4c1be88baf3fa5426bc1c9c96e104643155fca Documentation updates --- diff --git a/doc/cfg.texi b/doc/cfg.texi index 3f114c5..369ce78 100644 --- a/doc/cfg.texi +++ b/doc/cfg.texi @@ -1,4 +1,104 @@ @node Configuration @unnumbered Configuration file -TODO. +Example YAML configuration file: + +@verbatim +spool: /var/spool/nncp +log: /var/spool/nncp/log +notify: + file: + from: nncp@localhost + to: user+file@example.com + freq: + from: nncp@localhost + to: user+freq@example.com +self: + id: TIJQL...2NGIA + exchpub: CYVGQ...PSEWQ + exchprv: 65PUY...MPZ3Q + signpub: 2NMVC...CMH5Q + signprv: 555JD...RGD6Y + noiseprv: D62XU...NKYPA + noisepub: KIBKK...ESM7Q +neigh: + self: + id: TIJQL...2NGIA + exchpub: CYVGQ...PSEWQ + signpub: 2NMVC...CMH5Q + noisepub: KIBKK...ESM7Q + sendmail: [/usr/sbin/sendmail] + alice: + id: XJZBK...65IJQ + exchpub: MJACJ...FAI6A + signpub: T4AFC...N2FRQ + noisepub: UBM5K...VI42A + sendmail: [/bin/sh, -c, false] + incoming: /home/alice/incoming + addrs: + lan: "[fe80::1234%igb0]:5400" + internet: alice.com:3389 + bob: + id: 2IZNP...UYGYA + exchpub: WFLMZ...B7NHA + signpub: GTGXG...IE3OA + noisepub: EQAZM...J3NBA + sendmail: [/usr/sbin/sendmail] + freq: /home/bob/pub + via: [alice] +@end verbatim + +@strong{spool} field contains an absolute path to @ref{Spool, spool} +directory. @strong{log} field contains an absolute path to @ref{Log, +log} file. + +@strong{notify} section contains notification settings for successfully +tossed file and file request packets. Corresponding @strong{from} and +@strong{to} fields will substituted in notification email message. +@emph{neigh/self/sendmail} will be used as a local mailer. If +either of @emph{from}/@emph{to} fields are omitted, then no notification +will be sent. + +@strong{self} section contains our node's private keypairs. +@strong{exch*} and @strong{sign*} are used during @ref{Encrypted, +encrypted} packet creation. @strong{noise*} are used during @ref{Sync, +sync protocol} working in @ref{nncp-call}/@ref{nncp-daemon}. + +@strong{neigh} section contains all known neighbours information. It +always has @strong{self} neighbour that is copy of our node's public +data (public keys). It is useful for copy-paste sharing with your +friends. Each section's key is a human-readable name of the neighbour. + +Except for @emph{id}, @emph{exchpub} and @emph{signpub} each node has +the following fields: + +@table @strong +@item noisepub +Must be present, but can be dummy (only zeros) if no online +communication using @ref{Sync, sync protocol} will be used. + +@item sendmail +An array containing path to executable and its command line arguments +that is called for mail sending. + +@item incoming +Full path to directory where all file uploads will be saved. May be +omitted to forbid file uploading on that node. + +@item freq +Full path to directory from where file requests will queue files for +transmission. May be omitted to forbid freqing from that node. + +@item via +An array of node identifiers that will be used as a relay to that node. +For example @code{[foo,bar]} means that packet can reach current node by +transitioning through @code{foo} and then @code{bar} nodes. May be +omitted if direct connection exists and no relaying is required. + +@item addrs +Dictionary containing known network addresses of the node. Each key is +human-readable name of the link/address. Values are @code{addr:port} +pairs pointing to @ref{nncp-daemon}'s listening instance. May be omitted +if either no direct connection exists, or @ref{nncp-call} is used with +forced address specifying. +@end table diff --git a/doc/cmds.texi b/doc/cmds.texi index af9369a..38849a0 100644 --- a/doc/cmds.texi +++ b/doc/cmds.texi @@ -1,62 +1,242 @@ @node Commands @unnumbered Commands +Nearly all commands have the following common options: + +@table @code +@item -debug + Print debug messages. Normally this option should not be used. +@item -nice + Set desired outgoing packet niceness level. 1-255 values are + allowed. Higher value means lower priority. In some commands that + means processing of packets that have equal or lower nice value. + That is used for controlling network QoS. +@item -node + Process only single specified node. +@item -quiet + Print only errors, omit simple informational messages. In any case + those messages are logged, so you can reread them using + @ref{nncp-log} command. +@item -version + Print version information. +@item -warranty + Print warranty information (no warranty). +@end table + @node nncp-call @section nncp-call -TODO. +@verbatim +% nncp-call [options] [-rx|-tx] NODE[:ADDR] [FORCEADDR] +@end verbatim + +Call (connect to) specified @code{NODE} and run @ref{Sync, +synchronization} protocol with the @ref{nncp-daemon, daemon} on the +remote side. Normally this command could be run any time you wish to +either check for incoming packets, or to send out queued ones. +Synchronization protocol allows resuming and bidirectional packets +transfer. + +If @code{-rx} option is specified then only inbound packets transmission +is performed. If @code{-tx} option is specified, then only outbound +transmission is performed. + +Each @code{NODE} can contain several uniquely identified +@code{ADDR}esses in @ref{Configuration, configuration} file. If you do +not specify the exact one, then all will be tried until the first +success. Optionally you can force @code{FORCEADDR} address usage, +instead of addresses taken from configuration file. + +Pay attention that this command run integrity check for each completely +received packet in the background. This can be time consuming and +connection could be lost during that check time and remote node won't be +notified that file is done. But after successful integrity check that +file will be renamed from @code{.part} one and when you rerun +@code{nncp-call} again, remote node will receive completion at once. @node nncp-check @section nncp-check -TODO. +@verbatim +% nncp-check [options] +@end verbatim + +Perform @ref{Spool, spool} directory integrity check. Read all files +that has Base32-encoded filenames and compare it with recalculated +BLAKE2b hash output of their contents. This supplementary command should +not be used often in practice, if ever. @node nncp-daemon @section nncp-daemon -TODO. +@verbatim +% nncp-daemon [options] [-maxconn INT] [-bind ADDR] +@end verbatim + +Start listening TCP daemon, wait for incoming connections and run +@ref{Sync, sync protocol} with each of them. You can run @ref{nncp-toss} +utility in background to process inbound packets from time to time. + +@code{-maxconn} option specifies how many simultaneous clients daemon +can handle. @code{-bind} option specifies @code{addr:port} it must bind +to and listen. @node nncp-file @section nncp-file -TODO. +@verbatim +% nncp-file [options] SRC NODE:[DST] +@end verbatim + +Send @code{SRC} file to remote @code{NODE}. @code{DST} specifies +destination file name in remote's @ref{Configuration, incoming} +directory. If this file already exists there, then counter will be +appended to it. + +This command queues file in @ref{Spool, spool} directory immediately +(through the temporary file of course) -- so pay attention that sending +2 GiB file will create 2 GiB outbound encrypted packet. + +If @ref{Configuration, notification} is enabled on the remote side for +file transmissions, then it will sent simple letter after successful +file receiving. @node nncp-freq @section nncp-freq -TODO. +@verbatim +% nncp-freq [options] NODE:SRC DST +@end verbatim + +Send file request to @code{NODE}, asking it to send its @code{SRC} file +from @ref{Configuration, freq} directory to our node under @code{DST} +filename in our @ref{Configuration, incoming} one. + +If @ref{Configuration, notification} is enabled on the remote side for +file request, then it will sent simple letter after successful file +queuing. @node nncp-log @section nncp-log -TODO. +@verbatim +% nncp-log [options] +@end verbatim + +Parse @ref{Log, log} file and print out its records in human-readable form. @node nncp-mail @section nncp-mail -TODO. +@verbatim +% nncp-mail [options] NODE USER ... +@end verbatim + +Send mail, that is read from stdin, to @code{NODE} and specified +@code{USER}s. Mail message will be compressed. After receiving, remote +side will execute specified @ref{Configuration, sendmail} command with +@code{USER}s appended as a command line argument and feed decompressed +mail body to that command's stdin. @node nncp-newnode @section nncp-newnode -TODO. +@verbatim +% nncp-newnode [options] > mynewnode.yaml +@end verbatim + +Generate new node: private keys, example configuration file and print it +to stdout. You must use this command when you setup the new node. + +Pay attention that private keys generation consumes an entropy from your +operating system. @node nncp-pkt @section nncp-pkt -TODO. +@verbatim +% nncp-pkt [options] < pkt +% nncp-pkt [options] -dump < pkt > payload +@end verbatim + +Low level packet parser. Normally it should not be used, but can help in +debugging. + +By default it will print packet's type, for example: +@verbatim +Packet type: encrypted +Niceness: 64 +Sender: 2WHBV3TPZHDOZGUJEH563ZEK7M33J4UESRFO4PDKWD5KZNPROABQ +Payload size: 4.0 MiB (4162852 bytes) +@end verbatim + +If you specify @code{-dump} option and provide an @ref{Encrypted, +encrypted} packet, then it will verify and decrypt it to stdout. +Encrypted packets contain @ref{Plain, plain} ones, that also can be fed +to @code{nncp-pkt}: + +@verbatim +Packet type: plain +Payload type: transitional +Path: VHMTRWDOXPLK7BR55ICZ5N32ZJUMRKZEMFNGGCEAXV66GG43PEBQ + +Packet type: plain +Payload type: mail +Path: stargrave@stargrave.org +@end verbatim + +And with the @code{-dump} option it will give you the actual payload +(the whole file, mail message, and so on). @node nncp-stat @section nncp-stat -TODO. +@verbatim +% nncp-stat [options] +@end verbatim + +Print current @ref{Spool, spool} statistics about unsent and unprocessed +packets. For each node and each niceness level there will be printed how +many packets (with the total size) are in inbound (Rx) and outbound (Tx) +queues. @node nncp-toss @section nncp-toss -TODO. +@verbatim +% nncp-toss [options] [-dryrun] +@end verbatim + +Perform "tossing" operation on all inbound packets. This is the tool +that decrypts all packets and processes all payload packets in them: +copies files, sends mails, sends out file requests and relays transition +packets. It should be run after each online/offline exchange. + +@code{-dryrun} option does not perform any writing and sending, just +tells what it will do. @node nncp-xfer @section nncp-xfer -TODO. +@verbatim +% nncp-xfer [options] [-force] [-keep] [-rx|-tx] DIR +@end verbatim + +Search for directory in @code{DIR} containing inbound packets for us and +move them to local @ref{Spool, spool} directory. Also search for known +neighbours directories and move locally queued outbound packets to them. +This command is used for offline packets transmission. + +If @code{-force} option is specified, then outbound neighbour(s) +directories will be created. This is useful for the first time usage, +when storage device does not have any directories tree. + +If @code{-keep} option is specified, then keep copied files, do not +remove them. + +@code{-rx} option tells only to move inbound packets addressed to us. +@code{-tx} option tells exactly the opposite: move only outbound packets. + +@code{DIR} directory has the following structure: +@code{RECIPIENT/SENDER/PACKET}, where @code{RECIPIENT} is Base32 encoded +destination node, @code{SENDER} is Base32 encoded sender node. diff --git a/doc/index.texi b/doc/index.texi index 1307c0f..6814723 100644 --- a/doc/index.texi +++ b/doc/index.texi @@ -52,21 +52,27 @@ POSIX}-compatible systems. Easy integration with existing @menu * Comparison with existing solutions: Comparison. * Use cases:: -* Commands:: +* Workflow:: * Configuration file: Configuration. +* Commands:: +* Spool directory: Spool. +* Log format: Log. * Packet format: Packet. * Sync protocol: Sync. -* Copying conditions:: +* Copying conditions: Copying. @end menu @include comparison.texi @include usecases.texi -@include cmds.texi +@include workflow.texi @include cfg.texi +@include cmds.texi +@include spool.texi +@include log.texi @include pkt.texi @include sp.texi -@node Copying conditions +@node Copying @unnumbered Copying conditions @insertcopying diff --git a/doc/log.texi b/doc/log.texi new file mode 100644 index 0000000..3b567a0 --- /dev/null +++ b/doc/log.texi @@ -0,0 +1,31 @@ +@node Log +@unnumbered Log format + +Log is a plaintext file with single log entry per line. Lines are "\n" +separated. Each line has the following format: + +@verbatim +LEVEL | DATETIME | SD | MSG +@end verbatim + +Example log records: + +@verbatim +I 2017-01-09T08:41:54.751732131Z [nncp-xfer node="VHMTRWDOXPLK7BR55ICZ5N32ZJUMRKZEMFNGGCEAXV66GG43PEBQ" pkt="KMG6FO5UNEK7HWVFJPWQYC7MOZ76KEZ4FWCGM62PWA2QE5755NPA" size="4162548" xx="tx"] +I 2017-01-09T08:42:18.990005394Z [sp-infos node="BYRRQUULEHINPKEFN7CHMSHR5I5CK7PMX5HQNCYERTBAR4BOCG6Q" pkts="0" size="0" xx="tx"] +I 2017-01-09T08:48:59.264847401Z [call-finish duration="10" node="BYRRQUULEHINPKEFN7CHMSHR5I5CK7PMX5HQNCYERTBAR4BOCG6Q" rxbytes="60" rxspeed="60" txbytes="108" txspeed="108"] +@end verbatim + +@table @code +@item | + Space character. +@item LEVEL + Is single character log level. As a rule is is either @code{I} + (informational message), or @code{E} (error message). +@item DATETIME + UTC datetime in RFC 3339 @code{2006-01-02T15:04:05.999999999Z} format. +@item SD + Structured data as in RFC 5424. +@item MSG + Arbitrary UTF-8 encoded text data. +@end table diff --git a/doc/pkt.texi b/doc/pkt.texi index 87484a1..492871b 100644 --- a/doc/pkt.texi +++ b/doc/pkt.texi @@ -18,8 +18,6 @@ transition packet or email message. It is called "plain", because it contains plaintext, but plain packets would never be stored on your hard drive. -Each packet has the following header: - @verbatim HEADER +-------------------------------+--...---+ @@ -29,34 +27,31 @@ Each packet has the following header: @multitable @columnfractions 0.2 0.3 0.5 @headitem @tab XDR type @tab Value - @item Magic number @tab - 8-byte, fixed length opaque data @tab - @code{NNCPP0x10x00x00} - + 8-byte, fixed length opaque data @tab + @code{NNCPP0x10x00x00} @item Payload type @tab - unsigned integer @tab - 0 (file), 1 (freq), 2 (mail), 3 (transition) - + unsigned integer @tab + 0 (file), 1 (freq), 2 (mail), 3 (transition) @item Path length @tab - unsigned integer @tab - actual length of following field's payload - + unsigned integer @tab + actual length of following field's payload @item Path @tab - 255 byte, fixed length opaque data @tab - @itemize - @item UTF-8 encoded destination path for file transfer - @item UTF-8 encoded source path for file request - @item UTF-8 encoded, space separated, email recipients list - @item Node id the transition packet must be relayed on - @end itemize - + 255 byte, fixed length opaque data @tab + @itemize + @item UTF-8 encoded destination path for file transfer + @item UTF-8 encoded source path for file request + @item UTF-8 encoded, space separated, email recipients list + @item Node id the transition packet must be relayed on + @end itemize @end multitable Path has fixed size because of hiding its actual length -- it is -valuable metadata. +valuable metadata. Payload is appended to the header -- it is not stored +as XDR field, because most XDR libraries will store all that data in the +memory. -Actual payload comes after that header to the very end: +Depending on the packet's type, payload could store: @itemize @item File contents @@ -86,32 +81,25 @@ Each encrypted packet has the following header: @multitable @columnfractions 0.2 0.3 0.5 @headitem @tab XDR type @tab Value - @item Magic number @tab - 8-byte, fixed length opaque data @tab - @code{NNCPE0x10x00x00} - + 8-byte, fixed length opaque data @tab + @code{NNCPE0x10x00x00} @item Niceness @tab - unsigned integer @tab - 1-255, packet niceness level, its priority. - Lower value means higher precedence - + unsigned integer @tab + 1-255, packet niceness level, its priority. + Lower value means higher precedence @item Sender @tab - 32-byte, fixed length opaque data @tab - Sender node's id - + 32-byte, fixed length opaque data @tab + Sender node's id @item Exchange public key @tab - 32-byte, fixed length opaque data @tab - Ephemeral curve25519 public key - + 32-byte, fixed length opaque data @tab + Ephemeral curve25519 public key @item Signature @tab - 64-byte, fixed length opaque data @tab - ed25519 signature for that encrypted packet - + 64-byte, fixed length opaque data @tab + ed25519 signature for that encrypted packet @item Size @tab - unsigned hyper integer @tab - Encrypted payload size - + unsigned hyper integer @tab + Encrypted payload size @end multitable Signature is calculated over the following structure: diff --git a/doc/sp.texi b/doc/sp.texi index ff08090..b111988 100644 --- a/doc/sp.texi +++ b/doc/sp.texi @@ -1,16 +1,130 @@ @node Sync @unnumbered Sync protocol -So-called sync protocol is used in current TCP daemon's implementation. -It is aimed to be very simple and effective. It is used over reliable -transport like TCP connections. +So-called sync protocol (SP) is used in current TCP daemon's +implementation. It is used for synchronizing @ref{Spool, spool} +directory contents between two nodes. -It must be effective both on single-duplex and full-duplex links (for -example satellites have very high throughput, but high-delay links). -Acknowledging of each received packet, like +It is aimed to be very simple and effective. It uses reliable transport +like TCP connections. It must be effective both on single-duplex and +full-duplex links: for example satellites have very high throughput and +high-delay links, so acknowledging of each received packet, like @url{https://en.wikipedia.org/wiki/XMODEM, XMODEM} does, causes unacceptable performance degradation. -TODO +SP works on top of +@url{http://noiseprotocol.org/noise.html#interactive-patterns, +@code{Noise_IK_25519_ChaChaPoly_BLAKE2b}} protocol. Each Noise packet +are sent inside XDR envelope: -http://noiseprotocol.org/noise.html#interactive-patterns +@verbatim ++-----------------+ +| MAGIC | PAYLOAD | ++-----------------+ +@end verbatim + +@multitable @columnfractions 0.2 0.3 0.5 +@headitem @tab XDR type @tab Value +@item Magic number @tab + 8-byte, fixed length opaque data @tab + @code{NNCPS0x10x00x00} +@item Payload @tab + variable length opaque data @tab + Noise packet itself +@end multitable + +Peers static keys are specified as @ref{Configuration, @code{noisepub}} +configuration entry. + +Payload inside Noise packets has maximum size of @code{65 KiB - 256 B = +65280 B}. It is sent immediately in the first message by each side. The +very first payload (that is carried inside handshake messages) is always +padded to the maximum size with @code{HALT} packets (read below), for +hiding actual number of @code{INFO} packets (number of files available +for transmission). + +Each SP payload is a concatenation of various SP packets. Each packet +has XDR-encoded header and then corresponding XDR-encoded body. Header +is just an unsigned integer telling what body structure follows. + +@table @code + +@item HALT + Stop file transmission, empty sending queue on the remote side. + Actually @code{HALT} packet does not have any body, only the header + with the type. It is also used in the first payload for padding to + the maximum size. + +@item INFO + Information about the file we have for transmission. +@verbatim ++--------------------+ +| NICE | SIZE | HASH | ++--------------------+ +@end verbatim + @multitable @columnfractions 0.2 0.3 0.5 + @headitem @tab XDR type @tab Value + @item Niceness @tab + unsigned integer @tab + 1-255, file niceness level, its priority + @item Size @tab + unsigned hyper integer @tab + File size + @item Hash @tab + 32-byte, fixed length opaque data @tab + Unique file identifier, its checksum + @end multitable + +@item FREQ + File transmission request. Ask remote side to queue the file for + transmission. +@verbatim ++---------------+ +| HASH | OFFSET | ++---------------+ +@end verbatim + @multitable @columnfractions 0.2 0.3 0.5 + @headitem @tab XDR type @tab Value + @item Hash @tab + 32-byte, fixed length opaque data @tab + Unique file identifier, its checksum + @item Offset @tab + unsigned hyper integer @tab + Offset from which remote side must transmit the file + @end multitable + +@item FILE + Chunk of file. +@verbatim ++-------------------------+ +| HASH | OFFSET | PAYLOAD | ++-------------------------+ +@end verbatim + @multitable @columnfractions 0.2 0.3 0.5 + @headitem @tab XDR type @tab Value + @item Hash @tab + 32-byte, fixed length opaque data @tab + Unique file identifier, its checksum + @item Offset @tab + unsigned hyper integer @tab + Offset from which transmission goes + @item Payload @tab + variable length opaque data @tab + Chunk of file itself + @end multitable + +@item DONE + Signal remote side that we have successfully downloaded the file. +@verbatim ++------+ +| HASH | ++------+ +@end verbatim + @multitable @columnfractions 0.2 0.3 0.5 + @headitem @tab XDR type @tab Value + @item Hash @tab + 32-byte, fixed length opaque data @tab + Unique file identifier, its checksum + @end multitable + +@end table diff --git a/doc/spool.texi b/doc/spool.texi new file mode 100644 index 0000000..097b180 --- /dev/null +++ b/doc/spool.texi @@ -0,0 +1,34 @@ +@node Spool +@unnumbered Spool directory + +Spool directory holds @ref{Encrypted, encrypted packets} received from +remote nodes and queued for sending to them. It has the following +example structure: + +@verbatim +spool/tmp/ +spool/2WHB...OABQ/rx.lock +spool/2WHB...OABQ/rx/5ZIB...UMKW.part +spool/2WHB...OABQ/tx.lock +spool/BYRR...CG6Q/rx.lock +spool/BYRR...CG6Q/rx/ +spool/BYRR...CG6Q/tx.lock +spool/BYRR...CG6Q/tx/NSYY...ZUU6 +spool/BYRR...CG6Q/tx/ZI5U...5RRQ +@end verbatim + +Except for @code{tmp}, all other directories are Base32-encoded node +identifiers (@code{2WHB...OABQ}, @code{BYRR...CG6Q} in our example). +Each node subdirectory has @code{rx} (received, partly received and +currently unprocessed packets) and @code{tx} (for outbound packets) +directories. + +Each @code{rx}/@code{tx} directory contains one file per encrypted +packet. Its filename is Base32 encoded BLAKE2b hash of the contents. So +it can be integrity checked at any time. @code{5ZIB...UMKW.part} is +partly received file from @code{2WHB...OABQ} node. @code{tx} directory +can not contain partly written files -- they are moved atomically from +@code{tmp}. + +Only one process can work with @code{rx}/@code{tx} directories at once, +so there are corresponding lock files. diff --git a/doc/usecases.texi b/doc/usecases.texi index e498eb0..1af384e 100644 --- a/doc/usecases.texi +++ b/doc/usecases.texi @@ -1,9 +1,19 @@ @node Use cases @unnumbered Use cases -@table @strong - -@item Occasional connection to mail server +@menu +* Occasional connection to mail server: UsecaseMail. +* Unreliable/expensive communication link: UsecaseUnreliable. +* Slow/expensive link for high-volume data, bad QoS: UsecaseQoS. +* Extreme terrestrial environments, no link: UsecaseNoLink. +* Private, isolated MitM-resistant networks: UsecaseF2F. +* Highly secure isolated air-gap computers: UsecaseAirgap. +* Network censorship bypassing: UsecaseCensor. +* Reconnaissance, spying, intelligence, covert agents: UsecaseSpy. +@end menu + +@node UsecaseMail +@section Occasional connection to mail server Assume that you have got your own @url{http://www.postfix.org/, Postfix} SMTP server connected to the Internet. But you read and write emails on @@ -16,22 +26,35 @@ receive notification emails that his messages still are not delivered yet. Also you must have secure link (SSH, VPN, etc). Another possibility is to use POP3/IMAP4 servers, but this is too -overcomplicated and bloated for the simple task. Not an option. +overcomplicated and bloated for the simple task. Not an option. KISS! + +@anchor{Postfix} Just tell both of your Postfixes (on the server and notebook) to drop -email as a mail via NNCP to specified node. Search for @code{uucp} -related strings in @code{master.cf} and replace command to NNCP ones: +email as a mail via NNCP to specified node. This is done similarly as +with UUCP and as written in Postfix +@url{http://www.postfix.org/UUCP_README.html, documentation}. + +Search for @code{uucp} related strings in @code{master.cf} and replace +command to NNCP ones: + +@verbatim +nncp unix - n n - - pipe flags=Fqhu user=nncp argv=nncp-mail -quiet $nexthop $recipient +@end verbatim + +then add transport map, telling that mail for example.com domain can be +reached through NNCP transport to node @code{bob}: @verbatim -nncp unix - n n - - pipe - flags=Fqhu user=nncp argv=nncp-mail -quiet $nexthop $recipient +example.com nncp:bob @end verbatim Now, all mail will be stored in NNCP spool, that after exchanging and tossing will call local @code{sendmail} command to deliver them just that was happened on the same machine. -@item Unreliable/expensive communication link +@node UsecaseUnreliable +@section Unreliable/expensive communication link Assume that you have got slow modem/radio/cellular link that frequently disconnects and causes TCP timeouts. Not all HTTP servers support file @@ -54,16 +77,29 @@ will queue two files for sending to @code{bob} node. Fire and forget! Now this is daemon's job (or offline transfer) to send this file part by part to remote system when it is available. -@item Slow/expensive link for high-volume data +@node UsecaseQoS +@section Slow/expensive link for high-volume data, bad QoS Assume that you can give your relatively cheap 2 TiB removable hard drive to someone each day at the morning (and take it back at the evening). This equals to 185 Mbps good quality (without any speed degradation) link in single direction. What about more and bigger hard -drives? This type of data transferring is called +drives? This type of data exchange is called @url{https://en.wikipedia.org/wiki/Sneakernet, sneakernet}/floppynet. -@item Extreme terrestrial environments, no link +NNCP allows traffic prioritizing: each packet has niceness level, +that will guarantee that it will be processed earlier or later than the +other ones. Nearly all commands has corresponding option: + +@verbatim +% nncp-file -nice 32 myfile node:dst +% nncp-xfer -nice 192 /mnt/shared +% nncp-call -nice 224 bob +[...] +@end verbatim + +@node UsecaseNoLink +@section Extreme terrestrial environments, no link This is some kind of too slow link. Offline delivery methods is the only choice. Just send files as shown above, but use removable media for @@ -100,7 +136,8 @@ to find all packets related to their node and copy them locally for further processing. @code{nncp-xfer} is the only command used with removable devices. -@item Private, isolated MitM-resistant networks +@node UsecaseF2F +@section Private, isolated MitM-resistant networks All Internet connections can be eavesdropped and forged. You @strong{have to} to use encryption and authentication for securing them. @@ -141,7 +178,8 @@ configuration file) and send all related outbound packets and retrieve those the Bob has. All interrupted transfers will be automatically resumed. -@item Highly secure isolated air-gap computers +@node UsecaseAirgap +@section Highly secure isolated air-gap computers If you worry much about security, then air-gapped computer could be the only choice you can afford. Computer without any modems, wired and @@ -181,7 +219,26 @@ Pay attention that relaying node knows nothing about the packet inside, but just its size and priority. Transition packets are encrypted too. @code{bob} can not read @code{bob-airgap}'s packets. -@item Reconnaissance, spying, intelligence, covert agents +@node UsecaseCensor +@section Network censorship bypassing + +This is some kind of bad link too. Some governments tend to forbid +@strong{any} kind of private communication between people, allowing only +entertainment content delivering and popular social networks access +(that are already bloated with advertisements, local proprietary +JavaScript code execution (for spying on user activities, collect data +on them), shamelessly exploiting of very basic interhuman need of +communication). + +This is their natural right and wish. Nobody forces you to obey huge +corporations like Apple, Google or Microsoft. It is your choice to +create isolated friend-to-friend network with piles of harmless content +and private messaging. Only predators silently watch for their victims +in mammals world -- it harms your health being watched and feeling that +you are the victim that has already done something wrong. + +@node UsecaseSpy +@section Reconnaissance, spying, intelligence, covert agents Those guys know how Internet is a dangerous place incompatible with privacy. They require quick, fast dropping and picking of data. No @@ -196,8 +253,8 @@ be pretty fast, allowing to quickly fire chunks of queued packets. Very important property is that compromising of those dead drops and storages must not be fatal and even dangerous. Packets sent through the network and exchanged via those devices are end-to-end encrypted (but -unfortunately without forward secrecy property). No filenames, mail -recipients are seen. +unfortunately lacking forward secrecy). No filenames, mail recipients +are seen. All communications are done with so-called spool area: directory containing only those unprocessed encrypted packets. After packet @@ -206,9 +263,6 @@ another stage: tossing. Only that stage involves your private cryptographic keys. So even if your loose your computer, storage devices and so on -- it is not so bad, because you are not carrying private keys with it, you do not "toss" those packets immediately on the same device. - Tossing (reading those encrypted packets and extracting transferred files and mail messages) could and should be done on a separate computer. - -@end table diff --git a/doc/workflow.texi b/doc/workflow.texi new file mode 100644 index 0000000..dc4a3e4 --- /dev/null +++ b/doc/workflow.texi @@ -0,0 +1,31 @@ +@node Workflow +@unnumbered Workflow + +NNCP consists of several utilities. As a rule you will have the +following workflow with them. + +@enumerate +@item Run @ref{nncp-newnode} on each node to create an initial +@ref{Configuration, configuration} file. +@item Tune it up and set at least @ref{Spool, spool} and log paths. +@item Share your public keys and reachability addressees with your +neighbours. Add their keys to your configuration file and do any other +required configuration about their reachability, allowance of file or +freq transmissions. +@item Use @ref{nncp-file}, @ref{nncp-freq}, @ref{nncp-mail} +(@ref{Postfix, look how} Postfix SMTP server could be configured for its +usage) commands to queue file, freq and mail transmissions. Repeat as +many times any time as you wish. +@item Depending on connection methods, either: + @itemize + @item run @ref{nncp-daemon} to accept remotely initiated connections + to your node + @item run @ref{nncp-call} to initiate connection to required nodes + @item use @ref{nncp-xfer} with removable storage devices for copying + packets for/from other nodes + @end itemize +@item After successful packet exchanging (or just simply from time to +time), run @ref{nncp-toss} for tossing (decrypting and processing) all +inbound queues to receive mail messages, files, file requests and relay +transition packets to other nodes. +@end enumerate diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-call/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-call/main.go index aeabb96..36f3ff7 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-call/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-call/main.go @@ -47,7 +47,7 @@ func main() { rxOnly = flag.Bool("rx", false, "Only receive packets") txOnly = flag.Bool("tx", false, "Only transfer packets") quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") ) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-check/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-check/main.go index d1d2d04..cd8268e 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-check/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-check/main.go @@ -32,7 +32,7 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-check -- verify Rx/Tx packets checksum\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } @@ -41,7 +41,7 @@ func main() { cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") nodeRaw = flag.String("node", "", "Process only that node") quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") ) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go index 176c935..c14f4ba 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go @@ -35,7 +35,7 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-daemon -- TCP daemon\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } @@ -46,7 +46,7 @@ func main() { bind = flag.String("bind", "[::]:5400", "Address to bind to") maxConn = flag.Int("maxconn", 128, "Maximal number of simultaneous connections") quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") ) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-file/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-file/main.go index 6f37a96..46728ea 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-file/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-file/main.go @@ -33,7 +33,7 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-file -- send file\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options] SRC NODE:DST\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options] SRC NODE:[DST]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } @@ -42,7 +42,7 @@ func main() { cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") niceRaw = flag.Int("nice", nncp.DefaultNiceMail, "Outbound packet niceness") quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") ) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go index 7360f50..260c599 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go @@ -33,7 +33,7 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-freq -- send file request\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE:SRC DST\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE:SRC DST\nOptions:\n", os.Args[0]) flag.PrintDefaults() } @@ -42,7 +42,7 @@ func main() { cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") niceRaw = flag.Int("nice", nncp.DefaultNiceMail, "Outbound packet niceness") quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") ) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-log/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-log/main.go index d49b7f7..9a4f530 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-log/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-log/main.go @@ -33,14 +33,14 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-log -- read logs\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } func main() { var ( cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") ) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go index 8b01b8c..f23877b 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go @@ -34,7 +34,7 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-mail -- send email\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE USER ...\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE USER ...\nOptions:\n", os.Args[0]) flag.PrintDefaults() fmt.Fprintln(os.Stderr, "Email body is read from stdin.") } @@ -44,7 +44,7 @@ func main() { cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") niceRaw = flag.Int("nice", nncp.DefaultNiceMail, "Outbound packet niceness") quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") ) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go index d6a597f..674381e 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go @@ -38,7 +38,7 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-pkt -- parse raw packet\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() fmt.Fprintln(os.Stderr, "Packet is read from stdin.") } diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go index 9791b98..36cc1cb 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go @@ -33,7 +33,7 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-stat -- show queued Rx/Tx stats\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } @@ -41,7 +41,7 @@ func main() { var ( cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") nodeRaw = flag.String("node", "", "Process only that node") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") ) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go index e12e901..9b50866 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go @@ -32,7 +32,7 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-toss -- process inbound packets\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } @@ -43,7 +43,7 @@ func main() { niceRaw = flag.Int("nice", 255, "Minimal required niceness") dryRun = flag.Bool("dryrun", false, "Do not actually write any tossed data") quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") ) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go index f12fa5f..669eadc 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go @@ -37,7 +37,7 @@ import ( func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) fmt.Fprintln(os.Stderr, "nncp-xfer -- copy inbound and outbounds packets\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options] DIR\nOptions:", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [options] DIR\nOptions:\n", os.Args[0]) flag.PrintDefaults() } @@ -51,7 +51,7 @@ func main() { force = flag.Bool("force", false, "Force outbound directories creation") keep = flag.Bool("keep", false, "Do not delete transferred packets") quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Enable debugging information") + debug = flag.Bool("debug", false, "Print debug messages") version = flag.Bool("version", false, "Print version information") warranty = flag.Bool("warranty", false, "Print warranty information") )