two sockets for UDP, ignore dst and proto

This commit is contained in:
ruti 2024-04-26 01:15:02 +03:00
parent 15b9f50a5c
commit 4be8bd33f0
8 changed files with 88 additions and 124 deletions

View File

@ -162,20 +162,6 @@ bool check_proto_tcp(int proto, struct eval *val)
} }
bool check_proto_udp(int proto, char *buffer, size_t n)
{
if ((proto & IS_QUIC) &&
is_quic_inital(buffer, n)) {
return 1;
}
if ((proto & IS_DNS) &&
is_dns_req(buffer, n)) {
return 1;
}
return 0;
}
int on_torst(struct poolhd *pool, struct eval *val) int on_torst(struct poolhd *pool, struct eval *val)
{ {
int m = val->pair->attempt + 1; int m = val->pair->attempt + 1;
@ -371,41 +357,3 @@ int on_desync(struct poolhd *pool, struct eval *val,
val->pair->type = EV_PRE_TUNNEL; val->pair->type = EV_PRE_TUNNEL;
return 0; return 0;
} }
ssize_t udp_hook(struct eval *val,
char *buffer, size_t n, struct sockaddr_ina *dst)
{
int m = val->attempt;
struct desync_params *dp = &params.dp[m];
if (val->flag != FLAG_CONN) {
if (!m) for (; m < params.dp_count; m++) {
dp = &params.dp[m];
if ((!dp->proto || check_proto_udp(dp->proto, buffer, n))) {
break;
}
}
if (m >= params.dp_count) {
return -1;
}
val->attempt = m;
val->flag = FLAG_CONN;
}
struct sockaddr_ina addr;
if (dp->to_ip) {
addr.in6 = dp->addr;
if (dst->sa.sa_family == AF_INET6) {
map_fix(&addr, 6);
}
else {
map_fix(&addr, 0);
}
if (!addr.in.sin_port) {
addr.in.sin_port = dst->in.sin_port;
}
dst = &addr;
}
return sendto(val->fd, buffer, n, 0, &dst->sa, sizeof(*dst));
}

View File

@ -6,6 +6,3 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val,
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 udp_hook(struct eval *val,
char *buffer, size_t n, struct sockaddr_ina *dst);

45
main.c
View File

@ -56,6 +56,9 @@ struct params params = {
.baddr = { .baddr = {
.sin6_family = AF_INET6 .sin6_family = AF_INET6
}, },
.laddr = {
.sin6_family = AF_INET
},
.debug = 0 .debug = 0
}; };
@ -81,7 +84,7 @@ const char help_text[] = {
#ifdef TIMEOUT_SUPPORT #ifdef TIMEOUT_SUPPORT
" -T, --timeout <sec> Timeout waiting for response, after which trigger auto\n" " -T, --timeout <sec> Timeout waiting for response, after which trigger auto\n"
#endif #endif
" -K, --proto[=t,h,d,q] Protocol whitelist: tls,http,dns,quic\n" " -K, --proto[=t,h] Protocol whitelist: tls,http\n"
" -H, --hosts <file|:str> Hosts whitelist\n" " -H, --hosts <file|:str> Hosts whitelist\n"
" -D, --dst <ip[:port]> Custom destination IP\n" " -D, --dst <ip[:port]> Custom destination IP\n"
" -s, --split <n[+s]> Split packet at n\n" " -s, --split <n[+s]> Split packet at n\n"
@ -280,10 +283,13 @@ int get_addr(const char *str, struct sockaddr_ina *addr)
if (getaddrinfo(str, 0, &hints, &res) || !res) { if (getaddrinfo(str, 0, &hints, &res) || !res) {
return -1; return -1;
} }
if (res->ai_addr->sa_family == AF_INET6) if (res->ai_addr->sa_family == AF_INET6)
addr->in6 = *(struct sockaddr_in6 *)res->ai_addr; addr->in6.sin6_addr = (
(struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
else else
addr->in = *(struct sockaddr_in *)res->ai_addr; addr->in.sin_addr = (
(struct sockaddr_in *)res->ai_addr)->sin_addr;
freeaddrinfo(res); freeaddrinfo(res);
return 0; return 0;
@ -438,13 +444,6 @@ int main(int argc, char **argv)
return 0; return 0;
} }
#endif #endif
struct sockaddr_ina s = {
.in = {
.sin_family = AF_INET,
.sin_port = htons(1080)
}},
b = { .in6 = params.baddr };
int optc = sizeof(options)/sizeof(*options); int optc = sizeof(options)/sizeof(*options);
for (int i = 0, e = optc; i < e; i++) for (int i = 0, e = optc; i < e; i++)
optc += options[i].has_arg; optc += options[i].has_arg;
@ -460,14 +459,14 @@ int main(int argc, char **argv)
} }
} }
params.laddr.sin6_port = htons(1080);
int rez; int rez;
int invalid = 0; int invalid = 0;
long val = 0; long val = 0;
char *end = 0; char *end = 0;
uint16_t port = htons(1080);
struct desync_params *dp = add((void *)&params.dp, struct desync_params *dp = add((void *)&params.dp,
&params.dp_count, sizeof(struct desync_params)); &params.dp_count, sizeof(struct desync_params));
if (!dp) { if (!dp) {
@ -499,7 +498,8 @@ int main(int argc, char **argv)
return 0; return 0;
case 'i': case 'i':
if (get_addr(optarg, &s) < 0) if (get_addr(optarg,
(struct sockaddr_ina *)&params.laddr) < 0)
invalid = 1; invalid = 1;
break; break;
@ -508,14 +508,13 @@ int main(int argc, char **argv)
if (val <= 0 || val > 0xffff || *end) if (val <= 0 || val > 0xffff || *end)
invalid = 1; invalid = 1;
else else
port = htons(val); params.laddr.sin6_port = htons(val);
break; break;
case 'I': case 'I':
if (get_addr(optarg, &b) < 0) if (get_addr(optarg,
(struct sockaddr_ina *)&params.baddr) < 0)
invalid = 1; invalid = 1;
else
params.baddr = b.in6;
break; break;
case 'b': case 'b':
@ -625,12 +624,6 @@ int main(int argc, char **argv)
case 'h': case 'h':
dp->proto |= IS_HTTP; dp->proto |= IS_HTTP;
break; break;
case 'd':
dp->proto |= IS_DNS;
break;
case 'q':
dp->proto |= IS_QUIC;
break;
default: default:
invalid = 1; invalid = 1;
continue; continue;
@ -821,10 +814,8 @@ int main(int argc, char **argv)
return -1; return -1;
} }
} }
s.in.sin_port = port;
b.in.sin_port = 0;
if (b.sa.sa_family != AF_INET6) { if (params.laddr.sin6_family != AF_INET6) {
params.ipv6 = 0; params.ipv6 = 0;
} }
if (!params.def_ttl) { if (!params.def_ttl) {
@ -839,7 +830,7 @@ int main(int argc, char **argv)
clear_params(); clear_params();
return -1; return -1;
} }
int status = run(&s); int status = run((struct sockaddr_ina *)&params.laddr);
clear_params(); clear_params();
return status; return status;
} }

