mirror of
https://github.com/hufrea/byedpi.git
synced 2024-11-24 15:55:31 +03:00
--redirect
This commit is contained in:
parent
69286c71db
commit
015095d2ef
6 changed files with 299 additions and 141 deletions
7
conev.h
7
conev.h
|
@ -35,12 +35,15 @@ enum eid {
|
|||
EV_IGNORE,
|
||||
EV_TUNNEL,
|
||||
EV_PRE_TUNNEL,
|
||||
EV_REDIRECT,
|
||||
EV_DESYNC
|
||||
};
|
||||
|
||||
#define FLAG_S4 1
|
||||
#define FLAG_S5 2
|
||||
#define FLAG_CONN 4
|
||||
#define FLAG_AUTH 8
|
||||
#define FLAG_ANSWER 16
|
||||
|
||||
#ifndef CONEV_H
|
||||
char *eid_name[] = {
|
||||
|
@ -50,6 +53,7 @@ char *eid_name[] = {
|
|||
"EV_IGNORE",
|
||||
"EV_TUNNEL",
|
||||
"EV_PRE_TUNNEL",
|
||||
"EV_REDIRECT",
|
||||
"EV_DESYNC"
|
||||
};
|
||||
#endif
|
||||
|
@ -72,8 +76,7 @@ struct eval {
|
|||
struct sockaddr_in6 in6;
|
||||
};
|
||||
ssize_t recv_count;
|
||||
int try_count;
|
||||
int saved_m;
|
||||
int attempt;
|
||||
#ifndef NOEPOLL
|
||||
uint32_t events;
|
||||
#endif
|
||||
|
|
6
desync.c
6
desync.c
|
@ -181,7 +181,9 @@ int desync(int sfd, char *buffer, size_t bfsize,
|
|||
ssize_t n, struct sockaddr *dst, int dp_c)
|
||||
{
|
||||
struct desync_params dp = params.dp[dp_c];
|
||||
|
||||
if (dp.redirect) {
|
||||
dst = (struct sockaddr *)&dp.ext_proxy;
|
||||
}
|
||||
char *host = 0;
|
||||
int len = 0, type = 0;
|
||||
int fa = get_family(dst);
|
||||
|
@ -296,7 +298,7 @@ int desync(int sfd, char *buffer, size_t bfsize,
|
|||
lp = pos;
|
||||
}
|
||||
if (lp < n) {
|
||||
LOG(LOG_S, "send: pos=%ld-%ld\n", lp, n);
|
||||
LOG((lp ? LOG_S : LOG_L), "send: pos=%ld-%ld\n", lp, n);
|
||||
if (send(sfd, buffer + lp, n - lp, 0) < 0) {
|
||||
uniperror("send");
|
||||
return -1;
|
||||
|
|
46
main.c
46
main.c
|
@ -46,7 +46,7 @@ struct params params = {
|
|||
.custom_ttl = 0,
|
||||
.de_known = 0,
|
||||
|
||||
.cache_ttl = 3600,
|
||||
.cache_ttl = 21600,
|
||||
.ipv6 = 1,
|
||||
.resolve = 1,
|
||||
.max_open = 512,
|
||||
|
@ -71,6 +71,7 @@ const char help_text[] = {
|
|||
" -K, --desync-known Desync only HTTP and TLS with SNI\n"
|
||||
" -A, --auto Try desync params after this option\n"
|
||||
" -u, --cache-ttl <sec> Lifetime of cached desync params for IP\n"
|
||||
" -q, --redirect <ip:port> Redirect to external SOCKS5 proxy\n"
|
||||
" -s, --split <n[+s]> Split packet at n\n"
|
||||
" +s - add SNI offset\n"
|
||||
" +h - add HTTP Host offset\n"
|
||||
|
@ -119,7 +120,7 @@ const struct option options[] = {
|
|||
{"tlsrec", 1, 0, 'r'},
|
||||
{"def-ttl", 1, 0, 'g'},
|
||||
{"delay", 1, 0, 'w'}, //
|
||||
|
||||
{"redirect", 1, 0, 'q'},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -156,15 +157,40 @@ char *ftob(char *name, ssize_t *sl)
|
|||
}
|
||||
|
||||
|
||||
int get_addr(const char *str, struct sockaddr_ina *addr)
|
||||
int get_addr(char *str, struct sockaddr_ina *addr)
|
||||
{
|
||||
uint16_t port = 0;
|
||||
char *s = str, *e = 0;
|
||||
char *end = 0, *p = str;
|
||||
|
||||
if (*str == '[') {
|
||||
e = strchr(str, ']');
|
||||
if (!e) return -1;
|
||||
s++; p = e + 1;
|
||||
}
|
||||
p = strchr(p, ':');
|
||||
if (p) {
|
||||
long val = strtol(p + 1, &end, 0);
|
||||
if (val <= 0 || val > 0xffff || *end)
|
||||
return -1;
|
||||
else
|
||||
port = htons(val);
|
||||
if (!e) e = p;
|
||||
}
|
||||
if ((e - s) < 7) {
|
||||
return -1;
|
||||
}
|
||||
char str_ip[(e - s) + 1];
|
||||
memcpy(str_ip, s, e - s);
|
||||
str_ip[e - s] = 0;
|
||||
|
||||
struct addrinfo hints = {0}, *res = 0;
|
||||
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
|
||||
if (getaddrinfo(str, 0, &hints, &res) || !res) {
|
||||
if (getaddrinfo(str_ip, 0, &hints, &res) || !res) {
|
||||
return -1;
|
||||
}
|
||||
if (res->ai_addr->sa_family == AF_INET6)
|
||||
|
@ -172,6 +198,10 @@ int get_addr(const char *str, struct sockaddr_ina *addr)
|
|||
else
|
||||
addr->in = *(struct sockaddr_in *)res->ai_addr;
|
||||
freeaddrinfo(res);
|
||||
|
||||
if (port) {
|
||||
addr->in6.sin6_port = port;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -284,6 +314,7 @@ int main(int argc, char **argv)
|
|||
|
||||
long val = 0;
|
||||
char *end = 0;
|
||||
|
||||
uint16_t port = htons(1080);
|
||||
|
||||
struct desync_params *dp = add_dparams(
|
||||
|
@ -487,6 +518,13 @@ int main(int argc, char **argv)
|
|||
invalid = 1;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
if (get_addr(optarg, (struct sockaddr_ina *)&dp->ext_proxy) < 0)
|
||||
invalid = 1;
|
||||
else
|
||||
dp->redirect = 1;
|
||||
break;
|
||||
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
|
2
params.h
2
params.h
|
@ -25,6 +25,8 @@ struct part {
|
|||
};
|
||||
|
||||
struct desync_params {
|
||||
char redirect;
|
||||
struct sockaddr_in6 ext_proxy;
|
||||
int ttl;
|
||||
int parts_n;
|
||||
struct part *parts;
|
||||
|
|
369
proxy.c
369
proxy.c
|
@ -263,7 +263,7 @@ int s5_get_addr(char *buffer, ssize_t n,
|
|||
|
||||
|
||||
int create_conn(struct poolhd *pool,
|
||||
struct eval *val, struct sockaddr_ina *dst)
|
||||
struct eval *val, struct sockaddr_ina *dst, int next)
|
||||
{
|
||||
struct sockaddr_ina addr = *dst;
|
||||
|
||||
|
@ -319,7 +319,7 @@ int create_conn(struct poolhd *pool,
|
|||
close(sfd);
|
||||
return -1;
|
||||
}
|
||||
struct eval *pair = add_event(pool, EV_CONNECT, sfd, POLLOUT);
|
||||
struct eval *pair = add_event(pool, next, sfd, POLLOUT);
|
||||
if (!pair) {
|
||||
close(sfd);
|
||||
return -1;
|
||||
|
@ -332,60 +332,6 @@ int create_conn(struct poolhd *pool,
|
|||
}
|
||||
|
||||
|
||||
static inline int on_request(struct poolhd *pool, struct eval *val,
|
||||
char *buffer, size_t bfsize)
|
||||
{
|
||||
struct sockaddr_ina dst = {0};
|
||||
|
||||
ssize_t n = recv(val->fd, buffer, bfsize, 0);
|
||||
if (n < 1) {
|
||||
if (n) uniperror("ss recv");
|
||||
return -1;
|
||||
}
|
||||
if (*buffer == S_VER5) {
|
||||
if (val->flag != FLAG_S5) {
|
||||
if (auth_socks5(val->fd, buffer, n)) {
|
||||
return -1;
|
||||
}
|
||||
val->flag = FLAG_S5;
|
||||
return 0;
|
||||
}
|
||||
if (n < S_SIZE_MIN) {
|
||||
LOG(LOG_E, "ss: request to small\n");
|
||||
return -1;
|
||||
}
|
||||
int s5e = s5_get_addr(buffer, n, &dst);
|
||||
if (!s5e &&
|
||||
create_conn(pool, val, &dst)) {
|
||||
s5e = S_ER_GEN;
|
||||
}
|
||||
if (s5e) {
|
||||
resp_s5_error(val->fd, s5e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (*buffer == S_VER4) {
|
||||
val->flag = FLAG_S4;
|
||||
|
||||
int error = s4_get_addr(buffer, n, &dst);
|
||||
if (!error) {
|
||||
error = create_conn(pool, val, &dst);
|
||||
}
|
||||
if (error) {
|
||||
if (resp_error(val->fd, error, FLAG_S4) < 0)
|
||||
uniperror("send");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG(LOG_E, "ss: invalid version: 0x%x (%lu)\n", *buffer, n);
|
||||
return -1;
|
||||
}
|
||||
val->type = EV_IGNORE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int on_accept(struct poolhd *pool, struct eval *val)
|
||||
{
|
||||
struct sockaddr_ina client;
|
||||
|
@ -507,26 +453,9 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val,
|
|||
}
|
||||
|
||||
|
||||
int try_again(struct poolhd *pool, struct eval *val)
|
||||
{
|
||||
struct eval *client = val->pair;
|
||||
|
||||
int e = create_conn(pool, client,
|
||||
(struct sockaddr_ina *)&val->in6);
|
||||
if (e) {
|
||||
return -1;
|
||||
}
|
||||
val->pair = 0;
|
||||
del_event(pool, val);
|
||||
|
||||
client->type = EV_IGNORE;
|
||||
client->try_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mode_add_get(struct sockaddr_ina *dst, int m)
|
||||
{
|
||||
// m < 0: get, m > 0: set, m == 0: delete
|
||||
char *data;
|
||||
int len;
|
||||
time_t t;
|
||||
|
@ -561,28 +490,130 @@ int mode_add_get(struct sockaddr_ina *dst, int m)
|
|||
val = params.mempool->values[i];
|
||||
time(&t);
|
||||
if (t > val->time + params.cache_ttl) {
|
||||
LOG(LOG_S, "cache value is too old, ignore\n");
|
||||
return -1;
|
||||
LOG(LOG_S, "time=%ld, now=%ld, ignore\n", val->time, t);
|
||||
return 0;
|
||||
}
|
||||
return val->m;
|
||||
}
|
||||
|
||||
|
||||
static inline int on_request(struct poolhd *pool, struct eval *val,
|
||||
char *buffer, size_t bfsize)
|
||||
{
|
||||
struct sockaddr_ina dst = {0};
|
||||
|
||||
ssize_t n = recv(val->fd, buffer, bfsize, 0);
|
||||
if (n < 1) {
|
||||
if (n) uniperror("ss recv");
|
||||
return -1;
|
||||
}
|
||||
int e = 0, s5e = 0, m;
|
||||
|
||||
if (*buffer == S_VER5) {
|
||||
if (val->flag != FLAG_S5) {
|
||||
if (auth_socks5(val->fd, buffer, n)) {
|
||||
return -1;
|
||||
}
|
||||
val->flag = FLAG_S5;
|
||||
return 0;
|
||||
}
|
||||
if (n < S_SIZE_MIN) {
|
||||
LOG(LOG_E, "ss: request to small\n");
|
||||
return -1;
|
||||
}
|
||||
e = s5_get_addr(buffer, n, &dst);
|
||||
s5e = e;
|
||||
}
|
||||
else if (*buffer == S_VER4) {
|
||||
val->flag = FLAG_S4;
|
||||
e = s4_get_addr(buffer, n, &dst);
|
||||
}
|
||||
else {
|
||||
LOG(LOG_E, "ss: invalid version: 0x%x (%lu)\n", *buffer, n);
|
||||
return -1;
|
||||
}
|
||||
if (!e) {
|
||||
m = mode_add_get(&dst, -1);
|
||||
int next = EV_CONNECT;
|
||||
|
||||
if (m >= 0) {
|
||||
struct desync_params *dp = ¶ms.dp[m];
|
||||
if (dp->redirect) {
|
||||
next = EV_REDIRECT;
|
||||
e = create_conn(pool, val,
|
||||
(struct sockaddr_ina *)&dp->ext_proxy, next);
|
||||
val->pair->in6 = dst.in6;
|
||||
}
|
||||
}
|
||||
if (next == EV_CONNECT) {
|
||||
e = create_conn(pool, val, &dst, next);
|
||||
}
|
||||
}
|
||||
if (e) {
|
||||
if (s5e) {
|
||||
resp_s5_error(val->fd, s5e);
|
||||
}
|
||||
else if (resp_error(val->fd, e, val->flag) < 0) {
|
||||
uniperror("ss: send");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (m >= 0) {
|
||||
val->attempt = m;
|
||||
}
|
||||
val->pair->attempt = m;
|
||||
val->type = EV_IGNORE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int try_again(struct poolhd *pool, struct eval *val)
|
||||
{
|
||||
struct eval *client = val->pair;
|
||||
int e = 0;
|
||||
int m = client->attempt + 1;
|
||||
|
||||
if (m >= params.dp_count) {
|
||||
mode_add_get(
|
||||
(struct sockaddr_ina *)&val->in6, 0);
|
||||
return -1;
|
||||
}
|
||||
struct desync_params *dp = ¶ms.dp[m];
|
||||
if (dp->redirect) {
|
||||
e = create_conn(pool, client,
|
||||
(struct sockaddr_ina *)&dp->ext_proxy, EV_REDIRECT);
|
||||
client->pair->in6 = val->in6;
|
||||
}
|
||||
else {
|
||||
e = create_conn(pool, client,
|
||||
(struct sockaddr_ina *)&val->in6, EV_DESYNC);
|
||||
}
|
||||
if (e) {
|
||||
return -1;
|
||||
}
|
||||
val->pair = 0;
|
||||
del_event(pool, val);
|
||||
|
||||
client->type = EV_IGNORE;
|
||||
client->attempt++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int on_tunnel_check(struct poolhd *pool, struct eval *val,
|
||||
char *buffer, size_t bfsize, int out)
|
||||
{
|
||||
if (!out && val->flag == FLAG_CONN) {
|
||||
int e = on_tunnel(pool, val, buffer, bfsize, out);
|
||||
int e = on_tunnel(pool, val, buffer, bfsize, out);
|
||||
|
||||
if (val->flag == FLAG_CONN) {
|
||||
if (out) {
|
||||
return e;
|
||||
}
|
||||
if (e) {
|
||||
if (unie(e) != ECONNRESET) {
|
||||
return -1;
|
||||
}
|
||||
if (val->pair->try_count + 1 >= params.dp_count) {
|
||||
mode_add_get(
|
||||
(struct sockaddr_ina *)&val->in6, 0);
|
||||
return -1;
|
||||
}
|
||||
return try_again(pool, val);;
|
||||
return try_again(pool, val);
|
||||
}
|
||||
struct eval *pair = val->pair;
|
||||
val->type = EV_TUNNEL;
|
||||
|
@ -592,48 +623,37 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val,
|
|||
pair->buff.data = 0;
|
||||
pair->buff.size = 0;
|
||||
|
||||
int m = pair->try_count;
|
||||
if (m == 0 && !val->saved_m) {
|
||||
int m = pair->attempt;
|
||||
|
||||
if ((m == 0 && val->attempt < 0)
|
||||
|| (m && m == val->attempt)) {
|
||||
return 0;
|
||||
}
|
||||
if (m == 0) {
|
||||
LOG(LOG_S, "delete ip: m=%d\n", m);
|
||||
} else {
|
||||
LOG(LOG_S, "save ip: m=%d\n", m);
|
||||
}
|
||||
return mode_add_get(
|
||||
(struct sockaddr_ina *)&val->in6, m);
|
||||
}
|
||||
else {
|
||||
int e = on_tunnel(pool, val, buffer, bfsize, out);
|
||||
if (e) {
|
||||
if (val->flag == FLAG_CONN) {
|
||||
val = val->pair;
|
||||
}
|
||||
int m = val->try_count + 1;
|
||||
if (m >= params.dp_count) {
|
||||
m = 0;
|
||||
}
|
||||
mode_add_get(
|
||||
(struct sockaddr_ina *)&val->pair->in6, m);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
int on_desync(struct poolhd *pool, struct eval *val,
|
||||
char *buffer, size_t bfsize)
|
||||
{
|
||||
ssize_t n;
|
||||
int m;
|
||||
|
||||
if (!val->try_count) {
|
||||
m = mode_add_get(
|
||||
(struct sockaddr_ina *)&val->pair->in6, -1);
|
||||
if (m >= 0) {
|
||||
val->saved_m = m + 1;
|
||||
val->try_count = m;
|
||||
if (val->flag == FLAG_CONN) {
|
||||
if (mod_etype(pool, val, POLLOUT, 0)) {
|
||||
uniperror("mod_etype");
|
||||
return -1;
|
||||
}
|
||||
val = val->pair;
|
||||
}
|
||||
m = val->try_count;
|
||||
LOG(LOG_S, "desync params index: %d\n", m);
|
||||
ssize_t n;
|
||||
int m = val->attempt;
|
||||
LOG((m ? LOG_S : LOG_L), "desync params index: %d\n", m);
|
||||
|
||||
if (!val->buff.data) {
|
||||
n = recv(val->fd, buffer, bfsize, 0);
|
||||
|
@ -664,39 +684,120 @@ int on_desync(struct poolhd *pool, struct eval *val,
|
|||
}
|
||||
|
||||
|
||||
static inline int on_connect(struct poolhd *pool, struct eval *val,
|
||||
char *buffer, size_t bfsize, int e)
|
||||
static inline int on_connect(struct poolhd *pool, struct eval *val, int e)
|
||||
{
|
||||
int error = 0;
|
||||
socklen_t len = sizeof(error);
|
||||
struct eval *pair = val->pair;
|
||||
if (e) {
|
||||
if (getsockopt(val->fd, SOL_SOCKET,
|
||||
SO_ERROR, (char *)&error, &len)) {
|
||||
uniperror("getsockopt SO_ERROR");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!val->pair->try_count) {
|
||||
if (resp_error(val->pair->fd,
|
||||
error, val->pair->flag) < 0) {
|
||||
uniperror("send");
|
||||
return -1;
|
||||
if (unie(error) == ECONNREFUSED) {
|
||||
e = try_again(pool, val);
|
||||
if (!e) error = 0;
|
||||
}
|
||||
}
|
||||
if (e) {
|
||||
else {
|
||||
if (mod_etype(pool, val, POLLOUT, 0)) {
|
||||
uniperror("mod_etype");
|
||||
return -1;
|
||||
}
|
||||
val->type = EV_TUNNEL;
|
||||
val->pair->type = EV_DESYNC;
|
||||
}
|
||||
if (resp_error(pair->fd,
|
||||
error, pair->flag) < 0) {
|
||||
uniperror("send");
|
||||
return -1;
|
||||
}
|
||||
if (mod_etype(pool, val, POLLOUT, 0)) {
|
||||
uniperror("mod_etype");
|
||||
return -1;
|
||||
}
|
||||
val->type = EV_DESYNC;
|
||||
val->pair->type = EV_DESYNC;
|
||||
return e ? -1 : 0;
|
||||
}
|
||||
|
||||
if (val->pair->try_count) {
|
||||
|
||||
static inline int on_redirect(struct poolhd *pool, struct eval *val,
|
||||
char *buffer, size_t bfsize)
|
||||
{
|
||||
struct eval *pair = val->pair;
|
||||
int e = -1;
|
||||
|
||||
switch (val->flag) {
|
||||
case FLAG_CONN:;
|
||||
char a[3] = "\5\1\0";
|
||||
if (send(val->fd, &a, sizeof(a), 0) < 0) {
|
||||
uniperror("rr: send");
|
||||
break;
|
||||
}
|
||||
if (mod_etype(pool, val, POLLOUT, 0)) {
|
||||
uniperror("mod_etype");
|
||||
break;
|
||||
}
|
||||
val->flag = FLAG_AUTH;
|
||||
return 0;
|
||||
|
||||
case FLAG_AUTH:;
|
||||
ssize_t n = recv(val->fd, buffer, bfsize, 0);
|
||||
if (n < 2) {
|
||||
break;
|
||||
}
|
||||
if (!(buffer[0] == 5 && buffer[1] == 0)) {
|
||||
LOG(LOG_E, "rr: auth error: 0x%x\n", buffer[1]);
|
||||
break;
|
||||
}
|
||||
struct s5_req r = {.ver = 5, .cmd = S_CMD_CONN};
|
||||
|
||||
switch (val->in.sin_family) {
|
||||
case AF_INET:
|
||||
r.atp = S_ATP_I4;
|
||||
r.i4 = val->in.sin_addr;
|
||||
r.p4 = val->in.sin_port;
|
||||
break;
|
||||
case AF_INET6:
|
||||
r.atp = S_ATP_I6;
|
||||
r.i6 = val->in6.sin6_addr;
|
||||
r.p6 = val->in6.sin6_port;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (send(val->fd, &r, sizeof(r), 0) < 0) {
|
||||
uniperror("rr: send");
|
||||
break;
|
||||
}
|
||||
val->flag = FLAG_ANSWER;
|
||||
return 0;
|
||||
|
||||
case FLAG_ANSWER:
|
||||
n = recv(val->fd, buffer, bfsize, 0);
|
||||
if (n < sizeof(struct s5_rep)) {
|
||||
uniperror("rr: recv");
|
||||
break;
|
||||
}
|
||||
struct s5_rep *rr = (struct s5_rep *)buffer;
|
||||
if (rr->ver != 5 || rr->code != 0) {
|
||||
LOG(LOG_E, "rr: socks returned: %d\n", rr->code);
|
||||
break;
|
||||
}
|
||||
val->flag = FLAG_CONN;
|
||||
val->type = EV_TUNNEL;
|
||||
pair->type = EV_DESYNC;
|
||||
e = 0;
|
||||
}
|
||||
char is_first = (val->attempt == pair->attempt);
|
||||
|
||||
if (!e && !is_first) {
|
||||
return on_desync(pool, val->pair, buffer, bfsize);
|
||||
}
|
||||
return 0;
|
||||
else if (e) {
|
||||
e = try_again(pool, val);
|
||||
}
|
||||
if (is_first && resp_error(pair->fd,
|
||||
e, pair->flag) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
|
@ -765,8 +866,12 @@ int event_loop(int srvfd)
|
|||
continue;
|
||||
|
||||
case EV_CONNECT:
|
||||
if (on_connect(pool, val,
|
||||
buffer, bfsize, etype & POLLERR))
|
||||
if (on_connect(pool, val, etype & POLLERR))
|
||||
del_event(pool, val);
|
||||
continue;
|
||||
|
||||
case EV_REDIRECT:
|
||||
if (on_redirect(pool, val, buffer, bfsize))
|
||||
del_event(pool, val);
|
||||
continue;
|
||||
|
||||
|
|
10
readme.txt
10
readme.txt
|
@ -37,14 +37,22 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
|||
|
||||
-A, --auto
|
||||
Автоматический режим
|
||||
Если обнаружены признаки блокировки (соединение разорвано сразу после первого пакета),
|
||||
Если будет выполнено одно из следующих условий,
|
||||
то будут применены параметры обхода, следующие за данной опцией
|
||||
Условия:
|
||||
- Сервер сбросил подключение, не отправив ответ
|
||||
- Сервер прислал RST на этапе подключения
|
||||
- Резервный прокси отказывает в соединении
|
||||
Можно указывать несколько групп параметров, раделяя их данным флагом
|
||||
Если соединение успешно прошло, то параметры для данного IP будут закешированны
|
||||
|
||||
-u, --cache-ttl <sec>
|
||||
Время жизни значения в кеше, указывается в секундах
|
||||
|
||||
-q, --redirect <ip:port>
|
||||
Перенаправить подключение на другой SOCKS5 прокси
|
||||
Имеет смысл указывать после --auto, для перенаправление только заблокированных ресурсов
|
||||
|
||||
-s, --split <n[+s]>
|
||||
Разбить запрос по указанному смещению
|
||||
После числа можно добавить флаг:
|
||||
|
|
Loading…
Reference in a new issue