summaryrefslogtreecommitdiff
path: root/TLS.md
blob: ee24a8df5f7b2be5bfe6edab7eee235c5471a2a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
TLS Support -- Work In Progress
===============================

This is a brief note to capture current thoughts/ideas and track pending action
items.

Getting Started
---------------

### Building

To build with TLS support you'll need OpenSSL development libraries (e.g.
libssl-dev on Debian/Ubuntu).

Run `make BUILD_TLS=yes`.

### Tests

To run Redis test suite with TLS, you'll need TLS support for TCL (i.e.
`tcl-tls` package on Debian/Ubuntu).

1. Run `./utils/gen-test-certs.sh` to generate a root CA and a server
   certificate.

2. Run `./runtest --tls` or `./runtest-cluster --tls` to run Redis and Redis
   Cluster tests in TLS mode.

### Running manually

To manually run a Redis server with TLS mode (assuming `gen-test-certs.sh` was
invoked so sample certificates/keys are available):

    ./src/redis-server --tls-port 6379 --port 0 \
        --tls-cert-file ./tests/tls/redis.crt \
        --tls-key-file ./tests/tls/redis.key \
        --tls-ca-cert-file ./tests/tls/ca.crt

To connect to this Redis server with `redis-cli`:

    ./src/redis-cli --tls \
        --cert ./tests/tls/redis.crt \
        --key ./tests/tls/redis.key \
        --cacert ./tests/tls/ca.crt

This will disable TCP and enable TLS on port 6379. It's also possible to have
both TCP and TLS available, but you'll need to assign different ports.

To make a Replica connect to the master using TLS, use `--tls-replication yes`,
and to make Redis Cluster use TLS across nodes use `--tls-cluster yes`.

**NOTE: This is still very much work in progress and some configuration is still
missing or may change.**

Connections
-----------

Connection abstraction API is mostly done and seems to hold well for hiding
implementation details between TLS and TCP.

1. Still need to implement the equivalent of AE_BARRIER.  Because TLS
   socket-level read/write events don't correspond to logical operations, this
   should probably be done at the Read/Write handler level.

2. Multi-threading I/O is not supported.  The main issue to address is the need
   to manipulate AE based on OpenSSL return codes.  We can either propagate this
   out of the thread, or explore ways of further optimizing MT I/O by having
   event loops that live inside the thread and borrow connections in/out.

3. Finish cleaning up the implementation.  Make sure all error cases are handled
   and reflected into connection state, connection state validated before
   certain operations, etc.
    - Clean (non-errno) interface to report would-block.
    - Consistent error reporting.

4. Sync IO for TLS is currently implemented in a hackish way, i.e. making the
   socket blocking and configuring socket-level timeout.  This means the timeout
   value may not be so accurate, and there would be a lot of syscall overhead.
   However I believe that getting rid of syncio completely in favor of pure
   async work is probably a better move than trying to fix that. For replication
   it would probably not be so hard. For cluster keys migration it might be more
   difficult, but there are probably other good reasons to improve that part
   anyway.

5. A mechanism to re-trigger read callbacks for connections with unread buffers
   (the case of reading partial TLS frames):

    a) Before sleep should iterate connections looking for those with a read handler,
       SSL_pending() != 0 and no read event.
    b) If found, trigger read handler for these conns.
    c) After iteration if this state persists, epoll should be called in a way
       that won't block so the process continues and this behave the same as a
       level trigerred epoll.

Replication
-----------

Diskless master replication is broken, until child/parent connection proxying is
implemented.


TLS Features
------------

1. Add metrics to INFO.
2. Add certificate authentication configuration (i.e. option to skip client
auth, master auth, etc.).
3. Add TLS cipher configuration options.
4. [Optional] Add session caching support. Check if/how it's handled by clients
   to assess how useful/important it is.


redis-benchmark
---------------

The current implementation is a mix of using hiredis for parsing and basic
networking (establishing connections), but directly manipulating sockets for
most actions.

This will need to be cleaned up for proper TLS support. The best approach is
probably to migrate to hiredis async mode.


Others
------

Consider the implications of allowing TLS to be configured on a separate port,
making Redis listening on multiple ports.

This impacts many things, like
1. Startup banner port notification
2. Proctitle
3. How slaves announce themselves
4. Cluster bus port calculation