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 m = val->pair->attempt + 1;
@ -371,41 +357,3 @@ int on_desync(struct poolhd *pool, struct eval *val,
val->pair->type = EV_PRE_TUNNEL;
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,
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 = {
.sin6_family = AF_INET6
},
.laddr = {
.sin6_family = AF_INET
},
.debug = 0
};
@ -81,7 +84,7 @@ const char help_text[] = {
#ifdef TIMEOUT_SUPPORT
" -T, --timeout <sec> Timeout waiting for response, after which trigger auto\n"
#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"
" -D, --dst <ip[:port]> Custom destination IP\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) {
return -1;
}
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
addr->in = *(struct sockaddr_in *)res->ai_addr;
addr->in.sin_addr = (
(struct sockaddr_in *)res->ai_addr)->sin_addr;
freeaddrinfo(res);
return 0;
@ -438,13 +444,6 @@ int main(int argc, char **argv)
return 0;
}
#endif
struct sockaddr_ina s = {
.in = {
.sin_family = AF_INET,
.sin_port = htons(1080)
}},
b = { .in6 = params.baddr };
int optc = sizeof(options)/sizeof(*options);
for (int i = 0, e = optc; i < e; i++)
optc += options[i].has_arg;
@ -460,14 +459,14 @@ int main(int argc, char **argv)
}
}
params.laddr.sin6_port = htons(1080);
int rez;
int invalid = 0;
long val = 0;
char *end = 0;
uint16_t port = htons(1080);
struct desync_params *dp = add((void *)&params.dp,
&params.dp_count, sizeof(struct desync_params));
if (!dp) {
@ -499,7 +498,8 @@ int main(int argc, char **argv)
return 0;
case 'i':
if (get_addr(optarg, &s) < 0)
if (get_addr(optarg,
(struct sockaddr_ina *)&params.laddr) < 0)
invalid = 1;
break;
@ -508,14 +508,13 @@ int main(int argc, char **argv)
if (val <= 0 || val > 0xffff || *end)
invalid = 1;
else
port = htons(val);
params.laddr.sin6_port = htons(val);
break;
case 'I':
if (get_addr(optarg, &b) < 0)
if (get_addr(optarg,
(struct sockaddr_ina *)&params.baddr) < 0)
invalid = 1;
else
params.baddr = b.in6;
break;
case 'b':
@ -625,12 +624,6 @@ int main(int argc, char **argv)
case 'h':
dp->proto |= IS_HTTP;
break;
case 'd':
dp->proto |= IS_DNS;
break;
case 'q':
dp->proto |= IS_QUIC;
break;
default:
invalid = 1;
continue;
@ -821,10 +814,8 @@ int main(int argc, char **argv)
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;
}
if (!params.def_ttl) {
@ -839,7 +830,7 @@ int main(int argc, char **argv)
clear_params();
return -1;
}
int status = run(&s);
int status = run((struct sockaddr_ina *)&params.laddr);
clear_params();
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));
}
/*
bool is_dns_req(char *buffer, size_t n)
{
if (n < 12) {
@ -364,7 +364,7 @@ bool is_quic_inital(char *buffer, size_t bsize)
{
return (bsize > 64 && (buffer[0] & 0xc0) == 0xc0);
}
*/
int mod_http(char *buffer, size_t bsize, int m)
{

View File

@ -6,8 +6,8 @@
#define IS_UNKNOWN 0
#define IS_HTTP 1
#define IS_HTTPS 2
#define IS_QUIC 4
#define IS_DNS 8
//#define IS_QUIC 4
//#define IS_DNS 8
#define MH_HMIX 1
#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);
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;
size_t bfsize;
struct sockaddr_in6 baddr;
struct sockaddr_in6 laddr;
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(
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) {
return
*((uint32_t *)(&a->in.sin_addr)) ==
@ -398,7 +395,8 @@ int create_conn(struct poolhd *pool,
int udp_associate(struct poolhd *pool,
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);
if (ufd < 0) {
@ -420,21 +418,44 @@ int udp_associate(struct poolhd *pool,
close(ufd);
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);
if (!pair) {
close(ufd);
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 = {
.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)
{
char *data = buffer + S_SIZE_I6;
size_t data_len = bfsize - S_SIZE_I6;
char *data = buffer;
size_t data_len = bfsize;
if (val->flag != FLAG_CONN) {
data += S_SIZE_I6;
data_len -= S_SIZE_I6;
}
struct sockaddr_ina addr = {0};
do {
struct sockaddr_ina addr = {0};
struct sockaddr_ina *src = (struct sockaddr_ina *)&val->in6;
socklen_t asz = sizeof(addr);
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");
return -1;
}
if (!src->in.sin_port) {
src->in6 = addr.in6;
}
ssize_t ns = 0;
ssize_t ns;
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
continue;
}
int offs = s5_get_addr(data, n, &addr, SOCK_DGRAM);
if (offs < 0) {
LOG(LOG_E, "udp parse error\n");
return -1;
}
val->pair->in6 = addr.in6;
if (src->sa.sa_family == AF_INET6) {
if (params.baddr.sin6_family == AF_INET6) {
map_fix(&addr, 6);
}
if (src->sa.sa_family != addr.sa.sa_family) {
if (params.baddr.sin6_family != addr.sa.sa_family) {
return -1;
}
ns = udp_hook(val,
data + offs, n - offs, &addr);
ns = sendto(val->pair->fd,
data + offs, n - offs, 0, &addr.sa, sizeof(addr));
}
else {
//map_fix(&addr, 0);
map_fix(&addr, 0);
memset(buffer, 0, S_SIZE_I6);
int offs = s5_set_addr(data, S_SIZE_I6,
(struct sockaddr_ina *)&val->pair->in6, 1);
int offs = s5_set_addr(data, S_SIZE_I6, &addr, 1);
if (offs < 0 || offs > S_SIZE_I6) {
return -1;
}
ns = sendto(val->fd, data - offs, offs + n, 0,
(struct sockaddr *)&val->in6, sizeof(val->in6));
ns = send(val->pair->pair->fd, data - offs, offs + n, 0);
}
if (ns < 0) {
perror("sendto");

View File

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