mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
nfqws: preserve fwmark. bind-fix
This commit is contained in:
@@ -851,6 +851,7 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
|
||||
|
||||
|
||||
static int rawsend_sock4=-1, rawsend_sock6=-1;
|
||||
static bool b_bind_fix4=false, b_bind_fix6=false;
|
||||
static void rawsend_clean_sock(int *sock)
|
||||
{
|
||||
if (sock && *sock!=-1)
|
||||
@@ -934,7 +935,28 @@ static int rawsend_socket_raw(int domain, int proto)
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int rawsend_socket(sa_family_t family,uint32_t fwmark)
|
||||
static bool set_socket_fwmark(int sock, uint32_t fwmark)
|
||||
{
|
||||
#ifdef BSD
|
||||
#ifdef SO_USER_COOKIE
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_USER_COOKIE, &fwmark, sizeof(fwmark)) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(SO_USER_COOKIE)");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(SO_MARK)");
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static int rawsend_socket(sa_family_t family)
|
||||
{
|
||||
int yes=1;
|
||||
int *sock = rawsend_family_sock(family);
|
||||
@@ -971,20 +993,8 @@ static int rawsend_socket(sa_family_t family,uint32_t fwmark)
|
||||
goto exiterr;
|
||||
}
|
||||
#endif
|
||||
#ifdef SO_USER_COOKIE
|
||||
if (setsockopt(*sock, SOL_SOCKET, SO_USER_COOKIE, &fwmark, sizeof(fwmark)) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(SO_MARK)");
|
||||
goto exiterr;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
if (setsockopt(*sock, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(SO_MARK)");
|
||||
goto exiterr;
|
||||
}
|
||||
if (setsockopt(*sock, SOL_SOCKET, SO_PRIORITY, &pri, sizeof(pri)) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(SO_PRIORITY)");
|
||||
@@ -995,6 +1005,16 @@ static int rawsend_socket(sa_family_t family,uint32_t fwmark)
|
||||
perror("rawsend: setsockopt(IP_NODEFRAG)");
|
||||
goto exiterr;
|
||||
}
|
||||
if (family==AF_INET && setsockopt(*sock, IPPROTO_IP, IP_FREEBIND, &yes, sizeof(yes)) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(IP_FREEBIND)");
|
||||
goto exiterr;
|
||||
}
|
||||
if (family==AF_INET6 && setsockopt(*sock, SOL_IPV6, IPV6_FREEBIND, &yes, sizeof(yes)) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(IPV6_FREEBIND)");
|
||||
// dont error because it's supported only from kernel 4.15
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return *sock;
|
||||
@@ -1002,14 +1022,17 @@ exiterr:
|
||||
rawsend_clean_sock(sock);
|
||||
return -1;
|
||||
}
|
||||
bool rawsend_preinit(uint32_t fwmark)
|
||||
bool rawsend_preinit(bool bind_fix4, bool bind_fix6)
|
||||
{
|
||||
return rawsend_socket(AF_INET,fwmark)!=-1 && rawsend_socket(AF_INET6,fwmark)!=-1;
|
||||
b_bind_fix4 = bind_fix4;
|
||||
b_bind_fix6 = bind_fix6;
|
||||
return rawsend_socket(AF_INET)!=-1 && rawsend_socket(AF_INET6)!=-1;
|
||||
}
|
||||
bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len)
|
||||
bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len)
|
||||
{
|
||||
int sock=rawsend_socket(dst->sa_family,fwmark);
|
||||
int sock=rawsend_socket(dst->sa_family);
|
||||
if (sock==-1) return false;
|
||||
if (!set_socket_fwmark(sock,fwmark)) return false;
|
||||
|
||||
int salen = dst->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
|
||||
struct sockaddr_storage dst2;
|
||||
@@ -1028,7 +1051,7 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const void *data,size_t
|
||||
v = ((struct ip6_hdr *)data)->ip6_ctlun.ip6_un1.ip6_un1_hlim;
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &v, sizeof(v)) == -1)
|
||||
perror("rawsend: setsockopt(IPV6_HOPLIMIT)");
|
||||
[5~ // the only way to control source address is bind. make it equal to ip6_hdr
|
||||
// the only way to control source address is bind. make it equal to ip6_hdr
|
||||
if (bind(sock, (struct sockaddr*)&sa_src, salen) < 0)
|
||||
perror("rawsend bind: ");
|
||||
//printf("BSD v6 RAWSEND "); print_sockaddr((struct sockaddr*)&sa_src); printf(" -> "); print_sockaddr((struct sockaddr*)&dst2); printf("\n");
|
||||
@@ -1059,6 +1082,44 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const void *data,size_t
|
||||
((struct ip*)data)->ip_off = htons(((struct ip*)data)->ip_off);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
struct sockaddr_storage sa_src;
|
||||
switch(dst->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
if (!b_bind_fix4) goto nofix;
|
||||
extract_endpoints(data,NULL,NULL,NULL, &sa_src, NULL);
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (!b_bind_fix6) goto nofix;
|
||||
extract_endpoints(NULL,data,NULL,NULL, &sa_src, NULL);
|
||||
break;
|
||||
default:
|
||||
return false; // should not happen
|
||||
}
|
||||
//printf("family %u dev %s bind : ", dst->sa_family, ifout); print_sockaddr((struct sockaddr *)&sa_src); printf("\n");
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifout, ifout ? strlen(ifout)+1 : 0) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(SO_BINDTODEVICE)");
|
||||
return false;
|
||||
}
|
||||
if (bind(sock, (const struct sockaddr*)&sa_src, dst->sa_family==AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)))
|
||||
{
|
||||
perror("rawsend: bind (ignoring)");
|
||||
// do not fail. this can happen regardless of IP_FREEBIND
|
||||
// rebind to any address
|
||||
memset(&sa_src,0,sizeof(sa_src));
|
||||
sa_src.ss_family = dst->sa_family;
|
||||
if (bind(sock, (const struct sockaddr*)&sa_src, dst->sa_family==AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)))
|
||||
{
|
||||
perror("rawsend: bind to any");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
nofix:
|
||||
#endif
|
||||
|
||||
// normal raw socket sendto
|
||||
ssize_t bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen);
|
||||
#if defined(__FreeBSD) && __FreeBSD__<=10
|
||||
|
@@ -118,9 +118,9 @@ uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
|
||||
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
|
||||
|
||||
// auto creates internal socket and uses it for subsequent calls
|
||||
bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len);
|
||||
bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len);
|
||||
// should pre-do it if dropping privileges. otherwise its not necessary
|
||||
bool rawsend_preinit(uint32_t fwmark);
|
||||
bool rawsend_preinit(bool bind_fix4, bool bind_fix6);
|
||||
// cleans up socket autocreated by rawsend
|
||||
void rawsend_cleanup();
|
||||
|
||||
|
52
nfq/desync.c
52
nfq/desync.c
@@ -122,10 +122,10 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
|
||||
|
||||
|
||||
// auto creates internal socket and uses it for subsequent calls
|
||||
static bool rawsend_rep(const struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len)
|
||||
static bool rawsend_rep(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len)
|
||||
{
|
||||
for (int i=0;i<params.desync_repeats;i++)
|
||||
if (!rawsend(dst,fwmark,data,len))
|
||||
if (!rawsend(dst,fwmark,ifout,data,len))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -169,7 +169,7 @@ static void wssize_cutoff(t_ctrack *ctrack)
|
||||
}
|
||||
#define CONNTRACK_REQUIRED (params.wssize || params.desync_cutoff)
|
||||
// result : true - drop original packet, false = dont drop
|
||||
packet_process_result dpi_desync_tcp_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 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)
|
||||
{
|
||||
packet_process_result res=pass;
|
||||
t_ctrack *ctrack=NULL;
|
||||
@@ -200,6 +200,8 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
|
||||
if (bReverse) return res; // nothing to do. do not waste cpu
|
||||
|
||||
uint32_t desync_fwmark = fwmark | params.desync_fwmark;
|
||||
|
||||
if (params.wssize)
|
||||
{
|
||||
if (ctrack)
|
||||
@@ -243,7 +245,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
}
|
||||
DLOG("sending fake SYNACK\n");
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -424,7 +426,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
}
|
||||
DLOG("resending original packet with extension header\n");
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
// this mode is final, no other options available
|
||||
return drop;
|
||||
@@ -434,7 +436,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
|
||||
if (b)
|
||||
{
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
if (params.desync_mode2==DESYNC_NONE || !desync_valid_second_stage_tcp(params.desync_mode2))
|
||||
{
|
||||
@@ -453,7 +455,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
if (res==modify)
|
||||
#endif
|
||||
tcp_fix_checksum(tcphdr,len_tcp,ip,ip6hdr);
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, data_pkt, len_pkt))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , data_pkt, len_pkt))
|
||||
return res;
|
||||
}
|
||||
return drop;
|
||||
@@ -479,7 +481,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,len_payload-1, len_payload-split_pos)
|
||||
hexdump_limited_dlog(data_payload+split_pos,len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -493,7 +495,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -505,14 +507,14 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(data_payload,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
|
||||
if (desync_mode==DESYNC_DISORDER)
|
||||
{
|
||||
DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -534,7 +536,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -545,14 +547,14 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
DLOG("sending 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(data_payload,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
|
||||
if (desync_mode==DESYNC_SPLIT)
|
||||
{
|
||||
DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -565,7 +567,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ",split_pos,len_payload-1, len_payload-split_pos)
|
||||
hexdump_limited_dlog(data_payload+split_pos,len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -610,12 +612,12 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
|
||||
DLOG("sending 1st ip fragment 0-%zu len=%zu : ", ipfrag_pos-1, ipfrag_pos)
|
||||
hexdump_limited_dlog(pkt1,pkt1_len,IP_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt2, pkt2_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len))
|
||||
return res;
|
||||
|
||||
DLOG("sending 2nd ip fragment %zu-%zu len=%zu : ", ipfrag_pos, len_tcp-1, len_tcp-ipfrag_pos)
|
||||
hexdump_limited_dlog(pkt2,pkt2_len,IP_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
|
||||
return frag;
|
||||
@@ -628,7 +630,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
|
||||
|
||||
|
||||
packet_process_result dpi_desync_udp_packet(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)
|
||||
packet_process_result 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)
|
||||
{
|
||||
packet_process_result res=pass;
|
||||
t_ctrack *ctrack=NULL;
|
||||
@@ -760,6 +762,8 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
uint32_t desync_fwmark = fwmark | params.desync_fwmark;
|
||||
|
||||
pkt1_len = sizeof(pkt1);
|
||||
b = false;
|
||||
switch(desync_mode)
|
||||
@@ -776,7 +780,7 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
DLOG("sending fake request : ");
|
||||
hexdump_limited_dlog(fake,fake_size,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
b = true;
|
||||
break;
|
||||
@@ -793,7 +797,7 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
return res;
|
||||
}
|
||||
DLOG("resending original packet with extension header\n");
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
// this mode is final, no other options available
|
||||
return drop;
|
||||
@@ -815,7 +819,7 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
if (res==modify)
|
||||
#endif
|
||||
udp_fix_checksum(udphdr,sizeof(struct udphdr)+len_payload,ip,ip6hdr);
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, data_pkt, len_pkt))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , data_pkt, len_pkt))
|
||||
return res;
|
||||
return drop;
|
||||
}
|
||||
@@ -829,7 +833,7 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,fooling_orig, params.udplen_increment, data_payload, len_payload, pkt1, &pkt1_len))
|
||||
return res;
|
||||
DLOG("resending original packet with increased by %u length\n", params.udplen_increment);
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
return drop;
|
||||
case DESYNC_IPFRAG2:
|
||||
@@ -873,12 +877,12 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
|
||||
DLOG("sending 1st ip fragment 0-%zu len=%zu : ", ipfrag_pos-1, ipfrag_pos)
|
||||
hexdump_limited_dlog(pkt1,pkt1_len,IP_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt2, pkt2_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len))
|
||||
return res;
|
||||
|
||||
DLOG("sending 2nd ip fragment %zu-%zu len=%zu : ", ipfrag_pos, len_transport-1, len_transport-ipfrag_pos)
|
||||
hexdump_limited_dlog(pkt2,pkt2_len,IP_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
|
||||
return frag;
|
||||
|
@@ -49,5 +49,5 @@ 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();
|
||||
packet_process_result dpi_desync_tcp_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 dpi_desync_udp_packet(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);
|
||||
packet_process_result 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);
|
||||
packet_process_result 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);
|
||||
|
57
nfq/nfqws.c
57
nfq/nfqws.c
@@ -78,11 +78,7 @@ static void onusr1(int sig)
|
||||
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt, uint32_t *mark)
|
||||
#else
|
||||
static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt)
|
||||
#endif
|
||||
static packet_process_result processPacketData(uint32_t *mark, const char *ifout, uint8_t *data_pkt, size_t len_pkt)
|
||||
{
|
||||
struct ip *ip = NULL;
|
||||
struct ip6_hdr *ip6hdr = NULL;
|
||||
@@ -143,7 +139,7 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt
|
||||
|
||||
if (len) { DLOG("TCP: ") hexdump_limited_dlog(data, len, 32); DLOG("\n") }
|
||||
|
||||
res = dpi_desync_tcp_packet(data_pkt, len_pkt, ip, ip6hdr, tcphdr, len_with_th, data, len);
|
||||
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__
|
||||
@@ -168,7 +164,7 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt
|
||||
}
|
||||
if (len) { DLOG("UDP: ") hexdump_limited_dlog(data, len, 32); DLOG("\n") }
|
||||
|
||||
res = dpi_desync_udp_packet(data_pkt, len_pkt, ip, ip6hdr, udphdr, data, len);
|
||||
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==modify || res!=frag && ip6hdr)
|
||||
@@ -187,23 +183,35 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
|
||||
struct nfq_data *nfa, void *cookie)
|
||||
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie)
|
||||
{
|
||||
int id;
|
||||
int len;
|
||||
struct nfqnl_msg_packet_hdr *ph;
|
||||
uint8_t *data;
|
||||
uint32_t ifidx;
|
||||
char ifout[IFNAMSIZ+1];
|
||||
|
||||
ph = nfq_get_msg_packet_hdr(nfa);
|
||||
id = ph ? ntohl(ph->packet_id) : 0;
|
||||
|
||||
uint32_t mark = nfq_get_nfmark(nfa);
|
||||
len = nfq_get_payload(nfa, &data);
|
||||
DLOG("packet: id=%d len=%d\n", id, len)
|
||||
|
||||
*ifout=0;
|
||||
if (params.bind_fix4 || params.bind_fix6)
|
||||
{
|
||||
ifidx = nfq_get_outdev(nfa);
|
||||
if (ifidx) if_indextoname(ifidx,ifout);
|
||||
|
||||
DLOG("packet: id=%d len=%d ifout=%s(%u)\n", id, len, ifout, ifidx)
|
||||
}
|
||||
else
|
||||
// save some syscalls
|
||||
DLOG("packet: id=%d len=%d\n", id, len)
|
||||
if (len >= 0)
|
||||
{
|
||||
switch (processPacketData(data, len, &mark))
|
||||
switch (processPacketData(&mark, ifout, data, len))
|
||||
{
|
||||
case modify:
|
||||
DLOG("packet: id=%d pass modified\n", id);
|
||||
@@ -266,6 +274,10 @@ static int nfq_main()
|
||||
// dot not fail. not supported on old linuxes <3.6
|
||||
}
|
||||
|
||||
printf("initializing raw sockets bind-fix4=%u bind-fix6=%u\n",params.bind_fix4,params.bind_fix6);
|
||||
if (!rawsend_preinit(params.bind_fix4,params.bind_fix6))
|
||||
goto exiterr;
|
||||
|
||||
if (params.droproot && !droproot(params.uid, params.gid))
|
||||
goto exiterr;
|
||||
print_id();
|
||||
@@ -378,8 +390,8 @@ static int dvt_main()
|
||||
#endif
|
||||
fdmax = (fd[0]>fd[1] ? fd[0] : fd[1]) + 1;
|
||||
|
||||
printf("initializing raw sockets with sockarg 0x%08X (%u)\n", params.desync_fwmark, params.desync_fwmark);
|
||||
if (!rawsend_preinit(params.desync_fwmark))
|
||||
printf("initializing raw sockets\n");
|
||||
if (!rawsend_preinit(false,false))
|
||||
goto exiterr;
|
||||
|
||||
if (params.droproot && !droproot(params.uid, params.gid))
|
||||
@@ -420,8 +432,9 @@ static int dvt_main()
|
||||
}
|
||||
else if (rd>0)
|
||||
{
|
||||
uint32_t mark=0;
|
||||
DLOG("packet: id=%u len=%zd\n", id, rd)
|
||||
ppr = processPacketData(buf, rd);
|
||||
ppr = processPacketData(&mark, NULL, buf, rd);
|
||||
switch (ppr)
|
||||
{
|
||||
case pass:
|
||||
@@ -497,6 +510,10 @@ static void exithelp()
|
||||
" --pidfile=<filename>\t\t\t; write pid to file\n"
|
||||
" --user=<username>\t\t\t; drop root privs\n"
|
||||
" --uid=uid[:gid]\t\t\t; drop root privs\n"
|
||||
#ifdef __linux__
|
||||
" --bind-fix4\t\t\t\t; apply outgoing interface selection fix for generated ipv4 packets\n"
|
||||
" --bind-fix6\t\t\t\t; apply outgoing interface selection fix for generated ipv6 packets\n"
|
||||
#endif
|
||||
" --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. default scale_factor = 0.\n"
|
||||
" --wssize-cutoff=[n|d|s]N\t\t; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
|
||||
@@ -686,6 +703,10 @@ int main(int argc, char **argv)
|
||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=33
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=34
|
||||
{"hostlist",required_argument,0,0}, // optidx=35
|
||||
#ifdef __linux__
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=36
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=37
|
||||
#endif
|
||||
{NULL,0,NULL,0}
|
||||
};
|
||||
if (argc < 2) exithelp();
|
||||
@@ -986,6 +1007,14 @@ int main(int argc, char **argv)
|
||||
strncpy(params.hostfile,optarg,sizeof(params.hostfile));
|
||||
params.hostfile[sizeof(params.hostfile)-1]='\0';
|
||||
break;
|
||||
#ifdef __linux__
|
||||
case 36: /* bind-fix4 */
|
||||
params.bind_fix4 = true;
|
||||
break;
|
||||
case 37: /* bind-fix6 */
|
||||
params.bind_fix6 = true;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// not specified - use desync_ttl value instead
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <net/if.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -37,6 +38,7 @@ struct params_s
|
||||
#elif defined(BSD)
|
||||
uint16_t port; // divert port
|
||||
#endif
|
||||
char bind_fix4,bind_fix6;
|
||||
bool hostcase, hostnospace, domcase;
|
||||
char hostspell[4];
|
||||
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
|
||||
|
Reference in New Issue
Block a user