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->type = type;
val->pair = 0;
val->send_count = 0;
val->tmpbuf = 0;
val->size = 0;
val->offset = 0;
val->flag = 0;
#ifndef NOEPOLL
@ -80,6 +82,10 @@ void del_event(struct poolhd *pool, struct eval *val)
if (!val->fd) {
return;
}
if (val->tmpbuf) {
free(val->tmpbuf);
val->tmpbuf = 0;
}
close(val->fd);
val->fd = 0;
pool->count--;
@ -106,7 +112,13 @@ void destroy_pool(struct poolhd *pool)
{
for (int x = 0; x < pool->count; 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) {
free(pool->items);

View file

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

View file

@ -10,9 +10,10 @@
#ifdef __linux__
#include <sys/sendfile.h>
#define _sendfile(outfd, infd, start, len) sendfile(outfd, infd, start, len)
#else
#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
#ifdef MFD_CLOEXEC
@ -26,7 +27,25 @@
#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;
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);
if (setsockopt(sfd, IPPROTO_IP, IP_TTL,
&params.ttl, sizeof(params.ttl)) < 0) {
perror("setsockopt IP_TTL");
if (setttl(sfd, params.ttl, fa) < 0) {
break;
}
if (sendfile(sfd, ffd, 0, pos) < 0) {
if (_sendfile(sfd, ffd, 0, pos) < 0) {
perror("sendfile");
break;
}
@ -66,9 +83,7 @@ int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos)
nanosleep(&delay, 0);
memcpy(p, buffer, pos);
if (setsockopt(sfd, IPPROTO_IP, IP_TTL,
&params.def_ttl, sizeof(int)) < 0) {
perror("setsockopt IP_TTL");
if (setttl(sfd, params.def_ttl, fa) < 0) {
break;
}
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;
if (setsockopt(sfd, IPPROTO_IP, IP_TTL,
(char *)&bttl, sizeof(bttl)) < 0) {
perror("setsockopt IP_TTL");
if (setttl(sfd, bttl, fa) < 0) {
return -1;
}
if (send(sfd, buffer, pos, 0) < 0) {
perror("send");
return -1;
}
if (setsockopt(sfd, IPPROTO_IP, IP_TTL,
(char *)&params.def_ttl, sizeof(int)) < 0) {
perror("setsockopt IP_TTL");
if (setttl(sfd, params.def_ttl, fa) < 0) {
return -1;
}
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;
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))) {
type = IS_HTTPS;
}
@ -146,10 +166,11 @@ int desync(int sfd, char *buffer, ssize_t n)
}
else switch (params.attack) {
case DESYNC_FAKE:
return fake_attack(sfd, buffer, n, type, pos);
return fake_attack(sfd, buffer, n, type, pos, fa);
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:
default:

3
main.c
View file

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

View file

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

92
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,
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)
{
ssize_t n = 0;
int peek = 0;
char *rb = buffer;
struct eval *pair = val->pair;
if (val->flag & FLAG_NOSEND && out) {
val->flag &= ~FLAG_NOSEND;
if (pair->tmpbuf && out) {
mod_etype(pool, val, POLLOUT, 0);
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;
}
do {
if (pair->send_count >= params.nack_max) {
int wn = 0;
if (nsendc(pair->fd, &wn)) {
if (val->tmpbuf) {
n = val->size - val->offset;
rb = val->tmpbuf + val->offset;
} else {
n = recv(val->fd, buffer, bfsize, 0);
if (n < 0 && errno == EAGAIN)
break;
if (n < 1) {
if (n) perror("recv server");
return -1;
}
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);
ssize_t sn = send(pair->fd, rb, n, 0);
if (sn != n) {
if (sn < 0 && errno != EAGAIN) {
perror("send");
return -1;
}
LOG(LOG_S, "EAGAIN, set POLLOUT (fd: %d)\n", pair->fd);
mod_etype(pool, val, POLLIN, 0);
mod_etype(pool, pair, POLLOUT, 1);
if (n < 0 && errno == EAGAIN)
break;
if (n < 1) {
if (n) perror("recv server");
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;
if (val->tmpbuf) {
LOG(LOG_S, "EAGAIN, AGAIN ! (fd: %d)\n", pair->fd);
if (sn > 0)
val->offset += sn;
break;
}
perror("send");
return -1;
val->size = sn > 0 ? n - sn : n;
val->tmpbuf = malloc(val->size);
memcpy(val->tmpbuf, buffer + (sn > 0 ? sn : 0), val->size);
break;
}
if (peek) {
if (recv(val->fd, buffer, n, 0) != n) {
perror("recv");
return -1;
}
else if (val->tmpbuf) {
free(val->tmpbuf);
val->tmpbuf = 0;
rb = buffer;
continue;
}
pair->send_count += n;
} while (n == bfsize);
return 0;
}
@ -624,8 +601,7 @@ int big_loop(int srvfd)
continue;
case EV_TUNNEL:
if ((etype & POLLHUP) ||
on_tunnel(pool, val, buffer, bfsize, etype & POLLOUT))
if (on_tunnel(pool, val, buffer, bfsize, etype & POLLOUT))
del_event(pool, val);
continue;