Permalink
Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 260 lines (173 sloc) 9.42 KB

Basic architecture

The d3ck encrypts normal network traffic to it via HTTPS. It runs the nginx proxy to then transform to plain unencrypted http traffic within the d4ck - e.g. from nginx to node server. This was done in an effort to escape the hell that is javascript/browser/https interaction and retain zero configuration on the client (e.g. browser.)

So:

browser <- encrypted via https -> nginx <- plaintext http -> nodejs

When a d3ck wants to talk to another d3ck it mostly uses client-side certificates for authentication and encryption, but there is probably some plain HTTPS still left.

Most users will primarily interact with their d3ck(s) via a browser; it uses Javascript, HTML5 and all jazz, so throw away your old IE and welcome the new.

D3cks can become friends (sic) if the owner agrees to a friend request. The request will be followed up by a bundle of JSON that contains the requesting d3ck's public keys along with a client keypair that your d3ck will use to initiate communications with the other. This is passed along using the https and the public key of the respective server.

So:

knock knock, be my friend?

yes/no

    if yes, send along keys your d3ck wants the remote to use
    remote sends their d3ck's keys to your d3ck

    if no, tell them to go away

Then they reciprocate by sending you back keys your d3ck will use to communicate to them.

BTW, this means that the cryptographic profile for communication is set by the server, or, put another way, if you call someone you use their rules, not yours, and vice-versa.

The usual path of communication looks like:

user <-> browser <-> d3ck-one <-> encrypted channel <-> d3ck-two <-> browser <-> user-two

The "encrypted channel" is either client-side certificates (for file transfers or d3ck-to-deck communications) or OpenVPN for certain operations.

Self-signed certificates generated by openssl are used for the basic security and communications for 3 situations:

- OpenVPN (plus a shared secret and DH key exchange)

- client-side authentication and https encryption for for d3ck to d3ck communication

- browser to d3ck https communication

Most of the important operations are not written in node/javascript; instead I primarily chose to execute shell scripts and programs to do the dirty work. I thought this would be much easier to understand and check for errors if pieces of funcationality were broken out in this way.

Directory Structure, files, etc.

/etc/d3ck - main d3ck directory

exe         - where various OS/shell programs live, executed by the main

conf        - eventually decided things *should* be here, but have yet
              to migrate things.

f-u-openssl - the ssl cert generation stuff

public      - all the browser/client stuff, and where users go to browse
              and interact with their d3ck.

