]> Cypherpunks.ru repositories - govpn.git/blob - README
Initial commit
[govpn.git] / README
1                                  GoVPN
2                                  =====
3 SYNOPSIS
4
5 govpn is simple high-performance secure virtual private network daemon.
6 It uses DH-EKE for mutual zero-knowledge authentication and
7 authenticated encrypted transport.
8
9 DESCRIPTION
10
11 All packets captured on network interface are encrypted, authenticated
12 and sent to remote server, that writes them to his interface, and vice
13 versa. Client and server use pre-shared authentication key (PSK).
14 Because of stateless UDP nature, after some timeout of inactivity peers
15 forget about each other and have to retry handshake process again. As a
16 rule, there are enough time-to-time traffic in ordinary Ethernet
17 networks to heartbeat connection.
18
19 Handshake is used to mutually authenticate peers, exchange common secret
20 per-session encryption key and checks UDP transport availability.
21
22 Because of UDP and authentication overhead: each packet grows in size
23 during transmission, so you have to lower you maximum transmission unit
24 (MTU) on network interface.
25
26 High security and high performance are the goals for that daemon. It
27 uses fast cryptography algorithms with 128bit security margin, strong
28 mutual zero-knowledge authentication and perfect-forward secrecy
29 property. An attacker can not know anything from captured traffic, even
30 if pre-shared key is compromised.
31
32 COMPARISON TO OpenVPN
33
34 * Higher performance
35 * Perfect-forward secrecy (if long-term pre-shared keys are compromised,
36   no captured traffic can be decrypted anyway)
37 * Mutual two-side authentication (noone will send real network interface
38   data unless the other side is authenticated)
39 * Zero-knowledge authentication (pre-shared key is not transmitted in
40   any form between the peers, not even it's hash value)
41 * Fast handshake
42
43 CONSOLE OUTPUT LEGEND
44
45 B -- bad UDP packet (some system error)
46 T -- bad tag on packet (MiTM, unordered packet)
47 [HS?] -- unknown handshake message
48 w -- successful write to remote peer
49 r -- successful read from remote peer
50 [HS1], [HS2], [HS3], [HS4] -- handshake packet stage
51 [rS?] -- invalid server's random authentication number received (MiTM, bad PSK)
52 [rC?] -- invalid client's random authentication number received (MiTM, bad PSK)
53 [S?] -- invalid handshake stage is trying to perform (MiTM, duplicate packet)
54 [OK] -- handshake's stage passed
55
56 TECHNICAL INTERNALS
57
58 Encryption: Salsa20
59 Message authentication: Poly1305
60 Password authenticated key agreement: Curve25519 based DH-EKE
61 Packet overhead: 24 bytes per packet
62 Handshake overhead: 4 UDP (2 from client, 2 from server) packets,
63                     232 bytes total payload
64
65                            Transport protocol
66
67     SERIAL + ENC(KEY, SERIAL, DATA) + AUTH(SERIAL + ENC_DATA)
68
69 where SERIAL is message serial number. Odds are reserved for
70 client->server, evens are for server->client. SERIAL is used as a nonce
71 for DATA encryption: encryption key is different during each handshake,
72 so (key, nonce) pair is always used once.
73
74 We generate Salsa20's output using this key and nonce for each message:
75 * first 256 bits are used as a one-time key for Poly1305 authentication
76 * next 256 bits of output are ignored
77 * and all remaining ones XORed with the data, encrypting it
78
79                            Handshake protocol
80      ┌──────┐                                  ┌──────┐
81      │Client│                                  │Server│
82      └──┬───┘                                  └──┬───┘
83         │────┐
84         │    │ R=rand(64bit); CPrivKey=rand(256bit)
85         │<───┘
86         │                                         │
87         │         R, enc(PSK, R, CPubKey)         │
88         │ ────────────────────────────────────────>
89         │                                         │
90         │                                         │────┐
91         │                                         │    │ SPrivKey=rand(256bit)
92         │                                         │<───┘
93         │                                         │
94         │                                         │────┐
95         │                                         │    │ K=DH(SPrivKey, CPubKey)
96         │                                         │<───┘
97         │                                         │
98         │                                         │────┐
99         │                                         │    │ RS=rand(64bit); SS=rand(256bit)
100         │                                         │<───┘
101         │                                         │
102         │ enc(PSK, R+1, SPubKey); enc(K, R, RS+SS)│
103         │ <────────────────────────────────────────
104         │                                         │
105         │────┐                                    │
106         │    │ K=DH(CPrivKey, SPubKey)            │
107         │<───┘                                    │
108         │                                         │
109         │────┐                                    │
110         │    │ RC=rand(64bit); SC=rand(256bit)    │
111         │<───┘                                    │
112         │                                         │
113         │          enc(K, R+1, RS+RC+SC)          │
114         │ ────────────────────────────────────────>
115         │                                         │
116         │                                         │────┐
117         │                                         │    │ compare(RS)
118         │                                         │<───┘
119         │                                         │
120         │                                         │────┐
121         │                                         │    │ MasterKey=SS XOR SC
122         │                                         │<───┘
123         │                                         │
124         │             enc(K, 0x00, RC)            │
125         │ <────────────────────────────────────────
126         │                                         │
127         │────┐                                    │
128         │    │ compare(RC)                        │
129         │<───┘                                    │
130         │                                         │
131         │────┐                                    │
132         │    │ MasterKey=SS XOR SC                │
133         │<───┘                                    │
134      ┌──┴───┐                                  ┌──┴───┐
135      │Client│                                  │Server│
136      └──────┘                                  └──────┘
137
138 * client generates CPubKey, random 64bit R that is used as a nonce
139   for encryption
140 * R + enc(PSK, R, CPubKey) + NULLs -> Server [56 bytes]
141 * server remembers clients address, decrypt CPubKey, generates
142   SPrivKey/SPubKey, computes common shared key K (based on
143   CPubKey and SPrivKey), generates 64bit random number RS and
144   256bit random SS. PSK-encryption uses incremented R (from previous
145   message) for nonce
146 * enc(PSK, SPubKey) + enc(K, RS + SS) + NULLs -> Client [88 bytes]
147 * client decrypt SPubKey, computes K, decrypts RS, SS with key K,
148   remembers SS, generates 64bit random number RC and 256bit random SC,
149 * enc(K, RS + RC + SC) + NULLs -> Server [64 bytes]
150 * server decrypt RS, RC, SC with key K, compares RS with it's own one
151   send before, computes final main encryption key S = SS XOR SC
152 * ENC(K, RC) + NULLs -> Client [24 bytes]
153 * server switches to the new client
154 * client decrypts RC and compares with it's own generated one, computes
155   final main encryption key S
156
157 Where PSK is 256bit pre-shared key, NULLs are 16 null-bytes. R* are
158 required for handshake randomization and two-way authentication. K key
159 is used only during handshake. NULLs are required to differentiate
160 common transport protocol messages from handshake ones. DH public keys
161 can be trivially derived from private ones.
162
163
164 RELATED DOCUMENTS
165
166 * http://cr.yp.to/ecdh.html
167 * http://cr.yp.to/snuffle.html
168 * http://cr.yp.to/mac.html
169 * http://grouper.ieee.org/groups/1363/passwdPK/contributions/jablon.pdf
170 * Applied Cryptography (C) 1996 Bruce Schneier
171
172 TODO
173
174 * Move decryption and encryption processes into goroutines
175 * Add identity management (client can send it's identification, server has
176   on-disk id↔key plaintext database)
177 * Implement alternative Secure Remote Password protocol (it is much slower,
178   technically has more code, but human memorized passwords can be used
179   instead of keys)
180
181 LICENCE
182
183 This program is free software: you can redistribute it and/or modify
184 it under the terms of the GNU General Public License as published by
185 the Free Software Foundation, either version 3 of the License, or
186 any later version.
187
188 This program is distributed in the hope that it will be useful,
189 but WITHOUT ANY WARRANTY; without even the implied warranty of
190 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
191 GNU General Public License for more details.