mirror of
https://github.com/hufrea/byedpi.git
synced 2024-11-28 11:18:53 +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_IGNORE,
|
||||||
EV_TUNNEL,
|
EV_TUNNEL,
|
||||||
EV_PRE_TUNNEL,
|
EV_PRE_TUNNEL,
|
||||||
|
EV_REDIRECT,
|
||||||
EV_DESYNC
|
EV_DESYNC
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FLAG_S4 1
|
#define FLAG_S4 1
|
||||||
#define FLAG_S5 2
|
#define FLAG_S5 2
|
||||||
#define FLAG_CONN 4
|
#define FLAG_CONN 4
|
||||||
|
#define FLAG_AUTH 8
|
||||||
|
#define FLAG_ANSWER 16
|
||||||
|
|
||||||
#ifndef CONEV_H
|
#ifndef CONEV_H
|
||||||
char *eid_name[] = {
|
char *eid_name[] = {
|
||||||
|
@ -50,6 +53,7 @@ char *eid_name[] = {
|
||||||
"EV_IGNORE",
|
"EV_IGNORE",
|
||||||
"EV_TUNNEL",
|
"EV_TUNNEL",
|
||||||
"EV_PRE_TUNNEL",
|
"EV_PRE_TUNNEL",
|
||||||
|
"EV_REDIRECT",
|
||||||
"EV_DESYNC"
|
"EV_DESYNC"
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,8 +76,7 @@ struct eval {
|
||||||
struct sockaddr_in6 in6;
|
struct sockaddr_in6 in6;
|
||||||
};
|
};
|
||||||
ssize_t recv_count;
|
ssize_t recv_count;
|
||||||
int try_count;
|
int attempt;
|
||||||
int saved_m;
|
|
||||||
#ifndef NOEPOLL
|
#ifndef NOEPOLL
|
||||||
uint32_t events;
|
uint32_t events;
|
||||||
#endif
|
#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)
|
ssize_t n, struct sockaddr *dst, int dp_c)
|
||||||
{
|
{
|
||||||
struct desync_params dp = params.dp[dp_c];
|
struct desync_params dp = params.dp[dp_c];
|
||||||
|
if (dp.redirect) {
|
||||||
|
dst = (struct sockaddr *)&dp.ext_proxy;
|
||||||
|
}
|
||||||
char *host = 0;
|
char *host = 0;
|
||||||
int len = 0, type = 0;
|
int len = 0, type = 0;
|
||||||
int fa = get_family(dst);
|
int fa = get_family(dst);
|
||||||
|
@ -296,7 +298,7 @@ int desync(int sfd, char *buffer, size_t bfsize,
|
||||||
lp = pos;
|
lp = pos;
|
||||||
}
|
}
|
||||||
if (lp < n) {
|
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) {
|
if (send(sfd, buffer + lp, n - lp, 0) < 0) {
|
||||||
uniperror("send");
|
uniperror("send");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
46
main.c
46
main.c
|
@ -46,7 +46,7 @@ struct params params = {
|
||||||
.custom_ttl = 0,
|
.custom_ttl = 0,
|
||||||
.de_known = 0,
|
.de_known = 0,
|
||||||
|
|
||||||
.cache_ttl = 3600,
|
.cache_ttl = 21600,
|
||||||
.ipv6 = 1,
|
.ipv6 = 1,
|
||||||
.resolve = 1,
|
.resolve = 1,
|
||||||
.max_open = 512,
|
.max_open = 512,
|
||||||
|
@ -71,6 +71,7 @@ const char help_text[] = {
|
||||||
" -K, --desync-known Desync only HTTP and TLS with SNI\n"
|
" -K, --desync-known Desync only HTTP and TLS with SNI\n"
|
||||||
" -A, --auto Try desync params after this option\n"
|
" -A, --auto Try desync params after this option\n"
|
||||||
" -u, --cache-ttl <sec> Lifetime of cached desync params for IP\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, --split <n[+s]> Split packet at n\n"
|
||||||
" +s - add SNI offset\n"
|
" +s - add SNI offset\n"
|
||||||
" +h - add HTTP Host offset\n"
|
" +h - add HTTP Host offset\n"
|
||||||
|
@ -119,7 +120,7 @@ const struct option options[] = {
|
||||||
{"tlsrec", 1, 0, 'r'},
|
{"tlsrec", 1, 0, 'r'},
|
||||||
{"def-ttl", 1, 0, 'g'},
|
{"def-ttl", 1, 0, 'g'},
|
||||||
{"delay", 1, 0, 'w'}, //
|
{"delay", 1, 0, 'w'}, //
|
||||||
|
{"redirect", 1, 0, 'q'},
|
||||||
{0}
|
{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;
|
struct addrinfo hints = {0}, *res = 0;
|
||||||
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_flags = AI_NUMERICHOST;
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
|
|
||||||
if (getaddrinfo(str, 0, &hints, &res) || !res) {
|
if (getaddrinfo(str_ip, 0, &hints, &res) || !res) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (res->ai_addr->sa_family == AF_INET6)
|
if (res->ai_addr->sa_family == AF_INET6)
|
||||||
|
@ -172,6 +198,10 @@ int get_addr(const char *str, struct sockaddr_ina *addr)
|
||||||
else
|
else
|
||||||
addr->in = *(struct sockaddr_in *)res->ai_addr;
|
addr->in = *(struct sockaddr_in *)res->ai_addr;
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
|
|
||||||
|
if (port) {
|
||||||
|
addr->in6.sin6_port = port;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,6 +314,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
long val = 0;
|
long val = 0;
|
||||||
char *end = 0;
|
char *end = 0;
|
||||||
|
|
||||||
uint16_t port = htons(1080);
|
uint16_t port = htons(1080);
|
||||||
|
|
||||||
struct desync_params *dp = add_dparams(
|
struct desync_params *dp = add_dparams(
|
||||||
|
@ -487,6 +518,13 @@ int main(int argc, char **argv)
|
||||||
invalid = 1;
|
invalid = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
if (get_addr(optarg, (struct sockaddr_ina *)&dp->ext_proxy) < 0)
|
||||||
|
invalid = 1;
|
||||||
|
else
|
||||||
|
dp->redirect = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
|
2
params.h
2
params.h
|
@ -25,6 +25,8 @@ struct part {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct desync_params {
|
struct desync_params {
|
||||||
|
char redirect;
|
||||||
|
struct sockaddr_in6 ext_proxy;
|
||||||
int ttl;
|
int ttl;
|
||||||
int parts_n;
|
int parts_n;
|
||||||
struct part *parts;
|
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,
|
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;
|
struct sockaddr_ina addr = *dst;
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ int create_conn(struct poolhd *pool,
|
||||||
close(sfd);
|
close(sfd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
struct eval *pair = add_event(pool, EV_CONNECT, sfd, POLLOUT);
|
struct eval *pair = add_event(pool, next, sfd, POLLOUT);
|
||||||
if (!pair) {
|
if (!pair) {
|
||||||
close(sfd);
|
close(sfd);
|
||||||
return -1;
|
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)
|
static inline int on_accept(struct poolhd *pool, struct eval *val)
|
||||||
{
|
{
|
||||||
struct sockaddr_ina client;
|
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)
|
int mode_add_get(struct sockaddr_ina *dst, int m)
|
||||||
{
|
{
|
||||||
|
// m < 0: get, m > 0: set, m == 0: delete
|
||||||
char *data;
|
char *data;
|
||||||
int len;
|
int len;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
@ -561,28 +490,130 @@ int mode_add_get(struct sockaddr_ina *dst, int m)
|
||||||
val = params.mempool->values[i];
|
val = params.mempool->values[i];
|
||||||
time(&t);
|
time(&t);
|
||||||
if (t > val->time + params.cache_ttl) {
|
if (t > val->time + params.cache_ttl) {
|
||||||
LOG(LOG_S, "cache value is too old, ignore\n");
|
LOG(LOG_S, "time=%ld, now=%ld, ignore\n", val->time, t);
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
return val->m;
|
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,
|
int on_tunnel_check(struct poolhd *pool, struct eval *val,
|
||||||
char *buffer, size_t bfsize, int out)
|
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 (e) {
|
||||||
if (unie(e) != ECONNRESET) {
|
if (unie(e) != ECONNRESET) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (val->pair->try_count + 1 >= params.dp_count) {
|
return try_again(pool, val);
|
||||||
mode_add_get(
|
|
||||||
(struct sockaddr_ina *)&val->in6, 0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return try_again(pool, val);;
|
|
||||||
}
|
}
|
||||||
struct eval *pair = val->pair;
|
struct eval *pair = val->pair;
|
||||||
val->type = EV_TUNNEL;
|
val->type = EV_TUNNEL;
|
||||||
|
@ -592,48 +623,37 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val,
|
||||||
pair->buff.data = 0;
|
pair->buff.data = 0;
|
||||||
pair->buff.size = 0;
|
pair->buff.size = 0;
|
||||||
|
|
||||||
int m = pair->try_count;
|
int m = pair->attempt;
|
||||||
if (m == 0 && !val->saved_m) {
|
|
||||||
|
if ((m == 0 && val->attempt < 0)
|
||||||
|
|| (m && m == val->attempt)) {
|
||||||
return 0;
|
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(
|
return mode_add_get(
|
||||||
(struct sockaddr_ina *)&val->in6, m);
|
(struct sockaddr_ina *)&val->in6, m);
|
||||||
}
|
}
|
||||||
else {
|
return e;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int on_desync(struct poolhd *pool, struct eval *val,
|
int on_desync(struct poolhd *pool, struct eval *val,
|
||||||
char *buffer, size_t bfsize)
|
char *buffer, size_t bfsize)
|
||||||
{
|
{
|
||||||
ssize_t n;
|
if (val->flag == FLAG_CONN) {
|
||||||
int m;
|
if (mod_etype(pool, val, POLLOUT, 0)) {
|
||||||
|
uniperror("mod_etype");
|
||||||
if (!val->try_count) {
|
return -1;
|
||||||
m = mode_add_get(
|
|
||||||
(struct sockaddr_ina *)&val->pair->in6, -1);
|
|
||||||
if (m >= 0) {
|
|
||||||
val->saved_m = m + 1;
|
|
||||||
val->try_count = m;
|
|
||||||
}
|
}
|
||||||
|
val = val->pair;
|
||||||
}
|
}
|
||||||
m = val->try_count;
|
ssize_t n;
|
||||||
LOG(LOG_S, "desync params index: %d\n", m);
|
int m = val->attempt;
|
||||||
|
LOG((m ? LOG_S : LOG_L), "desync params index: %d\n", m);
|
||||||
|
|
||||||
if (!val->buff.data) {
|
if (!val->buff.data) {
|
||||||
n = recv(val->fd, buffer, bfsize, 0);
|
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,
|
static inline int on_connect(struct poolhd *pool, struct eval *val, int e)
|
||||||
char *buffer, size_t bfsize, int e)
|
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
socklen_t len = sizeof(error);
|
socklen_t len = sizeof(error);
|
||||||
|
struct eval *pair = val->pair;
|
||||||
if (e) {
|
if (e) {
|
||||||
if (getsockopt(val->fd, SOL_SOCKET,
|
if (getsockopt(val->fd, SOL_SOCKET,
|
||||||
SO_ERROR, (char *)&error, &len)) {
|
SO_ERROR, (char *)&error, &len)) {
|
||||||
uniperror("getsockopt SO_ERROR");
|
uniperror("getsockopt SO_ERROR");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
if (unie(error) == ECONNREFUSED) {
|
||||||
if (!val->pair->try_count) {
|
e = try_again(pool, val);
|
||||||
if (resp_error(val->pair->fd,
|
if (!e) error = 0;
|
||||||
error, val->pair->flag) < 0) {
|
|
||||||
uniperror("send");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
return -1;
|
||||||
}
|
}
|
||||||
if (mod_etype(pool, val, POLLOUT, 0)) {
|
return e ? -1 : 0;
|
||||||
uniperror("mod_etype");
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
val->type = EV_DESYNC;
|
static inline int on_redirect(struct poolhd *pool, struct eval *val,
|
||||||
val->pair->type = EV_DESYNC;
|
char *buffer, size_t bfsize)
|
||||||
|
{
|
||||||
|
struct eval *pair = val->pair;
|
||||||
|
int e = -1;
|
||||||
|
|
||||||
if (val->pair->try_count) {
|
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 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,11 +866,15 @@ int event_loop(int srvfd)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case EV_CONNECT:
|
case EV_CONNECT:
|
||||||
if (on_connect(pool, val,
|
if (on_connect(pool, val, etype & POLLERR))
|
||||||
buffer, bfsize, etype & POLLERR))
|
|
||||||
del_event(pool, val);
|
del_event(pool, val);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
case EV_REDIRECT:
|
||||||
|
if (on_redirect(pool, val, buffer, bfsize))
|
||||||
|
del_event(pool, val);
|
||||||
|
continue;
|
||||||
|
|
||||||
case EV_DESYNC:
|
case EV_DESYNC:
|
||||||
if (on_desync(pool, val, buffer, bfsize))
|
if (on_desync(pool, val, buffer, bfsize))
|
||||||
del_event(pool, val);
|
del_event(pool, val);
|
||||||
|
|
10
readme.txt
10
readme.txt
|
@ -37,14 +37,22 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
||||||
|
|
||||||
-A, --auto
|
-A, --auto
|
||||||
Автоматический режим
|
Автоматический режим
|
||||||
Если обнаружены признаки блокировки (соединение разорвано сразу после первого пакета),
|
Если будет выполнено одно из следующих условий,
|
||||||
то будут применены параметры обхода, следующие за данной опцией
|
то будут применены параметры обхода, следующие за данной опцией
|
||||||
|
Условия:
|
||||||
|
- Сервер сбросил подключение, не отправив ответ
|
||||||
|
- Сервер прислал RST на этапе подключения
|
||||||
|
- Резервный прокси отказывает в соединении
|
||||||
Можно указывать несколько групп параметров, раделяя их данным флагом
|
Можно указывать несколько групп параметров, раделяя их данным флагом
|
||||||
Если соединение успешно прошло, то параметры для данного IP будут закешированны
|
Если соединение успешно прошло, то параметры для данного IP будут закешированны
|
||||||
|
|
||||||
-u, --cache-ttl <sec>
|
-u, --cache-ttl <sec>
|
||||||
Время жизни значения в кеше, указывается в секундах
|
Время жизни значения в кеше, указывается в секундах
|
||||||
|
|
||||||
|
-q, --redirect <ip:port>
|
||||||
|
Перенаправить подключение на другой SOCKS5 прокси
|
||||||
|
Имеет смысл указывать после --auto, для перенаправление только заблокированных ресурсов
|
||||||
|
|
||||||
-s, --split <n[+s]>
|
-s, --split <n[+s]>
|
||||||
Разбить запрос по указанному смещению
|
Разбить запрос по указанному смещению
|
||||||
После числа можно добавить флаг:
|
После числа можно добавить флаг:
|
||||||
|
|
Loading…
Reference in a new issue