d3cks       - all the d3ck certificate files and junk (including the
              D3cks have a subdir corresponding to their d3ck ID (e.g.
              /etc/d3ck/d3cks/4EA45A067FD1DCCD65E442ECD31AEA5F69674A33);
              the d3ck nodejs is running on has a symlink - 'D3CK' -
              in that subdir for ease of access, so /etc/d3cks/D3CK
              will always go to the home d3ck area.

              if my d3ck sends yours keys for client-side-auth they'll
              also show up in your d3cks subdir, prefixed by an underscore;
              e.g.
              
                /etc/d3ck/d3cks/4EA...3/_cli3nt.cert
              
              No real reason it is this way, mostly for sanity, but
              it does make it simple to see what's going on.
              
              Finally a JSON bundle is in the client subdirs as well;
              this is a bundle of all the certs and basic d3ck info
              that was sent to each client, including the image that
              shows up in their UI. Left for testing as well, but
              perhaps not a bad thing.

All important data should also be kept in redis; currently basic d3ck, client, and logging info is there. MOST internal d3ck data access is done via Redis. All should be.

At this point you might reasonably say "Dan, you fool, why keep stuff in two places?" The answer is at least easy to respond to - it was just a lot easier to look at files and understand the system than it was to crawl through a database, however easy. And when I started I had a coauthor (the mighty Markus Fix, who had to bail due to real life), and he started it with Redis, so.....

Authentication

Auth is done via the passport auth package, and mostly in the "auth" function.

Bcrypt is used to encrypt the user's password and is kept in a json file "secretz.json" in /etc/d3ck.

If something comes from 127.0.0.1 it gets an auth bypass; this is used for things like "node, call-this-shell-exe to start vpn" or whatever.

D3cks authenticate themselves to other d3cks via client-side certificates.

OpenVPN is also used, using the same certificates, when video calls are made.

Authorization

Currently it is really just a skeleton, but it seems to work in the very limited fashion I'm using it for. For completeness, here's the basic model.

A d3ck has assorted functionaly or capabilities, such as video, file transfer, etc. Each other d3ck (lookup by d3ck-ID) you know about has a yes/no/??? for each potential capability, They try to do something, you look it up, it will pass/fail/need-confirm/etc.

For instance I might let Markus execute programs on my d3ck, but I would like to say yes or no to each request. I can only do that if I'm logged in, whether in real-time or queued up or whatever.

The capabilities structure is in D3CK.json; it looks something like this:

"capabilities" : {
    "friend request":       { "paranoid": "off", "moderate": "ask", "trusting": "on"  },
    "VPN":                  { "paranoid": "ask", "moderate": "ask", "trusting": "on"  },
 [...]
}

Each line is a capability; there are currently 3 types of user types, paranoid, moderate, and trusting, and they all have different defaults for various capabilities (the paranoid being the most... cautious.)

Eventually all these could be overwritten on a d3ck-by-d3ck basis - e.g. I'm paranoid, but for you, markus, I make an exception.

NOTE: if you are a client d3ck initiating communications with another d3ck then the 2nd d3ck's capability matrix will be used. In general this is true for the security model - you accept the remote's restrictions or lack of the same.

Logging/notifications

There is a weak mechanism for alerting the user of things by sending alerts to their browser (IF they are logged on!)

That means things can fail silently, even if the server has said "ackkkkk". Yes, I suck. So much wasted time on https got me here.

The nodejs server itself uses Winston for logging, and various sub-programs have their output save into the "logs" subdirectory.

Logging is currently voluminous. Life sux.

Networking/Firewall/packet-filter

I'm ready to put this in, but it sure makes testing difficult... so for now it's turned off (this is the 2nd thing I'll change from now.) So... keep behind a real firewall for now!

When it's a fully operational death-d3ck, one port will be open (currently TCP 8080) and another one optionally (SSH, TCP port 22.) If a VPN tries to start up (e.g. both d3cks accept) UDP port 8080 (currently) is opened - only up to the other IP address - and then closed after the VPN connection stops.

A list of ports used (all TCP except for OpenVPN); first, on external ports (whatever the IP address of the server):

22          SSH

8080/udp    OpenVPN

443         Nginx (redirects to 8080 currently)
8080        Nginx

Internal Only/localhost/127.0.0.1, unless you're suicidal

5555        node.js
6666        openVPN admin channel
6379        Redis server

Some crypto notes

A d3ck's OpenVPN connection uses the same certificates that were used for HTTPS. A static pre-shared key (PSK) is used to help protect against DoS attacks.

The minimum version of OpenVPN should be 2.3.2 (as of Jul-11th-2014, the most recent version is 2.3.4), which allows TLS v1.0 DHE et al9.

Key Management

I'm using an extraordinarily simple key management scheme; it may be too simple, but I hope it will work for relatively small amounts of d3cks.

Certificates aren't tied to particular IP addresses; indeed, effort has been made to kill this off so things will work, as machines and people move around.

When certificates are no longer valid (generally due to being out-of-date) they will simply stop working (UI needs to reflect this!)

Revocation will be done when a card is deleted. This may or may not be what the user really wants, but at least it's really, really gone! Note - if a d3ck is re-flashed/reinstalled it will have no memory of past certificates that have been revoked.

The revocation will ONLY apply to the d3ck that did the deletion; there is no passing around revocation lists or whatever.

Perhaps a short lifespan on certificates (weeks or even days or something) would be reasonable, because after you've befriended someone's d3ck it could just do the change automatically under the hood without user interaction the next time you talk to them. A d3ck could simply constantly revoke and reissue new keys.