mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
nfqws: conntrack
This commit is contained in:
294
nfq/conntrack.c
Normal file
294
nfq/conntrack.c
Normal file
@@ -0,0 +1,294 @@
|
||||
#include "conntrack.h"
|
||||
#include "darkmagic.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#undef uthash_nonfatal_oom
|
||||
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
|
||||
|
||||
static bool oom = false;
|
||||
static void ut_oom_recover(void *elem)
|
||||
{
|
||||
oom = true;
|
||||
}
|
||||
|
||||
|
||||
static const char *connstate_s[]={"SYN","ESTABLISHED","FIN"};
|
||||
|
||||
#define _connswap \
|
||||
memset(c2,0,sizeof(*c2)); \
|
||||
c2->e1 = c->e2; \
|
||||
c2->e2 = c->e1;
|
||||
|
||||
static void connswap4(const t_conn4 *c, t_conn4 *c2)
|
||||
{
|
||||
_connswap
|
||||
}
|
||||
static void connswap6(const t_conn6 *c, t_conn6 *c2)
|
||||
{
|
||||
_connswap
|
||||
}
|
||||
|
||||
|
||||
#define _ConntrackPoolDestroy(v) \
|
||||
t_conntrack##v *elem, *tmp; \
|
||||
HASH_ITER(hh, *pp, elem, tmp) { HASH_DEL(*pp, elem); free(elem); }
|
||||
static void ConntrackPoolDestroy4(t_conntrack4 **pp)
|
||||
{
|
||||
_ConntrackPoolDestroy(4)
|
||||
}
|
||||
static void ConntrackPoolDestroy6(t_conntrack6 **pp)
|
||||
{
|
||||
_ConntrackPoolDestroy(6)
|
||||
}
|
||||
void ConntrackPoolDestroy(t_conntrack *p)
|
||||
{
|
||||
ConntrackPoolDestroy4(&p->pool4);
|
||||
ConntrackPoolDestroy6(&p->pool6);
|
||||
}
|
||||
|
||||
void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin)
|
||||
{
|
||||
p->timeout_syn = timeout_syn;
|
||||
p->timeout_established = timeout_established;
|
||||
p->timeout_fin = timeout_fin;
|
||||
p->t_purge_interval = purge_interval;
|
||||
time(&p->t_last_purge);
|
||||
p->pool4 = NULL;
|
||||
p->pool6 = NULL;
|
||||
}
|
||||
|
||||
|
||||
#define _ConntrackExtractConn(v) \
|
||||
memset(c,0,sizeof(*c)); \
|
||||
if (bReverse) { \
|
||||
c->e1.adr = ip->ip##v##_dst; \
|
||||
c->e2.adr = ip->ip##v##_src; \
|
||||
c->e1.port = htons(tcphdr->th_dport); \
|
||||
c->e2.port = htons(tcphdr->th_sport); \
|
||||
} else { \
|
||||
c->e1.adr = ip->ip##v##_src; \
|
||||
c->e2.adr = ip->ip##v##_dst; \
|
||||
c->e1.port = htons(tcphdr->th_sport); \
|
||||
c->e2.port = htons(tcphdr->th_dport); \
|
||||
}
|
||||
void ConntrackExtractConn4(t_conn4 *c, bool bReverse, const struct ip *ip, const struct tcphdr *tcphdr)
|
||||
{
|
||||
_ConntrackExtractConn()
|
||||
}
|
||||
void ConntrackExtractConn6(t_conn6 *c, bool bReverse, const struct ip6_hdr *ip, const struct tcphdr *tcphdr)
|
||||
{
|
||||
_ConntrackExtractConn(6)
|
||||
}
|
||||
|
||||
#define _ConntrackPoolSearch(v) \
|
||||
t_conntrack##v *t; \
|
||||
HASH_FIND(hh, p, c, sizeof(*c), t); \
|
||||
return t;
|
||||
t_conntrack4 *ConntrackPoolSearch4(t_conntrack4 *p, const t_conn4 *c)
|
||||
{
|
||||
_ConntrackPoolSearch(4)
|
||||
}
|
||||
t_conntrack6 *ConntrackPoolSearch6(t_conntrack6 *p, const t_conn6 *c)
|
||||
{
|
||||
_ConntrackPoolSearch(6)
|
||||
}
|
||||
|
||||
|
||||
static void ConntrackInitTrack(t_ctrack *t)
|
||||
{
|
||||
memset(t,0,sizeof(*t));
|
||||
time(&t->t_start);
|
||||
}
|
||||
|
||||
#define _ConntrackNew(v) \
|
||||
t_conntrack##v *new; \
|
||||
if (!(new = calloc(1,sizeof(*new)))) return NULL; \
|
||||
new->conn = *c; \
|
||||
oom = false; \
|
||||
HASH_ADD(hh, *pp, conn, sizeof(*c), new); \
|
||||
if (oom) { free(new); return NULL; } \
|
||||
ConntrackInitTrack(&new->track); \
|
||||
return new;
|
||||
static t_conntrack4 *ConntrackNew4(t_conntrack4 **pp, const t_conn4 *c)
|
||||
{
|
||||
_ConntrackNew(4)
|
||||
}
|
||||
static t_conntrack6 *ConntrackNew6(t_conntrack6 **pp, const t_conn6 *c)
|
||||
{
|
||||
_ConntrackNew(6)
|
||||
}
|
||||
|
||||
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
|
||||
{
|
||||
if (tcp_syn_segment(tcphdr))
|
||||
{
|
||||
if (t->state==FIN) ConntrackInitTrack(t); // erase current entry
|
||||
if (t->state==SYN) t->seq0 = htonl(tcphdr->th_seq);
|
||||
}
|
||||
else if (tcp_synack_segment(tcphdr))
|
||||
{
|
||||
if (t->state==FIN) ConntrackInitTrack(t); // erase current entry
|
||||
if (t->state==SYN)
|
||||
{
|
||||
if (!t->seq0) t->seq0 = htonl(tcphdr->th_ack)-1;
|
||||
t->ack0 = htonl(tcphdr->th_seq);
|
||||
}
|
||||
}
|
||||
else if (tcphdr->th_flags & (TH_FIN|TH_RST))
|
||||
{
|
||||
t->state = FIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t->state==SYN)
|
||||
{
|
||||
t->state=ESTABLISHED;
|
||||
if (!bReverse && !t->ack0) t->ack0 = htonl(tcphdr->th_ack)-1;
|
||||
}
|
||||
}
|
||||
if (bReverse)
|
||||
{
|
||||
t->seq_last = htonl(tcphdr->th_ack);
|
||||
t->ack_last = htonl(tcphdr->th_seq) + len_payload;
|
||||
t->pcounter_reply++;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->seq_last = htonl(tcphdr->th_seq) + len_payload;
|
||||
t->ack_last = htonl(tcphdr->th_ack);
|
||||
t->pcounter_orig++;
|
||||
}
|
||||
time(&t->t_last);
|
||||
}
|
||||
|
||||
#define _ConntrackPoolFeed(v) \
|
||||
t_conn##v conn, connswap; \
|
||||
t_conntrack##v *ctr; \
|
||||
bool b_rev; \
|
||||
ConntrackExtractConn##v(&conn,false,ip,tcphdr); \
|
||||
if ((ctr=ConntrackPoolSearch##v(*pp,&conn))) \
|
||||
{ \
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev=false), tcphdr, len_payload); \
|
||||
goto ok; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
connswap##v(&conn,&connswap); \
|
||||
if ((ctr=ConntrackPoolSearch##v(*pp,&connswap))) \
|
||||
{ \
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev=true), tcphdr, len_payload); \
|
||||
goto ok; \
|
||||
} \
|
||||
} \
|
||||
b_rev = tcp_synack_segment(tcphdr); \
|
||||
if (tcp_syn_segment(tcphdr) || b_rev) \
|
||||
{ \
|
||||
if ((ctr=ConntrackNew##v(pp, b_rev ? &connswap : &conn))) \
|
||||
{ \
|
||||
ConntrackFeedPacket(&ctr->track, b_rev, tcphdr, len_payload); \
|
||||
goto ok; \
|
||||
} \
|
||||
} \
|
||||
return false; \
|
||||
ok: \
|
||||
if (ctrack) *ctrack = &ctr->track; \
|
||||
if (bReverse) *bReverse = b_rev; \
|
||||
return true;
|
||||
|
||||
static bool ConntrackPoolFeed4(t_conntrack4 **pp, const struct ip *ip, const struct tcphdr *tcphdr, uint32_t len_payload, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
_ConntrackPoolFeed(4)
|
||||
}
|
||||
static bool ConntrackPoolFeed6(t_conntrack6 **pp, const struct ip6_hdr *ip, const struct tcphdr *tcphdr, uint32_t len_payload, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
_ConntrackPoolFeed(6)
|
||||
}
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
return ip ? ConntrackPoolFeed4(&p->pool4,ip,tcphdr,(uint32_t)len_payload,ctrack,bReverse) : ip6 ? ConntrackPoolFeed6(&p->pool6,ip6,tcphdr,(uint32_t)len_payload,ctrack,bReverse) : false;
|
||||
}
|
||||
|
||||
|
||||
#define _ConntrackPoolDrop(v) \
|
||||
t_conn##v conn, connswap; \
|
||||
t_conntrack##v *t; \
|
||||
ConntrackExtractConn##v(&conn,false,ip,tcphdr); \
|
||||
if (!(t=ConntrackPoolSearch##v(*pp,&conn))) \
|
||||
{ \
|
||||
connswap##v(&conn,&connswap); \
|
||||
t=ConntrackPoolSearch##v(*pp,&connswap); \
|
||||
} \
|
||||
if (!t) return false; \
|
||||
HASH_DEL(*pp, t); free(t); \
|
||||
return true;
|
||||
static bool ConntrackPoolDrop4(t_conntrack4 **pp, const struct ip *ip, const struct tcphdr *tcphdr)
|
||||
{
|
||||
_ConntrackPoolDrop(4)
|
||||
}
|
||||
static bool ConntrackPoolDrop6(t_conntrack6 **pp, const struct ip6_hdr *ip, const struct tcphdr *tcphdr)
|
||||
{
|
||||
_ConntrackPoolDrop(6)
|
||||
}
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr)
|
||||
{
|
||||
return ip ? ConntrackPoolDrop4(&p->pool4,ip,tcphdr) : ip6 ? ConntrackPoolDrop6(&p->pool6,ip6,tcphdr) : false;
|
||||
}
|
||||
|
||||
#define _ConntrackPoolPurge(v, pp) \
|
||||
{ \
|
||||
t_conntrack##v *t, *tmp; \
|
||||
time_t tidle; \
|
||||
HASH_ITER(hh, *pp , t, tmp) { \
|
||||
tidle = tnow - t->track.t_last; \
|
||||
if ( t->track.b_cutoff || \
|
||||
t->track.state==SYN && tidle>=p->timeout_syn || \
|
||||
t->track.state==ESTABLISHED && tidle>=p->timeout_established || \
|
||||
t->track.state==FIN && tidle>=p->timeout_fin) \
|
||||
{ \
|
||||
HASH_DEL(*pp, t); free(t); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
void ConntrackPoolPurge(t_conntrack *p)
|
||||
{
|
||||
time_t tnow = time(NULL); \
|
||||
if ((tnow - p->t_last_purge)>=p->t_purge_interval)
|
||||
{
|
||||
_ConntrackPoolPurge(4, &p->pool4);
|
||||
_ConntrackPoolPurge(6, &p->pool6);
|
||||
p->t_last_purge = tnow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define _ConntrackPoolDump(v,f) \
|
||||
t_conntrack##v *t, *tmp; \
|
||||
char sa1[40],sa2[40]; \
|
||||
time_t tnow = time(NULL); \
|
||||
HASH_ITER(hh, p, t, tmp) { \
|
||||
*sa1=0; inet_ntop(AF_INET##f, &t->conn.e1.adr, sa1, sizeof(sa1)); \
|
||||
*sa2=0; inet_ntop(AF_INET##f, &t->conn.e2.adr, sa2, sizeof(sa2)); \
|
||||
printf("[%s]:%u => [%s]:%u : %s : t0=%lld last=t0+%lld now=last+%lld cutoff=%u packets_orig=%llu packets_reply=%llu seq0=%u rseq=%u ack0=%u rack=%u\n", \
|
||||
sa1, t->conn.e1.port, sa2, t->conn.e2.port, \
|
||||
connstate_s[t->track.state], \
|
||||
(unsigned long long)t->track.t_start, (unsigned long long)(t->track.t_last - t->track.t_start), (unsigned long long)(tnow - t->track.t_last), \
|
||||
t->track.b_cutoff, \
|
||||
(unsigned long long)t->track.pcounter_orig, (unsigned long long)t->track.pcounter_reply, \
|
||||
t->track.seq0, t->track.seq_last - t->track.seq0, t->track.ack0, t->track.ack_last - t->track.ack0); \
|
||||
};
|
||||
void ConntrackPoolDump4(t_conntrack4 *p)
|
||||
{
|
||||
_ConntrackPoolDump(4,)
|
||||
}
|
||||
void ConntrackPoolDump6(t_conntrack6 *p)
|
||||
{
|
||||
_ConntrackPoolDump(6,6)
|
||||
}
|
||||
void ConntrackPoolDump(t_conntrack *p)
|
||||
{
|
||||
ConntrackPoolDump4(p->pool4);
|
||||
ConntrackPoolDump6(p->pool6);
|
||||
}
|
92
nfq/conntrack.h
Normal file
92
nfq/conntrack.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
// this conntrack is not bullet-proof
|
||||
// its designed to satisfy dpi desync needs only
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
//#define HASH_BLOOM 20
|
||||
#define HASH_NONFATAL_OOM 1
|
||||
#undef HASH_FUNCTION
|
||||
#define HASH_FUNCTION HASH_BER
|
||||
#include "uthash.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct in_addr adr;
|
||||
uint16_t port;
|
||||
} t_endpoint4;
|
||||
typedef struct
|
||||
{
|
||||
struct in6_addr adr;
|
||||
uint16_t port;
|
||||
} t_endpoint6;
|
||||
// e1 - initiator. the one who have sent SYN
|
||||
// e2 - acceptor
|
||||
typedef struct
|
||||
{
|
||||
t_endpoint4 e1,e2;
|
||||
} t_conn4;
|
||||
typedef struct
|
||||
{
|
||||
t_endpoint6 e1,e2;
|
||||
} t_conn6;
|
||||
|
||||
// SYN - SYN or SYN/ACK received
|
||||
// ESTABLISHED - any except SYN or SYN/ACK received
|
||||
// FIN - FIN or RST received
|
||||
typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
|
||||
typedef struct
|
||||
{
|
||||
t_connstate state;
|
||||
time_t t_start, t_last;
|
||||
uint32_t seq0, ack0; // starting seq and ack
|
||||
uint32_t seq_last, ack_last; // current seq and ack
|
||||
uint64_t pcounter_orig, pcounter_reply; // packet counter
|
||||
|
||||
bool b_cutoff; // mark for deletion
|
||||
} t_ctrack;
|
||||
|
||||
// use separate pools for ipv4 and ipv6 to save RAM. otherwise could use union key
|
||||
typedef struct
|
||||
{
|
||||
t_ctrack track;
|
||||
UT_hash_handle hh; // makes this structure hashable
|
||||
t_conn4 conn; // key
|
||||
} t_conntrack4;
|
||||
typedef struct
|
||||
{
|
||||
t_ctrack track;
|
||||
UT_hash_handle hh; // makes this structure hashable
|
||||
t_conn6 conn; // key
|
||||
} t_conntrack6;
|
||||
typedef struct
|
||||
{
|
||||
// inactivity time to purge an entry in each connection state
|
||||
uint32_t timeout_syn,timeout_established,timeout_fin;
|
||||
time_t t_purge_interval, t_last_purge;
|
||||
t_conntrack4 *pool4;
|
||||
t_conntrack6 *pool6;
|
||||
} t_conntrack;
|
||||
|
||||
void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin);
|
||||
void ConntrackPoolDestroy(t_conntrack *p);
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse);
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr);
|
||||
|
||||
void ConntrackExtractConn4(t_conn4 *c, bool bReverse, const struct ip *ip, const struct tcphdr *tcphdr);
|
||||
void ConntrackExtractConn6(t_conn6 *c, bool bReverse, const struct ip6_hdr *ip, const struct tcphdr *tcphdr);
|
||||
|
||||
void ConntrackPoolDump4(t_conntrack4 *p);
|
||||
void ConntrackPoolDump6(t_conntrack6 *p);
|
||||
void ConntrackPoolDump(t_conntrack *p);
|
||||
|
||||
void ConntrackPoolPurge(t_conntrack *p);
|
@@ -513,7 +513,7 @@ static void str_srcdst_ip(char *s, size_t s_len, const void *saddr,const void *d
|
||||
}
|
||||
static void str_ip(char *s, size_t s_len, const struct ip *ip)
|
||||
{
|
||||
char ss[64],s_proto[16];
|
||||
char ss[35],s_proto[16];
|
||||
str_srcdst_ip(ss,sizeof(ss),&ip->ip_src,&ip->ip_dst);
|
||||
str_proto_name(s_proto,sizeof(s_proto),ip->ip_p);
|
||||
snprintf(s,s_len,"%s proto=%s",ss,s_proto);
|
||||
@@ -534,7 +534,7 @@ static void str_srcdst_ip6(char *s, size_t s_len, const void *saddr,const void *
|
||||
}
|
||||
static void str_ip6hdr(char *s, size_t s_len, const struct ip6_hdr *ip6hdr, uint8_t proto)
|
||||
{
|
||||
char ss[128],s_proto[16];
|
||||
char ss[83],s_proto[16];
|
||||
str_srcdst_ip6(ss,sizeof(ss),&ip6hdr->ip6_src,&ip6hdr->ip6_dst);
|
||||
str_proto_name(s_proto,sizeof(s_proto),proto);
|
||||
snprintf(s,s_len,"%s proto=%s",ss,s_proto);
|
||||
|
16
nfq/desync.c
16
nfq/desync.c
@@ -5,6 +5,7 @@
|
||||
#include "params.h"
|
||||
#include "helpers.h"
|
||||
#include "hostlist.h"
|
||||
#include "conntrack.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -103,21 +104,30 @@ static bool rawsend_rep(const struct sockaddr* dst,uint32_t fwmark,const void *d
|
||||
packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struct ip *ip, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, size_t len_tcp, uint8_t *data_payload, size_t len_payload)
|
||||
{
|
||||
packet_process_result res=pass;
|
||||
t_ctrack *ctrack=NULL;
|
||||
bool bReverse=false;
|
||||
|
||||
if (!!ip == !!ip6hdr) return res; // one and only one must be present
|
||||
|
||||
if (params.wssize)
|
||||
{
|
||||
ConntrackPoolPurge(¶ms.conntrack);
|
||||
if (ConntrackPoolFeed(¶ms.conntrack, ip, ip6hdr, tcphdr, len_payload, &ctrack, &bReverse))
|
||||
if (params.wssize_cutoff && ctrack->pcounter_orig>=params.wssize_cutoff)
|
||||
ctrack->b_cutoff=true;
|
||||
}
|
||||
if (params.wsize && tcp_synack_segment(tcphdr))
|
||||
{
|
||||
tcp_rewrite_winsize(tcphdr, params.wsize, params.wscale);
|
||||
res=modify;
|
||||
}
|
||||
if (params.wssize && !tcp_synack_segment(tcphdr))
|
||||
if (params.wssize && !bReverse && (ctrack && !ctrack->b_cutoff))
|
||||
{
|
||||
tcp_rewrite_winsize(tcphdr, params.wssize, params.wsscale);
|
||||
res=modify;
|
||||
}
|
||||
|
||||
if (params.desync_mode==DESYNC_NONE && !params.hostcase && !params.hostnospace && !params.domcase) return res; // nothing to do. do not waste cpu
|
||||
if (bReverse || !params.wssize && params.desync_mode==DESYNC_NONE && !params.hostcase && !params.hostnospace && !params.domcase) return res; // nothing to do. do not waste cpu
|
||||
|
||||
if (!(tcphdr->th_flags & TH_SYN) && len_payload)
|
||||
{
|
||||
@@ -132,6 +142,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
|
||||
if ((bIsHttp = IsHttp(data_payload,len_payload)))
|
||||
{
|
||||
DLOG("packet contains HTTP request\n")
|
||||
if (ctrack && !params.wssize_cutoff) ctrack->b_cutoff = true;
|
||||
fake = params.fake_http;
|
||||
fake_size = params.fake_http_size;
|
||||
if (params.hostlist || params.debug) bHaveHost=HttpExtractHost(data_payload,len_payload,host,sizeof(host));
|
||||
@@ -144,6 +155,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
|
||||
else if (IsTLSClientHello(data_payload,len_payload))
|
||||
{
|
||||
DLOG("packet contains TLS ClientHello\n")
|
||||
if (ctrack && !params.wssize_cutoff) ctrack->b_cutoff = true;
|
||||
fake = params.fake_tls;
|
||||
fake_size = params.fake_tls_size;
|
||||
if (params.hostlist || params.desync_skip_nosni || params.debug)
|
||||
|
109
nfq/nfqws.c
109
nfq/nfqws.c
@@ -36,6 +36,9 @@
|
||||
#define IPPROTO_DIVERT 258
|
||||
#endif
|
||||
|
||||
#define CTRACK_T_SYN 60
|
||||
#define CTRACK_T_EST 300
|
||||
#define CTRACK_T_FIN 60
|
||||
|
||||
struct params_s params;
|
||||
|
||||
@@ -65,6 +68,14 @@ static void dohup()
|
||||
}
|
||||
}
|
||||
|
||||
static void onusr1(int sig)
|
||||
{
|
||||
printf("\nCONNTRACK DUMP\n");
|
||||
ConntrackPoolDump(¶ms.conntrack);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt, uint32_t *mark)
|
||||
@@ -234,6 +245,7 @@ static int nfq_main()
|
||||
print_id();
|
||||
|
||||
signal(SIGHUP, onhup);
|
||||
signal(SIGUSR1, onusr1);
|
||||
|
||||
desync_init();
|
||||
|
||||
@@ -349,6 +361,7 @@ static int dvt_main()
|
||||
print_id();
|
||||
|
||||
signal(SIGHUP, onhup);
|
||||
signal(SIGUSR1, onusr1);
|
||||
|
||||
desync_init();
|
||||
|
||||
@@ -459,7 +472,9 @@ static void exithelp()
|
||||
" --user=<username>\t\t\t; drop root privs\n"
|
||||
" --uid=uid[:gid]\t\t\t; drop root privs\n"
|
||||
" --wsize=<window_size>[:<scale_factor>]\t; set window size. 0 = do not modify. OBSOLETE !\n"
|
||||
" --wssize=<window_size>[:<scale_factor>]; set window size for server. 0 = do not modify.\n"
|
||||
" --wssize=<window_size>[:<scale_factor>]; set window size for server. 0 = do not modify. default scale_factor = 0.\n"
|
||||
" --wssize-cutoff=N\t\t\t; apply server wsize only to packet numbers less than N\n"
|
||||
" --ctrack-timeouts=S:E:F\t\t; internal conntrack timeouts for SYN, ESTABLISHED and FIN stage. default %u:%u:%u\n"
|
||||
" --hostcase\t\t\t\t; change Host: => host:\n"
|
||||
" --hostspell\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
|
||||
" --hostnospace\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
||||
@@ -482,6 +497,7 @@ static void exithelp()
|
||||
" --dpi-desync-fake-http=<filename>\t; file containing fake http request\n"
|
||||
" --dpi-desync-fake-tls=<filename>\t; file containing fake TLS ClientHello (for https)\n"
|
||||
" --hostlist=<filename>\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply)\n",
|
||||
CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN,
|
||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||
DPI_DESYNC_FWMARK_DEFAULT,DPI_DESYNC_FWMARK_DEFAULT,
|
||||
#endif
|
||||
@@ -497,6 +513,7 @@ static void cleanup_params()
|
||||
StrPoolDestroy(¶ms.hostlist);
|
||||
params.hostlist = NULL;
|
||||
}
|
||||
ConntrackPoolDestroy(¶ms.conntrack);
|
||||
}
|
||||
static void exithelp_clean()
|
||||
{
|
||||
@@ -531,6 +548,9 @@ int main(int argc, char **argv)
|
||||
params.fake_http_size = strlen(fake_http_request_default);
|
||||
memcpy(params.fake_http,fake_http_request_default,params.fake_http_size);
|
||||
params.wscale=-1; // default - dont change scale factor (client)
|
||||
params.ctrack_t_syn = CTRACK_T_SYN;
|
||||
params.ctrack_t_est = CTRACK_T_EST;
|
||||
params.ctrack_t_fin = CTRACK_T_FIN;
|
||||
|
||||
if (can_drop_root()) // are we root ?
|
||||
{
|
||||
@@ -553,28 +573,30 @@ int main(int argc, char **argv)
|
||||
{"uid",required_argument,0,0 }, // optidx=5
|
||||
{"wsize",required_argument,0,0}, // optidx=6
|
||||
{"wssize",required_argument,0,0}, // optidx=7
|
||||
{"hostcase",no_argument,0,0}, // optidx=8
|
||||
{"hostspell",required_argument,0,0}, // optidx=9
|
||||
{"hostnospace",no_argument,0,0}, // optidx=10
|
||||
{"domcase",no_argument,0,0 }, // optidx=11
|
||||
{"dpi-desync",required_argument,0,0}, // optidx=12
|
||||
{"wssize-cutoff",required_argument,0,0},// optidx=8
|
||||
{"ctrack-timeouts",required_argument,0,0},// optidx=9
|
||||
{"hostcase",no_argument,0,0}, // optidx=10
|
||||
{"hostspell",required_argument,0,0}, // optidx=11
|
||||
{"hostnospace",no_argument,0,0}, // optidx=12
|
||||
{"domcase",no_argument,0,0 }, // optidx=13
|
||||
{"dpi-desync",required_argument,0,0}, // optidx=14
|
||||
#ifdef __linux__
|
||||
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=13
|
||||
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=15
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=13
|
||||
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=15
|
||||
#else
|
||||
{"disabled_argument_2",no_argument,0,0}, // optidx=13
|
||||
{"disabled_argument_2",no_argument,0,0}, // optidx=15
|
||||
#endif
|
||||
{"dpi-desync-ttl",required_argument,0,0}, // optidx=14
|
||||
{"dpi-desync-fooling",required_argument,0,0}, // optidx=15
|
||||
{"dpi-desync-retrans",optional_argument,0,0}, // optidx=16
|
||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=17
|
||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=18
|
||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=19
|
||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=20
|
||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=21
|
||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=22
|
||||
{"hostlist",required_argument,0,0}, // optidx=23
|
||||
{"dpi-desync-ttl",required_argument,0,0}, // optidx=16
|
||||
{"dpi-desync-fooling",required_argument,0,0}, // optidx=17
|
||||
{"dpi-desync-retrans",optional_argument,0,0}, // optidx=18
|
||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=19
|
||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=20
|
||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=21
|
||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=22
|
||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=23
|
||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=24
|
||||
{"hostlist",required_argument,0,0}, // optidx=25
|
||||
{NULL,0,NULL,0}
|
||||
};
|
||||
if (argc < 2) exithelp();
|
||||
@@ -643,10 +665,24 @@ int main(int argc, char **argv)
|
||||
if (!parse_scale_factor(optarg,¶ms.wssize,¶ms.wsscale))
|
||||
exit_clean(1);
|
||||
break;
|
||||
case 8: /* hostcase */
|
||||
case 8: /* wssize-cutoff */
|
||||
if (!sscanf(optarg, "%u", ¶ms.wssize_cutoff))
|
||||
{
|
||||
fprintf(stderr, "invalid wssize-cutoff value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 9: /* ctrack-timeouts */
|
||||
if (sscanf(optarg, "%u:%u:%u", ¶ms.ctrack_t_syn, ¶ms.ctrack_t_est, ¶ms.ctrack_t_fin)!=3)
|
||||
{
|
||||
fprintf(stderr, "invalid ctrack-timeouts value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 10: /* hostcase */
|
||||
params.hostcase = true;
|
||||
break;
|
||||
case 9: /* hostspell */
|
||||
case 11: /* hostspell */
|
||||
if (strlen(optarg) != 4)
|
||||
{
|
||||
fprintf(stderr, "hostspell must be exactly 4 chars long\n");
|
||||
@@ -655,13 +691,13 @@ int main(int argc, char **argv)
|
||||
params.hostcase = true;
|
||||
memcpy(params.hostspell, optarg, 4);
|
||||
break;
|
||||
case 10: /* hostnospace */
|
||||
case 12: /* hostnospace */
|
||||
params.hostnospace = true;
|
||||
break;
|
||||
case 11: /* domcase */
|
||||
case 13: /* domcase */
|
||||
params.domcase = true;
|
||||
break;
|
||||
case 12: /* dpi-desync */
|
||||
case 14: /* dpi-desync */
|
||||
{
|
||||
char *mode2;
|
||||
mode2 = optarg ? strchr(optarg,',') : NULL;
|
||||
@@ -681,7 +717,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 13: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
||||
case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||
params.desync_fwmark = 0;
|
||||
if (!sscanf(optarg, "0x%X", ¶ms.desync_fwmark)) sscanf(optarg, "%u", ¶ms.desync_fwmark);
|
||||
@@ -695,10 +731,10 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
#endif
|
||||
break;
|
||||
case 14: /* dpi-desync-ttl */
|
||||
case 16: /* dpi-desync-ttl */
|
||||
params.desync_ttl = (uint8_t)atoi(optarg);
|
||||
break;
|
||||
case 15: /* dpi-desync-fooling */
|
||||
case 17: /* dpi-desync-fooling */
|
||||
{
|
||||
char *e,*p = optarg;
|
||||
while (p)
|
||||
@@ -727,7 +763,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16: /* dpi-desync-retrans */
|
||||
case 18: /* dpi-desync-retrans */
|
||||
#ifdef __linux__
|
||||
params.desync_retrans = !optarg || atoi(optarg);
|
||||
#else
|
||||
@@ -735,7 +771,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
#endif
|
||||
break;
|
||||
case 17: /* dpi-desync-repeats */
|
||||
case 19: /* dpi-desync-repeats */
|
||||
params.desync_repeats = atoi(optarg);
|
||||
if (params.desync_repeats<=0 || params.desync_repeats>20)
|
||||
{
|
||||
@@ -743,10 +779,10 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 18: /* dpi-desync-skip-nosni */
|
||||
case 20: /* dpi-desync-skip-nosni */
|
||||
params.desync_skip_nosni = !optarg || atoi(optarg);
|
||||
break;
|
||||
case 19: /* dpi-desync-split-pos */
|
||||
case 21: /* dpi-desync-split-pos */
|
||||
params.desync_split_pos = atoi(optarg);
|
||||
if (params.desync_split_pos<1 || params.desync_split_pos>DPI_DESYNC_MAX_FAKE_LEN)
|
||||
{
|
||||
@@ -754,10 +790,10 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 20: /* dpi-desync-any-protocol */
|
||||
case 22: /* dpi-desync-any-protocol */
|
||||
params.desync_any_proto = !optarg || atoi(optarg);
|
||||
break;
|
||||
case 21: /* dpi-desync-fake-http */
|
||||
case 23: /* dpi-desync-fake-http */
|
||||
params.fake_http_size = sizeof(params.fake_http);
|
||||
if (!load_file_nonempty(optarg,params.fake_http,¶ms.fake_http_size))
|
||||
{
|
||||
@@ -765,7 +801,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 22: /* dpi-desync-fake-tls */
|
||||
case 24: /* dpi-desync-fake-tls */
|
||||
params.fake_tls_size = sizeof(params.fake_tls);
|
||||
if (!load_file_nonempty(optarg,params.fake_tls,¶ms.fake_tls_size))
|
||||
{
|
||||
@@ -773,7 +809,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 23: /* hostlist */
|
||||
case 25: /* hostlist */
|
||||
if (!LoadHostList(¶ms.hostlist, optarg))
|
||||
exit_clean(1);
|
||||
strncpy(params.hostfile,optarg,sizeof(params.hostfile));
|
||||
@@ -797,6 +833,9 @@ int main(int argc, char **argv)
|
||||
goto exiterr;
|
||||
}
|
||||
|
||||
DLOG("initializing conntrack with timeouts %u:%u:%u\n", params.ctrack_t_syn, params.ctrack_t_est, params.ctrack_t_fin)
|
||||
ConntrackPoolInit(¶ms.conntrack, 10, params.ctrack_t_syn, params.ctrack_t_est, params.ctrack_t_fin);
|
||||
|
||||
#ifdef __linux__
|
||||
result = nfq_main();
|
||||
#elif defined(BSD)
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "params.h"
|
||||
#include "strpool.h"
|
||||
#include "conntrack.h"
|
||||
#include "desync.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@@ -28,6 +29,7 @@ struct params_s
|
||||
bool debug;
|
||||
uint16_t wsize,wssize;
|
||||
uint8_t wscale,wsscale;
|
||||
unsigned int wssize_cutoff;
|
||||
#ifdef __linux__
|
||||
int qnum;
|
||||
#elif defined(BSD)
|
||||
@@ -48,6 +50,9 @@ struct params_s
|
||||
bool droproot;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
unsigned int ctrack_t_syn, ctrack_t_est, ctrack_t_fin;
|
||||
t_conntrack conntrack;
|
||||
};
|
||||
|
||||
extern struct params_s params;
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
//#define HASH_BLOOM 20
|
||||
#define HASH_NONFATAL_OOM 1
|
||||
#undef HASH_FUNCTION
|
||||
#define HASH_FUNCTION HASH_BER
|
||||
#include "uthash.h"
|
||||
|
||||
|
Reference in New Issue
Block a user