mirror of
https://github.com/hufrea/byedpi.git
synced 2024-12-22 06:15:14 +00:00
Fix UDP, SO_SNDBUF/RCVBUF option, custom bind address to out connections
This commit is contained in:
parent
067cbb0ff7
commit
ad697d9abd
309
main.c
309
main.c
@ -1,20 +1,26 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <params.h>
|
||||
#include <proxy.h>
|
||||
#include <packets.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#define FAKE_SUPPORT 1
|
||||
|
||||
#define VERSION 2
|
||||
|
||||
|
||||
struct packet fake_tls = {
|
||||
sizeof(tls_data), tls_data
|
||||
},
|
||||
@ -26,7 +32,6 @@ fake_udp = {
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct params params = {
|
||||
.ttl = 8,
|
||||
.split = 3,
|
||||
@ -36,19 +41,96 @@ struct params params = {
|
||||
.split_host = 0,
|
||||
.def_ttl = 0,
|
||||
.mod_http = 0,
|
||||
.de_known = 0,
|
||||
|
||||
.ipv6 = 1,
|
||||
.resolve = 1,
|
||||
.udp = 1,
|
||||
.de_known = 0,
|
||||
.max_open = 512,
|
||||
|
||||
.bfsize = 16384,
|
||||
.send_bfsz = 65536,
|
||||
.nodelay = 1,
|
||||
.send_bfsz = 0,
|
||||
.recv_bfsz = 0,
|
||||
.baddr = {
|
||||
.sin6_family = AF_INET6
|
||||
},
|
||||
.debug = 0
|
||||
};
|
||||
|
||||
|
||||
const char help_text[] = {
|
||||
" -i, --ip, <ip> Listening IP, default 0.0.0.0\n"
|
||||
" -p, --port <num> Listening port, default 1080\n"
|
||||
" -D, --daemon Daemonize\n"
|
||||
" -f, --pidfile <file> Write pid to file\n"
|
||||
" -c, --max-conn <count> Connection count limit, default 512\n"
|
||||
" -N, --no-domain Deny domain resolving\n"
|
||||
" -U, --no-udp Deny UDP associate\n"
|
||||
" -I --conn-ip <ip> Connection binded IP, default ::\n"
|
||||
" -b, --bfs <size> Buffer size, default 16384\n"
|
||||
//" -L, --nodelay <0 or 1> Set TCP_NODELAY option\n"
|
||||
" -S, --snd-buf <size> Set SO_SNDBUF option\n"
|
||||
" -R, --rcv-buf <size> Set SO_RCVBUF option\n"
|
||||
" -x, --debug Print logs, 0, 1 or 2\n"
|
||||
// desync options
|
||||
" -K, --desync-known Desync only HTTP and TLS with SNI\n"
|
||||
#ifdef FAKE_SUPPORT
|
||||
" -m, --method <s|d|f> Desync method: split,disorder,fake\n"
|
||||
#else
|
||||
" -m, --method <s|d> Desync method: split,disorder\n"
|
||||
#endif
|
||||
" -s, --split-pos <offset> Split position, default 3\n"
|
||||
" -H, --split-at-host Add Host/SNI offset to split position\n"
|
||||
#ifdef FAKE_SUPPORT
|
||||
" -t, --ttl <num> TTL of fake packets, default 8\n"
|
||||
" -l, --fake-tls <file>\n"
|
||||
" -o, --fake-http <file>\n"
|
||||
" -e, --fake-udp <file> Set custom fake packet\n"
|
||||
" -n, --tls-sni <str> Change SNI in fake CH\n"
|
||||
#endif
|
||||
" -M, --mod-http <h,d,r> Modify http: hcsmix,dcsmix,rmspace\n"
|
||||
" -u, --desync-udp <f> UDP desync method: fake\n"
|
||||
};
|
||||
|
||||
|
||||
const struct option options[] = {
|
||||
{"daemon", 0, 0, 'D'},
|
||||
{"no-domain", 0, 0, 'N'},
|
||||
{"no-ipv6", 0, 0, 'X'},
|
||||
{"no-udp", 0, 0, 'U'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{"version", 0, 0, 'v'},
|
||||
{"pidfile", 1, 0, 'f'},
|
||||
{"ip", 1, 0, 'i'},
|
||||
{"port", 1, 0, 'p'},
|
||||
{"conn-ip", 1, 0, 'I'},
|
||||
{"bfs", 1, 0, 'b'},
|
||||
//{"nodelay", 1, 0, 'L'},
|
||||
{"snd-buf", 1, 0, 'S'},
|
||||
{"rcv-buf", 1, 0, 'R'},
|
||||
{"max-conn", 1, 0, 'c'},
|
||||
{"debug", 1, 0, 'x'},
|
||||
|
||||
{"desync-known ", 0, 0, 'K'},
|
||||
{"split-at-host", 0, 0, 'H'},
|
||||
{"method", 1, 0, 'm'},
|
||||
{"split-pos", 1, 0, 's'},
|
||||
{"ttl", 1, 0, 't'},
|
||||
#ifdef FAKE_SUPPORT
|
||||
{"fake-tls", 1, 0, 'l'},
|
||||
{"fake-http", 1, 0, 'o'},
|
||||
{"fake-udp", 1, 0, 'e'},
|
||||
{"tls-sni", 1, 0, 'n'},
|
||||
#endif
|
||||
{"mod-http", 1, 0, 'M'},
|
||||
{"desync-udp", 1, 0, 'u'},
|
||||
{"global-ttl", 1, 0, 'g'}, //
|
||||
{"delay", 1, 0, 'w'}, //
|
||||
|
||||
{0}
|
||||
};
|
||||
|
||||
|
||||
char *ftob(char *name, ssize_t *sl)
|
||||
{
|
||||
char *buffer = 0;
|
||||
@ -80,7 +162,6 @@ char *ftob(char *name, ssize_t *sl)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
void daemonize(void)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
@ -103,6 +184,25 @@ void daemonize(void)
|
||||
dup(0);
|
||||
}
|
||||
|
||||
int get_addr(char *str, struct sockaddr_ina *addr)
|
||||
{
|
||||
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) {
|
||||
return -1;
|
||||
}
|
||||
if (res->ai_addr->sa_family == AF_INET6)
|
||||
addr->in6 = *(struct sockaddr_in6 *)res->ai_addr;
|
||||
else
|
||||
addr->in = *(struct sockaddr_in *)res->ai_addr;
|
||||
freeaddrinfo(res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@ -110,80 +210,41 @@ int main(int argc, char **argv)
|
||||
.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;
|
||||
|
||||
char opt[optc + 1];
|
||||
opt[optc] = 0;
|
||||
|
||||
for (int i = 0, o = 0; o < optc; i++, o++) {
|
||||
opt[o] = options[i].val;
|
||||
for (int c = options[i].has_arg; c; c--) {
|
||||
o++;
|
||||
opt[o] = ':';
|
||||
}
|
||||
}
|
||||
|
||||
char daemon = 0;
|
||||
char *pidfile = 0;
|
||||
|
||||
const char help_text[] = {
|
||||
//"Proxy:\n"
|
||||
" -i, --ip, <ip> Listening IP address\n"
|
||||
" -p, --port <num> Listening port num\n"
|
||||
" -D, --daemon Daemonize\n"
|
||||
" -f, --pidfile <file> Write pid to file\n"
|
||||
" -c, --max-conn <count> Connection count limit, default 512\n"
|
||||
" -N, --no-domain Deny domain resolving\n"
|
||||
" -U, --no-udp Deny UDP associate\n"
|
||||
" -K, --desync-known Desync only HTTP and TLS with SNI\n"
|
||||
//"Desync:\n"
|
||||
" -m, --method <s|d|f> Desync method: split,disorder,fake\n"
|
||||
" -s, --split-pos <offset> Split position, default 3\n"
|
||||
" -H, --split-at-host Add Host/SNI offset to split position\n"
|
||||
" -t, --ttl <num> TTL of fake packets, default 8\n"
|
||||
" -l, --fake-tls <file>\n"
|
||||
" -o, --fake-http <file>\n"
|
||||
" -e, --fake-udp <file> Set custom fake packet\n"
|
||||
" -n, --tls-sni <str> Change SNI in fake CH\n"
|
||||
" -M, --mod-http <h,d,r> Modify http: hcsmix,dcsmix,rmspace\n"
|
||||
" -u, --desync-udp <f> UDP desync method: fake\n"
|
||||
};
|
||||
|
||||
const struct option options[] = {
|
||||
{"daemon", 0, 0, 'D'},
|
||||
{"no-domain", 0, 0, 'N'},
|
||||
{"no-ipv6", 0, 0, 'X'}, //
|
||||
{"no-udp", 0, 0, 'U'},
|
||||
{"desync-known ", 0, 0, 'K'},
|
||||
{"split-at-host", 0, 0, 'H'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{"version", 0, 0, 'v'},
|
||||
{"pidfile", 1, 0, 'f'},
|
||||
{"ip", 1, 0, 'i'},
|
||||
{"port", 1, 0, 'p'},
|
||||
{"bfs", 1, 0, 'b'}, //
|
||||
{"snd-bfs", 1, 0, 'B'}, //
|
||||
{"max-conn", 1, 0, 'c'},
|
||||
{"method", 1, 0, 'm'},
|
||||
{"split-pos", 1, 0, 's'},
|
||||
{"ttl", 1, 0, 't'},
|
||||
{"fake-tls", 1, 0, 'l'},
|
||||
{"fake-http", 1, 0, 'o'},
|
||||
{"fake-udp", 1, 0, 'e'},
|
||||
{"tls-sni", 1, 0, 'n'},
|
||||
{"mod-http", 1, 0, 'M'},
|
||||
{"desync-udp", 1, 0, 'u'},
|
||||
{"global-ttl", 1, 0, 'g'}, //
|
||||
{"delay", 1, 0, 'w'}, //
|
||||
{"debug", 1, 0, 'x'}, //
|
||||
|
||||
{0}
|
||||
};
|
||||
int rez;
|
||||
int invalid = 0;
|
||||
|
||||
long val = 0;
|
||||
char *end = 0;
|
||||
uint16_t port = htons(1080);
|
||||
|
||||
while (!invalid && (rez = getopt_long_only(argc, argv,
|
||||
"DNXUKHhvf:i:p:b:B:c:m:s:t:l:o:e:n:M:u:g:w:x:", options, 0)) != -1) {
|
||||
while (!invalid && (rez = getopt_long_only(
|
||||
argc, argv, opt, options, 0)) != -1) {
|
||||
switch (rez) {
|
||||
|
||||
case 'D':
|
||||
daemon = 1;
|
||||
break;
|
||||
case 'f':
|
||||
pidfile = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
params.resolve = 0;
|
||||
break;
|
||||
@ -193,41 +254,18 @@ int main(int argc, char **argv)
|
||||
case 'U':
|
||||
params.udp = 0;
|
||||
break;
|
||||
case 'K':
|
||||
params.de_known = 1;
|
||||
break;
|
||||
case 'h':
|
||||
printf(help_text);
|
||||
return 0;
|
||||
case 'v':
|
||||
printf("%d\n", VERSION);
|
||||
return 0;
|
||||
|
||||
case 'b': //
|
||||
val = strtol(optarg, &end, 0);
|
||||
if (val <= 0 || val > INT_MAX/4 || *end)
|
||||
invalid = 1;
|
||||
else
|
||||
params.bfsize = val;
|
||||
case 'f':
|
||||
pidfile = optarg;
|
||||
break;
|
||||
|
||||
case 'B': //
|
||||
val = strtol(optarg, &end, 0);
|
||||
if (val <= 0 || val > INT_MAX || *end)
|
||||
invalid = 1;
|
||||
else
|
||||
params.send_bfsz = val;
|
||||
break;
|
||||
|
||||
|
||||
case 'i':
|
||||
if (strchr(optarg, ':'))
|
||||
s.in.sin_family = AF_INET6;
|
||||
else
|
||||
s.in.sin_family = AF_INET;
|
||||
|
||||
if (!inet_pton(s.in.sin_family, optarg,
|
||||
(s.in.sin_family == AF_INET ?
|
||||
(char *)&s.in.sin_addr : (char *)&s.in6.sin6_addr)))
|
||||
if (get_addr(optarg, &s) < 0)
|
||||
invalid = 1;
|
||||
break;
|
||||
|
||||
@ -236,7 +274,46 @@ int main(int argc, char **argv)
|
||||
if (val <= 0 || val > 0xffff || *end)
|
||||
invalid = 1;
|
||||
else
|
||||
s.in.sin_port = htons(val);
|
||||
port = htons(val);
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
if (get_addr(optarg, &b) < 0)
|
||||
invalid = 1;
|
||||
else
|
||||
params.baddr = b.in6;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
val = strtol(optarg, &end, 0);
|
||||
if (val <= 0 || val > INT_MAX/4 || *end)
|
||||
invalid = 1;
|
||||
else
|
||||
params.bfsize = val;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
val = strtol(optarg, &end, 0);
|
||||
if (val < 0 || val > 1 || *end)
|
||||
invalid = 1;
|
||||
else
|
||||
params.nodelay = val;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
val = strtol(optarg, &end, 0);
|
||||
if (val <= 0 || val > INT_MAX || *end)
|
||||
invalid = 1;
|
||||
else
|
||||
params.send_bfsz = val;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
val = strtol(optarg, &end, 0);
|
||||
if (val <= 0 || val > INT_MAX || *end)
|
||||
invalid = 1;
|
||||
else
|
||||
params.recv_bfsz = val;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
@ -247,6 +324,22 @@ int main(int argc, char **argv)
|
||||
params.max_open = val;
|
||||
break;
|
||||
|
||||
case 'x': //
|
||||
params.debug = strtol(optarg, 0, 0);
|
||||
if (params.debug < 0)
|
||||
invalid = 1;
|
||||
break;
|
||||
|
||||
// desync options
|
||||
|
||||
case 'K':
|
||||
params.de_known = 1;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
params.split_host = 1;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (params.attack != DESYNC_NONE) {
|
||||
fprintf(stderr, "methods incompatible\n");
|
||||
@ -275,10 +368,6 @@ int main(int argc, char **argv)
|
||||
params.split = val;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
params.split_host = 1;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
val = strtol(optarg, &end, 0);
|
||||
if (val <= 0 || val > 255 || *end)
|
||||
@ -362,11 +451,6 @@ int main(int argc, char **argv)
|
||||
invalid = 1;
|
||||
break;
|
||||
|
||||
case 'x': //
|
||||
params.debug = strtol(optarg, 0, 0);
|
||||
if (params.debug < 0)
|
||||
invalid = 1;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
@ -383,10 +467,18 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "invalid value: -%c %s\n", rez, optarg);
|
||||
return -1;
|
||||
}
|
||||
if (params.send_bfsz * 2 <= params.bfsize) {
|
||||
s.in.sin_port = port;
|
||||
b.in.sin_port = 0;
|
||||
|
||||
if (b.sa.sa_family != AF_INET6) {
|
||||
params.ipv6 = 0;
|
||||
}
|
||||
if (params.send_bfsz &&
|
||||
params.send_bfsz * 2 <= params.bfsize) {
|
||||
fprintf(stderr, "send buffer too small\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *file;
|
||||
if (pidfile) {
|
||||
file = fopen(pidfile, "w");
|
||||
@ -419,5 +511,6 @@ int main(int argc, char **argv)
|
||||
close(fd);
|
||||
params.def_ttl = orig_ttl;
|
||||
}
|
||||
|
||||
return listener(s);
|
||||
}
|
||||
}
|
||||
|
12
params.h
12
params.h
@ -1,4 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
enum demode {
|
||||
DESYNC_NONE,
|
||||
@ -10,6 +11,7 @@ enum demode {
|
||||
#define DESYNC_UDP_FAKE 1
|
||||
|
||||
struct params {
|
||||
char de_known;
|
||||
int ttl;
|
||||
int split;
|
||||
size_t sfdelay;
|
||||
@ -22,19 +24,20 @@ struct params {
|
||||
char ipv6;
|
||||
char resolve;
|
||||
char udp;
|
||||
char de_known;
|
||||
int max_open;
|
||||
|
||||
int debug;
|
||||
size_t bfsize;
|
||||
int nodelay;
|
||||
int send_bfsz;
|
||||
int recv_bfsz;
|
||||
struct sockaddr_in6 baddr;
|
||||
};
|
||||
|
||||
extern struct params params;
|
||||
|
||||
struct packet {
|
||||
ssize_t size;
|
||||
char *data;
|
||||
ssize_t size;
|
||||
char *data;
|
||||
};
|
||||
extern struct packet fake_tls;
|
||||
extern struct packet fake_http;
|
||||
@ -45,3 +48,4 @@ extern struct packet fake_udp;
|
||||
|
||||
#define LOG(s, str, ...) \
|
||||
if (params.debug >= s) printf(str, ##__VA_ARGS__)
|
||||
|
||||
|
218
proxy.c
218
proxy.c
@ -6,6 +6,11 @@
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <proxy.h>
|
||||
#include <params.h>
|
||||
#include <conev.h>
|
||||
#include <desync.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@ -15,11 +20,7 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <proxy.h>
|
||||
#include <params.h>
|
||||
#include <conev.h>
|
||||
#include <desync.h>
|
||||
|
||||
|
||||
int NOT_EXIT = 1;
|
||||
|
||||
static void on_cancel(int sig) {
|
||||
@ -27,18 +28,18 @@ static void on_cancel(int sig) {
|
||||
}
|
||||
|
||||
|
||||
static inline int ip_cmp(
|
||||
static inline int ip_equ(
|
||||
struct sockaddr_ina *a, struct sockaddr_ina *b)
|
||||
{
|
||||
if (a->sa.sa_family == AF_INET) {
|
||||
return
|
||||
*((uint32_t *)(&a->in.sin_addr)) !=
|
||||
*((uint32_t *)(&a->in.sin_addr)) ==
|
||||
*((uint32_t *)(&b->in.sin_addr));
|
||||
}
|
||||
return
|
||||
*((uint64_t *)(&a->in6.sin6_addr)) !=
|
||||
*((uint64_t *)(&b->in6.sin6_addr)) ||
|
||||
*((uint64_t *)(&a->in6.sin6_addr) + 1) !=
|
||||
*((uint64_t *)(&a->in6.sin6_addr)) ==
|
||||
*((uint64_t *)(&b->in6.sin6_addr)) &&
|
||||
*((uint64_t *)(&a->in6.sin6_addr) + 1) ==
|
||||
*((uint64_t *)(&b->in6.sin6_addr) + 1);
|
||||
}
|
||||
|
||||
@ -67,7 +68,8 @@ void map_fix(struct sockaddr_ina *addr, char f6)
|
||||
}
|
||||
|
||||
|
||||
static inline int nb_socket(int domain, int type) {
|
||||
static inline int nb_socket(int domain, int type)
|
||||
{
|
||||
#ifdef __linux__
|
||||
int fd = socket(domain, type | SOCK_NONBLOCK, 0);
|
||||
#else
|
||||
@ -88,14 +90,38 @@ static inline int nb_socket(int domain, int type) {
|
||||
}
|
||||
|
||||
|
||||
int setopts(int fd)
|
||||
{
|
||||
if (params.nodelay &&
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
|
||||
(char *)¶ms.nodelay, sizeof(params.nodelay))) {
|
||||
perror("setsockopt TCP_NODELAY");
|
||||
return -1;
|
||||
}
|
||||
if (params.send_bfsz &&
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
|
||||
(char *)¶ms.send_bfsz, sizeof(params.send_bfsz))) {
|
||||
perror("setsockopt SO_SNDBUF");
|
||||
return -1;
|
||||
}
|
||||
if (params.recv_bfsz &&
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *)¶ms.recv_bfsz, sizeof(params.recv_bfsz))) {
|
||||
perror("setsockopt SO_RCVBUF");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int resolve(char *host, int len,
|
||||
struct sockaddr_ina *addr, int type)
|
||||
{
|
||||
struct addrinfo hints = {0}, *res = 0;
|
||||
|
||||
hints.ai_socktype = type;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
hints.ai_family = params.ipv6 ? AF_UNSPEC : AF_INET;
|
||||
|
||||
char rchar = host[len];
|
||||
host[len] = '\0';
|
||||
@ -141,7 +167,7 @@ int resp_error(int fd, int e, int flag, int re)
|
||||
struct s4_req s4r = {
|
||||
.cmd = e ? S4_ER : S4_OK
|
||||
};
|
||||
return send(fd, &s4r, sizeof(s4r), 0);
|
||||
return send(fd, (char *)&s4r, sizeof(s4r), 0);
|
||||
}
|
||||
else if (flag == FLAG_S5) {
|
||||
uint8_t se;
|
||||
@ -165,7 +191,7 @@ int resp_error(int fd, int e, int flag, int re)
|
||||
.ver = 0x05, .code = se,
|
||||
.atp = S_ATP_I4
|
||||
};
|
||||
return send(fd, &s5r, sizeof(s5r), 0);
|
||||
return send(fd, (char *)&s5r, sizeof(s5r), 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -235,7 +261,7 @@ int s_get_addr(char *buffer, ssize_t n,
|
||||
if (!params.resolve) {
|
||||
return -S_ER_ATP;
|
||||
}
|
||||
if (r->id.len == 1) {
|
||||
if (r->id.len == 1 && type == SOCK_DGRAM) {
|
||||
addr->in.sin_family = AF_INET;
|
||||
LOG(LOG_S, "domain len=1\n");
|
||||
}
|
||||
@ -291,34 +317,45 @@ int s_set_addr(char *buffer, ssize_t n,
|
||||
int create_conn(struct poolhd *pool,
|
||||
struct eval *val, struct sockaddr_ina *dst)
|
||||
{
|
||||
int sfd = nb_socket(dst->sa.sa_family, SOCK_STREAM);
|
||||
struct sockaddr_ina addr = *dst;
|
||||
|
||||
if (params.baddr.sin6_family == AF_INET6) {
|
||||
map_fix(&addr, 6);
|
||||
}
|
||||
int sfd = nb_socket(addr.sa.sa_family, SOCK_STREAM);
|
||||
if (sfd < 0) {
|
||||
perror("socket");
|
||||
return -1;
|
||||
}
|
||||
if (addr.sa.sa_family == AF_INET6) {
|
||||
int no = 0;
|
||||
if (setsockopt(sfd, IPPROTO_IPV6,
|
||||
IPV6_V6ONLY, (char *)&no, sizeof(no))) {
|
||||
perror("setsockopt IPV6_V6ONLY");
|
||||
close(sfd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (bind(sfd, (struct sockaddr *)¶ms.baddr,
|
||||
sizeof(params.baddr)) < 0) {
|
||||
perror("bind");
|
||||
close(sfd);
|
||||
return -1;
|
||||
}
|
||||
#ifdef __linux__
|
||||
int syn_count = 1;
|
||||
if (setsockopt(sfd, IPPROTO_TCP,
|
||||
TCP_SYNCNT, &syn_count, sizeof(syn_count))) {
|
||||
TCP_SYNCNT, (char *)&syn_count, sizeof(syn_count))) {
|
||||
perror("setsockopt TCP_SYNCNT");
|
||||
close(sfd);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
int one = 1;
|
||||
if (setsockopt(sfd, IPPROTO_TCP,
|
||||
TCP_NODELAY, (char *)&one, sizeof(one))) {
|
||||
perror("setsockopt TCP_NODELAY");
|
||||
if (setopts(sfd) < 0) {
|
||||
close(sfd);
|
||||
return -1;
|
||||
}
|
||||
if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF,
|
||||
¶ms.send_bfsz, sizeof(params.send_bfsz)) < 0) {
|
||||
close(sfd);
|
||||
perror("setsockopt SO_SNDBUF");
|
||||
return -1;
|
||||
}
|
||||
int status = connect(sfd, &dst->sa, sizeof(*dst));
|
||||
int status = connect(sfd, &addr.sa, sizeof(addr));
|
||||
if (status < 0 && errno != EINPROGRESS) {
|
||||
perror("connect");
|
||||
close(sfd);
|
||||
@ -340,22 +377,47 @@ int create_conn(struct poolhd *pool,
|
||||
int udp_asc(struct poolhd *pool,
|
||||
struct eval *val, struct sockaddr_ina *dst)
|
||||
{
|
||||
int ufd = nb_socket(AF_INET6, SOCK_DGRAM);
|
||||
struct sockaddr_ina bnda = {
|
||||
.sa = {.sa_family = dst->sa.sa_family}}, dsta = {0};
|
||||
socklen_t asz = sizeof(bnda);
|
||||
|
||||
int ip_not_set = ip_equ(&bnda, dst);
|
||||
bnda.in6 = params.baddr;
|
||||
|
||||
if (ip_not_set) {
|
||||
dsta.in6 = val->in6;
|
||||
dsta.in.sin_port = dst->in.sin_port;
|
||||
} else {
|
||||
dsta.in6 = dst->in6;
|
||||
}
|
||||
|
||||
if (bnda.sa.sa_family == AF_INET6) {
|
||||
map_fix(&dsta, 6);
|
||||
}
|
||||
if (dsta.sa.sa_family == AF_INET6) {
|
||||
map_fix(&bnda, 6);
|
||||
}
|
||||
|
||||
int ufd = nb_socket(bnda.sa.sa_family, SOCK_DGRAM);
|
||||
if (ufd < 0) {
|
||||
perror("socket");
|
||||
return -1;
|
||||
}
|
||||
struct sockaddr_ina addr = {0};
|
||||
socklen_t asz = sizeof(addr);
|
||||
int ip_is_set = ip_cmp(dst, &addr);
|
||||
|
||||
addr.sa.sa_family = AF_INET6;
|
||||
if (bind(ufd, &addr.sa, sizeof(addr)) < 0) {
|
||||
if (bnda.sa.sa_family == AF_INET6) {
|
||||
int no = 0;
|
||||
if (setsockopt(ufd, IPPROTO_IPV6,
|
||||
IPV6_V6ONLY, (char *)&no, sizeof(no))) {
|
||||
perror("setsockopt IPV6_V6ONLY");
|
||||
close(ufd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (bind(ufd, &bnda.sa, sizeof(bnda)) < 0) {
|
||||
perror("bind");
|
||||
close(ufd);
|
||||
return -1;
|
||||
}
|
||||
if (getsockname(ufd, &addr.sa, &asz)) {
|
||||
if (getsockname(ufd, &bnda.sa, &asz)) {
|
||||
perror("getsockname");
|
||||
close(ufd);
|
||||
return -1;
|
||||
@ -365,25 +427,18 @@ int udp_asc(struct poolhd *pool,
|
||||
close(ufd);
|
||||
return -1;
|
||||
}
|
||||
upair->in6 = dst->in6;
|
||||
if (!ip_is_set) {
|
||||
if (dst->sa.sa_family == AF_INET)
|
||||
upair->in.sin_addr = val->in.sin_addr;
|
||||
else
|
||||
upair->in6.sin6_addr = val->in6.sin6_addr;
|
||||
}
|
||||
map_fix((struct sockaddr_ina *)&upair->in6, 6);
|
||||
val->pair = upair;
|
||||
upair->pair = val;
|
||||
upair->in6 = dsta.in6;
|
||||
|
||||
struct s5_req s5r = {
|
||||
.ver = 0x05
|
||||
};
|
||||
int offs = s_set_addr((char *)&s5r, sizeof(s5r), &addr, 0);
|
||||
int offs = s_set_addr((char *)&s5r, sizeof(s5r), &bnda, 0);
|
||||
if (offs < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (send(val->fd, &s5r, offs, 0) < 0) {
|
||||
if (send(val->fd, (char *)&s5r, offs, 0) < 0) {
|
||||
perror("send");
|
||||
return -1;
|
||||
}
|
||||
@ -471,7 +526,8 @@ static inline int on_accept(struct poolhd *pool, struct eval *val)
|
||||
int c = accept(val->fd, &client.sa, &len);
|
||||
#endif
|
||||
if (c < 0) {
|
||||
if (errno == EAGAIN)
|
||||
if (errno == EAGAIN ||
|
||||
errno == EINPROGRESS)
|
||||
break;
|
||||
perror("accept");
|
||||
return -1;
|
||||
@ -483,16 +539,7 @@ static inline int on_accept(struct poolhd *pool, struct eval *val)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
int one = 1;
|
||||
if (setsockopt(c, IPPROTO_TCP,
|
||||
TCP_NODELAY, (char *)&one, sizeof(one))) {
|
||||
perror("setsockopt TCP_NODELAY");
|
||||
close(c);
|
||||
continue;
|
||||
}
|
||||
if (setsockopt(c, SOL_SOCKET, SO_SNDBUF,
|
||||
¶ms.send_bfsz, sizeof(params.send_bfsz)) < 0) {
|
||||
perror("setsockopt SO_SNDBUF");
|
||||
if (setopts(c) < 0) {
|
||||
close(c);
|
||||
continue;
|
||||
}
|
||||
@ -506,22 +553,6 @@ static inline int on_accept(struct poolhd *pool, struct eval *val)
|
||||
}
|
||||
|
||||
|
||||
static inline int on_data(struct eval *val, char *buffer, size_t bfsize)
|
||||
{
|
||||
ssize_t n = recv(val->fd, buffer, bfsize, 0);
|
||||
if (n <= 0) {
|
||||
if (n) perror("recv data");
|
||||
return -1;
|
||||
}
|
||||
if (desync(val->pair->fd, buffer,
|
||||
n, (struct sockaddr *)&val->pair->in6)) {
|
||||
return -1;
|
||||
}
|
||||
val->type = EV_TUNNEL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int on_connect(struct poolhd *pool, struct eval *val,
|
||||
char *buffer, size_t bfsize, int e)
|
||||
{
|
||||
@ -546,9 +577,20 @@ static inline int on_connect(struct poolhd *pool, struct eval *val,
|
||||
val->type = EV_TUNNEL;
|
||||
mod_etype(pool, val, POLLOUT, 0);
|
||||
val->pair->type = EV_CONNECT;
|
||||
return 0;
|
||||
}
|
||||
return on_data(val, buffer, bfsize);
|
||||
else {
|
||||
ssize_t n = recv(val->fd, buffer, bfsize, 0);
|
||||
if (n <= 0) {
|
||||
if (n) perror("recv data");
|
||||
return -1;
|
||||
}
|
||||
if (desync(val->pair->fd, buffer,
|
||||
n, (struct sockaddr *)&val->pair->in6)) {
|
||||
return -1;
|
||||
}
|
||||
val->type = EV_TUNNEL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -618,10 +660,12 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val,
|
||||
|
||||
int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize)
|
||||
{
|
||||
struct sockaddr_ina addr;
|
||||
int skip = S_SIZE_I6, offs;
|
||||
do {
|
||||
struct sockaddr_ina addr = {0};
|
||||
struct sockaddr_ina *dst = (struct sockaddr_ina *)&val->in6;
|
||||
socklen_t asz = sizeof(addr);
|
||||
|
||||
ssize_t n = recvfrom(val->fd, buffer + skip,
|
||||
bfsize - skip, 0, &addr.sa, &asz), ns;
|
||||
|
||||
@ -632,11 +676,11 @@ int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!val->in6.sin6_port) {
|
||||
val->in6.sin6_port = addr.in6.sin6_port;
|
||||
if (!dst->in.sin_port) {
|
||||
dst->in.sin_port = addr.in.sin_port;
|
||||
}
|
||||
if (!ip_cmp((struct sockaddr_ina *)&val->in6, &addr) &&
|
||||
addr.in6.sin6_port == val->in6.sin6_port) {
|
||||
|
||||
if (ip_equ(dst, &addr) && dst->in.sin_port == addr.in.sin_port) {
|
||||
if (buffer[skip + 2]) { // frag
|
||||
continue;
|
||||
}
|
||||
@ -644,8 +688,12 @@ int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize)
|
||||
if (offs < 0) {
|
||||
return -1;
|
||||
}
|
||||
map_fix(&addr, 6);
|
||||
|
||||
if (dst->in.sin_family == AF_INET6) {
|
||||
map_fix(&addr, 6);
|
||||
}
|
||||
if (dst->in.sin_family != addr.sa.sa_family) {
|
||||
return -1;
|
||||
}
|
||||
if (val->flag == FLAG_CONN)
|
||||
ns = sendto(val->fd,
|
||||
buffer + skip + offs, n - offs, 0, &addr.sa, asz);
|
||||
@ -661,6 +709,7 @@ int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize)
|
||||
if (offs < 0 || offs > skip) {
|
||||
return -1;
|
||||
}
|
||||
memset(buffer + skip - offs, 0, 3);
|
||||
ns = sendto(val->fd, buffer + skip - offs,
|
||||
n + offs, 0, (struct sockaddr *)&val->in6, sizeof(val->in6));
|
||||
}
|
||||
@ -751,9 +800,10 @@ int big_loop(int srvfd)
|
||||
|
||||
int listener(struct sockaddr_ina srv)
|
||||
{
|
||||
#ifdef SIGPIPE
|
||||
if (signal(SIGPIPE, SIG_IGN))
|
||||
perror("signal SIGPIPE!");
|
||||
|
||||
#endif
|
||||
if (signal(SIGINT, on_cancel))
|
||||
perror("signal SIGINT!");
|
||||
|
||||
@ -782,4 +832,4 @@ int listener(struct sockaddr_ina srv)
|
||||
int status = big_loop(srvfd);
|
||||
close(srvfd);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user