zapret/nfq/conntrack.h

138 lines
5.2 KiB
C
Raw Normal View History

2021-03-18 17:21:25 +03:00
#pragma once
2021-03-18 17:21:25 +03:00
// this conntrack is not bullet-proof
// its designed to satisfy dpi desync needs only
#include "packet_queue.h"
2021-03-18 17:21:25 +03:00
#include <stdbool.h>
#include <stdint.h>
#include <ctype.h>
#include <sys/types.h>
#include <time.h>
#include <netinet/in.h>
#define __FAVOR_BSD
2021-03-18 17:21:25 +03:00
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
2022-01-01 20:22:04 +03:00
#include <netinet/udp.h>
2021-03-18 17:21:25 +03:00
2024-04-20 20:59:45 +03:00
2021-03-18 17:21:25 +03:00
//#define HASH_BLOOM 20
#define HASH_NONFATAL_OOM 1
#undef HASH_FUNCTION
#define HASH_FUNCTION HASH_BER
#include "uthash.h"
2023-10-26 15:12:32 +03:00
#define RETRANS_COUNTER_STOP ((uint8_t)-1)
2022-01-01 20:22:04 +03:00
typedef union {
struct in_addr ip;
struct in6_addr ip6;
} t_addr;
2021-03-18 17:21:25 +03:00
typedef struct
{
2022-01-01 20:22:04 +03:00
t_addr src, dst;
uint16_t sport,dport;
uint8_t l3proto; // IPPROTO_IP, IPPROTO_IPV6
uint8_t l4proto; // IPPROTO_TCP, IPPROTO_UDP
} t_conn;
2021-03-18 17:21:25 +03:00
2023-11-15 19:36:34 +03:00
// this structure helps to reassemble continuous packets streams. it does not support out-of-orders
typedef struct {
uint8_t *packet; // allocated for size during reassemble request. requestor must know the message size.
2024-04-22 14:30:05 +03:00
uint32_t seq; // current seq number. if a packet comes with an unexpected seq - it fails reassemble session.
2023-11-15 19:36:34 +03:00
size_t size; // expected message size. success means that we have received exactly 'size' bytes and have them in 'packet'
size_t size_present; // how many bytes already stored in 'packet'
} t_reassemble;
2021-03-18 17:21:25 +03:00
// 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;
2024-10-16 13:42:59 +03:00
2023-10-26 15:12:32 +03:00
typedef enum {UNKNOWN=0, HTTP, TLS, QUIC, WIREGUARD, DHT} t_l7proto;
2024-10-16 13:42:59 +03:00
#define L7_PROTO_HTTP 0x00000001
#define L7_PROTO_TLS 0x00000002
#define L7_PROTO_QUIC 0x00000004
#define L7_PROTO_WIREGUARD 0x00000008
#define L7_PROTO_DHT 0x00000010
#define L7_PROTO_UNKNOWN 0x80000000
const char *l7proto_str(t_l7proto l7);
bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7);
2021-03-18 17:21:25 +03:00
typedef struct
{
2024-10-16 13:42:59 +03:00
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
2024-09-17 19:57:21 +03:00
struct desync_profile *dp; // desync profile cache
bool dp_search_complete;
2022-01-01 20:22:04 +03:00
// common state
2021-03-18 17:21:25 +03:00
time_t t_start, t_last;
uint64_t pcounter_orig, pcounter_reply; // packet counter
2021-12-27 16:51:30 +03:00
uint64_t pdcounter_orig, pdcounter_reply; // data packet counter (with payload)
2022-01-01 20:22:04 +03:00
uint32_t pos_orig, pos_reply; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
uint32_t seq_last, ack_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
// tcp only state, not used in udp
t_connstate state;
uint32_t seq0, ack0; // starting seq and ack
2021-03-19 15:39:32 +03:00
uint16_t winsize_orig, winsize_reply; // last seen window size
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
2023-10-26 15:12:32 +03:00
uint8_t req_retrans_counter; // number of request retransmissions
2024-04-24 17:03:18 +03:00
bool req_seq_present,req_seq_finalized,req_seq_abandoned;
2023-11-15 19:36:34 +03:00
uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions)
2021-03-18 17:21:25 +03:00
2024-10-16 13:42:59 +03:00
uint8_t incoming_ttl, autottl;
2024-03-02 17:53:37 +03:00
2021-03-18 17:21:25 +03:00
bool b_cutoff; // mark for deletion
bool b_wssize_cutoff, b_desync_cutoff;
2023-10-26 15:12:32 +03:00
t_l7proto l7proto;
2024-10-16 13:42:59 +03:00
bool l7proto_discovered;
2023-10-26 15:12:32 +03:00
char *hostname;
2024-04-24 17:03:18 +03:00
bool hostname_ah_check; // should perform autohostlist checks
2024-04-20 20:59:45 +03:00
t_reassemble reasm_orig;
struct rawpacket_tailhead delayed;
2021-03-18 17:21:25 +03:00
} t_ctrack;
typedef struct
{
t_ctrack track;
UT_hash_handle hh; // makes this structure hashable
2022-01-01 20:22:04 +03:00
t_conn conn; // key
} t_conntrack_pool;
2021-03-18 17:21:25 +03:00
typedef struct
{
// inactivity time to purge an entry in each connection state
2022-01-01 20:22:04 +03:00
uint32_t timeout_syn,timeout_established,timeout_fin,timeout_udp;
2021-03-18 17:21:25 +03:00
time_t t_purge_interval, t_last_purge;
2022-01-01 20:22:04 +03:00
t_conntrack_pool *pool;
2021-03-18 17:21:25 +03:00
} t_conntrack;
2022-01-01 20:22:04 +03:00
void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin, uint32_t timeout_udp);
2021-03-18 17:21:25 +03:00
void ConntrackPoolDestroy(t_conntrack *p);
2022-01-01 20:22:04 +03:00
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse);
2024-04-20 20:59:45 +03:00
// do not create, do not update. only find existing
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse);
2022-01-01 20:22:04 +03:00
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
void ConntrackPoolDump(const t_conntrack *p);
2021-03-18 17:21:25 +03:00
void ConntrackPoolPurge(t_conntrack *p);
2023-11-15 19:36:34 +03:00
void ConntrackClearHostname(t_ctrack *track);
bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start);
2024-04-20 20:59:45 +03:00
bool ReasmResize(t_reassemble *reasm, size_t new_size);
2023-11-15 19:36:34 +03:00
void ReasmClear(t_reassemble *reasm);
// false means reassemble session has failed and we should ReasmClear() it
2024-04-22 14:30:05 +03:00
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len);
// check if it has enough space to buffer 'len' bytes
bool ReasmHasSpace(t_reassemble *reasm, size_t len);
2023-11-15 19:36:34 +03:00
inline static bool ReasmIsEmpty(t_reassemble *reasm) {return !reasm->size;}
inline static bool ReasmIsFull(t_reassemble *reasm) {return !ReasmIsEmpty(reasm) && (reasm->size==reasm->size_present);}