mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-26 20:20:53 +03:00
nfqws: preserve fwmark. bind-fix
This commit is contained in:
parent
ba5bde81a3
commit
877adbd6f6
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -140,6 +140,8 @@ nfqws takes the following parameters:
|
||||
```
|
||||
--debug=0|1 ; 1=print debug info
|
||||
--qnum=<nfqueue_number>
|
||||
--bind-fix4 ; apply outgoing interface selection fix for generated ipv4 packets
|
||||
--bind-fix6 ; apply outgoing interface selection fix for generated ipv6 packets
|
||||
--wsize=<winsize>[:<scale_factor>] ; change window size in SYN,ACK packets. default is not to change scale factor (OBSOLETE !)
|
||||
--wssize=<winsize>[:<scale_factor>] ; change window size in outgoing packets. default scale factor is 0. (see CONNTRACK)
|
||||
--wssize-cutoff=[n|d|s]N ; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
||||
|
@ -197,6 +197,8 @@ nfqws
|
||||
--user=<username> ; менять uid процесса
|
||||
--uid=uid[:gid] ; менять uid процесса
|
||||
--qnum=N ; номер очереди N
|
||||
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
|
||||
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
|
||||
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
|
||||
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !)
|
||||
--wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user