mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-25 11:05:15 +00:00
Modified options packet to change more than 1 option at a time
This commit is contained in:
parent
4f16dd10e6
commit
e454a7edb5
@ -111,12 +111,14 @@ Options:
|
|||||||
Client sends:
|
Client sends:
|
||||||
First byte o or O
|
First byte o or O
|
||||||
5 bits coded as Base32 char, meaning userid
|
5 bits coded as Base32 char, meaning userid
|
||||||
1 char, meaning option
|
number of options (n) as decimal digit
|
||||||
|
n chars, each a valid option (to be processed in order)
|
||||||
CMC as 3 Base32 chars
|
CMC as 3 Base32 chars
|
||||||
Server sends:
|
Server sends:
|
||||||
Full name of option if accepted. After this, option immediately takes
|
Option chars in the same order as request, indicating that options were
|
||||||
effect in server.
|
accepted by the server.
|
||||||
BADCODEC if not accepted. Previous situation remains.
|
BADCODEC if not accepted. Previous situation remains.
|
||||||
|
BADLEN if number of options doesn't match length of query.
|
||||||
All options affect only the requesting client.
|
All options affect only the requesting client.
|
||||||
|
|
||||||
Option chars:
|
Option chars:
|
||||||
|
229
src/client.c
229
src/client.c
@ -474,7 +474,7 @@ send_query(int fd, uint8_t *hostname)
|
|||||||
" always work any more. Start with -L0 next time on this network.");
|
" always work any more. Start with -L0 next time on this network.");
|
||||||
lazymode = 0;
|
lazymode = 0;
|
||||||
server_timeout_ms = 0;
|
server_timeout_ms = 0;
|
||||||
handshake_lazyoff(fd);
|
handshake_switch_options(fd, 0, compression_down, downenc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1455,51 +1455,21 @@ send_codec_switch(int fd, int userid, int bits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_compression_switch(int fd, int userid)
|
send_server_options(int fd, int userid, int lazy, int compression, char denc, char *options)
|
||||||
|
/* Options must be length >=4 */
|
||||||
{
|
{
|
||||||
char buf[512] = "o_____.";
|
char buf[512] = "oU3___CMC.";
|
||||||
buf[1] = b32_5to8(userid);
|
|
||||||
buf[2] = compression_down ? 'c' : 'd';
|
|
||||||
|
|
||||||
buf[3] = b32_5to8((rand_seed >> 10) & 0x1f);
|
|
||||||
buf[4] = b32_5to8((rand_seed >> 5) & 0x1f);
|
|
||||||
buf[5] = b32_5to8((rand_seed) & 0x1f);
|
|
||||||
rand_seed++;
|
|
||||||
|
|
||||||
strncat(buf, topdomain, 512 - strlen(buf));
|
|
||||||
send_query(fd, (uint8_t *)buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
send_downenc_switch(int fd, int userid)
|
|
||||||
{
|
|
||||||
char buf[512] = "o_____.";
|
|
||||||
buf[1] = b32_5to8(userid);
|
|
||||||
buf[2] = tolower(downenc);
|
|
||||||
|
|
||||||
buf[3] = b32_5to8((rand_seed >> 10) & 0x1f);
|
|
||||||
buf[4] = b32_5to8((rand_seed >> 5) & 0x1f);
|
|
||||||
buf[5] = b32_5to8((rand_seed) & 0x1f);
|
|
||||||
rand_seed++;
|
|
||||||
|
|
||||||
strncat(buf, topdomain, 512 - strlen(buf));
|
|
||||||
send_query(fd, (uint8_t *)buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
send_lazy_switch(int fd, int userid)
|
|
||||||
{
|
|
||||||
char buf[512] = "o_____.";
|
|
||||||
buf[1] = b32_5to8(userid);
|
buf[1] = b32_5to8(userid);
|
||||||
|
|
||||||
if (lazymode)
|
options[0] = tolower(denc);
|
||||||
buf[2] = 'l';
|
options[1] = lazy ? 'l' : 'i';
|
||||||
else
|
options[2] = compression ? 'c' : 'd';
|
||||||
buf[2] = 'i';
|
options[3] = 0;
|
||||||
|
strncpy(buf + 3, options, 3);
|
||||||
|
|
||||||
buf[3] = b32_5to8((rand_seed >> 10) & 0x1f);
|
buf[6] = b32_5to8((rand_seed >> 10) & 0x1f);
|
||||||
buf[4] = b32_5to8((rand_seed >> 5) & 0x1f);
|
buf[7] = b32_5to8((rand_seed >> 5) & 0x1f);
|
||||||
buf[5] = b32_5to8((rand_seed ) & 0x1f);
|
buf[8] = b32_5to8((rand_seed) & 0x1f);
|
||||||
rand_seed++;
|
rand_seed++;
|
||||||
|
|
||||||
strncat(buf, topdomain, 512 - strlen(buf));
|
strncat(buf, topdomain, 512 - strlen(buf));
|
||||||
@ -2185,87 +2155,54 @@ codec_revert:
|
|||||||
fprintf(stderr, "Falling back to upstream codec %s\n", dataenc->name);
|
fprintf(stderr, "Falling back to upstream codec %s\n", dataenc->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
handshake_switch_downcompression(int dns_fd)
|
handshake_switch_options(int dns_fd, int lazy, int compression, char denc)
|
||||||
{
|
{
|
||||||
char in[4096];
|
char in[4096];
|
||||||
int i;
|
|
||||||
int read;
|
int read;
|
||||||
char *status;
|
char *dname, *comp_status, *lazy_status;
|
||||||
|
char opts[4];
|
||||||
|
|
||||||
status = compression_down ? "on" : "off";
|
comp_status = compression ? "enabled" : "disabled";
|
||||||
fprintf(stderr, "Switching %s downstream data compression\n", status);
|
|
||||||
for (i = 0; running && i < 5; i++) {
|
|
||||||
|
|
||||||
send_compression_switch(dns_fd, userid);
|
|
||||||
|
|
||||||
read = handshake_waitdns(dns_fd, in, sizeof(in), 'O', i+1);
|
|
||||||
|
|
||||||
if (read > 0) {
|
|
||||||
if (strncmp("BADLEN", in, 6) == 0) {
|
|
||||||
fprintf(stderr, "Server got bad message length.\n");
|
|
||||||
goto fail;
|
|
||||||
} else if (strncmp("BADIP", in, 5) == 0) {
|
|
||||||
fprintf(stderr, "Server rejected sender IP address.\n");
|
|
||||||
goto fail;
|
|
||||||
} else if (strncmp("BADCODEC", in, 8) == 0) {
|
|
||||||
fprintf(stderr, "Server rejected the compression option.\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
in[read] = 0; /* zero terminate */
|
|
||||||
fprintf(stderr, "Server %s downstream compression\n", in);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Retrying downstream compression switch...\n");
|
|
||||||
}
|
|
||||||
if (!running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fprintf(stderr, "No reply from server on downstream compression switch.\n");
|
|
||||||
|
|
||||||
fail:
|
|
||||||
fprintf(stderr, "Failed to switch %s downstream data compression\n", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handshake_switch_downenc(int dns_fd)
|
|
||||||
{
|
|
||||||
char in[4096];
|
|
||||||
int i;
|
|
||||||
int read;
|
|
||||||
char *dname;
|
|
||||||
|
|
||||||
dname = "Base32";
|
dname = "Base32";
|
||||||
if (downenc == 'S')
|
if (denc == 'S')
|
||||||
dname = "Base64";
|
dname = "Base64";
|
||||||
else if (downenc == 'U')
|
else if (denc == 'U')
|
||||||
dname = "Base64u";
|
dname = "Base64u";
|
||||||
else if (downenc == 'V')
|
else if (denc == 'V')
|
||||||
dname = "Base128";
|
dname = "Base128";
|
||||||
else if (downenc == 'R')
|
else if (denc == 'R')
|
||||||
dname = "Raw";
|
dname = "Raw";
|
||||||
|
|
||||||
fprintf(stderr, "Switching downstream to codec %s\n", dname);
|
lazy_status = lazy ? "lazy" : "immediate";
|
||||||
for (i=0; running && i<5 ;i++) {
|
|
||||||
|
|
||||||
send_downenc_switch(dns_fd, userid);
|
fprintf(stderr, "Switching server options: %s mode, downstream codec %s, compression %s...\n",
|
||||||
|
lazy_status, dname, comp_status);
|
||||||
|
for (int i = 0; running && i < 5; i++) {
|
||||||
|
|
||||||
read = handshake_waitdns(dns_fd, in, sizeof(in), 'O', i+1);
|
send_server_options(dns_fd, userid, lazy, compression, denc, opts);
|
||||||
|
|
||||||
|
read = handshake_waitdns(dns_fd, in, sizeof(in) - 1, 'O', i + 1);
|
||||||
|
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
if (strncmp("BADLEN", in, 6) == 0) {
|
if (strncmp("BADLEN", in, 6) == 0) {
|
||||||
fprintf(stderr, "Server got bad message length.\n");
|
fprintf(stderr, "Server got bad message length.\n");
|
||||||
goto codec_revert;
|
goto opt_revert;
|
||||||
} else if (strncmp("BADIP", in, 5) == 0) {
|
} else if (strncmp("BADIP", in, 5) == 0) {
|
||||||
fprintf(stderr, "Server rejected sender IP address.\n");
|
fprintf(stderr, "Server rejected sender IP address.\n");
|
||||||
goto codec_revert;
|
goto opt_revert;
|
||||||
} else if (strncmp("BADCODEC", in, 8) == 0) {
|
} else if (strncmp("BADCODEC", in, 8) == 0) {
|
||||||
fprintf(stderr, "Server rejected the selected codec.\n");
|
fprintf(stderr, "Server rejected the selected options.\n");
|
||||||
goto codec_revert;
|
goto opt_revert;
|
||||||
|
} else if (strncasecmp(opts, in + 3, 3) != 0) {
|
||||||
|
fprintf(stderr, "Server failed to change options.\n");
|
||||||
|
goto opt_revert;
|
||||||
}
|
}
|
||||||
in[read] = 0; /* zero terminate */
|
fprintf(stderr, "Switched server options successfully. (%s)\n", opts);
|
||||||
fprintf(stderr, "Server switched downstream to codec %s\n", in);
|
lazymode = lazy;
|
||||||
|
compression_down = compression;
|
||||||
|
downenc = denc;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2276,79 +2213,9 @@ handshake_switch_downenc(int dns_fd)
|
|||||||
|
|
||||||
fprintf(stderr, "No reply from server on codec switch.\n");
|
fprintf(stderr, "No reply from server on codec switch.\n");
|
||||||
|
|
||||||
codec_revert:
|
opt_revert:
|
||||||
fprintf(stderr, "Falling back to downstream codec Base32\n");
|
fprintf(stderr, "Falling back to previous configuration, downstream codec %s.\n",
|
||||||
}
|
dataenc->name);
|
||||||
|
|
||||||
static void
|
|
||||||
handshake_try_lazy(int dns_fd)
|
|
||||||
{
|
|
||||||
char in[4096];
|
|
||||||
int i;
|
|
||||||
int read;
|
|
||||||
|
|
||||||
fprintf(stderr, "Switching to lazy mode for low-latency\n");
|
|
||||||
for (i=0; running && i<5; i++) {
|
|
||||||
|
|
||||||
send_lazy_switch(dns_fd, userid);
|
|
||||||
|
|
||||||
read = handshake_waitdns(dns_fd, in, sizeof(in), 'O', i+1);
|
|
||||||
|
|
||||||
if (read > 0) {
|
|
||||||
if (strncmp("BADLEN", in, 6) == 0) {
|
|
||||||
fprintf(stderr, "Server got bad message length.\n");
|
|
||||||
goto codec_revert;
|
|
||||||
} else if (strncmp("BADIP", in, 5) == 0) {
|
|
||||||
fprintf(stderr, "Server rejected sender IP address.\n");
|
|
||||||
goto codec_revert;
|
|
||||||
} else if (strncmp("BADCODEC", in, 8) == 0) {
|
|
||||||
fprintf(stderr, "Server rejected lazy mode.\n");
|
|
||||||
goto codec_revert;
|
|
||||||
} else if (strncmp("Lazy", in, 4) == 0) {
|
|
||||||
fprintf(stderr, "Server switched to lazy mode\n");
|
|
||||||
lazymode = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Retrying lazy mode switch...\n");
|
|
||||||
}
|
|
||||||
if (!running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fprintf(stderr, "No reply from server on lazy switch.\n");
|
|
||||||
|
|
||||||
codec_revert:
|
|
||||||
fprintf(stderr, "Falling back to legacy mode\n");
|
|
||||||
lazymode = 0;
|
|
||||||
max_timeout_ms = 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
handshake_lazyoff(int dns_fd)
|
|
||||||
/* Used in the middle of data transfer, timing is different and no error msgs */
|
|
||||||
{
|
|
||||||
char in[4096];
|
|
||||||
int i;
|
|
||||||
int read;
|
|
||||||
|
|
||||||
for (i=0; running && i<5; i++) {
|
|
||||||
|
|
||||||
send_lazy_switch(dns_fd, userid);
|
|
||||||
|
|
||||||
read = handshake_waitdns(dns_fd, in, sizeof(in), 'O', 1);
|
|
||||||
|
|
||||||
if (read == 9 && strncmp("Immediate", in, 9) == 0) {
|
|
||||||
warnx("Server switched back to legacy mode.");
|
|
||||||
lazymode = 0;
|
|
||||||
max_timeout_ms = 1000;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
warnx("No reply from server on legacy mode switch.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2600,16 +2467,8 @@ client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsiz
|
|||||||
if (!running)
|
if (!running)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
handshake_switch_downenc(dns_fd);
|
/* Set options for compression, lazymode and downstream codec */
|
||||||
if (!running)
|
handshake_switch_options(dns_fd, lazymode, compression_down, downenc);
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!compression_down)
|
|
||||||
handshake_switch_downcompression(dns_fd);
|
|
||||||
|
|
||||||
if (lazymode) {
|
|
||||||
handshake_try_lazy(dns_fd);
|
|
||||||
}
|
|
||||||
if (!running)
|
if (!running)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ void client_set_hostname_maxlen(size_t i);
|
|||||||
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize);
|
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize);
|
||||||
int client_tunnel(int tun_fd, int dns_fd);
|
int client_tunnel(int tun_fd, int dns_fd);
|
||||||
|
|
||||||
void handshake_lazyoff(int dns_fd);
|
void handshake_switch_options(int dns_fd, int lazy, int compression, char denc);
|
||||||
void send_ping(int fd, int ping_response, int ack);
|
void send_ping(int fd, int ping_response, int ack);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
68
src/server.c
68
src/server.c
@ -1388,7 +1388,12 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if(in[0] == 'O' || in[0] == 'o') { /* Protocol options */
|
} else if(in[0] == 'O' || in[0] == 'o') { /* Protocol options */
|
||||||
if (domain_len < 3) { /* len at least 3, example: "O1T" */
|
int bits = 0;
|
||||||
|
int numopts;
|
||||||
|
char num[2], *opts;
|
||||||
|
|
||||||
|
int tmp_lazy, tmp_downenc, tmp_comp;
|
||||||
|
if (domain_len < 7) { /* len at least 7, example: "oa1tcmc" */
|
||||||
write_dns(dns_fd, q, "BADLEN", 6, 'T');
|
write_dns(dns_fd, q, "BADLEN", 6, 'T');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1400,59 +1405,67 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
return; /* illegal id */
|
return; /* illegal id */
|
||||||
}
|
}
|
||||||
|
|
||||||
int bits = 0;
|
num[0] = in[2];
|
||||||
switch (toupper(in[2])) {
|
num[1] = 0;
|
||||||
|
numopts = atoi(num);
|
||||||
|
|
||||||
|
if (domain_len != numopts + 6 || numopts == 0) {
|
||||||
|
write_dns(dns_fd, q, "BADLEN", 6, 'T');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Temporary variables: don't change anything until all options parsed */
|
||||||
|
tmp_lazy = users[userid].lazy;
|
||||||
|
tmp_comp = users[userid].down_compression;
|
||||||
|
tmp_downenc = users[userid].downenc;
|
||||||
|
|
||||||
|
opts = (char *) in + 3;
|
||||||
|
|
||||||
|
for (int i = 0; i < numopts; i++) {
|
||||||
|
switch (toupper(opts[i])) {
|
||||||
case 'T':
|
case 'T':
|
||||||
users[userid].downenc = 'T';
|
tmp_downenc = 'T';
|
||||||
write_dns(dns_fd, q, "Base32", 6, users[userid].downenc);
|
|
||||||
bits = 5;
|
bits = 5;
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
users[userid].downenc = 'S';
|
tmp_downenc = 'S';
|
||||||
write_dns(dns_fd, q, "Base64", 6, users[userid].downenc);
|
|
||||||
bits = 6;
|
bits = 6;
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
users[userid].downenc = 'U';
|
tmp_downenc = 'U';
|
||||||
write_dns(dns_fd, q, "Base64u", 7, users[userid].downenc);
|
|
||||||
bits = 6;
|
bits = 6;
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
users[userid].downenc = 'V';
|
tmp_downenc = 'V';
|
||||||
write_dns(dns_fd, q, "Base128", 7, users[userid].downenc);
|
|
||||||
bits = 7;
|
bits = 7;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
users[userid].downenc = 'R';
|
tmp_downenc = 'R';
|
||||||
write_dns(dns_fd, q, "Raw", 3, users[userid].downenc);
|
|
||||||
bits = 8;
|
bits = 8;
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
users[userid].lazy = 1;
|
tmp_lazy = 1;
|
||||||
write_dns(dns_fd, q, "Lazy", 4, users[userid].downenc);
|
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
users[userid].lazy = 0;
|
tmp_lazy = 0;
|
||||||
write_dns(dns_fd, q, "Immediate", 9, users[userid].downenc);
|
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
users[userid].down_compression = 1;
|
tmp_comp = 1;
|
||||||
write_dns(dns_fd, q, "Enabled", 7, users[userid].downenc);
|
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
users[userid].down_compression = 0;
|
tmp_comp = 0;
|
||||||
write_dns(dns_fd, q, "Disabled", 8, users[userid].downenc);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
write_dns(dns_fd, q, "BADCODEC", 8, users[userid].downenc);
|
write_dns(dns_fd, q, "BADCODEC", 8, users[userid].downenc);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Automatically switch to raw encoding if PRIVATE or NULL request */
|
/* Automatically switch to raw encoding if PRIVATE or NULL request */
|
||||||
if (q->type == T_NULL || q->type == T_PRIVATE) {
|
if ((q->type == T_NULL || q->type == T_PRIVATE) && !bits) {
|
||||||
users[userid].downenc = 'R';
|
users[userid].downenc = 'R';
|
||||||
bits = 8;
|
bits = 8;
|
||||||
if (debug >= 3)
|
if (debug >= 3)
|
||||||
warnx("Assuming raw data encoding due to NULL/PRIVATE requests for user %d.", userid);
|
warnx("Assuming raw data encoding with NULL/PRIVATE requests for user %d.", userid);
|
||||||
}
|
}
|
||||||
if (bits) {
|
if (bits) {
|
||||||
int f = users[userid].fragsize;
|
int f = users[userid].fragsize;
|
||||||
@ -1462,6 +1475,13 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
users[userid].outgoing->maxfraglen, userid, bits, users[userid].downenc);
|
users[userid].outgoing->maxfraglen, userid, bits, users[userid].downenc);
|
||||||
users[userid].downenc_bits = bits;
|
users[userid].downenc_bits = bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store any changes */
|
||||||
|
users[userid].down_compression = tmp_comp;
|
||||||
|
users[userid].downenc = tmp_downenc;
|
||||||
|
users[userid].lazy = tmp_lazy;
|
||||||
|
|
||||||
|
write_dns(dns_fd, q, opts, numopts, users[userid].downenc);
|
||||||
return;
|
return;
|
||||||
} else if(in[0] == 'Y' || in[0] == 'y') { /* Downstream codec check */
|
} else if(in[0] == 'Y' || in[0] == 'y') { /* Downstream codec check */
|
||||||
int i;
|
int i;
|
||||||
|
Loading…
Reference in New Issue
Block a user