mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-28 20:45:12 +00:00
Updated docs + protocol description (800)
This commit is contained in:
parent
92f3963790
commit
0fcd8d337d
305
doc/proto_00000800.txt
Normal file
305
doc/proto_00000800.txt
Normal file
@ -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.
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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_ */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user