Skip to content

IAmScottCH/snapcap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 

Repository files navigation

SnapCap

Version 2.0

SnapCap is a simple application remote backup suite of utilities. The first version was a bash script that ran on the server where the application to back up was deployed. I took its operations and turned them into a very simple protocol for client/server operation.

There's nothing fancy about what SnapCap really does:

  • it produces a MySQL/MariaDB database dump into a file
  • it produces a tar-gzip of the files

SnapCap encrypts backups server-side with an application public key, which the client-side can decrypt with the private key. Protocol commands exchanged between the client and server are also encrypted.

For initial setup, SnapCap is packaged with a setup public key. A client with the setup private key can send a SUP command with an application public key as an argument, and the server will store the application public key and blank its copy of the setup public key (so SUP can't be issued again).

The initial release of version 2.0 only has a PHP client/server pair, but I plan on adding clients/servers in other languages/communication mechanisms as the needs arise in my own work. Thus, while the PHP session is used server side for what little state needs to be maintained, that is only an envelope. An independent session ID is generated by SnapCap for its own use as the truly significant session ID for its operations. So, when I refer to the session ID (or SID), I'm talking about SnapCap's session ID, not PHP's (or any other platform-specific one).

The protocol commands the client can send follow. arguments in [] are optional and those in <> are required. Possible server responses are also listed after each client command. NOTE: The server may not respond for internal errors or for things that indicate a stupid client (and possibly an attack attempt). If it responds in-protocol to an error, it will send back an ERR response, as noted below.

IMPORTANT! The blank space character is used as a delimiter, and so no argument on a command can contain a space character. To deal with this possibility a space might be necessary, all arguments are themselves base64 encoded. The command string itself, (HLO, BYE, etc.) is not base64 encoded. Here's a kind of pseudocode example of how it is packaged:

base64encode(encrypt(SUP base64encode(SID) base64encode(appkey)))

HLO: hello -- used to setup a session.  Encrypted with setup key if SUP has not been issued yet, else encrypted with application key.
    HLO <SID> Encrypted with setup key if SUP has not been issued yet, else encrypted with application key.
SUP <SID> <application public key>: finish setting yourself up with the provided application key.  Encrypted with setup key.
    SUP <SID>
BDB <SID> <mode> <symkey> <ivec> [more args]: backup the database.  <mode> is how to go about it.  <symkey> and <iv> are the symmetric key and initialization vector for the backup file encryption. [more args] is other possible arguments, depending on mode.  The only mode currently supported is "wordpress".  In wordpress mode, no other arguments are required: the SnapCap server assumes it is installed as a WordPress plugin and finds and loads wp-config.php to get the database parameters.  There is an optional argument, "noencrypt" that can be provided -- if provided, the output file is NOT encrypted.  Though not used in that case, <symkey> and <ivec> must still be provided since the arguments are positional.
	BDB <checksum>: checksum is the MD5 checksum of the encrypted DB dump.
BFL <SID> <mode> [more args]: backup the files.  <mode> is how to go about it.   <symkey> and <iv> are the symmetric key and initialization vector for the backup file encryption. [more args] is other possible arguments, depending on mode.  The only mode currently supported is "wordpress".  In wordpress mode, no other arguments are required: the SnapCap server assumes it should backup all files in and under the standard directory location for wp-config.php.  There is an optional argument, "noencrypt" that can be provided -- if provided, the output file is NOT encrypted.  Though not used in that case, <symkey> and <ivec> must still be provided since the arguments are positional. 
	BFL <checksum>: checksum is the MD5 checksum of the encrypted tar-gzip file archived.
SND <SID> [mode]: send the last backup file generated.  This must follow either a BDB or a BFL in the same session. 
    The server responds by dumping the encrypted backup data file down to the client.  After the data is received, the client is expected to generate its own MD5 sum of the downloaded data and compare it to the one previously returned by the server in response to the BDB or BFL commands.  Thus, even if the server fails to successfully complete the dump back the client, the client will detect it via a checksum mismatch.  [mode] is an optional parameter, and if set to "download" (without the quotes) the server will send back a URL for the file it would send rather than sending it.  Use this in cases where the host has low RAM resources to prevent out-of-memory due to readfile()'s buffering.
BYE <SID>: close the session.
	BYE <SID>: The server "forgets" the session, so the SID may not be used for any more commands.

Additional possible server response:

ERR <msg>: error. Message is a hint as to what went wrong. Encrypted with whatever key is currently in use.

A plain text temp file is utilized during BDB and BFL on the server, which it deletes immediately after encrypting it. The encrypted file is deleted by the BYE command processing, if the server "remembers" having one in the session. It forgets having a file in the session immediately after deleting it. It's not really a big deal if the file ends up lying around, since it is encrypted and the private key is needed to decrypt it.

Note that all commands from the client except HLO require the argument. Since HLO initiates a session, the server must generate the SID. The only responses from the server that do not have the as the data are responses to the BDB, BFL, and SND commands. SND cannot provide any in a simple way, since it is file download, though in the future I may add a header. BDB and BFL provide a checksum for data. That may also change in the future to provide the SID in some way, but I doubt it.

Where the SID is provided the client or server may verify it is the correct SID (and the server really must).

NOTE: SnapCap must be able to create subdirectory (and files in it) under its own directory. Alternatively, you may pre-create a subdirectory called "sctmp" that it has r/w permissions to under its directory. By that, I of course mean the user under which SnapCap is executing must effectively have those abilities/permissions.

SnapCap client exit codes

The SnapCap clients exit with a status code indicating success or severity of failure, for use in automated scripts and stuff for notifications and whatnot.

  • 0: success. No anamolies detected during execution.
  • 1: warning. ... weird things are happening.... Processing should continue after a warning.
  • 2: error. Danger, Will Robinson! Processing usually exits immediately upon encountering an error condition.

About the WordPress plugin file

I wanted to be able to get SnapCap in place and working for WordPress installs with only admin access on the WordPress Dashboard -- that is, without having to have FTP or SSH access to the hosting system. Since SnapCap is written to be independent of any application, all I really need to get it going is the setup public key and snapserver.php on the target system. So, all this plugin file does is provide the means for WordPress to see a plugin. If you zip up the snapcap directory in the src folder, and then install the zip as a new plugin via the WordPress Dashboard, you can run snapclient.php with the SUP command and voila! You're up and running with SnapCap.

Then if you ever need to remove it, you can "Delete" it from the Plugins section of the WordPress Dashboard, and all its files will be gone (it doesn't use any database tables or anything).

Here's an example of getting it running on a site and using it to get both a file and database backup of the WordPress instance it is installed in:

php snapclient.php SUP /home/feran/mykeys/sc_example.com example.com wp-content/plugins/snapcap

php snapclient.php BDB /home/feran/mykeys/sc_example.com example.com wp-content/plugins/snapcap /mnt/phatboy/example.com/BDB_2021-04-10.bin

php snapclient.php BFL /home/feran/mykeys/sc_example.com example.com wp-content/plugins/snapcap /mnt/phatboy/example.com/BFL_2021-04-10.bin

Note on format of encrypted data

Encrypted data is encrypted in 400 byte chunks, due to how PHP's implementation of openssl_private_encrypt() (and openssl_public_encrypt(), for that matter) works. The symmetric key encryption is done the same way to keep things consistently simple (in other words, I was being lazy). I know that is specific to a run-time/platform, but it is the first I wrote version 2.0 for, so decided to just go with it. On the other hand, I understand why -- the data to encrypt has to be shorter in bits than the key length. Anyway, the chunks are encrypted and then base64 encoded. Any message, therefore, greater than 400 bytes will have multiple chunks. The chunks are separated by commas, since a comma is not a valid character in a base64 encoding. Then the whole resulting blob is base64 encoded again (to get commas out of the mix for transit). Thus, to decrypt a message of more than one chunk, you first need to decrypt each chunk up to but not including the next comma, and reassemble the whole thing. I did it that way so the decryption algorithm doesn't have to know/figure out anything about the key size and how to chunk the data coming from the file for decryption.

That's all actually harder to explain than to do. See encryptString(), decryptString(), and decryptFile() in snapclient.php for examples. Also encryptFile() in snapserver.php.

The symmetric key and IV used to encrypt files is stored in the filename with ".keyring" appended, alongside the encrypted file. The client's decryptfile handler knows how to deal with that.

Note on PHP implementation

Really for web servers. The command is sent in the POST var named "snapcap".

About

My own personal backer upper system

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages