Delete UDP support

This commit is contained in:
ruti 2023-10-10 20:24:46 +02:00
parent ad697d9abd
commit 391dd8e758
8 changed files with 29 additions and 298 deletions

View File

@ -24,8 +24,7 @@ enum eid {
EV_REQUEST, EV_REQUEST,
EV_CONNECT, EV_CONNECT,
EV_IGNORE, EV_IGNORE,
EV_TUNNEL, EV_TUNNEL
EV_UDP_TUNNEL
}; };
#define FLAG_S4 1 #define FLAG_S4 1
@ -38,8 +37,7 @@ char *eid_name[] = {
"EV_REQUEST", "EV_REQUEST",
"EV_CONNECT", "EV_CONNECT",
"EV_IGNORE", "EV_IGNORE",
"EV_TUNNEL", "EV_TUNNEL"
"EV_UDP_TUNNEL"
}; };
#endif #endif

View File

@ -197,32 +197,3 @@ int desync(int sfd, char *buffer,
} }
return 0; return 0;
} }
int desync_udp(int fd, char *buffer,
ssize_t n, struct sockaddr *dst)
{
int fa = get_family(dst);
socklen_t s = dst->sa_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
if (params.desync_udp & DESYNC_UDP_FAKE) {
if (setttl(fd, params.ttl, fa) < 0) {
return -1;
}
if (sendto(fd, fake_udp.data,
fake_udp.size, 0, dst, s) < 0) {
perror("sendto");
return -1;
}
if (setttl(fd, params.def_ttl, fa) < 0) {
return -1;
}
}
ssize_t ns = sendto(fd, buffer, n, 0, dst, s);
if (ns < 0) {
perror("sendto");
return -1;
}
return 0;
}

View File

@ -1,2 +1 @@
int desync(int sfd, char *buffer, ssize_t n, struct sockaddr *dst); int desync(int sfd, char *buffer, ssize_t n, struct sockaddr *dst);
int desync_udp(int fd, char *buffer, ssize_t n, struct sockaddr *dst);

31
main.c
View File

