byedpi/main.c

902 lines
23 KiB
C
Raw Normal View History

2023-06-03 19:52:10 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
2023-06-12 04:00:33 +00:00
#include <limits.h>
2023-06-03 19:52:10 +00:00
2024-05-02 16:36:29 +00:00
#include "params.h"
#include "proxy.h"
#include "packets.h"
#include "error.h"
2023-06-03 19:52:10 +00:00
2024-02-18 20:20:52 +00:00
#ifndef _WIN32
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <netinet/in.h>
2024-03-19 23:23:56 +00:00
#include <netinet/tcp.h>
#include <sys/socket.h>
2024-02-18 20:20:52 +00:00
#else
#include <ws2tcpip.h>
2024-04-23 12:48:37 +00:00
#include "win_service.h"
2024-02-18 20:20:52 +00:00
#define close(fd) closesocket(fd)
#endif
2024-09-17 19:51:39 +00:00
#define VERSION "14.1"
2024-04-09 11:06:34 +00:00
char ip_option[1] = "\0";
2023-06-03 19:52:10 +00:00
struct packet fake_tls = {
sizeof(tls_data), tls_data
},
fake_http = {
sizeof(http_data), http_data
2024-02-29 17:07:59 +00:00
},
2024-07-29 09:26:42 +00:00
fake_udp = {
sizeof(udp_data), udp_data
2023-06-03 19:52:10 +00:00
};
struct params params = {
.sfdelay = 3,
2024-03-20 22:01:36 +00:00
.wait_send = 1,
2023-06-03 19:52:10 +00:00
2024-03-13 19:18:16 +00:00
.cache_ttl = 100800,
2023-06-03 19:52:10 +00:00
.ipv6 = 1,
.resolve = 1,
2024-04-23 05:47:27 +00:00
.udp = 1,
2023-06-03 19:52:10 +00:00
.max_open = 512,
.bfsize = 16384,
.baddr = {
.sin6_family = AF_INET6
},
.laddr = {
.sin6_family = AF_INET
},
.debug = 0,
.auto_level = 0
2023-06-03 19:52:10 +00:00
};
const char help_text[] = {
" -i, --ip, <ip> Listening IP, default 0.0.0.0\n"
" -p, --port <num> Listening port, default 1080\n"
#ifdef __linux__
" -E, --transparent Transparent proxy mode\n"
#endif
" -c, --max-conn <count> Connection count limit, default 512\n"
" -N, --no-domain Deny domain resolving\n"
2024-04-23 05:47:27 +00:00
" -U, --no-udp Deny UDP association\n"
" -I --conn-ip <ip> Connection binded IP, default ::\n"
2023-10-16 12:44:24 +00:00
" -b, --buf-size <size> Buffer size, default 16384\n"
" -x, --debug <level> Print logs, 0, 1 or 2\n"
2023-10-16 12:44:24 +00:00
" -g, --def-ttl <num> TTL for all outgoing connections\n"
// desync options
2024-03-19 23:23:56 +00:00
#ifdef TCP_FASTOPEN_CONNECT
" -F, --tfo Enable TCP Fast Open\n"
#endif
2024-08-13 14:00:03 +00:00
" -A, --auto <t,r,s,n> Try desync params after this option\n"
" Detect: torst,redirect,ssl_err,none\n"
" -L, --auto-mode <0|1> 1 - handle trigger after several packets\n"
2024-03-08 18:33:25 +00:00
" -u, --cache-ttl <sec> Lifetime of cached desync params for IP\n"
2024-03-13 19:18:16 +00:00
#ifdef TIMEOUT_SUPPORT
2024-03-16 21:19:14 +00:00
" -T, --timeout <sec> Timeout waiting for response, after which trigger auto\n"
2024-03-13 19:18:16 +00:00
#endif
2024-07-29 09:26:42 +00:00
" -K, --proto <t,h,u> Protocol whitelist: tls,http,udp\n"
2024-07-29 13:08:35 +00:00
" -H, --hosts <file|:str> Hosts whitelist, filename or :string\n"
2024-07-29 14:58:56 +00:00
" -V, --pf <port[-portr]> Ports range whitelist\n"
2024-03-06 17:37:59 +00:00
" -s, --split <n[+s]> Split packet at n\n"
" +s - add SNI offset\n"
" +h - add HTTP Host offset\n"
2024-03-26 14:15:34 +00:00
" -d, --disorder <n[+s]> Split and send reverse order\n"
" -o, --oob <n[+s]> Split and send as OOB data\n"
2024-08-16 16:08:22 +00:00
" -q, --disoob <n[+s]> Split and send reverse order as OOB data\n"
#ifdef FAKE_SUPPORT
" -f, --fake <n[+s]> Split and send fake packet\n"
" -t, --ttl <num> TTL of fake packets, default 8\n"
2024-03-26 14:15:34 +00:00
#ifdef __linux__
" -k, --ip-opt[=f|:str] IP options of fake packets\n"
2024-03-26 14:15:34 +00:00
" -S, --md5sig Add MD5 Signature option for fake packets\n"
#endif
2024-08-16 16:08:22 +00:00
" -O, --fake-offset <n> Fake data start offset\n"
2024-04-23 05:47:27 +00:00
" -l, --fake-data <f|:str> Set custom fake packet\n"
2024-03-06 17:37:59 +00:00
" -n, --tls-sni <str> Change SNI in fake ClientHello\n"
#endif
2024-08-22 15:15:14 +00:00
" -e, --oob-data <char> Set custom OOB data\n"
2024-03-06 17:37:59 +00:00
" -M, --mod-http <h,d,r> Modify HTTP: hcsmix,dcsmix,rmspace\n"
2024-03-16 21:19:14 +00:00
" -r, --tlsrec <n[+s]> Make TLS record at position\n"
2024-07-29 14:58:56 +00:00
" -a, --udp-fake <count> UDP fakes count, default 0\n"
2024-08-09 19:49:44 +00:00
#ifdef __linux__
" -Y, --drop-sack Drop packets with SACK extension\n"
#endif
};
const struct option options[] = {
{"no-domain", 0, 0, 'N'},
{"no-ipv6", 0, 0, 'X'},
2024-04-23 05:47:27 +00:00
{"no-udp", 0, 0, 'U'},
{"help", 0, 0, 'h'},
{"version", 0, 0, 'v'},
{"ip", 1, 0, 'i'},
{"port", 1, 0, 'p'},
#ifdef __linux__
{"transparent", 0, 0, 'E'},
#endif
{"conn-ip", 1, 0, 'I'},
2023-10-16 12:44:24 +00:00
{"buf-size", 1, 0, 'b'},
{"max-conn", 1, 0, 'c'},
{"debug", 1, 0, 'x'},
2024-03-19 23:23:56 +00:00
#ifdef TCP_FASTOPEN_CONNECT
{"tfo ", 0, 0, 'F'},
#endif
2024-08-13 14:00:03 +00:00
{"auto", 1, 0, 'A'},
{"auto-mode", 1, 0, 'L'},
2024-03-08 18:33:25 +00:00
{"cache-ttl", 1, 0, 'u'},
2024-03-13 19:18:16 +00:00
#ifdef TIMEOUT_SUPPORT
{"timeout", 1, 0, 'T'},
#endif
2024-07-29 09:26:42 +00:00
{"proto", 1, 0, 'K'},
2024-04-16 17:55:41 +00:00
{"hosts", 1, 0, 'H'},
2024-07-29 13:08:35 +00:00
{"pf", 1, 0, 'V'},
{"split", 1, 0, 's'},
{"disorder", 1, 0, 'd'},
{"oob", 1, 0, 'o'},
2024-08-16 16:08:22 +00:00
{"disoob", 1, 0, 'q'},
#ifdef FAKE_SUPPORT
{"fake", 1, 0, 'f'},
{"ttl", 1, 0, 't'},
2024-03-26 14:15:34 +00:00
#ifdef __linux__
{"ip-opt", 2, 0, 'k'},
2024-03-26 14:15:34 +00:00
{"md5sig", 0, 0, 'S'},
#endif
2024-04-23 05:47:27 +00:00
{"fake-data", 1, 0, 'l'},
{"tls-sni", 1, 0, 'n'},
2024-08-16 16:08:22 +00:00
{"fake-offset", 1, 0, 'O'},
#endif
2024-02-29 17:07:59 +00:00
{"oob-data", 1, 0, 'e'},
{"mod-http", 1, 0, 'M'},
2024-02-18 14:19:11 +00:00
{"tlsrec", 1, 0, 'r'},
2024-07-29 09:26:42 +00:00
{"udp-fake", 1, 0, 'a'},
2023-10-16 12:44:24 +00:00
{"def-ttl", 1, 0, 'g'},
{"delay", 1, 0, 'w'}, //
2024-03-26 14:15:34 +00:00
{"not-wait-send", 0, 0, 'W'}, //
2024-04-27 23:50:46 +00:00
#ifdef __linux__
2024-08-09 19:49:44 +00:00
{"drop-sack", 0, 0, 'Y'},
2024-04-27 23:50:46 +00:00
{"protect-path", 1, 0, 'P'}, //
#endif
{0}
};
2024-08-16 16:08:22 +00:00
size_t parse_cform(char *buffer, size_t blen,
const char *str, size_t slen)
2023-06-03 19:52:10 +00:00
{
2024-03-16 21:19:14 +00:00
static char esca[] = {
'r','\r','n','\n','t','\t','\\','\\',
'f','\f','b','\b','v','\v','a','\a', 0
};
ssize_t i = 0, p = 0;
2024-08-16 16:08:22 +00:00
for (; p < slen && i < blen; ++p && ++i) {
2024-03-16 21:19:14 +00:00
if (str[p] != '\\') {
2024-08-16 16:08:22 +00:00
buffer[i] = str[p];
2024-03-16 21:19:14 +00:00
continue;
}
p++;
char *e = esca;
for (; *e; e += 2) {
if (*e == str[p]) {
2024-08-16 16:08:22 +00:00
buffer[i] = *(e + 1);
2024-03-16 21:19:14 +00:00
break;
}
}
if (*e) {
continue;
}
int n = 0;
2024-08-16 16:08:22 +00:00
if (sscanf(&str[p], "x%2hhx%n", &buffer[i], &n) == 1
|| sscanf(&str[p], "%3hho%n", &buffer[i], &n) == 1) {
2024-03-16 21:19:14 +00:00
p += (n - 1);
continue;
}
i--; p--;
}
2024-08-16 16:08:22 +00:00
return i;
}
char *data_from_str(const char *str, ssize_t *size)
{
ssize_t len = strlen(str);
if (len == 0) {
return 0;
}
char *d = malloc(len);
if (!d) {
return 0;
}
size_t i = parse_cform(d, len, str, len);
char *m = len != i ? realloc(d, i) : 0;
if (i == 0) {
return 0;
}
*size = i;
2024-03-16 21:19:14 +00:00
return m ? m : d;
}
char *ftob(const char *str, ssize_t *sl)
{
if (*str == ':') {
2024-08-16 16:08:22 +00:00
return data_from_str(str + 1, sl);
2024-03-16 21:19:14 +00:00
}
2023-06-03 19:52:10 +00:00
char *buffer = 0;
2023-07-07 20:07:27 +00:00
long size;
2023-06-03 19:52:10 +00:00
2024-03-16 21:19:14 +00:00
FILE *file = fopen(str, "rb");
2024-04-16 17:55:41 +00:00
if (!file) {
2023-06-03 19:52:10 +00:00
return 0;
2024-04-16 17:55:41 +00:00
}
2023-06-03 19:52:10 +00:00
do {
if (fseek(file, 0, SEEK_END)) {
break;
}
2023-07-07 20:07:27 +00:00
size = ftell(file);
2024-04-16 17:55:41 +00:00
if (size <= 0) {
break;
}
if (fseek(file, 0, SEEK_SET)) {
break;
}
2023-06-03 19:52:10 +00:00
if (!(buffer = malloc(size))) {
break;
}
if (fread(buffer, 1, size, file) != size) {
free(buffer);
buffer = 0;
}
} while (0);
2023-07-07 20:07:27 +00:00
if (buffer) {
*sl = size;
}
2023-06-03 19:52:10 +00:00
fclose(file);
return buffer;
}
2023-10-16 12:44:24 +00:00
static inline int lower_char(char *cl)
{
char c = *cl;
if (c < 'A') {
if (c > '9' || c < '-')
return -1;
}
else if (c < 'a') {
if (c > 'Z')
return -1;
*cl = c + 32;
}
else if (c > 'z')
return -1;
return 0;
}
2024-04-16 17:55:41 +00:00
struct mphdr *parse_hosts(char *buffer, size_t size)
{
struct mphdr *hdr = mem_pool(1);
if (!hdr) {
return 0;
}
size_t num = 0;
2024-04-16 17:55:41 +00:00
char *end = buffer + size;
char *e = buffer, *s = buffer;
for (; e <= end; e++) {
2024-07-18 22:53:25 +00:00
if (e != end && *e != ' ' && *e != '\n' && *e != '\r') {
if (lower_char(e)) {
LOG(LOG_E, "invalid host: num: %zd (%.*s)\n", num + 1, (int )(e - s + 1), s);
}
2024-04-16 17:55:41 +00:00
continue;
}
if (s == e) {
s++;
continue;
}
if (mem_add(hdr, s, e - s) == 0) {
free(hdr);
return 0;
}
num++;
2024-04-16 17:55:41 +00:00
s = e + 1;
}
return hdr;
}
2024-03-16 21:19:14 +00:00
int get_addr(const 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;
2024-03-13 19:18:16 +00:00
if (getaddrinfo(str, 0, &hints, &res) || !res) {
return -1;
}
if (res->ai_addr->sa_family == AF_INET6)
addr->in6.sin6_addr = (
(struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
else
addr->in.sin_addr = (
(struct sockaddr_in *)res->ai_addr)->sin_addr;
addr->sa.sa_family = res->ai_addr->sa_family;
freeaddrinfo(res);
2024-03-11 15:38:39 +00:00
return 0;
}
2023-06-03 19:52:10 +00:00
2023-10-16 12:44:24 +00:00
int get_default_ttl()
{
int orig_ttl = -1, fd;
socklen_t tsize = sizeof(orig_ttl);
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
2024-02-18 20:20:52 +00:00
uniperror("socket");
2023-10-16 12:44:24 +00:00
return -1;
}
if (getsockopt(fd, IPPROTO_IP, IP_TTL,
(char *)&orig_ttl, &tsize) < 0) {
2024-02-18 20:20:52 +00:00
uniperror("getsockopt IP_TTL");
2023-10-16 12:44:24 +00:00
}
close(fd);
return orig_ttl;
}
int parse_offset(struct part *part, const char *str)
{
char *end = 0;
long val = strtol(str, &end, 0);
if (*end == '+') switch (*(end + 1)) {
case 's':
part->flag = OFFSET_SNI;
2024-03-04 12:30:23 +00:00
break;
case 'h':
part->flag = OFFSET_HOST;
2024-03-04 12:30:23 +00:00
break;
2024-08-06 16:11:01 +00:00
case 'e':
part->flag = OFFSET_END;
break;
default:
return -1;
2024-03-04 12:30:23 +00:00
}
else if (*end) {
return -1;
}
part->pos = val;
return 0;
2024-03-04 12:30:23 +00:00
}
2024-03-16 21:19:14 +00:00
void *add(void **root, int *n, size_t ss)
2024-03-08 00:37:02 +00:00
{
2024-04-16 17:55:41 +00:00
char *p = realloc(*root, ss * (*n + 1));
2024-03-08 00:37:02 +00:00
if (!p) {
uniperror("realloc");
return 0;
}
*root = p;
2024-04-16 17:55:41 +00:00
p = (p + ((*n) * ss));
2024-03-16 21:19:14 +00:00
memset(p, 0, ss);
2024-03-08 00:37:02 +00:00
*n = *n + 1;
return p;
}
void clear_params(void)
{
#ifdef _WIN32
WSACleanup();
#endif
if (params.mempool) {
mem_destroy(params.mempool);
params.mempool = 0;
}
if (params.dp) {
for (int i = 0; i < params.dp_count; i++) {
struct desync_params s = params.dp[i];
if (s.ip_options != ip_option) {
free(s.ip_options);
s.ip_options = ip_option;
}
2024-03-26 20:47:01 +00:00
if (s.parts != 0) {
free(s.parts);
s.parts = 0;
}
2024-05-02 18:23:14 +00:00
if (s.tlsrec != 0) {
free(s.tlsrec);
s.tlsrec = 0;
}
if (s.fake_data.data != 0) {
free(s.fake_data.data);
2024-04-23 05:47:27 +00:00
s.fake_data.data = 0;
}
if (s.file_ptr != 0) {
free(s.file_ptr);
2024-04-27 23:50:46 +00:00
s.file_ptr = 0;
}
2024-07-18 22:53:25 +00:00
if (s.hosts != 0) {
mem_destroy(s.hosts);
s.hosts = 0;
}
}
free(params.dp);
params.dp = 0;
}
}
2023-06-03 19:52:10 +00:00
int main(int argc, char **argv)
{
2024-02-18 20:20:52 +00:00
#ifdef _WIN32
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa)) {
uniperror("WSAStartup");
return -1;
}
if (register_winsvc(argc, argv)) {
return 0;
}
2024-02-18 20:20:52 +00:00
#endif
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] = ':';
}
}
params.laddr.sin6_port = htons(1080);
2023-06-03 19:52:10 +00:00
int rez;
int invalid = 0;
long val = 0;
2023-06-03 19:52:10 +00:00
char *end = 0;
bool all_limited = 1;
2024-03-11 15:38:39 +00:00
2024-03-16 21:19:14 +00:00
struct desync_params *dp = add((void *)&params.dp,
&params.dp_count, sizeof(struct desync_params));
2024-03-08 00:37:02 +00:00
if (!dp) {
clear_params();
2024-03-08 00:37:02 +00:00
return -1;
}
2024-04-16 17:55:41 +00:00
while (!invalid && (rez = getopt_long(
argc, argv, opt, options, 0)) != -1) {
2023-06-03 19:52:10 +00:00
switch (rez) {
case 'N':
params.resolve = 0;
break;
case 'X':
params.ipv6 = 0;
break;
2024-04-23 05:47:27 +00:00
case 'U':
params.udp = 0;
break;
#ifdef __linux__
case 'E':
params.transparent = 1;
break;
#endif
2024-04-23 05:47:27 +00:00
2023-06-03 19:52:10 +00:00
case 'h':
printf(help_text);
clear_params();
2023-06-03 19:52:10 +00:00
return 0;
case 'v':
2024-04-09 11:06:34 +00:00
printf("%s\n", VERSION);
clear_params();
2023-06-03 19:52:10 +00:00
return 0;
case 'i':
if (get_addr(optarg,
(struct sockaddr_ina *)&params.laddr) < 0)
invalid = 1;
break;
2023-06-03 19:52:10 +00:00
case 'p':
val = strtol(optarg, &end, 0);
if (val <= 0 || val > 0xffff || *end)
invalid = 1;
else
params.laddr.sin6_port = htons(val);
break;
case 'I':
if (get_addr(optarg,
(struct sockaddr_ina *)&params.baddr) < 0)
invalid = 1;
break;
case 'b':
2023-06-03 19:52:10 +00:00
val = strtol(optarg, &end, 0);
if (val <= 0 || val > INT_MAX/4 || *end)
invalid = 1;
else
params.bfsize = val;
break;
case 'c':
val = strtol(optarg, &end, 0);
if (val <= 0 || val >= (0xffff/2) || *end)
invalid = 1;
else
params.max_open = val;
break;
case 'x': //
params.debug = strtol(optarg, 0, 0);
if (params.debug < 0)
invalid = 1;
break;
// desync options
2024-03-19 23:23:56 +00:00
case 'F':
params.tfo = 1;
break;
case 'L':
val = strtol(optarg, &end, 0);
if (val < 0 || val > 1 || *end)
invalid = 1;
else
params.auto_level = val;
break;
2024-03-08 00:37:02 +00:00
case 'A':
if (!(dp->hosts || dp->proto || dp->pf[0] || dp->detect)) {
all_limited = 0;
}
2024-03-16 21:19:14 +00:00
dp = add((void *)&params.dp, &params.dp_count,
sizeof(struct desync_params));
2024-03-08 00:37:02 +00:00
if (!dp) {
clear_params();
2024-03-08 00:37:02 +00:00
return -1;
}
2024-04-03 19:51:02 +00:00
end = optarg;
while (end && !invalid) {
switch (*end) {
2024-04-04 01:19:40 +00:00
case 't':
dp->detect |= DETECT_TORST;
break;
2024-04-03 19:51:02 +00:00
case 'r':
dp->detect |= DETECT_HTTP_LOCAT;
break;
2024-08-13 14:00:03 +00:00
case 'a':
2024-04-03 19:51:02 +00:00
case 's':
2024-08-13 14:00:03 +00:00
dp->detect |= DETECT_TLS_ERR;
2024-04-03 19:51:02 +00:00
break;
2024-04-16 17:55:41 +00:00
case 'n':
break;
2024-04-03 19:51:02 +00:00
default:
invalid = 1;
continue;
2024-03-16 21:19:14 +00:00
}
2024-04-03 19:51:02 +00:00
end = strchr(end, ',');
if (end) end++;
2024-03-16 21:19:14 +00:00
}
break;
2024-04-04 01:19:40 +00:00
case 'u':
val = strtol(optarg, &end, 0);
if (val <= 0 || *end)
invalid = 1;
else
params.cache_ttl = val;
break;
case 'T':;
#ifdef __linux__
float f = strtof(optarg, &end);
val = (long)(f * 1000);
#else
val = strtol(optarg, &end, 0);
#endif
if (val <= 0 || val > UINT_MAX || *end)
invalid = 1;
else
params.timeout = val;
break;
2024-04-23 05:47:27 +00:00
case 'K':
end = optarg;
while (end && !invalid) {
switch (*end) {
case 't':
dp->proto |= IS_HTTPS;
break;
case 'h':
dp->proto |= IS_HTTP;
break;
2024-07-29 09:26:42 +00:00
case 'u':
dp->proto |= IS_UDP;
break;
2024-04-23 05:47:27 +00:00
default:
invalid = 1;
continue;
}
end = strchr(end, ',');
if (end) end++;
}
break;
2024-04-16 17:55:41 +00:00
case 'H':;
2024-04-27 23:50:46 +00:00
if (dp->file_ptr) {
continue;
}
dp->file_ptr = ftob(optarg, &dp->file_size);
if (!dp->file_ptr) {
2024-04-16 17:55:41 +00:00
uniperror("read/parse");
invalid = 1;
2024-04-29 20:35:40 +00:00
continue;
2024-04-16 17:55:41 +00:00
}
2024-04-27 23:50:46 +00:00
dp->hosts = parse_hosts(dp->file_ptr, dp->file_size);
2024-04-16 17:55:41 +00:00
if (!dp->hosts) {
perror("parse_hosts");
clear_params();
return -1;
}
break;
case 's':
case 'd':
case 'o':
2024-08-16 16:08:22 +00:00
case 'q':
case 'f':
;
2024-03-16 21:19:14 +00:00
struct part *part = add((void *)&dp->parts,
&dp->parts_n, sizeof(struct part));
if (!part) {
clear_params();
return -1;
}
if (parse_offset(part, optarg)) {
invalid = 1;
break;
}
switch (rez) {
case 's': part->m = DESYNC_SPLIT;
2023-06-03 19:52:10 +00:00
break;
case 'd': part->m = DESYNC_DISORDER;
2024-02-29 17:07:59 +00:00
break;
case 'o': part->m = DESYNC_OOB;
2023-06-03 19:52:10 +00:00
break;
2024-08-16 16:08:22 +00:00
case 'q': part->m = DESYNC_DISOOB;
2024-08-06 16:11:01 +00:00
break;
case 'f': part->m = DESYNC_FAKE;
}
2023-06-03 19:52:10 +00:00
break;
case 't':
val = strtol(optarg, &end, 0);
if (val <= 0 || val > 255 || *end)
invalid = 1;
else
2024-03-08 00:37:02 +00:00
dp->ttl = val;
2023-06-03 19:52:10 +00:00
break;
2024-03-20 22:01:36 +00:00
case 'k':
if (dp->ip_options) {
2024-04-27 23:50:46 +00:00
continue;
}
if (optarg)
dp->ip_options = ftob(optarg, &dp->ip_options_len);
else {
dp->ip_options = ip_option;
dp->ip_options_len = sizeof(ip_option);
}
2024-03-20 22:01:36 +00:00
if (!dp->ip_options) {
uniperror("read/parse");
invalid = 1;
2024-03-20 22:01:36 +00:00
}
break;
2024-03-26 14:15:34 +00:00
case 'S':
dp->md5sig = 1;
break;
2024-08-16 16:08:22 +00:00
case 'O':
2024-08-06 16:11:01 +00:00
val = strtol(optarg, &end, 0);
if (val <= 0 || *end)
invalid = 1;
else
dp->fake_offset = val;
break;
2023-06-03 19:52:10 +00:00
case 'n':
if (change_tls_sni(optarg, fake_tls.data, fake_tls.size)) {
fprintf(stderr, "error chsni\n");
clear_params();
2023-06-03 19:52:10 +00:00
return -1;
}
printf("sni: %s\n", optarg);
break;
case 'l':
2024-04-27 23:50:46 +00:00
if (dp->fake_data.data) {
continue;
}
2024-04-23 05:47:27 +00:00
dp->fake_data.data = ftob(optarg, &dp->fake_data.size);
if (!dp->fake_data.data) {
2024-03-16 21:19:14 +00:00
uniperror("read/parse");
invalid = 1;
2023-06-03 19:52:10 +00:00
}
break;
2024-02-29 17:07:59 +00:00
case 'e':
2024-08-16 16:08:22 +00:00
val = parse_cform(dp->oob_char, 1, optarg, strlen(optarg));
if (val != 1) {
invalid = 1;
2024-02-29 17:07:59 +00:00
}
2024-08-16 16:08:22 +00:00
else dp->oob_char[1] = 1;
2024-02-29 17:07:59 +00:00
break;
2023-06-03 19:52:10 +00:00
case 'M':
end = optarg;
while (end && !invalid) {
switch (*end) {
case 'r':
2024-03-08 00:37:02 +00:00
dp->mod_http |= MH_SPACE;
2023-06-03 19:52:10 +00:00
break;
case 'h':
2024-03-08 00:37:02 +00:00
dp->mod_http |= MH_HMIX;
2023-06-03 19:52:10 +00:00
break;
case 'd':
2024-03-08 00:37:02 +00:00
dp->mod_http |= MH_DMIX;
2023-06-03 19:52:10 +00:00
break;
default:
invalid = 1;
continue;
}
end = strchr(end, ',');
if (end) end++;
}
break;
2024-02-18 14:19:11 +00:00
case 'r':
2024-03-16 21:19:14 +00:00
part = add((void *)&dp->tlsrec,
&dp->tlsrec_n, sizeof(struct part));
2024-03-04 12:30:23 +00:00
if (!part) {
clear_params();
2024-03-04 12:30:23 +00:00
return -1;
2024-02-18 14:19:11 +00:00
}
if (parse_offset(part, optarg)
|| part->pos > 0xffff) {
invalid = 1;
break;
}
2024-02-18 14:19:11 +00:00
break;
2024-07-29 09:26:42 +00:00
case 'a':
val = strtol(optarg, &end, 0);
if (val < 0 || val > INT_MAX || *end)
invalid = 1;
else
dp->udp_fake_count = val;
break;
2024-07-29 13:08:35 +00:00
case 'V':
val = strtol(optarg, &end, 0);
if (val <= 0 || val > USHRT_MAX)
invalid = 1;
else {
dp->pf[0] = htons(val);
if (*end == '-') {
val = strtol(end + 1, &end, 0);
if (val <= 0 || val > USHRT_MAX)
invalid = 1;
}
if (*end)
invalid = 1;
else
dp->pf[1] = htons(val);
}
break;
2023-10-16 12:44:24 +00:00
case 'g':
2023-06-03 19:52:10 +00:00
val = strtol(optarg, &end, 0);
if (val <= 0 || val > 255 || *end)
invalid = 1;
2023-10-16 12:44:24 +00:00
else {
2023-06-03 19:52:10 +00:00
params.def_ttl = val;
2023-10-16 12:44:24 +00:00
params.custom_ttl = 1;
}
2023-06-03 19:52:10 +00:00
break;
2024-08-09 19:49:44 +00:00
case 'Y':
dp->drop_sack = 1;
break;
2024-03-26 14:15:34 +00:00
case 'w': //
2024-03-01 15:00:25 +00:00
params.sfdelay = strtol(optarg, &end, 0);
if (params.sfdelay < 0 || optarg == end
|| params.sfdelay >= 1000 || *end)
2023-06-03 19:52:10 +00:00
invalid = 1;
break;
2024-03-20 22:01:36 +00:00
case 'W':
params.wait_send = 0;
break;
2024-04-27 23:50:46 +00:00
#ifdef __linux__
case 'P':
params.protect_path = optarg;
break;
#endif
2023-06-03 19:52:10 +00:00
case 0:
break;
case '?':
clear_params();
2023-06-03 19:52:10 +00:00
return -1;
default:
printf("?: %c\n", rez);
clear_params();
2023-06-03 19:52:10 +00:00
return -1;
}
}
if (invalid) {
fprintf(stderr, "invalid value: -%c %s\n", rez, optarg);
clear_params();
2023-06-03 19:52:10 +00:00
return -1;
}
if (all_limited) {
2024-04-16 17:55:41 +00:00
dp = add((void *)&params.dp,
&params.dp_count, sizeof(struct desync_params));
if (!dp) {
clear_params();
return -1;
}
}
2024-04-25 22:18:44 +00:00
if (params.baddr.sin6_family != AF_INET6) {
params.ipv6 = 0;
}
if (!params.def_ttl) {
2023-10-16 12:44:24 +00:00
if ((params.def_ttl = get_default_ttl()) < 1) {
clear_params();
2023-06-03 19:52:10 +00:00
return -1;
}
}
2024-04-16 17:55:41 +00:00
params.mempool = mem_pool(0);
2024-03-08 00:37:02 +00:00
if (!params.mempool) {
uniperror("mem_pool");
clear_params();
2024-03-08 00:37:02 +00:00
return -1;
}
int status = run((struct sockaddr_ina *)&params.laddr);
clear_params();
2024-02-18 20:20:52 +00:00
return status;
}