| 1 | Detailed specification of protocol in version 00000502 |
|---|
| 2 | ====================================================== |
|---|
| 3 | |
|---|
| 4 | Note: work in progress!! |
|---|
| 5 | |
|---|
| 6 | ====================================================== |
|---|
| 7 | 1. DNS protocol |
|---|
| 8 | ====================================================== |
|---|
| 9 | |
|---|
| 10 | Quick alphabetical index / register: |
|---|
| 11 | 0-9 Data packet |
|---|
| 12 | A-F Data packet |
|---|
| 13 | I IP address |
|---|
| 14 | L Login |
|---|
| 15 | N Downstream fragsize (NS.topdomain A-type reply) |
|---|
| 16 | O Options |
|---|
| 17 | P Ping |
|---|
| 18 | R Downstream fragsize probe |
|---|
| 19 | S Switch upstream codec |
|---|
| 20 | V Version |
|---|
| 21 | W (WWW.topdomain A-type reply) |
|---|
| 22 | Y Downstream codec check |
|---|
| 23 | Z Upstream codec check |
|---|
| 24 | |
|---|
| 25 | |
|---|
| 26 | CMC = 2 byte Cache Miss Counter, increased every time it is used |
|---|
| 27 | |
|---|
| 28 | Version: |
|---|
| 29 | Client sends: |
|---|
| 30 | First byte v or V |
|---|
| 31 | Rest encoded with base32: |
|---|
| 32 | 4 bytes big endian protocol version |
|---|
| 33 | CMC |
|---|
| 34 | Server replies: |
|---|
| 35 | 4 chars: |
|---|
| 36 | VACK (version ok), followed by login challenge |
|---|
| 37 | VNAK (version differs), followed by server protocol version |
|---|
| 38 | VFUL (server has no free slots), followed by max users |
|---|
| 39 | 4 byte value: means login challenge/server protocol version/max users |
|---|
| 40 | 1 byte userid of the new user, or any byte if not VACK |
|---|
| 41 | |
|---|
| 42 | Login: |
|---|
| 43 | Client sends: |
|---|
| 44 | First byte l or L |
|---|
| 45 | Rest encoded with base32: |
|---|
| 46 | 1 byte userid |
|---|
| 47 | 16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge) |
|---|
| 48 | CMC |
|---|
| 49 | Server replies: |
|---|
| 50 | LNAK means not accepted |
|---|
| 51 | x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits) |
|---|
| 52 | |
|---|
| 53 | IP Request: |
|---|
| 54 | Client sends: |
|---|
| 55 | First byte i or I |
|---|
| 56 | 5 bits coded as Base32 char, meaning userid |
|---|
| 57 | CMC as 3 Base32 chars |
|---|
| 58 | Server replies |
|---|
| 59 | BADIP if bad userid, or |
|---|
| 60 | I and then 4 bytes network order external IP address of iodined server |
|---|
| 61 | |
|---|
| 62 | Upstream codec check / bounce: |
|---|
| 63 | Client sends: |
|---|
| 64 | First byte z or Z |
|---|
| 65 | Lots of data that should not be decoded |
|---|
| 66 | Server replies: |
|---|
| 67 | The requested domain copied raw, in the lowest-grade downstream codec |
|---|
| 68 | available for the request type. |
|---|
| 69 | |
|---|
| 70 | Downstream codec check: |
|---|
| 71 | Client sends: |
|---|
| 72 | First byte y or Y |
|---|
| 73 | 1 char, meaning downstream codec to use |
|---|
| 74 | 5 bits coded as Base32 char, meaning check variant |
|---|
| 75 | CMC as 3 Base32 chars |
|---|
| 76 | Possibly extra data, depending on check variant |
|---|
| 77 | Server sends: |
|---|
| 78 | Data encoded with requested downstream codec; data content depending |
|---|
| 79 | on check variant number. |
|---|
| 80 | BADCODEC if requested downstream codec not available. |
|---|
| 81 | BADLEN if check variant is not available, or problem with extra data. |
|---|
| 82 | |
|---|
| 83 | Downstream codec chars are same as in 'O' Option request, below. |
|---|
| 84 | |
|---|
| 85 | Check variants: |
|---|
| 86 | 1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h |
|---|
| 87 | |
|---|
| 88 | (Other variants reserved; possibly variant that sends a decoded-encoded |
|---|
| 89 | copy of Base32-encoded extra data in the request) |
|---|
| 90 | |
|---|
| 91 | Switch codec: |
|---|
| 92 | Client sends: |
|---|
| 93 | First byte s or S |
|---|
| 94 | 5 bits coded as Base32 char, meaning userid |
|---|
| 95 | 5 bits coded as Base32 char, representing number of raw bits per |
|---|
| 96 | encoded byte: |
|---|
| 97 | 5: Base32 (a-z0-5) |
|---|
| 98 | 6: Base64 (a-zA-Z0-9+-) |
|---|
| 99 | 26: Base64u (a-zA-Z0-9_-) |
|---|
| 100 | 7: Base128 (a-zA-Z0-9\274-\375) |
|---|
| 101 | CMC as 3 Base32 chars |
|---|
| 102 | Server sends: |
|---|
| 103 | Name of codec if accepted. After this all upstream data packets must |
|---|
| 104 | be encoded with the new codec. |
|---|
| 105 | BADCODEC if not accepted. Client must then revert to previous codec |
|---|
| 106 | BADLEN if length of query is too short |
|---|
| 107 | |
|---|
| 108 | Options: |
|---|
| 109 | Client sends: |
|---|
| 110 | First byte o or O |
|---|
| 111 | 5 bits coded as Base32 char, meaning userid |
|---|
| 112 | 1 char, meaning option |
|---|
| 113 | CMC as 3 Base32 chars |
|---|
| 114 | Server sends: |
|---|
| 115 | Full name of option if accepted. After this, option immediately takes |
|---|
| 116 | effect in server. |
|---|
| 117 | BADCODEC if not accepted. Previous situation remains. |
|---|
| 118 | All options affect only the requesting client. |
|---|
| 119 | |
|---|
| 120 | Option chars: |
|---|
| 121 | t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default) |
|---|
| 122 | s or S: Downstream encoding Base64, for TXT/CNAME/A/MX |
|---|
| 123 | u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX |
|---|
| 124 | v or V: Downstream encoding Base128, for TXT/CNAME/A/MX |
|---|
| 125 | r or R: Downstream encoding Raw, for TXT/NULL (default for NULL) |
|---|
| 126 | If codec unsupported for request type, server will use Base32; note |
|---|
| 127 | that server will answer any mix of request types that a client sends. |
|---|
| 128 | Server may disregard this option; client must always use the downstream |
|---|
| 129 | encoding type indicated in every downstream DNS packet. |
|---|
| 130 | |
|---|
| 131 | l or L: Lazy mode, server will keep one request unanswered until the |
|---|
| 132 | next one comes in. Applies only to data transfer; handshake is always |
|---|
| 133 | answered immediately. |
|---|
| 134 | i or I: Immediate (non-lazy) mode, server will answer all requests |
|---|
| 135 | (nearly) immediately. |
|---|
| 136 | |
|---|
| 137 | Probe downstream fragment size: |
|---|
| 138 | Client sends: |
|---|
| 139 | First byte r or R |
|---|
| 140 | 15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF |
|---|
| 141 | meaning 4 bits userid, 11 bits fragment size |
|---|
| 142 | Then follows a long random query which contents does not matter |
|---|
| 143 | Server sends: |
|---|
| 144 | Requested number of bytes as a response. The first two bytes contain |
|---|
| 145 | the requested length. The third byte is 107 (0x6B). The fourth byte |
|---|
| 146 | is a random value, and each following byte is incremented with 107. |
|---|
| 147 | This is checked by the client to determine corruption. |
|---|
| 148 | BADFRAG if requested length not accepted. |
|---|
| 149 | |
|---|
| 150 | Set downstream fragment size: |
|---|
| 151 | Client sends: |
|---|
| 152 | First byte n or N |
|---|
| 153 | Rest encoded with base32: |
|---|
| 154 | 1 byte userid |
|---|
| 155 | 2 bytes new downstream fragment size |
|---|
| 156 | CMC |
|---|
| 157 | Server sends: |
|---|
| 158 | 2 bytes new downstream fragment size. After this all downstream |
|---|
| 159 | payloads will be max (fragsize + 2) bytes long. |
|---|
| 160 | BADFRAG if not accepted. |
|---|
| 161 | |
|---|
| 162 | Data: |
|---|
| 163 | Upstream data header: |
|---|
| 164 | 3210 432 10 43 210 4321 0 43210 |
|---|
| 165 | +----+---+--+--+---+----+-+-----+ |
|---|
| 166 | |UUUU|SSS|FF|FF|DDD|GGGG|L|UDCMC| |
|---|
| 167 | +----+---+--+--+---+----+-+-----+ |
|---|
| 168 | |
|---|
| 169 | Downstream data header: |
|---|
| 170 | 7 654 3210 765 4321 0 |
|---|
| 171 | +-+---+----+---+----+-+ |
|---|
| 172 | |C|SSS|FFFF|DDD|GGGG|L| |
|---|
| 173 | +-+---+----+---+----+-+ |
|---|
| 174 | |
|---|
| 175 | UUUU = Userid |
|---|
| 176 | L = Last fragment in packet flag |
|---|
| 177 | SS = Upstream packet sequence number |
|---|
| 178 | FFFF = Upstream fragment number |
|---|
| 179 | DDD = Downstream packet sequence number |
|---|
| 180 | GGGG = Downstream fragment number |
|---|
| 181 | C = Compression enabled for downstream packet |
|---|
| 182 | UDCMC = Upstream Data CMC, 36 steps a-z0-9, case-insensitive |
|---|
| 183 | |
|---|
| 184 | Upstream data packet starts with 1 byte ASCII hex coded user byte; then 3 bytes |
|---|
| 185 | Base32 encoded header; then 1 char data-CMC; then comes the payload data, |
|---|
| 186 | encoded with the chosen upstream codec. |
|---|
| 187 | |
|---|
| 188 | Downstream data starts with 2 byte header. Then payload data, which may be |
|---|
| 189 | compressed. |
|---|
| 190 | |
|---|
| 191 | In NULL responses, downstream data is always raw. In all other response types, |
|---|
| 192 | downstream data is encoded (see Options above). |
|---|
| 193 | Encoding type is indicated by 1 prefix char: |
|---|
| 194 | TXT: |
|---|
| 195 | End result is always DNS-chopped (series of len-prefixed strings |
|---|
| 196 | <=255 bytes) |
|---|
| 197 | t or T: Base32 encoded before chop, decoded after un-chop |
|---|
| 198 | s or S: Base64 encoded before chop, decoded after un-chop |
|---|
| 199 | u or U: Base64u encoded before chop, decoded after un-chop |
|---|
| 200 | v or V: Base128 encoded before chop, decoded after un-chop |
|---|
| 201 | r or R: Raw no encoding, only DNS-chop |
|---|
| 202 | SRV/MX/CNAME/A: |
|---|
| 203 | h or H: Hostname encoded with Base32 |
|---|
| 204 | i or I: Hostname encoded with Base64 |
|---|
| 205 | j or J: Hostname encoded with Base64u |
|---|
| 206 | k or K: Hostname encoded with Base128 |
|---|
| 207 | SRV and MX may reply with multiple hostnames, each encoded separately. Each |
|---|
| 208 | has a 10-multiple priority, and encoding/decoding is done in strictly |
|---|
| 209 | increasing priority sequence 10, 20, 30, etc. without gaps. Note that some DNS |
|---|
| 210 | relays will shuffle the answer records in the response. |
|---|
| 211 | |
|---|
| 212 | Ping: |
|---|
| 213 | Client sends: |
|---|
| 214 | First byte p or P |
|---|
| 215 | Rest encoded with Base32: |
|---|
| 216 | 1 byte with 4 bits userid |
|---|
| 217 | 1 byte with: |
|---|
| 218 | 3 bits downstream seqno |
|---|
| 219 | 4 bits downstream fragment |
|---|
| 220 | CMC |
|---|
| 221 | |
|---|
| 222 | The server response to Ping and Data packets is a DNS NULL/TXT/.. type response, |
|---|
| 223 | always starting with the 2 bytes downstream data header as shown above. |
|---|
| 224 | If server has nothing to send, no data is added after the header. |
|---|
| 225 | If server has something to send, it will add the downstream data packet |
|---|
| 226 | (or some fragment of it) after the header. |
|---|
| 227 | |
|---|
| 228 | |
|---|
| 229 | "Lazy-mode" operation |
|---|
| 230 | ===================== |
|---|
| 231 | |
|---|
| 232 | Client-server DNS traffic sequence has been reordered to provide increased |
|---|
| 233 | (interactive) performance and greatly reduced latency. |
|---|
| 234 | |
|---|
| 235 | Idea taken from Lucas Nussbaum's slides (24th IFIP International Security |
|---|
| 236 | Conference, 2009) at http://www.loria.fr/~lnussbau/tuns.html. Current |
|---|
| 237 | implementation is original to iodine, no code or documentation from any other |
|---|
| 238 | project was consulted during development. |
|---|
| 239 | |
|---|
| 240 | Server: |
|---|
| 241 | Upstream data is acked immediately*, to keep the slow upstream data flowing |
|---|
| 242 | as fast as possible (client waits for ack to send next frag). |
|---|
| 243 | |
|---|
| 244 | Upstream pings are answered _only_ when 1) downstream data arrives from tun, |
|---|
| 245 | OR 2) new upstream ping/data arrives from client. |
|---|
| 246 | In most cases, this means we answer the previous DNS query instead of the |
|---|
| 247 | current one. The current query is kept in queue and used as soon as |
|---|
| 248 | downstream data has to be sent. |
|---|
| 249 | |
|---|
| 250 | *: upstream data ack is usually done as reply on the previous ping packet, |
|---|
| 251 | and the upstream-data packet itself is kept in queue. |
|---|
| 252 | |
|---|
| 253 | Client: |
|---|
| 254 | Downstream data is acked immediately, to keep it flowing fast (includes a |
|---|
| 255 | ping after last downstream frag). |
|---|
| 256 | |
|---|
| 257 | Also, after all available upstream data is sent & acked by the server (which |
|---|
| 258 | in some cases uses up the last query), send an additional ping to prime the |
|---|
| 259 | server for the next downstream data. |
|---|
| 260 | |
|---|
| 261 | |
|---|
| 262 | ====================================================== |
|---|
| 263 | 2. Raw UDP protocol |
|---|
| 264 | ====================================================== |
|---|
| 265 | |
|---|
| 266 | All Raw UDP protcol messages start with a 3 byte header: 0x10d19e |
|---|
| 267 | This is not the start of a valid DNS message so it is easy to identify. |
|---|
| 268 | The fourth byte contains the command and the user id. |
|---|
| 269 | |
|---|
| 270 | 7654 3210 |
|---|
| 271 | +----+----+ |
|---|
| 272 | |CCCC|UUUU| |
|---|
| 273 | +----+----+ |
|---|
| 274 | |
|---|
| 275 | Login message (command = 1): |
|---|
| 276 | The header is followed by a MD5 hash with the same password as in the DNS |
|---|
| 277 | login. The client starts the raw mode by sending this message, and uses |
|---|
| 278 | the login challenge +1, and the server responds using the login challenge -1. |
|---|
| 279 | After the login message has been exchanged, both the server and the client |
|---|
| 280 | switch to raw udp mode for the rest of the connection. |
|---|
| 281 | |
|---|
| 282 | Data message (command = 2): |
|---|
| 283 | After the header comes the payload data, which may be compressed. |
|---|
| 284 | |
|---|
| 285 | Ping message (command = 3): |
|---|
| 286 | Sent from client to server and back to keep session open. Has no payload. |
|---|
| 287 | |
|---|