mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
nfqws: packet delay support
This commit is contained in:
@@ -37,6 +37,7 @@ static void ConntrackClearTrack(t_ctrack *track)
|
||||
{
|
||||
ConntrackClearHostname(track);
|
||||
ReasmClear(&track->reasm_orig);
|
||||
rawpacket_queue_destroy(&track->delayed);
|
||||
}
|
||||
|
||||
static void ConntrackFreeElem(t_conntrack_pool *elem)
|
||||
@@ -99,19 +100,24 @@ static void ConntrackInitTrack(t_ctrack *t)
|
||||
memset(t,0,sizeof(*t));
|
||||
t->scale_orig = t->scale_reply = SCALE_NONE;
|
||||
time(&t->t_start);
|
||||
rawpacket_queue_init(&t->delayed);
|
||||
}
|
||||
static void ConntrackReInitTrack(t_ctrack *t)
|
||||
{
|
||||
ConntrackClearTrack(t);
|
||||
ConntrackInitTrack(t);
|
||||
}
|
||||
|
||||
|
||||
static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
|
||||
{
|
||||
t_conntrack_pool *new;
|
||||
if (!(new = malloc(sizeof(*new)))) return NULL;
|
||||
new->conn = *c;
|
||||
t_conntrack_pool *ctnew;
|
||||
if (!(ctnew = malloc(sizeof(*ctnew)))) return NULL;
|
||||
ctnew->conn = *c;
|
||||
oom = false;
|
||||
HASH_ADD(hh, *pp, conn, sizeof(*c), new);
|
||||
if (oom) { free(new); return NULL; }
|
||||
ConntrackInitTrack(&new->track);
|
||||
return new;
|
||||
HASH_ADD(hh, *pp, conn, sizeof(*c), ctnew);
|
||||
if (oom) { free(ctnew); return NULL; }
|
||||
ConntrackInitTrack(&ctnew->track);
|
||||
return ctnew;
|
||||
}
|
||||
|
||||
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
|
||||
@@ -135,13 +141,13 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
{
|
||||
if (tcp_syn_segment(tcphdr))
|
||||
{
|
||||
if (t->state!=SYN) ConntrackInitTrack(t); // erase current entry
|
||||
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
t->seq0 = htonl(tcphdr->th_seq);
|
||||
}
|
||||
else if (tcp_synack_segment(tcphdr))
|
||||
{
|
||||
if (t->state!=SYN) ConntrackInitTrack(t); // erase current entry
|
||||
if (!t->seq0) t->seq0 = htonl(tcphdr->th_ack)-1;
|
||||
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
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))
|
||||
@@ -192,6 +198,35 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
time(&t->t_last);
|
||||
}
|
||||
|
||||
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
bool b_rev;
|
||||
t_conn conn,connswp;
|
||||
t_conntrack_pool *ctr;
|
||||
|
||||
ConntrackExtractConn(&conn,false,ip,ip6,tcphdr,udphdr);
|
||||
if ((ctr=ConntrackPoolSearch(*pp,&conn)))
|
||||
{
|
||||
if (bReverse) *bReverse = false;
|
||||
if (ctrack) *ctrack = &ctr->track;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
connswap(&conn,&connswp);
|
||||
if ((ctr=ConntrackPoolSearch(*pp,&connswp)))
|
||||
{
|
||||
if (bReverse) *bReverse = true;
|
||||
if (ctrack) *ctrack = &ctr->track;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
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)
|
||||
{
|
||||
return ConntrackPoolDoubleSearchPool(&p->pool, ip, ip6, tcphdr, udphdr, ctrack, bReverse);
|
||||
}
|
||||
|
||||
static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, 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)
|
||||
{
|
||||
@@ -343,9 +378,18 @@ bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start)
|
||||
reasm->seq = seq_start;
|
||||
return true;
|
||||
}
|
||||
bool ReasmResize(t_reassemble *reasm, size_t new_size)
|
||||
{
|
||||
uint8_t *p = realloc(reasm->packet, new_size);
|
||||
if (!p) return false;
|
||||
reasm->packet = p;
|
||||
reasm->size = new_size;
|
||||
if (reasm->size_present > new_size) reasm->size_present = new_size;
|
||||
return true;
|
||||
}
|
||||
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len)
|
||||
{
|
||||
if (reasm->seq!=seq) return false; // fail session if out of sequence
|
||||
if (seq!=-1 && reasm->seq!=seq) return false; // fail session if out of sequence
|
||||
|
||||
size_t szcopy;
|
||||
szcopy = reasm->size - reasm->size_present;
|
||||
|
@@ -14,6 +14,8 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include "packet_queue.h"
|
||||
|
||||
//#define HASH_BLOOM 20
|
||||
#define HASH_NONFATAL_OOM 1
|
||||
#undef HASH_FUNCTION
|
||||
@@ -63,7 +65,7 @@ typedef struct
|
||||
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
|
||||
|
||||
uint8_t req_retrans_counter; // number of request retransmissions
|
||||
bool req_seq_start_present, req_seq_present;
|
||||
bool req_seq_present,req_seq_finalized;
|
||||
uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions)
|
||||
|
||||
uint8_t autottl;
|
||||
@@ -71,10 +73,11 @@ typedef struct
|
||||
bool b_cutoff; // mark for deletion
|
||||
bool b_wssize_cutoff, b_desync_cutoff;
|
||||
|
||||
t_reassemble reasm_orig;
|
||||
|
||||
t_l7proto l7proto;
|
||||
char *hostname;
|
||||
|
||||
t_reassemble reasm_orig;
|
||||
struct rawpacket_tailhead delayed;
|
||||
} t_ctrack;
|
||||
|
||||
typedef struct
|
||||
@@ -94,6 +97,8 @@ typedef struct
|
||||
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);
|
||||
void ConntrackPoolDestroy(t_conntrack *p);
|
||||
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);
|
||||
// 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);
|
||||
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);
|
||||
@@ -101,6 +106,7 @@ void ConntrackPoolPurge(t_conntrack *p);
|
||||
void ConntrackClearHostname(t_ctrack *track);
|
||||
|
||||
bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start);
|
||||
bool ReasmResize(t_reassemble *reasm, size_t new_size);
|
||||
void ReasmClear(t_reassemble *reasm);
|
||||
// false means reassemble session has failed and we should ReasmClear() it
|
||||
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len);
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#include "params.h"
|
||||
|
||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
||||
{
|
||||
@@ -840,6 +840,64 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
|
||||
// we have garbage
|
||||
}
|
||||
|
||||
void proto_dissect_l3l4(
|
||||
uint8_t *data, size_t len,
|
||||
struct ip **ip, struct ip6_hdr **ip6,
|
||||
uint8_t *proto,
|
||||
struct tcphdr **tcp,
|
||||
struct udphdr **udp,
|
||||
size_t *transport_len,
|
||||
uint8_t **data_payload, size_t *len_payload)
|
||||
{
|
||||
*ip = NULL;
|
||||
*ip6 = NULL;
|
||||
*proto = 0;
|
||||
*tcp = NULL;
|
||||
*transport_len = 0;
|
||||
*udp = NULL;
|
||||
*data_payload = NULL;
|
||||
*len_payload = 0;
|
||||
|
||||
if (proto_check_ipv4(data, len))
|
||||
{
|
||||
*ip = (struct ip *) data;
|
||||
*proto = (*ip)->ip_p;
|
||||
proto_skip_ipv4(&data, &len);
|
||||
}
|
||||
else if (proto_check_ipv6(data, len))
|
||||
{
|
||||
*ip6 = (struct ip6_hdr *) data;
|
||||
proto_skip_ipv6(&data, &len, proto, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (*proto==IPPROTO_TCP && proto_check_tcp(data, len))
|
||||
{
|
||||
*tcp = (struct tcphdr *) data;
|
||||
*transport_len = len;
|
||||
|
||||
proto_skip_tcp(&data, &len);
|
||||
|
||||
*data_payload = data;
|
||||
*len_payload = len;
|
||||
|
||||
}
|
||||
else if (*proto==IPPROTO_UDP && proto_check_udp(data, len))
|
||||
{
|
||||
*udp = (struct udphdr *) data;
|
||||
*transport_len = len;
|
||||
|
||||
proto_skip_udp(&data, &len);
|
||||
|
||||
*data_payload = data;
|
||||
*len_payload = len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool tcp_synack_segment(const struct tcphdr *tcphdr)
|
||||
{
|
||||
/* check for set bits in TCP hdr */
|
||||
@@ -1204,6 +1262,20 @@ nofix:
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct rawpacket *rp;
|
||||
bool b;
|
||||
for (b=true; (rp=rawpacket_dequeue(q)) ; rawpacket_free(rp))
|
||||
b &= rawsend_rp(rp);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
|
||||
// ttl = TTL of incoming packet
|
||||
uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
|
||||
@@ -1233,3 +1305,27 @@ uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
|
||||
|
||||
return fake;
|
||||
}
|
||||
|
||||
|
||||
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||
#else
|
||||
// if original packet was tampered earlier it needs checksum fixed
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||
#endif
|
||||
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
|
||||
}
|
||||
void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||
#else
|
||||
// if original packet was tampered earlier it needs checksum fixed
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||
#endif
|
||||
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
|
||||
}
|
||||
|
@@ -11,6 +11,8 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "packet_queue.h"
|
||||
|
||||
#ifndef IPPROTO_DIVERT
|
||||
#define IPPROTO_DIVERT 258
|
||||
#endif
|
||||
@@ -39,6 +41,12 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
|
||||
|
||||
#define SCALE_NONE ((uint8_t)-1)
|
||||
|
||||
#define VERDICT_PASS 0
|
||||
#define VERDICT_MODIFY 1
|
||||
#define VERDICT_DROP 2
|
||||
#define VERDICT_MASK 3
|
||||
#define VERDICT_NOCSUM 4
|
||||
|
||||
// seq and wsize have network byte order
|
||||
bool prepare_tcp_segment4(
|
||||
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
||||
@@ -136,6 +144,9 @@ bool tcp_has_fastopen(const struct tcphdr *tcp);
|
||||
|
||||
// auto creates internal socket and uses it for subsequent calls
|
||||
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);
|
||||
// should pre-do it if dropping privileges. otherwise its not necessary
|
||||
bool rawsend_preinit(bool bind_fix4, bool bind_fix6);
|
||||
// cleans up socket autocreated by rawsend
|
||||
@@ -158,6 +169,14 @@ bool proto_check_tcp(const uint8_t *data, size_t len);
|
||||
void proto_skip_tcp(uint8_t **data, size_t *len);
|
||||
bool proto_check_udp(const uint8_t *data, size_t len);
|
||||
void proto_skip_udp(uint8_t **data, size_t *len);
|
||||
void proto_dissect_l3l4(
|
||||
uint8_t *data, size_t len,
|
||||
struct ip **ip, struct ip6_hdr **ip6,
|
||||
uint8_t *proto,
|
||||
struct tcphdr **tcp,
|
||||
struct udphdr **udp,
|
||||
size_t *transport_len,
|
||||
uint8_t **data_payload, size_t *len_payload);
|
||||
|
||||
bool tcp_synack_segment(const struct tcphdr *tcphdr);
|
||||
bool tcp_syn_segment(const struct tcphdr *tcphdr);
|
||||
@@ -177,3 +196,6 @@ typedef struct
|
||||
#define AUTOTTL_SET_DEFAULT(a) {(a).delta=AUTOTTL_DEFAULT_DELTA; (a).min=AUTOTTL_DEFAULT_MIN; (a).max=AUTOTTL_DEFAULT_MAX;}
|
||||
|
||||
uint8_t autottl_guess(uint8_t ttl, const autottl *attl);
|
||||
|
||||
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);
|
||||
void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);
|
||||
|
878
nfq/desync.c
878
nfq/desync.c
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "darkmagic.h"
|
||||
#include "nfqws.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
@@ -51,5 +50,4 @@ bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode);
|
||||
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode);
|
||||
|
||||
void desync_init(void);
|
||||
uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, 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);
|
||||
uint8_t dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt, struct ip *ip, struct ip6_hdr *ip6hdr, struct udphdr *udphdr, uint8_t *data_payload, size_t len_payload);
|
||||
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt);
|
||||
|
@@ -5,9 +5,11 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include "params.h"
|
||||
|
||||
void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
|
||||
{
|
||||
size_t k;
|
||||
|
@@ -5,9 +5,9 @@
|
||||
#include <sys/socket.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "params.h"
|
||||
#include <time.h>
|
||||
|
||||
void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit);
|
||||
char *strncasestr(const char *s,const char *find, size_t slen);
|
||||
|
236
nfq/nfqws.c
236
nfq/nfqws.c
@@ -79,108 +79,16 @@ static void onusr2(int sig)
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt)
|
||||
{
|
||||
struct ip *ip = NULL;
|
||||
struct ip6_hdr *ip6hdr = NULL;
|
||||
struct tcphdr *tcphdr = NULL;
|
||||
struct udphdr *udphdr = NULL;
|
||||
size_t len = *len_pkt, len_with_th;
|
||||
uint8_t *data = data_pkt;
|
||||
uint8_t res = VERDICT_PASS;
|
||||
uint8_t proto;
|
||||
|
||||
#ifdef __linux__
|
||||
if (*mark & params.desync_fwmark)
|
||||
{
|
||||
DLOG("ignoring generated packet\n")
|
||||
return res;
|
||||
return VERDICT_PASS;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (proto_check_ipv4(data, len))
|
||||
{
|
||||
ip = (struct ip *) data;
|
||||
proto = ip->ip_p;
|
||||
proto_skip_ipv4(&data, &len);
|
||||
if (params.debug)
|
||||
{
|
||||
printf("IP4: ");
|
||||
print_ip(ip);
|
||||
}
|
||||
}
|
||||
else if (proto_check_ipv6(data, len))
|
||||
{
|
||||
ip6hdr = (struct ip6_hdr *) data;
|
||||
proto_skip_ipv6(&data, &len, &proto, NULL);
|
||||
if (params.debug)
|
||||
{
|
||||
printf("IP6: ");
|
||||
print_ip6hdr(ip6hdr, proto);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// not ipv6 and not ipv4
|
||||
return res;
|
||||
}
|
||||
|
||||
if (proto==IPPROTO_TCP && proto_check_tcp(data, len))
|
||||
{
|
||||
tcphdr = (struct tcphdr *) data;
|
||||
len_with_th = len;
|
||||
proto_skip_tcp(&data, &len);
|
||||
|
||||
if (params.debug)
|
||||
{
|
||||
printf(" ");
|
||||
print_tcphdr(tcphdr);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (len) { DLOG("TCP: ") hexdump_limited_dlog(data, len, 32); DLOG("\n") }
|
||||
|
||||
res = dpi_desync_tcp_packet(*mark, ifout, data_pkt, len_pkt, ip, ip6hdr, tcphdr, len_with_th, data, len);
|
||||
// in my FreeBSD divert tests only ipv4 packets were reinjected with correct checksum
|
||||
// ipv6 packets were with incorrect checksum
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if (!(res & VERDICT_NOCSUM) && ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr && (res & VERDICT_MASK)==VERDICT_PASS))
|
||||
#else
|
||||
if (!(res & VERDICT_NOCSUM) && (res & VERDICT_MASK)==VERDICT_MODIFY)
|
||||
#endif
|
||||
tcp_fix_checksum(tcphdr,len_with_th,ip,ip6hdr);
|
||||
}
|
||||
else if (proto==IPPROTO_UDP && proto_check_udp(data, len))
|
||||
{
|
||||
udphdr = (struct udphdr *) data;
|
||||
len_with_th = len;
|
||||
proto_skip_udp(&data, &len);
|
||||
|
||||
if (params.debug)
|
||||
{
|
||||
printf(" ");
|
||||
print_udphdr(udphdr);
|
||||
printf("\n");
|
||||
}
|
||||
if (len) { DLOG("UDP: ") hexdump_limited_dlog(data, len, 32); DLOG("\n") }
|
||||
|
||||
res = dpi_desync_udp_packet(*mark, ifout, data_pkt, len_pkt, ip, ip6hdr, udphdr, data, len);
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if (!(res & VERDICT_NOCSUM) && ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr && (res & VERDICT_MASK)==VERDICT_PASS))
|
||||
#else
|
||||
if (!(res & VERDICT_NOCSUM) && (res & VERDICT_MASK)==VERDICT_MODIFY)
|
||||
#endif
|
||||
udp_fix_checksum(udphdr,len_with_th,ip,ip6hdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (params.debug) printf("\n");
|
||||
}
|
||||
|
||||
return res;
|
||||
return dpi_desync_packet(*mark, ifout, data_pkt, len_pkt);
|
||||
}
|
||||
|
||||
|
||||
@@ -214,8 +122,8 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
|
||||
if (ilen >= 0)
|
||||
{
|
||||
len = ilen;
|
||||
uint8_t res = processPacketData(&mark, ifout, data, &len);
|
||||
switch(res & VERDICT_MASK)
|
||||
uint8_t verdict = processPacketData(&mark, ifout, data, &len);
|
||||
switch(verdict & VERDICT_MASK)
|
||||
{
|
||||
case VERDICT_MODIFY:
|
||||
DLOG("packet: id=%d pass modified. len=%zu\n", id, len);
|
||||
@@ -438,16 +346,16 @@ static int dvt_main(void)
|
||||
else if (rd>0)
|
||||
{
|
||||
uint32_t mark=0;
|
||||
uint8_t res;
|
||||
uint8_t verdict;
|
||||
size_t len = rd;
|
||||
|
||||
DLOG("packet: id=%u len=%zu\n", id, len)
|
||||
res = processPacketData(&mark, NULL, buf, &len);
|
||||
switch (res & VERDICT_MASK)
|
||||
verdict = processPacketData(&mark, NULL, buf, &len);
|
||||
switch (verdict & VERDICT_MASK)
|
||||
{
|
||||
case VERDICT_PASS:
|
||||
case VERDICT_MODIFY:
|
||||
if ((res & VERDICT_MASK)==VERDICT_PASS)
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_PASS)
|
||||
DLOG("packet: id=%u reinject unmodified\n", id)
|
||||
else
|
||||
DLOG("packet: id=%u reinject modified len=%zu\n", id, len)
|
||||
@@ -544,9 +452,6 @@ static void exithelp(void)
|
||||
" --dpi-desync-autottl=[<delta>[:<min>[-<max>]]]\t; auto ttl mode for both ipv4 and ipv6. default: %u:%u-%u\n"
|
||||
" --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only\n"
|
||||
" --dpi-desync-fooling=<mode>[,<mode>]\t\t; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2\n"
|
||||
#ifdef __linux__
|
||||
" --dpi-desync-retrans=0|1\t\t\t; 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission\n"
|
||||
#endif
|
||||
" --dpi-desync-repeats=<N>\t\t\t; send every desync packet N times\n"
|
||||
" --dpi-desync-skip-nosni=0|1\t\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n"
|
||||
" --dpi-desync-split-pos=<1..%u>\t\t; data payload split position\n"
|
||||
@@ -765,38 +670,37 @@ int main(int argc, char **argv)
|
||||
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=18
|
||||
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=19
|
||||
{"dpi-desync-fooling",required_argument,0,0}, // optidx=20
|
||||
{"dpi-desync-retrans",optional_argument,0,0}, // optidx=21
|
||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=22
|
||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=23
|
||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=24
|
||||
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=25
|
||||
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=26
|
||||
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=27
|
||||
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=28
|
||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=29
|
||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=30
|
||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=31
|
||||
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=32
|
||||
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=33
|
||||
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=34
|
||||
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=35
|
||||
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=36
|
||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=37
|
||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=38
|
||||
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=39
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=40
|
||||
{"dpi-desync-start",required_argument,0,0},// optidx=41
|
||||
{"hostlist",required_argument,0,0}, // optidx=42
|
||||
{"hostlist-exclude",required_argument,0,0}, // optidx=43
|
||||
{"hostlist-auto",required_argument,0,0}, // optidx=44
|
||||
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=45
|
||||
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=46
|
||||
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=47
|
||||
{"hostlist-auto-debug",required_argument,0,0}, // optidx=48
|
||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=21
|
||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=22
|
||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=23
|
||||
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=24
|
||||
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=25
|
||||
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=26
|
||||
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=27
|
||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=28
|
||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=29
|
||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=30
|
||||
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=31
|
||||
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=32
|
||||
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=33
|
||||
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=34
|
||||
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=35
|
||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=36
|
||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=37
|
||||
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=38
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=39
|
||||
{"dpi-desync-start",required_argument,0,0},// optidx=40
|
||||
{"hostlist",required_argument,0,0}, // optidx=41
|
||||
{"hostlist-exclude",required_argument,0,0}, // optidx=42
|
||||
{"hostlist-auto",required_argument,0,0}, // optidx=43
|
||||
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=44
|
||||
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=45
|
||||
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=46
|
||||
{"hostlist-auto-debug",required_argument,0,0}, // optidx=47
|
||||
|
||||
#ifdef __linux__
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=49
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=50
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=48
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=49
|
||||
#endif
|
||||
{NULL,0,NULL,0}
|
||||
};
|
||||
@@ -1012,32 +916,24 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 21: /* dpi-desync-retrans */
|
||||
#ifdef __linux__
|
||||
params.desync_retrans = !optarg || atoi(optarg);
|
||||
#else
|
||||
fprintf(stderr, "dpi-desync-retrans is only supported in linux\n");
|
||||
exit_clean(1);
|
||||
#endif
|
||||
break;
|
||||
case 22: /* dpi-desync-repeats */
|
||||
case 21: /* dpi-desync-repeats */
|
||||
if (sscanf(optarg,"%u",¶ms.desync_repeats)<1 || !params.desync_repeats || params.desync_repeats>20)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-repeats must be within 1..20\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 23: /* dpi-desync-skip-nosni */
|
||||
case 22: /* dpi-desync-skip-nosni */
|
||||
params.desync_skip_nosni = !optarg || atoi(optarg);
|
||||
break;
|
||||
case 24: /* dpi-desync-split-pos */
|
||||
case 23: /* dpi-desync-split-pos */
|
||||
if (sscanf(optarg,"%u",¶ms.desync_split_pos)<1 || params.desync_split_pos<1 || params.desync_split_pos>DPI_DESYNC_MAX_FAKE_LEN)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-split-pos must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 25: /* dpi-desync-ipfrag-pos-tcp */
|
||||
case 24: /* dpi-desync-ipfrag-pos-tcp */
|
||||
if (sscanf(optarg,"%u",¶ms.desync_ipfrag_pos_tcp)<1 || params.desync_ipfrag_pos_tcp<1 || params.desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||
@@ -1049,7 +945,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 26: /* dpi-desync-ipfrag-pos-udp */
|
||||
case 25: /* dpi-desync-ipfrag-pos-udp */
|
||||
if (sscanf(optarg,"%u",¶ms.desync_ipfrag_pos_udp)<1 || params.desync_ipfrag_pos_udp<1 || params.desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||
@@ -1061,63 +957,63 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 27: /* dpi-desync-badseq-increments */
|
||||
case 26: /* dpi-desync-badseq-increments */
|
||||
if (!parse_badseq_increment(optarg,¶ms.desync_badseq_increment))
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 28: /* dpi-desync-badack-increment */
|
||||
case 27: /* dpi-desync-badack-increment */
|
||||
if (!parse_badseq_increment(optarg,¶ms.desync_badseq_ack_increment))
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 29: /* dpi-desync-any-protocol */
|
||||
case 28: /* dpi-desync-any-protocol */
|
||||
params.desync_any_proto = !optarg || atoi(optarg);
|
||||
break;
|
||||
case 30: /* dpi-desync-fake-http */
|
||||
case 29: /* dpi-desync-fake-http */
|
||||
params.fake_http_size = sizeof(params.fake_http);
|
||||
load_file_or_exit(optarg,params.fake_http,¶ms.fake_http_size);
|
||||
break;
|
||||
case 31: /* dpi-desync-fake-tls */
|
||||
case 30: /* dpi-desync-fake-tls */
|
||||
params.fake_tls_size = sizeof(params.fake_tls);
|
||||
load_file_or_exit(optarg,params.fake_tls,¶ms.fake_tls_size);
|
||||
break;
|
||||
case 32: /* dpi-desync-fake-unknown */
|
||||
case 31: /* dpi-desync-fake-unknown */
|
||||
params.fake_unknown_size = sizeof(params.fake_unknown);
|
||||
load_file_or_exit(optarg,params.fake_unknown,¶ms.fake_unknown_size);
|
||||
break;
|
||||
case 33: /* dpi-desync-fake-syndata */
|
||||
case 32: /* dpi-desync-fake-syndata */
|
||||
params.fake_syndata_size = sizeof(params.fake_syndata);
|
||||
load_file_or_exit(optarg,params.fake_syndata,¶ms.fake_syndata_size);
|
||||
break;
|
||||
case 34: /* dpi-desync-fake-quic */
|
||||
case 33: /* dpi-desync-fake-quic */
|
||||
params.fake_quic_size = sizeof(params.fake_quic);
|
||||
load_file_or_exit(optarg,params.fake_quic,¶ms.fake_quic_size);
|
||||
break;
|
||||
case 35: /* dpi-desync-fake-wireguard */
|
||||
case 34: /* dpi-desync-fake-wireguard */
|
||||
params.fake_wg_size = sizeof(params.fake_wg);
|
||||
load_file_or_exit(optarg,params.fake_wg,¶ms.fake_wg_size);
|
||||
break;
|
||||
case 36: /* dpi-desync-fake-dht */
|
||||
case 35: /* dpi-desync-fake-dht */
|
||||
params.fake_dht_size = sizeof(params.fake_dht);
|
||||
load_file_or_exit(optarg,params.fake_dht,¶ms.fake_dht_size);
|
||||
break;
|
||||
case 37: /* dpi-desync-fake-unknown-udp */
|
||||
case 36: /* dpi-desync-fake-unknown-udp */
|
||||
params.fake_unknown_udp_size = sizeof(params.fake_unknown_udp);
|
||||
load_file_or_exit(optarg,params.fake_unknown_udp,¶ms.fake_unknown_udp_size);
|
||||
break;
|
||||
case 38: /* dpi-desync-udplen-increment */
|
||||
case 37: /* dpi-desync-udplen-increment */
|
||||
if (sscanf(optarg,"%d",¶ms.udplen_increment)<1 || params.udplen_increment>0x7FFF || params.udplen_increment<-0x8000)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 39: /* dpi-desync-udplen-pattern */
|
||||
case 38: /* dpi-desync-udplen-pattern */
|
||||
{
|
||||
char buf[sizeof(params.udplen_pattern)];
|
||||
size_t sz=sizeof(buf);
|
||||
@@ -1125,35 +1021,35 @@ int main(int argc, char **argv)
|
||||
fill_pattern(params.udplen_pattern,sizeof(params.udplen_pattern),buf,sz);
|
||||
}
|
||||
break;
|
||||
case 40: /* desync-cutoff */
|
||||
case 39: /* desync-cutoff */
|
||||
if (!parse_cutoff(optarg, ¶ms.desync_cutoff, ¶ms.desync_cutoff_mode))
|
||||
{
|
||||
fprintf(stderr, "invalid desync-cutoff value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 41: /* desync-start */
|
||||
case 40: /* desync-start */
|
||||
if (!parse_cutoff(optarg, ¶ms.desync_start, ¶ms.desync_start_mode))
|
||||
{
|
||||
fprintf(stderr, "invalid desync-start value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 42: /* hostlist */
|
||||
case 41: /* hostlist */
|
||||
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||
{
|
||||
fprintf(stderr, "strlist_add failed\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 43: /* hostlist-exclude */
|
||||
case 42: /* hostlist-exclude */
|
||||
if (!strlist_add(¶ms.hostlist_exclude_files, optarg))
|
||||
{
|
||||
fprintf(stderr, "strlist_add failed\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 44: /* hostlist-auto */
|
||||
case 43: /* hostlist-auto */
|
||||
if (*params.hostlist_auto_filename)
|
||||
{
|
||||
fprintf(stderr, "only one auto hostlist is supported\n");
|
||||
@@ -1184,7 +1080,7 @@ int main(int argc, char **argv)
|
||||
strncpy(params.hostlist_auto_filename, optarg, sizeof(params.hostlist_auto_filename));
|
||||
params.hostlist_auto_filename[sizeof(params.hostlist_auto_filename) - 1] = '\0';
|
||||
break;
|
||||
case 45: /* hostlist-auto-fail-threshold */
|
||||
case 44: /* hostlist-auto-fail-threshold */
|
||||
params.hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||
if (params.hostlist_auto_fail_threshold<1 || params.hostlist_auto_fail_threshold>20)
|
||||
{
|
||||
@@ -1192,7 +1088,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 46: /* hostlist-auto-fail-time */
|
||||
case 45: /* hostlist-auto-fail-time */
|
||||
params.hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||
if (params.hostlist_auto_fail_time<1)
|
||||
{
|
||||
@@ -1200,7 +1096,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 47: /* hostlist-auto-retrans-threshold */
|
||||
case 46: /* hostlist-auto-retrans-threshold */
|
||||
params.hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
|
||||
if (params.hostlist_auto_retrans_threshold<2 || params.hostlist_auto_retrans_threshold>10)
|
||||
{
|
||||
@@ -1208,7 +1104,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 48: /* hostlist-auto-debug */
|
||||
case 47: /* hostlist-auto-debug */
|
||||
{
|
||||
FILE *F = fopen(optarg,"a+t");
|
||||
if (!F)
|
||||
@@ -1224,10 +1120,10 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
#ifdef __linux__
|
||||
case 49: /* bind-fix4 */
|
||||
case 48: /* bind-fix4 */
|
||||
params.bind_fix4 = true;
|
||||
break;
|
||||
case 50: /* bind-fix6 */
|
||||
case 49: /* bind-fix6 */
|
||||
params.bind_fix6 = true;
|
||||
break;
|
||||
#endif
|
||||
|
@@ -1,7 +1 @@
|
||||
#pragma once
|
||||
|
||||
#define VERDICT_PASS 0
|
||||
#define VERDICT_MODIFY 1
|
||||
#define VERDICT_DROP 2
|
||||
#define VERDICT_MASK 3
|
||||
#define VERDICT_NOCSUM 4
|
||||
|
67
nfq/packet_queue.c
Normal file
67
nfq/packet_queue.c
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "packet_queue.h"
|
||||
|
||||
void rawpacket_queue_init(struct rawpacket_tailhead *q)
|
||||
{
|
||||
TAILQ_INIT(q);
|
||||
}
|
||||
void rawpacket_free(struct rawpacket *rp)
|
||||
{
|
||||
if (rp) free(rp->packet);
|
||||
free(rp);
|
||||
}
|
||||
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q)
|
||||
{
|
||||
struct rawpacket *rp;
|
||||
rp = TAILQ_FIRST(q);
|
||||
if (rp) TAILQ_REMOVE(q, rp, next);
|
||||
return rp;
|
||||
}
|
||||
void rawpacket_queue_destroy(struct rawpacket_tailhead *q)
|
||||
{
|
||||
struct rawpacket *rp;
|
||||
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
|
||||
}
|
||||
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len)
|
||||
{
|
||||
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
|
||||
if (!rp) return NULL;
|
||||
|
||||
rp->packet = malloc(len);
|
||||
if (!rp->packet)
|
||||
{
|
||||
free(rp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rp->dst = *dst;
|
||||
rp->fwmark = fwmark;
|
||||
if (ifout)
|
||||
{
|
||||
strncpy(rp->ifout,ifout,sizeof(rp->ifout));
|
||||
rp->ifout[sizeof(rp->ifout)-1]=0;
|
||||
}
|
||||
else
|
||||
rp->ifout[0]=0;
|
||||
memcpy(rp->packet,data,len);
|
||||
rp->len=len;
|
||||
|
||||
TAILQ_INSERT_TAIL(q, rp, next);
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q)
|
||||
{
|
||||
const struct rawpacket *rp;
|
||||
unsigned int ct=0;
|
||||
TAILQ_FOREACH(rp, q, next) ct++;
|
||||
return ct;
|
||||
}
|
||||
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q)
|
||||
{
|
||||
return !TAILQ_FIRST(q);
|
||||
}
|
26
nfq/packet_queue.h
Normal file
26
nfq/packet_queue.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/queue.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
struct rawpacket
|
||||
{
|
||||
struct sockaddr_storage dst;
|
||||
char ifout[IFNAMSIZ+1];
|
||||
uint32_t fwmark;
|
||||
size_t len;
|
||||
uint8_t *packet;
|
||||
TAILQ_ENTRY(rawpacket) next;
|
||||
};
|
||||
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,const char *ifout,const void *data,size_t len);
|
||||
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
|
||||
void rawpacket_free(struct rawpacket *rp);
|
@@ -125,6 +125,20 @@ bool IsTLSClientHello(const uint8_t *data, size_t len, bool bPartialIsOK)
|
||||
return len >= 6 && data[0] == 0x16 && data[1] == 0x03 && data[2] >= 0x01 && data[2] <= 0x03 && data[5] == 0x01 && (bPartialIsOK || TLSRecordLen(data) <= len);
|
||||
}
|
||||
|
||||
size_t TLSHandshakeLen(const uint8_t *data)
|
||||
{
|
||||
return data[1] << 16 | data[2] << 8 | data[3]; // HandshakeProtocol length
|
||||
}
|
||||
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len>=4 && data[0]==0x01;
|
||||
}
|
||||
bool IsTLSHandshakeFull(const uint8_t *data, size_t len)
|
||||
{
|
||||
return (4+TLSHandshakeLen(data))<=len;
|
||||
}
|
||||
|
||||
|
||||
// bPartialIsOK=true - accept partial packets not containing the whole TLS message
|
||||
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK)
|
||||
{
|
||||
@@ -143,14 +157,11 @@ bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const
|
||||
|
||||
size_t l, ll;
|
||||
|
||||
if (!bPartialIsOK && !IsTLSHandshakeFull(data,len)) return false;
|
||||
|
||||
l = 1 + 3 + 2 + 32;
|
||||
// SessionIDLength
|
||||
if (len < (l + 1)) return false;
|
||||
if (!bPartialIsOK)
|
||||
{
|
||||
ll = data[1] << 16 | data[2] << 8 | data[3]; // HandshakeProtocol length
|
||||
if (len < (ll + 4)) return false;
|
||||
}
|
||||
l += data[l] + 1;
|
||||
// CipherSuitesLength
|
||||
if (len < (l + 2)) return false;
|
||||
@@ -276,7 +287,7 @@ bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, si
|
||||
// offset must be 0 if it's a full segment, not just a chunk
|
||||
if (coff || (offset+tvb_get_size(data[offset])) >= len) return false;
|
||||
offset += tvb_get_varint(data + offset, &clen);
|
||||
if (data[offset] != 0x01 || (offset + clen) > len) return false;
|
||||
if ((offset + clen) > len || !IsTLSHandshakeClientHello(data+offset,clen)) return false;
|
||||
if (hello_offset) *hello_offset = offset;
|
||||
if (hello_len) *hello_len = (size_t)clen;
|
||||
return true;
|
||||
|
@@ -22,6 +22,9 @@ uint16_t TLSRecordDataLen(const uint8_t *data);
|
||||
size_t TLSRecordLen(const uint8_t *data);
|
||||
bool IsTLSRecordFull(const uint8_t *data, size_t len);
|
||||
bool IsTLSClientHello(const uint8_t *data, size_t len, bool bPartialIsOK);
|
||||
size_t TLSHandshakeLen(const uint8_t *data);
|
||||
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len);
|
||||
bool IsTLSHandshakeFull(const uint8_t *data, size_t len);
|
||||
bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
|
||||
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
|
||||
bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
|
||||
|
Reference in New Issue
Block a user