diff --git a/docs/changes.txt b/docs/changes.txt index 11ff6bd..c1c2581 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -311,3 +311,4 @@ v0.9.4.3 1.0.3 * nfqws2: accept string or function in timer_set(). remember function as a function, not as a string. +* nfqws2: limit delayed packet queue to 64 packets (anti-ddos) diff --git a/nfq2/conntrack.c b/nfq2/conntrack.c index 13bca37..e085df9 100644 --- a/nfq2/conntrack.c +++ b/nfq2/conntrack.c @@ -106,7 +106,7 @@ static void ConntrackInitTrack(t_ctrack *t) t->l7proto = L7_UNKNOWN; t->reasm_client_payload = L7P_UNKNOWN; t->pos.client.scale = t->pos.server.scale = 0; - rawpacket_queue_init(&t->delayed); + rawpacket_queue_init(&t->delayed, RAW_PACKET_QUEUE_DELAYED_MAX); lua_newtable(params.L); t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX); lua_newtable(params.L); diff --git a/nfq2/conntrack.h b/nfq2/conntrack.h index 3381d76..42caf8b 100644 --- a/nfq2/conntrack.h +++ b/nfq2/conntrack.h @@ -29,6 +29,8 @@ #define RETRANS_COUNTER_STOP ((uint8_t)-1) +#define RAW_PACKET_QUEUE_DELAYED_MAX 64 + typedef union { struct in_addr ip; struct in6_addr ip6; @@ -82,7 +84,7 @@ typedef struct t_l7payload reasm_client_payload; // payload type being reassembled t_reassemble reasm_client; - struct rawpacket_tailhead delayed; + struct rawpacket_queue delayed; } t_ctrack; typedef struct diff --git a/nfq2/darkmagic.c b/nfq2/darkmagic.c index 8b6f92b..cbf0751 100644 --- a/nfq2/darkmagic.c +++ b/nfq2/darkmagic.c @@ -2048,7 +2048,7 @@ bool rawsend_rp(const struct rawpacket *rp) { return rawsend((struct sockaddr*)&rp->dst,rp->fwmark,rp->ifout,rp->packet,rp->len); } -bool rawsend_queue(struct rawpacket_tailhead *q) +bool rawsend_queue(struct rawpacket_queue *q) { struct rawpacket *rp; bool b; diff --git a/nfq2/darkmagic.h b/nfq2/darkmagic.h index dccdf86..452689f 100644 --- a/nfq2/darkmagic.h +++ b/nfq2/darkmagic.h @@ -147,7 +147,7 @@ bool rawsend_preinit(bool bind_fix4, bool bind_fix6); bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len); bool rawsend_rp(const struct rawpacket *rp); // return trues if all packets were send successfully -bool rawsend_queue(struct rawpacket_tailhead *q); +bool rawsend_queue(struct rawpacket_queue *q); // cleans up socket autocreated by rawsend void rawsend_cleanup(void); bool rawsend_rep(int repeats, const struct sockaddr* dst, uint32_t fwmark, const char *ifout, const void *data, size_t len); diff --git a/nfq2/desync.c b/nfq2/desync.c index 30b0d72..ecaac4c 100644 --- a/nfq2/desync.c +++ b/nfq2/desync.c @@ -705,7 +705,7 @@ static bool check_pos_range(const t_ctrack_position *pos, const struct packet_ra } -static bool replay_queue(struct rawpacket_tailhead *q); +static bool replay_queue(struct rawpacket_queue *q); static bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, const char *hostname, bool hostname_is_ip) { @@ -1583,7 +1583,10 @@ static uint8_t dpi_desync_tcp_packet_play( } else { + // likely exceeded packet limit or unlikely out of memory DLOG_ERR("rawpacket_queue failed !\n"); + reasm_client_cancel(ps.ctrack); + ps.l7payload = L7P_UNKNOWN; // middle packet may be not L7P_TLS_CLIENT_HELLO goto rediscover; } if (ReasmIsFull(&ps.ctrack->reasm_client)) @@ -2194,7 +2197,7 @@ uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, -static bool replay_queue(struct rawpacket_tailhead *q) +static bool replay_queue(struct rawpacket_queue *q) { struct rawpacket *rp; size_t offset; diff --git a/nfq2/packet_queue.c b/nfq2/packet_queue.c index c1b0836..20fb69c 100644 --- a/nfq2/packet_queue.c +++ b/nfq2/packet_queue.c @@ -4,37 +4,40 @@ #include "packet_queue.h" -void rawpacket_queue_init(struct rawpacket_tailhead *q) +void rawpacket_queue_init(struct rawpacket_queue *q, unsigned int max_packets) { - TAILQ_INIT(q); + TAILQ_INIT(&q->q); + q->max_packets = max_packets; } void rawpacket_free(struct rawpacket *rp) { if (rp) free(rp->packet); free(rp); } -struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q) +struct rawpacket *rawpacket_dequeue(struct rawpacket_queue *q) { struct rawpacket *rp; - rp = TAILQ_FIRST(q); - if (rp) TAILQ_REMOVE(q, rp, next); + rp = TAILQ_FIRST(&q->q); + if (rp) TAILQ_REMOVE(&q->q, rp, next); return rp; } -void rawpacket_queue_destroy(struct rawpacket_tailhead *q) +void rawpacket_queue_destroy(struct rawpacket_queue *q) { struct rawpacket *rp; while((rp = rawpacket_dequeue(q))) rawpacket_free(rp); } struct rawpacket *rawpacket_queue( - struct rawpacket_tailhead *q, + struct rawpacket_queue *q, const struct sockaddr_storage* dst, - uint32_t fwmark_orig,uint32_t fwmark, - const char *ifin,const char *ifout, - const void *data,size_t len,size_t len_payload, + uint32_t fwmark_orig, uint32_t fwmark, + const char *ifin, const char *ifout, + const void *data, size_t len, size_t len_payload, const t_ctrack_positions *tpos, bool server_side) { + if (q->max_packets && rawpacket_queue_count(q)>=q->max_packets) return NULL; + struct rawpacket *rp = malloc(sizeof(struct rawpacket)); if (!rp) return NULL; @@ -44,7 +47,7 @@ struct rawpacket *rawpacket_queue( free(rp); return NULL; } - + rp->dst = *dst; rp->fwmark_orig = fwmark_orig; rp->fwmark = fwmark; @@ -70,19 +73,19 @@ struct rawpacket *rawpacket_queue( rp->tpos_present = false; rp->server_side = server_side; - TAILQ_INSERT_TAIL(q, rp, next); + TAILQ_INSERT_TAIL(&q->q, rp, next); return rp; } -unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q) +unsigned int rawpacket_queue_count(const struct rawpacket_queue *q) { const struct rawpacket *rp; unsigned int ct=0; - TAILQ_FOREACH(rp, q, next) ct++; + TAILQ_FOREACH(rp, &q->q, next) ct++; return ct; } -bool rawpacket_queue_empty(const struct rawpacket_tailhead *q) +bool rawpacket_queue_empty(const struct rawpacket_queue *q) { - return !TAILQ_FIRST(q); + return !TAILQ_FIRST(&q->q); } diff --git a/nfq2/packet_queue.h b/nfq2/packet_queue.h index 898991c..cbf6e85 100644 --- a/nfq2/packet_queue.h +++ b/nfq2/packet_queue.h @@ -23,10 +23,16 @@ struct rawpacket }; TAILQ_HEAD(rawpacket_tailhead, rawpacket); -void rawpacket_queue_init(struct rawpacket_tailhead *q); -void rawpacket_queue_destroy(struct rawpacket_tailhead *q); -bool rawpacket_queue_empty(const struct rawpacket_tailhead *q); -unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q); -struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos,bool server_side); -struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q); +struct rawpacket_queue +{ + struct rawpacket_tailhead q; + unsigned int max_packets; +}; + +void rawpacket_queue_init(struct rawpacket_queue *q, unsigned int max_packets); +void rawpacket_queue_destroy(struct rawpacket_queue *q); +bool rawpacket_queue_empty(const struct rawpacket_queue *q); +unsigned int rawpacket_queue_count(const struct rawpacket_queue *q); +struct rawpacket *rawpacket_queue(struct rawpacket_queue *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos,bool server_side); +struct rawpacket *rawpacket_dequeue(struct rawpacket_queue *q); void rawpacket_free(struct rawpacket *rp);