byedpi/main.c

489 lines
12 KiB
C
Raw Normal View History

#define _GNU_SOURCE
2023-06-03 22:52:10 +03:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
2023-06-12 07:00:33 +03:00
#include <limits.h>
2023-06-03 22:52:10 +03:00
#include <params.h>
#include <proxy.h>
#include <packets.h>
2024-02-18 23:20:52 +03:00
#include <error.h>
2023-06-03 22:52:10 +03:00
2024-02-18 23:20:52 +03:00
#ifndef _WIN32
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
2024-02-18 23:20:52 +03:00
#define FAKE_SUPPORT 1
#else
#include <ws2tcpip.h>
#define close(fd) closesocket(fd)
#endif
2024-02-18 23:20:52 +03:00
#define VERSION 4
2023-06-03 22:52:10 +03:00
2023-06-03 22:52:10 +03:00
struct packet fake_tls = {
sizeof(tls_data), tls_data
},
fake_http = {
sizeof(http_data), http_data
2024-02-29 20:07:59 +03:00
},
oob_data = {
1, "a"
2023-06-03 22:52:10 +03:00
};
2024-02-29 20:07:59 +03:00
2023-06-03 22:52:10 +03:00
struct params params = {
.ttl = 8,
.parts = 0,
2023-06-03 22:52:10 +03:00
.sfdelay = 3000,
.split_host = 0,
.def_ttl = 0,
2023-10-16 15:44:24 +03:00
.custom_ttl = 0,
2023-06-03 22:52:10 +03:00
.mod_http = 0,
2024-02-18 17:19:11 +03:00
.tlsrec = 0,
.tlsrec_pos = 0,
.tlsrec_sni = 0,
.de_known = 0,
2023-06-03 22:52:10 +03:00
.ipv6 = 1,
.resolve = 1,
.max_open = 512,
.bfsize = 16384,
.baddr = {
.sin6_family = AF_INET6
},
2023-06-03 22:52:10 +03:00
.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"
" -c, --max-conn <count> Connection count limit, default 512\n"
" -N, --no-domain Deny domain resolving\n"
" -I --conn-ip <ip> Connection binded IP, default ::\n"
2023-10-16 15:44:24 +03:00
" -b, --buf-size <size> Buffer size, default 16384\n"
" -x, --debug Print logs, 0, 1 or 2\n"
2023-10-16 15:44:24 +03:00
" -g, --def-ttl <num> TTL for all outgoing connections\n"
// desync options
" -K, --desync-known Desync only HTTP and TLS with SNI\n"
" -H, --split-at-host Add Host/SNI offset to split position\n"
" -s, --split <offset> Split packet at spec position\n"
" -s, --disorder <offset> Split and send reverse order\n"
" -o, --oob <offset> Split and send as OOB data\n"
#ifdef FAKE_SUPPORT
" -f, --fake <offset> Split and send fake packet\n"
" -t, --ttl <num> TTL of fake packets, default 8\n"
" -l, --fake-tls <file>\n"
" -j, --fake-http <file> Set custom fake packet\n"
" -n, --tls-sni <str> Change SNI in fake CH\n"
#endif
2024-02-29 20:07:59 +03:00
" -e, --oob-data <file> Set custom oob bytes\n"
" -M, --mod-http <h,d,r> Modify http: hcsmix,dcsmix,rmspace\n"
2024-02-18 17:19:11 +03:00
" -r, --tlsrec <offset> Make 2 TLS records\n"
" -L, --tlsrec-at-sni Add SNI offset to tlsrec position\n"
};
const struct option options[] = {
{"no-domain", 0, 0, 'N'},
{"no-ipv6", 0, 0, 'X'},
{"help", 0, 0, 'h'},
{"version", 0, 0, 'v'},
{"ip", 1, 0, 'i'},
{"port", 1, 0, 'p'},
{"conn-ip", 1, 0, 'I'},
2023-10-16 15:44:24 +03:00
{"buf-size", 1, 0, 'b'},
{"max-conn", 1, 0, 'c'},
{"debug", 1, 0, 'x'},
{"desync-known ", 0, 0, 'K'},
{"split-at-host", 0, 0, 'H'},
{"split", 1, 0, 's'},
{"disorder", 1, 0, 'd'},
{"oob", 1, 0, 'o'},
{"fake", 1, 0, 'f'},
{"ttl", 1, 0, 't'},
#ifdef FAKE_SUPPORT
{"fake-tls", 1, 0, 'l'},
{"fake-http", 1, 0, 'j'},
{"tls-sni", 1, 0, 'n'},
#endif
2024-02-29 20:07:59 +03:00
{"oob-data", 1, 0, 'e'},
{"mod-http", 1, 0, 'M'},
2024-02-18 17:19:11 +03:00
{"tlsrec", 1, 0, 'r'},
{"tlsrec-at-sni", 0, 0, 'L'},
2023-10-16 15:44:24 +03:00
{"def-ttl", 1, 0, 'g'},
{"delay", 1, 0, 'w'}, //
{0}
};
2023-07-07 23:07:27 +03:00
char *ftob(char *name, ssize_t *sl)
2023-06-03 22:52:10 +03:00
{
char *buffer = 0;
2023-07-07 23:07:27 +03:00
long size;
2023-06-03 22:52:10 +03:00
FILE *file = fopen(name, "rb");
if (!file)
return 0;
do {
if (fseek(file, 0, SEEK_END)) {
break;
}
2023-07-07 23:07:27 +03:00
size = ftell(file);
2023-06-03 22:52:10 +03:00
if (!size || fseek(file, 0, SEEK_SET)) {
break;
}
if (!(buffer = malloc(size))) {
break;
}
if (fread(buffer, 1, size, file) != size) {
free(buffer);
buffer = 0;
}
} while (0);
2023-07-07 23:07:27 +03:00
if (buffer) {
*sl = size;
}
2023-06-03 22:52:10 +03:00
fclose(file);
return buffer;
}
2023-10-16 15:44:24 +03:00
2024-02-27 00:52:59 +03: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;
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;
}
2023-06-03 22:52:10 +03:00
2023-10-16 15:44:24 +03: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 23:20:52 +03:00
uniperror("socket");
2023-10-16 15:44:24 +03:00
return -1;
}
if (getsockopt(fd, IPPROTO_IP, IP_TTL,
(char *)&orig_ttl, &tsize) < 0) {
2024-02-18 23:20:52 +03:00
uniperror("getsockopt IP_TTL");
2023-10-16 15:44:24 +03:00
}
close(fd);
return orig_ttl;
}
2023-06-03 22:52:10 +03:00
int main(int argc, char **argv)
{
2024-02-18 23:20:52 +03:00
#ifdef _WIN32
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa)) {
uniperror("WSAStartup");
return -1;
}
#endif
2023-06-03 22:52:10 +03:00
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;
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] = ':';
}
}
2023-06-03 22:52:10 +03:00
char daemon = 0;
char *pidfile = 0;
int rez;
int invalid = 0;
long val = 0;
char *end = 0;
uint16_t port = htons(1080);
2023-06-03 22:52:10 +03:00
while (!invalid && (rez = getopt_long_only(
argc, argv, opt, options, 0)) != -1) {
2023-06-03 22:52:10 +03:00
switch (rez) {
case 'N':
params.resolve = 0;
break;
case 'X':
params.ipv6 = 0;
break;
case 'h':
printf(help_text);
return 0;
case 'v':
printf("%d\n", VERSION);
return 0;
case 'i':
if (get_addr(optarg, &s) < 0)
invalid = 1;
break;
2023-06-03 22:52:10 +03:00
case 'p':
val = strtol(optarg, &end, 0);
if (val <= 0 || val > 0xffff || *end)
invalid = 1;
else
port = htons(val);
break;
case 'I':
if (get_addr(optarg, &b) < 0)
invalid = 1;
else
params.baddr = b.in6;
break;
case 'b':
2023-06-03 22:52:10 +03: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
case 'K':
params.de_known = 1;
break;
case 'H':
params.split_host = 1;
break;
case 's':
case 'd':
case 'o':
case 'f':
val = strtol(optarg, &end, 0);
if (*end) {
2023-06-03 22:52:10 +03:00
invalid = 1;
break;
2023-06-03 22:52:10 +03:00
}
struct part *part = malloc(sizeof(struct part));
if (!part) {
uniperror("malloc");
return -1;
}
switch (rez) {
case 's': part->m = DESYNC_SPLIT;
2023-06-03 22:52:10 +03:00
break;
case 'd': part->m = DESYNC_DISORDER;
2024-02-29 20:07:59 +03:00
break;
case 'o': part->m = DESYNC_OOB;
2023-06-03 22:52:10 +03:00
break;
case 'f': part->m = DESYNC_FAKE;
}
part->pos = val;
if (!params.parts) {
params.parts = part;
}
else {
struct part *p = params.parts, *v = 0;
while (p) {
if (val < p->pos) {
if (v) {
part->next = p;
v->next = part;
}
else {
part->next = params.parts;
params.parts = part;
}
break;
}
if (!p->next) {
p->next = part;
part->next = 0;
break;
}
v = p;
p = p->next;
}
2023-06-03 22:52:10 +03:00
}
break;
case 't':
val = strtol(optarg, &end, 0);
if (val <= 0 || val > 255 || *end)
invalid = 1;
else
params.ttl = val;
break;
case 'n':
if (change_tls_sni(optarg, fake_tls.data, fake_tls.size)) {
fprintf(stderr, "error chsni\n");
return -1;
}
printf("sni: %s\n", optarg);
break;
case 'l':
2023-07-07 23:07:27 +03:00
fake_tls.data = ftob(optarg, &fake_tls.size);
2023-06-03 22:52:10 +03:00
if (!fake_tls.data) {
2024-03-02 14:14:02 +03:00
uniperror("read file");
2023-06-03 22:52:10 +03:00
return -1;
}
break;
case 'j':
2023-07-07 23:07:27 +03:00
fake_http.data = ftob(optarg, &fake_http.size);
2023-06-03 22:52:10 +03:00
if (!fake_http.data) {
2024-03-02 14:14:02 +03:00
uniperror("read file");
2023-06-03 22:52:10 +03:00
return -1;
}
break;
2024-02-29 20:07:59 +03:00
case 'e':
oob_data.data = ftob(optarg, &oob_data.size);
if (!oob_data.data) {
2024-03-02 14:14:02 +03:00
uniperror("read file");
2024-02-29 20:07:59 +03:00
return -1;
}
break;
2023-06-03 22:52:10 +03:00
case 'M':
end = optarg;
while (end && !invalid) {
switch (*end) {
case 'r':
params.mod_http |= MH_SPACE;
break;
case 'h':
params.mod_http |= MH_HMIX;
break;
case 'd':
params.mod_http |= MH_DMIX;
break;
default:
invalid = 1;
continue;
}
end = strchr(end, ',');
if (end) end++;
}
break;
2024-02-18 17:19:11 +03:00
case 'r':
val = strtol(optarg, &end, 0);
if (val > 0xffff || *end)
invalid = 1;
else {
params.tlsrec_pos = val;
params.tlsrec = 1;
}
break;
case 'L':
params.tlsrec_sni = 1;
break;
2023-10-16 15:44:24 +03:00
case 'g':
2023-06-03 22:52:10 +03:00
val = strtol(optarg, &end, 0);
if (val <= 0 || val > 255 || *end)
invalid = 1;
2023-10-16 15:44:24 +03:00
else {
2023-06-03 22:52:10 +03:00
params.def_ttl = val;
2023-10-16 15:44:24 +03:00
params.custom_ttl = 1;
}
2023-06-03 22:52:10 +03:00
break;
case 'w': //
2024-03-01 18:00:25 +03:00
params.sfdelay = strtol(optarg, &end, 0);
if (params.sfdelay < 0 || optarg == end
|| params.sfdelay >= 1000000 || *end)
2023-06-03 22:52:10 +03:00
invalid = 1;
break;
case 0:
break;
case '?':
return -1;
default:
printf("?: %c\n", rez);
return -1;
}
}
if (invalid) {
fprintf(stderr, "invalid value: -%c %s\n", rez, optarg);
return -1;
}
s.in.sin_port = port;
b.in.sin_port = 0;
if (b.sa.sa_family != AF_INET6) {
params.ipv6 = 0;
}
if (!params.def_ttl) {
2023-10-16 15:44:24 +03:00
if ((params.def_ttl = get_default_ttl()) < 1) {
2023-06-03 22:52:10 +03:00
return -1;
}
}
2024-02-27 18:34:02 +03:00
int status = run(&s);
2024-02-18 23:20:52 +03:00
#ifdef _WIN32
WSACleanup();
#endif
return status;
}