set ttl and EAGAIN handler

This commit is contained in:
ruti 2023-07-03 19:59:39 +02:00
parent a542ede01a
commit c4dc80498b
6 changed files with 91 additions and 84 deletions

16
conev.c
View file

@ -51,7 +51,9 @@ struct eval *add_event(struct poolhd *pool, enum eid type,
val->index = pool->count; val->index = pool->count;
val->type = type; val->type = type;
val->pair = 0; val->pair = 0;
val->send_count = 0; val->tmpbuf = 0;
val->size = 0;
val->offset = 0;
val->flag = 0; val->flag = 0;
#ifndef NOEPOLL #ifndef NOEPOLL
@ -80,6 +82,10 @@ void del_event(struct poolhd *pool, struct eval *val)
if (!val->fd) { if (!val->fd) {
return; return;
} }
if (val->tmpbuf) {
free(val->tmpbuf);
val->tmpbuf = 0;
}
close(val->fd); close(val->fd);
val->fd = 0; val->fd = 0;
pool->count--; pool->count--;
@ -106,7 +112,13 @@ void destroy_pool(struct poolhd *pool)
{ {
for (int x = 0; x < pool->count; x++) { for (int x = 0; x < pool->count; x++) {
struct eval *val = pool->links[x]; struct eval *val = pool->links[x];
if (val->fd) close(val->fd); if (val->fd) {
close(val->fd);
}
if (val->tmpbuf) {
free(val->tmpbuf);
val->tmpbuf = 0;
}
} }
if (pool->items) { if (pool->items) {
free(pool->items); free(pool->items);

View file

@ -48,7 +48,9 @@ struct eval {
int index; int index;
enum eid type; enum eid type;
struct eval *pair; struct eval *pair;
size_t send_count; char *tmpbuf;
ssize_t size;
int offset;
int flag; int flag;
#ifndef NOEPOLL #ifndef NOEPOLL
uint32_t events; uint32_t events;

View file

@ -10,9 +10,10 @@
#ifdef __linux__ #ifdef __linux__
#include <sys/sendfile.h> #include <sys/sendfile.h>
#define _sendfile(outfd, infd, start, len) sendfile(outfd, infd, start, len)
#else #else
#include <sys/uio.h> #include <sys/uio.h>
#define sendfile(outfd, infd, start, len) sendfile(infd, outfd, start, len, 0, 0) #define _sendfile(outfd, infd, start, len) sendfile(infd, outfd, start, len, 0, 0)
#endif #endif
#ifdef MFD_CLOEXEC #ifdef MFD_CLOEXEC
@ -26,7 +27,25 @@
#include <packets.h> #include <packets.h>
int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos) int setttl(int fd, int ttl, int family) {
int _ttl = ttl;
if (family == AF_INET) {
if (setsockopt(fd, IPPROTO_IP, IP_TTL,
&_ttl, sizeof(_ttl)) < 0) {
perror("setsockopt IP_TTL");
return -1;
}
}
else if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
&_ttl, sizeof(_ttl)) < 0) {
perror("setsockopt IPV6_UNICAST_HOPS");
return -1;
}
return 0;
}
int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos, int fa)
{ {
struct packet pkt = cnt != IS_HTTP ? fake_tls : fake_http; struct packet pkt = cnt != IS_HTTP ? fake_tls : fake_http;
size_t psz = pkt.size; size_t psz = pkt.size;
@ -51,12 +70,10 @@ int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos)
} }
memcpy(p, pkt.data, psz < pos ? psz : pos); memcpy(p, pkt.data, psz < pos ? psz : pos);
if (setsockopt(sfd, IPPROTO_IP, IP_TTL, if (setttl(sfd, params.ttl, fa) < 0) {
&params.ttl, sizeof(params.ttl)) < 0) {
perror("setsockopt IP_TTL");
break; break;
} }
if (sendfile(sfd, ffd, 0, pos) < 0) { if (_sendfile(sfd, ffd, 0, pos) < 0) {
perror("sendfile"); perror("sendfile");
break; break;
} }
@ -66,9 +83,7 @@ int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos)
nanosleep(&delay, 0); nanosleep(&delay, 0);
memcpy(p, buffer, pos); memcpy(p, buffer, pos);
if (setsockopt(sfd, IPPROTO_IP, IP_TTL, if (setttl(sfd, params.def_ttl, fa) < 0) {
&params.def_ttl, sizeof(int)) < 0) {
perror("setsockopt IP_TTL");
break; break;
} }
if (send(sfd, buffer + pos, n - pos, 0) < 0) { if (send(sfd, buffer + pos, n - pos, 0) < 0) {
@ -83,21 +98,17 @@ int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos)
} }
int disorder_attack(int sfd, char *buffer, ssize_t n, int pos) int disorder_attack(int sfd, char *buffer, ssize_t n, int pos, int fa)
{ {
int bttl = 1; int bttl = 1;
if (setsockopt(sfd, IPPROTO_IP, IP_TTL, if (setttl(sfd, bttl, fa) < 0) {
(char *)&bttl, sizeof(bttl)) < 0) {
perror("setsockopt IP_TTL");
return -1; return -1;
} }
if (send(sfd, buffer, pos, 0) < 0) { if (send(sfd, buffer, pos, 0) < 0) {
perror("send"); perror("send");
return -1; return -1;
} }
if (setsockopt(sfd, IPPROTO_IP, IP_TTL, if (setttl(sfd, params.def_ttl, fa) < 0) {
(char *)&params.def_ttl, sizeof(int)) < 0) {
perror("setsockopt IP_TTL");
return -1; return -1;
} }
if (send(sfd, buffer + pos, n - pos, 0) < 0) { if (send(sfd, buffer + pos, n - pos, 0) < 0) {
@ -114,6 +125,15 @@ int desync(int sfd, char *buffer, ssize_t n)
char *host = 0; char *host = 0;
int len = 0, type = 0; int len = 0, type = 0;
struct sockaddr sa;
socklen_t alen = sizeof(sa);
if (getsockname(sfd, &sa, &alen)) {
perror("getsockname");
return -1;
}
int fa = sa.sa_family;
if ((len = parse_tls(buffer, n, &host))) { if ((len = parse_tls(buffer, n, &host))) {
type = IS_HTTPS; type = IS_HTTPS;
} }
@ -146,10 +166,11 @@ int desync(int sfd, char *buffer, ssize_t n)
} }
else switch (params.attack) { else switch (params.attack) {
case DESYNC_FAKE: case DESYNC_FAKE:
return fake_attack(sfd, buffer, n, type, pos); return fake_attack(sfd, buffer, n, type, pos, fa);
case DESYNC_DISORDER: case DESYNC_DISORDER:
return disorder_attack(sfd, buffer, n, pos); printf("disorder attack\n");
return disorder_attack(sfd, buffer, n, pos, fa);
case DESYNC_SPLIT: case DESYNC_SPLIT:
default: default:

3
main.c
View file

@ -40,7 +40,6 @@ struct params params = {
.bfsize = 16384, .bfsize = 16384,
.send_bfsz = 65536, .send_bfsz = 65536,
.nack_max = 65536 * 2 - 16384,
.debug = 0 .debug = 0
}; };
@ -369,8 +368,6 @@ int main(int argc, char **argv)
if (params.send_bfsz * 2 <= params.bfsize) { if (params.send_bfsz * 2 <= params.bfsize) {
fprintf(stderr, "send buffer too small\n"); fprintf(stderr, "send buffer too small\n");
return -1; return -1;
} else {
params.nack_max = val * 2 - params.bfsize;
} }
FILE *file; FILE *file;
if (pidfile) { if (pidfile) {

View file

@ -30,7 +30,6 @@ struct params {
int debug; int debug;
size_t bfsize; size_t bfsize;
size_t nack_max;
int send_bfsz; int send_bfsz;
}; };

86
proxy.c
View file

@ -283,24 +283,6 @@ int handle_http(int fd, char *buffer,
} }
int nsendc(int fd, int *wn)
{
#ifdef SO_NWRITE
socklen_t len = sizeof(*wn);
if (getsockopt(fd, SOL_SOCKET, SO_NWRITE, wn, &len) < 0) {
perror("getsockopt SO_NWRITE");
return -1;
}
#else
if (ioctl(fd, TIOCOUTQ, wn) < 0 ) {
perror("ioctl");
return -1;
}
#endif
return 0;
}
static inline int create_conn(struct poolhd *pool, struct eval *val, static inline int create_conn(struct poolhd *pool, struct eval *val,
enum eid nxt, struct sockaddr_ina *dst) enum eid nxt, struct sockaddr_ina *dst)
{ {
@ -519,12 +501,10 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize, int out) char *buffer, size_t bfsize, int out)
{ {
ssize_t n = 0; ssize_t n = 0;
int peek = 0; char *rb = buffer;
struct eval *pair = val->pair; struct eval *pair = val->pair;
if (val->flag & FLAG_NOSEND && out) { if (pair->tmpbuf && out) {
val->flag &= ~FLAG_NOSEND;
mod_etype(pool, val, POLLOUT, 0); mod_etype(pool, val, POLLOUT, 0);
mod_etype(pool, val->pair, POLLIN, 1); mod_etype(pool, val->pair, POLLIN, 1);
@ -532,48 +512,45 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val,
val = val->pair; val = val->pair;
} }
do { do {
if (pair->send_count >= params.nack_max) { if (val->tmpbuf) {
int wn = 0; n = val->size - val->offset;
if (nsendc(pair->fd, &wn)) { rb = val->tmpbuf + val->offset;
return -1; } else {
} n = recv(val->fd, buffer, bfsize, 0);
pair->send_count = wn;
if (wn) {
LOG(LOG_S, "not ack: %d (fd: %d)\n", wn, pair->fd);
}
if (wn >= params.nack_max) {
peek = MSG_PEEK;
}
}
n = recv(val->fd, buffer, bfsize, peek);
if (n < 0 && errno == EAGAIN) if (n < 0 && errno == EAGAIN)
break; break;
if (n < 1) { if (n < 1) {
if (n) perror("recv server"); if (n) perror("recv server");
return -1; return -1;
} }
if (send(pair->fd, buffer, n, 0) < 0) {
if (errno == EAGAIN && peek) {
LOG(LOG_S, "EAGAIN, set POLLOUT (fd: %d)\n", pair->fd);
mod_etype(pool, val, POLLIN, 0);
mod_etype(pool, pair, POLLOUT, 1);
pair->flag |= FLAG_NOSEND;
break;
} }
ssize_t sn = send(pair->fd, rb, n, 0);
if (sn != n) {
if (sn < 0 && errno != EAGAIN) {
perror("send"); perror("send");
return -1; return -1;
} }
if (peek) { LOG(LOG_S, "EAGAIN, set POLLOUT (fd: %d)\n", pair->fd);
if (recv(val->fd, buffer, n, 0) != n) { mod_etype(pool, val, POLLIN, 0);
perror("recv"); mod_etype(pool, pair, POLLOUT, 1);
return -1;
}
}
pair->send_count += n;
if (val->tmpbuf) {
LOG(LOG_S, "EAGAIN, AGAIN ! (fd: %d)\n", pair->fd);
if (sn > 0)
val->offset += sn;
break;
}
val->size = sn > 0 ? n - sn : n;
val->tmpbuf = malloc(val->size);
memcpy(val->tmpbuf, buffer + (sn > 0 ? sn : 0), val->size);
break;
}
else if (val->tmpbuf) {
free(val->tmpbuf);
val->tmpbuf = 0;
rb = buffer;
continue;
}
} while (n == bfsize); } while (n == bfsize);
return 0; return 0;
} }
@ -624,8 +601,7 @@ int big_loop(int srvfd)
continue; continue;
case EV_TUNNEL: case EV_TUNNEL:
if ((etype & POLLHUP) || if (on_tunnel(pool, val, buffer, bfsize, etype & POLLOUT))
on_tunnel(pool, val, buffer, bfsize, etype & POLLOUT))
del_event(pool, val); del_event(pool, val);
continue; continue;