diff --git a/doc/proto_00000800.txt b/doc/proto_00000800.txt new file mode 100644 index 0000000..2b5a8b7 --- /dev/null +++ b/doc/proto_00000800.txt @@ -0,0 +1,305 @@ +Detailed specification of protocol in version 00000800 +====================================================== + +Note: work in progress!! + +====================================================== +1. DNS protocol +====================================================== + +Quick alphabetical index / register: + 0-9 Data packet + A-F Data packet + I IP address + L Login + N Downstream fragsize (NS.topdomain A-type reply) + O Options + P Ping + R Downstream fragsize probe + S Switch upstream codec + V Version + W (WWW.topdomain A-type reply) + Y Downstream codec check + Z Upstream codec check + + +CMC = 2 byte Cache Miss Counter, increased every time it is used + +Version: +Client sends: + First byte v or V + Rest encoded with base32: + 4 bytes big endian protocol version + CMC +Server replies: + 4 chars: + VACK (version ok), followed by login challenge + VNAK (version differs), followed by server protocol version + VFUL (server has no free slots), followed by max users + 4 byte value: means login challenge/server protocol version/max users + 1 byte userid of the new user, or any byte if not VACK + +Login: +Client sends: + First byte l or L + Rest encoded with base32: + 1 byte userid + 16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge) + CMC +Server replies: + LNAK means not accepted + x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits) + +IP Request: (for where to try raw login or set data pipe mode) +Client sends: + First byte i or I + 5 bits coded as Base32 char, meaning userid + CMC as 3 Base32 chars +Server replies + BADIP if bad userid + First byte I + Then comes external IP address of iodined server + as 4 bytes (IPv4) or 16 bytes (IPv6) + +Upstream codec check / bounce: +Client sends: + First byte z or Z + Lots of data that should not be decoded +Server replies: + The requested domain copied raw, in the lowest-grade downstream codec + available for the request type. + +Downstream codec check: +Client sends: + First byte y or Y + 1 char, meaning downstream codec to use + 5 bits coded as Base32 char, meaning check variant + CMC as 3 Base32 chars + Possibly extra data, depending on check variant +Server sends: + Data encoded with requested downstream codec; data content depending + on check variant number. + BADCODEC if requested downstream codec not available. + BADLEN if check variant is not available, or problem with extra data. + + Downstream codec chars are same as in 'O' Option request, below. + + Check variants: + 1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h + + (Other variants reserved; possibly variant that sends a decoded-encoded + copy of Base32-encoded extra data in the request) + +Switch codec: +Client sends: + First byte s or S + 5 bits coded as Base32 char, meaning userid + 5 bits coded as Base32 char, representing number of raw bits per + encoded byte: + 5: Base32 (a-z0-5) + 6: Base64 (a-zA-Z0-9+-) + 26: Base64u (a-zA-Z0-9_-) + 7: Base128 (a-zA-Z0-9\274-\375) + CMC as 3 Base32 chars +Server sends: + Name of codec if accepted. After this all upstream data packets must + be encoded with the new codec. + BADCODEC if not accepted. Client must then revert to previous codec + BADLEN if length of query is too short + +Options: +Client sends: + First byte o or O + 5 bits coded as Base32 char, meaning userid + 1 char, meaning option + CMC as 3 Base32 chars +Server sends: + Full name of option if accepted. After this, option immediately takes + effect in server. + BADCODEC if not accepted. Previous situation remains. + All options affect only the requesting client. + + Option chars: + t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default) + s or S: Downstream encoding Base64, for TXT/CNAME/A/MX + u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX + v or V: Downstream encoding Base128, for TXT/CNAME/A/MX + r or R: Downstream encoding Raw, for PRIVATE/TXT/NULL (default for + PRIVATE and NULL) + If codec unsupported for request type, server will use Base32; note + that server will answer any mix of request types that a client sends. + Server may disregard this option; client must always use the downstream + encoding type indicated in every downstream DNS packet. + + l or L: Lazy mode, server will keep one request unanswered until the + next one comes in. Applies only to data transfer; handshake is always + answered immediately. + i or I: Immediate (non-lazy) mode, server will answer all requests + (nearly) immediately. + +Probe downstream fragment size: +Client sends: + First byte r or R + 15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF + meaning 4 bits userid, 11 bits fragment size + Then follows a long random query which contents does not matter +Server sends: + Requested number of bytes as a response. The first two bytes contain + the requested length. The third byte is 107 (0x6B). The fourth byte + is a random value, and each following byte is incremented with 107. + This is checked by the client to determine corruption. + BADFRAG if requested length not accepted. + +Set downstream fragment size: +Client sends: + First byte n or N + Rest encoded with base32: + 1 byte userid + 2 bytes new downstream fragment size + CMC +Server sends: + 2 bytes new downstream fragment size. After this all downstream + payloads will be max (fragsize + 2) bytes long. + BADFRAG if not accepted. + +Upstream data header: + 76543 21076 54321076 54321076 5432 + +!----+!----+!----!--+--!----!+----+ + |0UUUU|UDCMC|SSSSSSSS|DDDDDDDD|ANFL| + +-----+-----+--------+--------+----+ + +Downstream data header: |=> only if P(ing) bit set + 76543210 76543210 76543210 76543210 76543210 + +--------+--------+--------+--------+--------+ + |DDDDDDDD|SSSSSSSS|00PCANFL|ZZZZZZZZ|WWWWWWWW| + +--------+--------+--------+--------+--------+ + +UUUU = Userid +L = Last fragment flag +A = ACK flag +N = NACK flag (unused) +F = First fragment flag +C = Compression enabled for downstream packet +P = is ping response +SSSSSSSS = Upstream packet sequence number/ACK +DDDDDDDD = Downstream packet sequence number/ACK +ZZZZZZZZ = Downstream window size +WWWWWWWW = Upstream window size +UDCMC = Upstream Data CMC char (actually base36 [a-z0-9]), case-insensitive + +Upstream data packet starts with 1 byte ASCII hex coded user byte; then +1 char data-CMC; then 4 bytes Base32 encoded header; then comes the payload +data, encoded with the chosen upstream codec. + +Downstream data starts with 3 byte header. Then payload data, which may be +compressed. If Ping flag is set, another 8 bits of downstream window size and +8 bits of upstream window size are appended to the header and the downstream or +upstream sequence IDs are the start of the remote windows. This occurs either +when the server wants to re-sync its window parameters or when the client has +requested a ping response. + +In NULL and PRIVATE responses, downstream data is always raw. In all other +response types, downstream data is encoded (see Options above). +Encoding type is indicated by 1 prefix char: +TXT: + End result is always DNS-chopped (series of len-prefixed strings + <=255 bytes) + t or T: Base32 encoded before chop, decoded after un-chop + s or S: Base64 encoded before chop, decoded after un-chop + u or U: Base64u encoded before chop, decoded after un-chop + v or V: Base128 encoded before chop, decoded after un-chop + r or R: Raw no encoding, only DNS-chop +SRV/MX/CNAME/A: + h or H: Hostname encoded with Base32 + i or I: Hostname encoded with Base64 + j or J: Hostname encoded with Base64u + k or K: Hostname encoded with Base128 +SRV and MX may reply with multiple hostnames, each encoded separately. Each +has a 10-multiple priority, and encoding/decoding is done in strictly +increasing priority sequence 10, 20, 30, etc. without gaps. Note that some DNS +relays will shuffle the answer records in the response. + +Ping: +Client sends: + First byte p or P + Second byte CMC + Rest encoded with Base32: + 76543 21076543 21076543 21076543 21076543 210 + +!----+!----!--+--!----!+----!---+-!----!-+--------+ + |0UUUU|DDDDDDDD|SSSSSSSS|WWWWWWWW|ZZZZZZZZ|0000000R| + +-----+--------+--------+--------+--------+--------+ + 4 bits Userid + 1 byte Downstream seq ID of window start + 1 byte upStream seq ID of window start + 1 byte Window size (upstream) + 1 byte window siZe (downstream) + 1 byte "Respond with ping" flag + 2 bytes CMC + +The server response to Ping and Data packets is a DNS NULL/TXT/.. type response, +always starting with the 3 bytes downstream data header as shown above. If R bit +set, server must respond with a ping downstream header. +If server has nothing to send, no data is added after the header. +If server has something to send, it will add the downstream data packet +(or some fragment of it) after the header. + + +"Lazy-mode" operation +===================== + +Client-server DNS traffic sequence has been reordered to provide increased +(interactive) performance and greatly reduced latency. + +Idea taken from Lucas Nussbaum's slides (24th IFIP International Security +Conference, 2009) at http://www.loria.fr/~lnussbau/tuns.html. Current +implementation is original to iodine, no code or documentation from any other +project was consulted during development. + +Server: +Upstream data is acked immediately*, to keep the slow upstream data flowing +as fast as possible (client waits for ack to send next frag). + +Upstream pings are answered _only_ when 1) downstream data arrives from tun, +OR 2) new upstream ping/data arrives from client. +In most cases, this means we answer the previous DNS query instead of the +current one. The current query is kept in queue and used as soon as +downstream data has to be sent. + +*: upstream data ack is usually done as reply on the previous ping packet, +and the upstream-data packet itself is kept in queue. + +Client: +Downstream data is acked immediately, to keep it flowing fast (includes a +ping after last downstream frag). + +Also, after all available upstream data is sent & acked by the server (which +in some cases uses up the last query), send an additional ping to prime the +server for the next downstream data. + + +====================================================== +2. Raw UDP protocol +====================================================== + +All Raw UDP protcol messages start with a 3 byte header: 0x10d19e +This is not the start of a valid DNS message so it is easy to identify. +The fourth byte contains the command and the user id. + + 7654 3210 + +----+----+ + |CCCC|UUUU| + +----+----+ + +Login message (command = 1): +The header is followed by a MD5 hash with the same password as in the DNS +login. The client starts the raw mode by sending this message, and uses +the login challenge +1, and the server responds using the login challenge -1. +After the login message has been exchanged, both the server and the client +switch to raw udp mode for the rest of the connection. + +Data message (command = 2): +After the header comes the payload data, which may be compressed. + +Ping message (command = 3): +Sent from client to server and back to keep session open. Has no payload. + diff --git a/man/iodine.8 b/man/iodine.8 index 0eb9b9b..b394d90 100644 --- a/man/iodine.8 +++ b/man/iodine.8 @@ -36,10 +36,13 @@ iodine, iodined \- tunnel IPv4 over DNS .B ] [-I .I interval .B ] +.I topdomain .B [ .I nameserver -.B ] -.I topdomain +.B [ +.I nameserver2 +.B [...] ] ] + .B iodined [-v] diff --git a/src/version.h b/src/version.h index 5843a7a..440a7ba 100644 --- a/src/version.h +++ b/src/version.h @@ -20,7 +20,7 @@ /* This is the version of the network protocol It is usually equal to the latest iodine version number */ -#define PROTOCOL_VERSION 0x00000502 +#define PROTOCOL_VERSION 0x00000800 #endif /* _VERSION_H_ */