@ -26,9 +26,6 @@ struct packet fake_tls = {
}, },
fake_http = { fake_http = {
sizeof(http_data), http_data sizeof(http_data), http_data
},
fake_udp = {
sizeof(udp_data), udp_data
}; };
@ -37,7 +34,6 @@ struct params params = {
.split = 3, .split = 3,
.sfdelay = 3000, .sfdelay = 3000,
.attack = DESYNC_NONE, .attack = DESYNC_NONE,
.desync_udp = 0,
.split_host = 0, .split_host = 0,
.def_ttl = 0, .def_ttl = 0,
.mod_http = 0, .mod_http = 0,
@ -45,7 +41,6 @@ struct params params = {
.ipv6 = 1, .ipv6 = 1,
.resolve = 1, .resolve = 1,
.udp = 1,
.max_open = 512, .max_open = 512,
.bfsize = 16384, .bfsize = 16384,
.nodelay = 1, .nodelay = 1,
@ -65,7 +60,6 @@ const char help_text[] = {
" -f, --pidfile <file> Write pid to file\n" " -f, --pidfile <file> Write pid to file\n"
" -c, --max-conn <count> Connection count limit, default 512\n" " -c, --max-conn <count> Connection count limit, default 512\n"
" -N, --no-domain Deny domain resolving\n" " -N, --no-domain Deny domain resolving\n"
" -U, --no-udp Deny UDP associate\n"
" -I --conn-ip <ip> Connection binded IP, default ::\n" " -I --conn-ip <ip> Connection binded IP, default ::\n"
" -b, --bfs <size> Buffer size, default 16384\n" " -b, --bfs <size> Buffer size, default 16384\n"
//" -L, --nodelay <0 or 1> Set TCP_NODELAY option\n" //" -L, --nodelay <0 or 1> Set TCP_NODELAY option\n"
@ -84,12 +78,10 @@ const char help_text[] = {
#ifdef FAKE_SUPPORT #ifdef FAKE_SUPPORT
" -t, --ttl <num> TTL of fake packets, default 8\n" " -t, --ttl <num> TTL of fake packets, default 8\n"
" -l, --fake-tls <file>\n" " -l, --fake-tls <file>\n"
" -o, --fake-http <file>\n" " -o, --fake-http <file> Set custom fake packet\n"
" -e, --fake-udp <file> Set custom fake packet\n"
" -n, --tls-sni <str> Change SNI in fake CH\n" " -n, --tls-sni <str> Change SNI in fake CH\n"
#endif #endif
" -M, --mod-http <h,d,r> Modify http: hcsmix,dcsmix,rmspace\n" " -M, --mod-http <h,d,r> Modify http: hcsmix,dcsmix,rmspace\n"
" -u, --desync-udp <f> UDP desync method: fake\n"
}; };
@ -97,7 +89,6 @@ const struct option options[] = {
{"daemon", 0, 0, 'D'}, {"daemon", 0, 0, 'D'},
{"no-domain", 0, 0, 'N'}, {"no-domain", 0, 0, 'N'},
{"no-ipv6", 0, 0, 'X'}, {"no-ipv6", 0, 0, 'X'},
{"no-udp", 0, 0, 'U'},
{"help", 0, 0, 'h'}, {"help", 0, 0, 'h'},
{"version", 0, 0, 'v'}, {"version", 0, 0, 'v'},
{"pidfile", 1, 0, 'f'}, {"pidfile", 1, 0, 'f'},
@ -119,11 +110,9 @@ const struct option options[] = {
#ifdef FAKE_SUPPORT #ifdef FAKE_SUPPORT
{"fake-tls", 1, 0, 'l'}, {"fake-tls", 1, 0, 'l'},
{"fake-http", 1, 0, 'o'}, {"fake-http", 1, 0, 'o'},
{"fake-udp", 1, 0, 'e'},
{"tls-sni", 1, 0, 'n'}, {"tls-sni", 1, 0, 'n'},
#endif #endif
{"mod-http", 1, 0, 'M'}, {"mod-http", 1, 0, 'M'},
{"desync-udp", 1, 0, 'u'},
{"global-ttl", 1, 0, 'g'}, // {"global-ttl", 1, 0, 'g'}, //
{"delay", 1, 0, 'w'}, // {"delay", 1, 0, 'w'}, //
@ -251,9 +240,6 @@ int main(int argc, char **argv)
case 'X': case 'X':
params.ipv6 = 0; params.ipv6 = 0;
break; break;
case 'U':
params.udp = 0;
break;
case 'h': case 'h':
printf(help_text); printf(help_text);
return 0; return 0;
@ -400,14 +386,6 @@ int main(int argc, char **argv)
} }
break; break;
case 'e':
fake_udp.data = ftob(optarg, &fake_udp.size);
if (!fake_udp.data) {
perror("read file");
return -1;
}
break;
case 'M': case 'M':
end = optarg; end = optarg;
while (end && !invalid) { while (end && !invalid) {
@ -430,13 +408,6 @@ int main(int argc, char **argv)
} }
break; break;
case 'u':
if (*optarg != 'f')
invalid = 1;
else
params.desync_udp = DESYNC_UDP_FAKE;
break;
case 'g': // case 'g': //
val = strtol(optarg, &end, 0); val = strtol(optarg, &end, 0);
if (val <= 0 || val > 255 || *end) if (val <= 0 || val > 255 || *end)

View File

@ -47,8 +47,6 @@ char http_data[43] = {
"Host: www.wikipedia.org\r\n\r\n" "Host: www.wikipedia.org\r\n\r\n"
}; };
char udp_data[64] = {0};
int find_tls_ext_offset(uint16_t type, char *data, size_t size) int find_tls_ext_offset(uint16_t type, char *data, size_t size)
{ {

View File

@ -11,7 +11,6 @@
extern char tls_data[517]; extern char tls_data[517];
extern char http_data[43]; extern char http_data[43];
extern char udp_data[64];
int change_tls_sni(char *host, char *buffer, size_t bsize); int change_tls_sni(char *host, char *buffer, size_t bsize);

View File

@ -8,22 +8,18 @@ enum demode {
DESYNC_FAKE DESYNC_FAKE
}; };
#define DESYNC_UDP_FAKE 1
struct params { struct params {
char de_known; char de_known;
int ttl; int ttl;
int split; int split;
size_t sfdelay; size_t sfdelay;
enum demode attack; enum demode attack;
int desync_udp;
char split_host; char split_host;
int def_ttl; int def_ttl;
int mod_http; int mod_http;
char ipv6; char ipv6;
char resolve; char resolve;
char udp;
int max_open; int max_open;
int debug; int debug;
size_t bfsize; size_t bfsize;
@ -41,7 +37,6 @@ struct packet {
}; };
extern struct packet fake_tls; extern struct packet fake_tls;
extern struct packet fake_http; extern struct packet fake_http;
extern struct packet fake_udp;
#define LOG_S 1 #define LOG_S 1
#define LOG_L 2 #define LOG_L 2

242
proxy.c
View File

@ -28,22 +28,6 @@ static void on_cancel(int sig) {
} }
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 *)(&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 *)(&b->in6.sin6_addr) + 1);
}
void map_fix(struct sockaddr_ina *addr, char f6) void map_fix(struct sockaddr_ina *addr, char f6)
{ {
struct { struct {
@ -115,11 +99,11 @@ int setopts(int fd)
int resolve(char *host, int len, int resolve(char *host, int len,
struct sockaddr_ina *addr, int type) struct sockaddr_ina *addr)
{ {
struct addrinfo hints = {0}, *res = 0; struct addrinfo hints = {0}, *res = 0;
hints.ai_socktype = type; hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG; hints.ai_flags = AI_ADDRCONFIG;
hints.ai_family = params.ipv6 ? AF_UNSPEC : AF_INET; hints.ai_family = params.ipv6 ? AF_UNSPEC : AF_INET;
@ -219,7 +203,7 @@ int handle_socks4(int fd, char *bf,
int len = (bf + n - ie) - 2; int len = (bf + n - ie) - 2;
if (len < 3) if (len < 3)
break; break;
if (resolve(ie + 1, len, dst, SOCK_STREAM)) { if (resolve(ie + 1, len, dst)) {
fprintf(stderr, "not resolved: %.*s\n", len, ie + 1); fprintf(stderr, "not resolved: %.*s\n", len, ie + 1);
break; break;
} }
@ -240,7 +224,7 @@ int handle_socks4(int fd, char *bf,
int s_get_addr(char *buffer, ssize_t n, int s_get_addr(char *buffer, ssize_t n,
struct sockaddr_ina *addr, int type) struct sockaddr_ina *addr)
{ {
struct s5_req *r = (struct s5_req *)buffer; struct s5_req *r = (struct s5_req *)buffer;
@ -249,7 +233,7 @@ int s_get_addr(char *buffer, ssize_t n,
(r->atp == S_ATP_I6 ? S_SIZE_I6 : 0))); (r->atp == S_ATP_I6 ? S_SIZE_I6 : 0)));
if (n < o) { if (n < o) {
fprintf(stderr, "ss: bad request\n"); fprintf(stderr, "ss: bad request\n");
return -S_ER_GEN; return S_ER_GEN;
} }
switch (r->atp) { switch (r->atp) {
case S_ATP_I4: case S_ATP_I4:
@ -259,58 +243,25 @@ int s_get_addr(char *buffer, ssize_t n,
case S_ATP_ID: case S_ATP_ID:
if (!params.resolve) { if (!params.resolve) {
return -S_ER_ATP; return S_ER_ATP;
} }
if (r->id.len == 1 && type == SOCK_DGRAM) { if (r->id.len < 3 ||
addr->in.sin_family = AF_INET; resolve(r->id.domain, r->id.len, addr)) {
LOG(LOG_S, "domain len=1\n");
}
else if (resolve(r->id.domain, r->id.len, addr, type)) {
fprintf(stderr, "not resolved: %.*s\n", r->id.len, r->id.domain); fprintf(stderr, "not resolved: %.*s\n", r->id.len, r->id.domain);
return -S_ER_HOST; return S_ER_HOST;
} }
break; break;
case S_ATP_I6: case S_ATP_I6:
if (!params.ipv6) if (!params.ipv6)
return -S_ER_ATP; return S_ER_ATP;
else { else {
addr->in6.sin6_family = AF_INET6; addr->in6.sin6_family = AF_INET6;
addr->in6.sin6_addr = r->i6; addr->in6.sin6_addr = r->i6;
} }
} }
addr->in.sin_port = *(uint16_t *)&buffer[o - 2]; addr->in.sin_port = *(uint16_t *)&buffer[o - 2];
return o; return 0;
}
int s_set_addr(char *buffer, ssize_t n,
struct sockaddr_ina *addr, char end)
{
struct s5_req *r = (struct s5_req *)buffer;
if (n < S_SIZE_I4) {
return -1;
}
if (addr->sa.sa_family == AF_INET) {
if (end) {
r = (struct s5_req *)(buffer - S_SIZE_I4);
}
r->atp = S_ATP_I4;
r->i4 = addr->in.sin_addr;
r->p4 = addr->in.sin_port;
return S_SIZE_I4;
} else {
if (n < S_SIZE_I6) {
return -1;
}
if (end) {
r = (struct s5_req *)(buffer - S_SIZE_I6);
}
r->atp = S_ATP_I6;
r->i6 = addr->in6.sin6_addr;
r->p6 = addr->in6.sin6_port;
return S_SIZE_I6;
}
} }
@ -374,83 +325,11 @@ int create_conn(struct poolhd *pool,
} }
int udp_asc(struct poolhd *pool,
struct eval *val, struct sockaddr_ina *dst)
{
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;
}
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, &bnda.sa, &asz)) {
perror("getsockname");
close(ufd);
return -1;
}
struct eval *upair = add_event(pool, EV_UDP_TUNNEL, ufd, POLLIN);
if (!upair) {
close(ufd);
return -1;
}
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), &bnda, 0);
if (offs < 0) {
return -1;
}
if (send(val->fd, (char *)&s5r, offs, 0) < 0) {
perror("send");
return -1;
}
return 0;
}
static inline int on_request(struct poolhd *pool, struct eval *val, static inline int on_request(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize) char *buffer, size_t bfsize)
{ {
struct sockaddr_ina dst = {0}; struct sockaddr_ina dst = {0};
int error = 0, offs_e = 0; int error = 0, s5e = 0;
ssize_t n = recv(val->fd, buffer, bfsize, 0); ssize_t n = recv(val->fd, buffer, bfsize, 0);
if (n < 1) { if (n < 1) {
@ -471,25 +350,15 @@ static inline int on_request(struct poolhd *pool, struct eval *val,
} }
struct s5_req *r = (struct s5_req *)buffer; struct s5_req *r = (struct s5_req *)buffer;
switch (r->cmd) { if (r->cmd != S_CMD_CONN) {
case S_CMD_CONN: fprintf(stderr, "ss: unsupported cmd: 0x%x\n", r->cmd);
offs_e = s_get_addr(buffer, n, &dst, SOCK_STREAM); s5e = S_ER_CMD;
if (offs_e > 0) { }
else {
s5e = s_get_addr(buffer, n, &dst);
if (!s5e) {
error = create_conn(pool, val, &dst); error = create_conn(pool, val, &dst);
} }
break;
case S_CMD_AUDP:
offs_e = s_get_addr(buffer, n, &dst, SOCK_DGRAM);
if (offs_e <= 0) {
break;
}
if (params.udp) {
error = udp_asc(pool, val, &dst);
break;
}
default:
fprintf(stderr, "ss: unsupported cmd: 0x%x\n", r->cmd);
offs_e = -S_ER_CMD;
} }
} }
else if (*buffer == S_VER4) { else if (*buffer == S_VER4) {
@ -503,8 +372,8 @@ static inline int on_request(struct poolhd *pool, struct eval *val,
fprintf(stderr, "ss: invalid version: 0x%x (%lu)\n", *buffer, n); fprintf(stderr, "ss: invalid version: 0x%x (%lu)\n", *buffer, n);
return -1; return -1;
} }
if (error || offs_e < 0) { if (error || s5e) {
if (resp_error(val->fd, errno, val->flag, -offs_e) < 0) if (resp_error(val->fd, error ? errno : 0, val->flag, s5e) < 0)
perror("send"); perror("send");
return -1; return -1;
} }
@ -658,70 +527,6 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val,
} }
int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize)
{
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;
if (n < 0 && errno == EAGAIN)
break;
if (n < 1) {
perror("recv udp");
return -1;
}
if (!dst->in.sin_port) {
dst->in.sin_port = addr.in.sin_port;
}
if (ip_equ(dst, &addr) && dst->in.sin_port == addr.in.sin_port) {
if (buffer[skip + 2]) { // frag
continue;
}
offs = s_get_addr(buffer + skip, n, &addr, SOCK_DGRAM);
if (offs < 0) {
return -1;
}
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);
else {
ns = desync_udp(val->fd,
buffer + skip + offs, n - offs, &addr.sa);
val->flag = FLAG_CONN;
}
} else {
map_fix(&addr, 0);
offs = s_set_addr(buffer + skip, skip, &addr, 1);
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));
}
if (ns < 0) {
perror("sendto");
return -1;
}
} while(1);
return 0;
}
int big_loop(int srvfd) int big_loop(int srvfd)
{ {
size_t bfsize = params.bfsize; size_t bfsize = params.bfsize;
@ -776,11 +581,6 @@ int big_loop(int srvfd)
del_event(pool, val); del_event(pool, val);
continue; continue;
case EV_UDP_TUNNEL:
if (on_udp_tunnel(val, buffer, bfsize))
del_event(pool, val);
continue;
case EV_IGNORE: case EV_IGNORE:
if (etype & (POLLHUP | POLLERR | POLLRDHUP)) if (etype & (POLLHUP | POLLERR | POLLRDHUP))
del_event(pool, val); del_event(pool, val);