View File

@ -350,7 +350,7 @@ bool is_tls_alert(char *resp, size_t sn) {
&& !memcmp(resp, "\x15\x03\x01\x00\x02\x02", 6)); && !memcmp(resp, "\x15\x03\x01\x00\x02\x02", 6));
} }
/*
bool is_dns_req(char *buffer, size_t n) bool is_dns_req(char *buffer, size_t n)
{ {
if (n < 12) { if (n < 12) {
@ -364,7 +364,7 @@ bool is_quic_inital(char *buffer, size_t bsize)
{ {
return (bsize > 64 && (buffer[0] & 0xc0) == 0xc0); return (bsize > 64 && (buffer[0] & 0xc0) == 0xc0);
} }
*/
int mod_http(char *buffer, size_t bsize, int m) int mod_http(char *buffer, size_t bsize, int m)
{ {

View File

@ -6,8 +6,8 @@
#define IS_UNKNOWN 0 #define IS_UNKNOWN 0
#define IS_HTTP 1 #define IS_HTTP 1
#define IS_HTTPS 2 #define IS_HTTPS 2
#define IS_QUIC 4 //#define IS_QUIC 4
#define IS_DNS 8 //#define IS_DNS 8
#define MH_HMIX 1 #define MH_HMIX 1
#define MH_SPACE 2 #define MH_SPACE 2
@ -38,6 +38,6 @@ bool is_tls_alert(char *resp, size_t sn);
int part_tls(char *buffer, size_t bsize, ssize_t n, long pos); int part_tls(char *buffer, size_t bsize, ssize_t n, long pos);
bool is_dns_req(char *buffer, size_t n); //bool is_dns_req(char *buffer, size_t n);
bool is_quic_inital(char *buffer, size_t bsize); //bool is_quic_inital(char *buffer, size_t bsize);

View File

@ -91,6 +91,7 @@ struct params {
int debug; int debug;
size_t bfsize; size_t bfsize;
struct sockaddr_in6 baddr; struct sockaddr_in6 baddr;
struct sockaddr_in6 laddr;
struct mphdr *mempool; struct mphdr *mempool;
}; };

93
proxy.c
View File

@ -64,9 +64,6 @@ void map_fix(struct sockaddr_ina *addr, char f6)
static inline char addr_equ( static inline char addr_equ(
struct sockaddr_ina *a, struct sockaddr_ina *b) struct sockaddr_ina *a, struct sockaddr_ina *b)
{ {
if (a->in.sin_port != b->in.sin_port) {
return 0;
}
if (a->sa.sa_family == AF_INET) { if (a->sa.sa_family == AF_INET) {
return return
*((uint32_t *)(&a->in.sin_addr)) == *((uint32_t *)(&a->in.sin_addr)) ==
@ -398,7 +395,8 @@ int create_conn(struct poolhd *pool,
int udp_associate(struct poolhd *pool, int udp_associate(struct poolhd *pool,
struct eval *val, struct sockaddr_ina *dst) struct eval *val, struct sockaddr_ina *dst)
{ {
struct sockaddr_ina addr = {}; struct sockaddr_ina addr = { .in6 = params.laddr };
addr.in.sin_port = 0;
int ufd = nb_socket(params.baddr.sin6_family, SOCK_DGRAM); int ufd = nb_socket(params.baddr.sin6_family, SOCK_DGRAM);
if (ufd < 0) { if (ufd < 0) {
@ -420,21 +418,44 @@ int udp_associate(struct poolhd *pool,
close(ufd); close(ufd);
return -1; return -1;
} }
socklen_t sz = sizeof(addr);
if (getsockname(ufd, &addr.sa, &sz)) {
perror("getsockname");
close(ufd);
return -1;
}
struct eval *pair = add_event(pool, EV_UDP_TUNNEL, ufd, POLLIN); struct eval *pair = add_event(pool, EV_UDP_TUNNEL, ufd, POLLIN);
if (!pair) { if (!pair) {
close(ufd); close(ufd);
return -1; return -1;
} }
val->pair = pair;
pair->pair = val;
pair->in6.sin6_port = 0;
int cfd = nb_socket(addr.sa.sa_family, SOCK_DGRAM);
if (cfd < 0) {
perror("socket");
del_event(pool, pair);
return -1;
}
if (bind(cfd, &addr.sa, sizeof(addr)) < 0) {
uniperror("bind");
del_event(pool, pair);
close(cfd);
return -1;
}
struct eval *client = add_event(pool, EV_UDP_TUNNEL, cfd, POLLIN);
if (!pair) {
del_event(pool, pair);
close(cfd);
return -1;
}
val->type = EV_IGNORE;
val->pair = client;
client->pair = pair;
pair->pair = val;
client->flag = FLAG_CONN;
client->in6 = val->in6;
client->in6.sin6_port = 0;
socklen_t sz = sizeof(addr);
if (getsockname(cfd, &addr.sa, &sz)) {
perror("getsockname");
return -1;
}
struct s5_req s5r = { struct s5_req s5r = {
.ver = 0x05 .ver = 0x05
}; };
@ -573,11 +594,16 @@ int on_tunnel(struct poolhd *pool, struct eval *val,
int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize) int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize)
{ {
char *data = buffer + S_SIZE_I6; char *data = buffer;
size_t data_len = bfsize - S_SIZE_I6; size_t data_len = bfsize;
do {
if (val->flag != FLAG_CONN) {
data += S_SIZE_I6;
data_len -= S_SIZE_I6;
}
struct sockaddr_ina addr = {0}; struct sockaddr_ina addr = {0};
struct sockaddr_ina *src = (struct sockaddr_ina *)&val->in6;
do {
socklen_t asz = sizeof(addr); socklen_t asz = sizeof(addr);
ssize_t n = recvfrom(val->fd, data, data_len, 0, &addr.sa, &asz); ssize_t n = recvfrom(val->fd, data, data_len, 0, &addr.sa, &asz);
@ -587,41 +613,42 @@ int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize)
perror("recv udp"); perror("recv udp");
return -1; return -1;
} }
if (!src->in.sin_port) { ssize_t ns;
src->in6 = addr.in6;
}
ssize_t ns = 0;
if (addr_equ(src, &addr)) { if (val->flag == FLAG_CONN) {
if (!val->in6.sin6_port) {
if (connect(val->fd, &addr.sa, sizeof(addr)) < 0) {
uniperror("connect");
return -1;
}
val->in6 = addr.in6;
}
if (*(data + 2) != 0) { // frag if (*(data + 2) != 0) { // frag
continue; continue;
} }
int offs = s5_get_addr(data, n, &addr, SOCK_DGRAM); int offs = s5_get_addr(data, n, &addr, SOCK_DGRAM);
if (offs < 0) { if (offs < 0) {
LOG(LOG_E, "udp parse error\n");
return -1; return -1;
} }
val->pair->in6 = addr.in6; if (params.baddr.sin6_family == AF_INET6) {
if (src->sa.sa_family == AF_INET6) {
map_fix(&addr, 6); map_fix(&addr, 6);
} }
if (src->sa.sa_family != addr.sa.sa_family) { if (params.baddr.sin6_family != addr.sa.sa_family) {
return -1; return -1;
} }
ns = udp_hook(val, ns = sendto(val->pair->fd,
data + offs, n - offs, &addr); data + offs, n - offs, 0, &addr.sa, sizeof(addr));
} }
else { else {
//map_fix(&addr, 0); map_fix(&addr, 0);
memset(buffer, 0, S_SIZE_I6); memset(buffer, 0, S_SIZE_I6);
int offs = s5_set_addr(data, S_SIZE_I6, int offs = s5_set_addr(data, S_SIZE_I6, &addr, 1);
(struct sockaddr_ina *)&val->pair->in6, 1);
if (offs < 0 || offs > S_SIZE_I6) { if (offs < 0 || offs > S_SIZE_I6) {
return -1; return -1;
} }
ns = sendto(val->fd, data - offs, offs + n, 0, ns = send(val->pair->pair->fd, data - offs, offs + n, 0);
(struct sockaddr *)&val->in6, sizeof(val->in6));
} }
if (ns < 0) { if (ns < 0) {
perror("sendto"); perror("sendto");

View File

@ -74,8 +74,8 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
В Linux переводится в миллисекунды, поэтому можно указать дробное число В Linux переводится в миллисекунды, поэтому можно указать дробное число
Истечение таймаута будет обработано --auto Истечение таймаута будет обработано --auto
-K, --proto[=t,h,d,q] -K, --proto[=t,h]
Белый список протоколов: tls,http,dns,quic Белый список протоколов: tls,http
-H, --hosts <file|:string> -H, --hosts <file|:string>
Ограничить область действия параметров списком доменов Ограничить область действия параметров списком доменов