mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-26 20:20:53 +03:00
Compare commits
No commits in common. "d1389f25276d685ca0304a2a5a011fd26d753b1b" and "99c6014adb2b687aba84e8ed34cc0ea2b09df23f" have entirely different histories.
d1389f2527
...
99c6014adb
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.
@ -906,16 +906,15 @@ pktws_check_domain_http_bypass_()
|
|||||||
[ "$SCANLEVEL" = quick ] && return
|
[ "$SCANLEVEL" = quick ] && return
|
||||||
}
|
}
|
||||||
done
|
done
|
||||||
|
# do not do wssize test for http. it's useless
|
||||||
|
[ "$sec" = 1 ] || break
|
||||||
|
done
|
||||||
|
|
||||||
s="http_iana_org.bin"
|
s="http_iana_org.bin"
|
||||||
[ "$sec" = 1 ] && s="tls_clienthello_iana_org.bin"
|
[ "$sec" = 1 ] && s="tls_clienthello_iana_org.bin"
|
||||||
for desync in syndata syndata,split2 syndata,disorder2 syndata,split2 syndata,disorder2 ; do
|
for desync in syndata syndata,split2 syndata,disorder2 syndata,split2 syndata,disorder2 ; do
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync $e && [ "$SCANLEVEL" = quick ] && return
|
pktws_curl_test_update_vary $1 $2 $3 $desync && [ "$SCANLEVEL" = quick ] && return
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fake-syndata="$ZAPRET_BASE/files/fake/$s" $e && [ "$SCANLEVEL" = quick ] && return
|
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fake-syndata="$ZAPRET_BASE/files/fake/$s" && [ "$SCANLEVEL" = quick ] && return
|
||||||
done
|
|
||||||
|
|
||||||
# do not do wssize test for http. it's useless
|
|
||||||
[ "$sec" = 1 ] || break
|
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
pktws_check_domain_http_bypass()
|
pktws_check_domain_http_bypass()
|
||||||
|
130
nfq/desync.c
130
nfq/desync.c
@ -321,60 +321,40 @@ static void reasm_orig_fin(t_ctrack *ctrack)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, struct ip *ip, struct ip6_hdr *ip6, uint8_t proto, struct udphdr *udp, struct tcphdr *tcp, size_t *len_pkt)
|
static packet_process_result ct_new_postnat_fix(const t_ctrack *ctrack, struct ip *ip, packet_process_result res)
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
// if used in postnat chain, dropping initial packet will cause conntrack connection teardown
|
// if used in postnat chain, dropping initial packet will cause conntrack connection teardown
|
||||||
// so we need to workaround this.
|
// so we need to workaround this.
|
||||||
// we can't use low ttl because TCP/IP stack listens to ttl expired ICMPs and notify socket
|
// we can't use low ttl for UDP because TCP/IP stack listens to ttl expired ICMPs and notify socket
|
||||||
// we also can't use fooling because DPI would accept fooled packets
|
// we also can't use TCP fooling because DPI would accept fooled packets
|
||||||
if (ctrack && ctrack->pcounter_orig==1)
|
if (ip && ctrack && ctrack->pcounter_orig==1)
|
||||||
{
|
{
|
||||||
DLOG("applying linux postnat conntrack workaround\n")
|
// routers will drop IP frames with invalid checksum
|
||||||
if (proto==IPPROTO_UDP && udp && len_pkt)
|
if (ip->ip_p==IPPROTO_TCP)
|
||||||
{
|
{
|
||||||
// make malformed udp packet with zero length and invalid checksum
|
// linux recalc ip checksum in tcp
|
||||||
udp->len = 0; // invalid length. must be >=8
|
// need another limiter
|
||||||
udp_fix_checksum(udp,sizeof(struct udphdr),ip,ip6);
|
ip->ip_ttl=1;
|
||||||
udp->check ^= htons(0xBEAF);
|
|
||||||
// truncate packet
|
|
||||||
*len_pkt = (uint8_t*)udp - (ip ? (uint8_t*)ip : (uint8_t*)ip6) + sizeof(struct udphdr);
|
|
||||||
if (ip)
|
|
||||||
{
|
|
||||||
ip->ip_len = htons((uint16_t)*len_pkt);
|
|
||||||
ip4_fix_checksum(ip);
|
|
||||||
}
|
}
|
||||||
else if (ip6)
|
else
|
||||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = (uint16_t)htons(sizeof(struct udphdr));
|
ip->ip_sum ^= htons(0xBEAF);
|
||||||
}
|
|
||||||
else if (proto==IPPROTO_TCP && tcp)
|
return res==frag ? modfrag : modify;
|
||||||
{
|
|
||||||
// only SYN here is expected
|
|
||||||
// make flags invalid and also corrupt checksum
|
|
||||||
tcp->th_flags = 0;
|
|
||||||
}
|
|
||||||
if (ip) ip->ip_sum ^= htons(0xBEAF);
|
|
||||||
return VERDICT_MODIFY | VERDICT_NOCSUM;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
return VERDICT_DROP;
|
// ipv6 does not have checksum
|
||||||
|
// consider we are free of NAT in ipv6 case. just drop
|
||||||
|
// BSDs also do not need this
|
||||||
|
return drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t ct_new_postnat_fix_tcp(const t_ctrack *ctrack, struct ip *ip, struct ip6_hdr *ip6, struct tcphdr *tcphdr)
|
|
||||||
{
|
|
||||||
return ct_new_postnat_fix(ctrack,ip,ip6,IPPROTO_TCP,NULL,tcphdr,NULL);
|
|
||||||
}
|
|
||||||
static uint8_t ct_new_postnat_fix_udp(const t_ctrack *ctrack, struct ip *ip, struct ip6_hdr *ip6, struct udphdr *udphdr, size_t *len_pkt)
|
|
||||||
{
|
|
||||||
return ct_new_postnat_fix(ctrack,ip,ip6,IPPROTO_UDP,udphdr,NULL,len_pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// result : true - drop original packet, false = dont drop
|
// result : true - drop original packet, false = dont drop
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
uint8_t res=VERDICT_PASS;
|
packet_process_result res=pass;
|
||||||
t_ctrack *ctrack=NULL;
|
t_ctrack *ctrack=NULL;
|
||||||
bool bReverse=false;
|
bool bReverse=false;
|
||||||
|
|
||||||
@ -397,7 +377,7 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
if (params.wsize && tcp_synack_segment(tcphdr))
|
if (params.wsize && tcp_synack_segment(tcphdr))
|
||||||
{
|
{
|
||||||
tcp_rewrite_winsize(tcphdr, params.wsize, params.wscale);
|
tcp_rewrite_winsize(tcphdr, params.wsize, params.wscale);
|
||||||
res=VERDICT_MODIFY;
|
res=modify;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bReverse)
|
if (bReverse)
|
||||||
@ -470,7 +450,7 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
{
|
{
|
||||||
if (params.wssize_cutoff) DLOG("wssize-cutoff not reached (mode %c): %llu/%u\n", params.wssize_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,params.wssize_cutoff_mode), params.wssize_cutoff);
|
if (params.wssize_cutoff) DLOG("wssize-cutoff not reached (mode %c): %llu/%u\n", params.wssize_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,params.wssize_cutoff_mode), params.wssize_cutoff);
|
||||||
tcp_rewrite_winsize(tcphdr, params.wssize, params.wsscale);
|
tcp_rewrite_winsize(tcphdr, params.wssize, params.wsscale);
|
||||||
res=VERDICT_MODIFY;
|
res=modify;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -528,7 +508,7 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
res = ct_new_postnat_fix_tcp(ctrack, ip, ip6hdr, tcphdr);
|
res = ct_new_postnat_fix(ctrack, ip, drop);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// can do nothing else with SYN packet
|
// can do nothing else with SYN packet
|
||||||
@ -683,14 +663,14 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
{
|
{
|
||||||
DLOG("modifying Host: => %c%c%c%c:\n", params.hostspell[0], params.hostspell[1], params.hostspell[2], params.hostspell[3])
|
DLOG("modifying Host: => %c%c%c%c:\n", params.hostspell[0], params.hostspell[1], params.hostspell[2], params.hostspell[3])
|
||||||
memcpy(phost + 2, params.hostspell, 4);
|
memcpy(phost + 2, params.hostspell, 4);
|
||||||
res=VERDICT_MODIFY;
|
res=modify;
|
||||||
}
|
}
|
||||||
if (params.domcase)
|
if (params.domcase)
|
||||||
{
|
{
|
||||||
DLOG("mixing domain case\n");
|
DLOG("mixing domain case\n");
|
||||||
for (p = phost+7; p < (data_payload + len_payload) && *p != '\r' && *p != '\n'; p++)
|
for (p = phost+7; p < (data_payload + len_payload) && *p != '\r' && *p != '\n'; p++)
|
||||||
*p = (((size_t)p) & 1) ? tolower(*p) : toupper(*p);
|
*p = (((size_t)p) & 1) ? tolower(*p) : toupper(*p);
|
||||||
res=VERDICT_MODIFY;
|
res=modify;
|
||||||
}
|
}
|
||||||
uint8_t *pua;
|
uint8_t *pua;
|
||||||
if (params.hostnospace &&
|
if (params.hostnospace &&
|
||||||
@ -708,7 +688,7 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
memmove(pua + 1, pua, phost - pua + 7);
|
memmove(pua + 1, pua, phost - pua + 7);
|
||||||
*pua = ' ';
|
*pua = ' ';
|
||||||
}
|
}
|
||||||
res=VERDICT_MODIFY;
|
res=modify;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -776,7 +756,7 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||||
return res;
|
return res;
|
||||||
// this mode is final, no other options available
|
// this mode is final, no other options available
|
||||||
return VERDICT_DROP;
|
return drop;
|
||||||
}
|
}
|
||||||
desync_mode = params.desync_mode2;
|
desync_mode = params.desync_mode2;
|
||||||
}
|
}
|
||||||
@ -789,23 +769,23 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
{
|
{
|
||||||
if (params.desync_retrans)
|
if (params.desync_retrans)
|
||||||
{
|
{
|
||||||
DLOG("dropping original packet to force retransmission. len=%zu len_payload=%zu\n", *len_pkt, len_payload)
|
DLOG("dropping original packet to force retransmission. len=%zu len_payload=%zu\n", len_pkt, len_payload)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", *len_pkt, len_payload)
|
DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", len_pkt, len_payload)
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
if ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
if (res==modify || ip6hdr)
|
||||||
#else
|
#else
|
||||||
// if original packet was tampered earlier it needs checksum fixed
|
// if original packet was tampered earlier it needs checksum fixed
|
||||||
if ((res & VERDICT_MASK)==VERDICT_MODIFY)
|
if (res==modify)
|
||||||
#endif
|
#endif
|
||||||
tcp_fix_checksum(tcphdr,len_tcp,ip,ip6hdr);
|
tcp_fix_checksum(tcphdr,len_tcp,ip,ip6hdr);
|
||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , data_pkt, *len_pkt))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , data_pkt, len_pkt))
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
return VERDICT_DROP;
|
return drop;
|
||||||
}
|
}
|
||||||
desync_mode = params.desync_mode2;
|
desync_mode = params.desync_mode2;
|
||||||
}
|
}
|
||||||
@ -865,7 +845,7 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return VERDICT_DROP;
|
return drop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DESYNC_SPLIT:
|
case DESYNC_SPLIT:
|
||||||
@ -918,17 +898,17 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return VERDICT_DROP;
|
return drop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DESYNC_IPFRAG2:
|
case DESYNC_IPFRAG2:
|
||||||
{
|
{
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
if ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
if (res==modify || ip6hdr)
|
||||||
#else
|
#else
|
||||||
// if original packet was tampered earlier it needs checksum fixed
|
// if original packet was tampered earlier it needs checksum fixed
|
||||||
if ((res & VERDICT_MASK)==VERDICT_MODIFY)
|
if (res==modify)
|
||||||
#endif
|
#endif
|
||||||
tcp_fix_checksum(tcphdr,len_tcp,ip,ip6hdr);
|
tcp_fix_checksum(tcphdr,len_tcp,ip,ip6hdr);
|
||||||
|
|
||||||
@ -944,14 +924,14 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
if (ip6hdr && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT))
|
if (ip6hdr && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT))
|
||||||
{
|
{
|
||||||
pkt_orig_len = sizeof(pkt3);
|
pkt_orig_len = sizeof(pkt3);
|
||||||
if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, data_pkt, *len_pkt, pkt3, &pkt_orig_len))
|
if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, data_pkt, len_pkt, pkt3, &pkt_orig_len))
|
||||||
return res;
|
return res;
|
||||||
pkt_orig = pkt3;
|
pkt_orig = pkt3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pkt_orig = data_pkt;
|
pkt_orig = data_pkt;
|
||||||
pkt_orig_len = *len_pkt;
|
pkt_orig_len = len_pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ip_frag(pkt_orig, pkt_orig_len, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len))
|
if (!ip_frag(pkt_orig, pkt_orig_len, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len))
|
||||||
@ -967,7 +947,7 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
return VERDICT_DROP;
|
return frag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -978,9 +958,9 @@ uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
uint8_t res=VERDICT_PASS;
|
packet_process_result res=pass;
|
||||||
t_ctrack *ctrack=NULL;
|
t_ctrack *ctrack=NULL;
|
||||||
bool bReverse=false;
|
bool bReverse=false;
|
||||||
|
|
||||||
@ -1176,7 +1156,7 @@ uint8_t dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||||
return res;
|
return res;
|
||||||
// this mode is final, no other options available
|
// this mode is final, no other options available
|
||||||
return ct_new_postnat_fix_udp(ctrack, ip, ip6hdr, udphdr, len_pkt);
|
return ct_new_postnat_fix(ctrack, ip, drop);
|
||||||
}
|
}
|
||||||
desync_mode = params.desync_mode2;
|
desync_mode = params.desync_mode2;
|
||||||
break;
|
break;
|
||||||
@ -1186,18 +1166,18 @@ uint8_t dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
{
|
{
|
||||||
if (params.desync_mode2==DESYNC_NONE || !desync_valid_second_stage_udp(params.desync_mode2))
|
if (params.desync_mode2==DESYNC_NONE || !desync_valid_second_stage_udp(params.desync_mode2))
|
||||||
{
|
{
|
||||||
DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", *len_pkt, len_payload)
|
DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", len_pkt, len_payload)
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
if ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
if (res==modify || ip6hdr)
|
||||||
#else
|
#else
|
||||||
// if original packet was tampered earlier it needs checksum fixed
|
// if original packet was tampered earlier it needs checksum fixed
|
||||||
if ((res & VERDICT_MASK)==VERDICT_MODIFY)
|
if (res==modify)
|
||||||
#endif
|
#endif
|
||||||
udp_fix_checksum(udphdr,sizeof(struct udphdr)+len_payload,ip,ip6hdr);
|
udp_fix_checksum(udphdr,sizeof(struct udphdr)+len_payload,ip,ip6hdr);
|
||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , data_pkt, *len_pkt))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , data_pkt, len_pkt))
|
||||||
return res;
|
return res;
|
||||||
return ct_new_postnat_fix_udp(ctrack, ip, ip6hdr, udphdr, len_pkt);
|
return ct_new_postnat_fix(ctrack, ip, drop);
|
||||||
}
|
}
|
||||||
desync_mode = params.desync_mode2;
|
desync_mode = params.desync_mode2;
|
||||||
}
|
}
|
||||||
@ -1214,7 +1194,7 @@ uint8_t dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
DLOG("resending original packet with increased by %d length\n", params.udplen_increment);
|
DLOG("resending original packet with increased by %d length\n", params.udplen_increment);
|
||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||||
return res;
|
return res;
|
||||||
return ct_new_postnat_fix_udp(ctrack, ip, ip6hdr, udphdr, len_pkt);
|
return ct_new_postnat_fix(ctrack, ip, drop);
|
||||||
case DESYNC_TAMPER:
|
case DESYNC_TAMPER:
|
||||||
if (IsDhtD1(data_payload,len_payload))
|
if (IsDhtD1(data_payload,len_payload))
|
||||||
{
|
{
|
||||||
@ -1239,7 +1219,7 @@ uint8_t dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
DLOG("resending tampered DHT\n");
|
DLOG("resending tampered DHT\n");
|
||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||||
return res;
|
return res;
|
||||||
return ct_new_postnat_fix_udp(ctrack, ip, ip6hdr, udphdr, len_pkt);
|
return ct_new_postnat_fix(ctrack, ip, drop);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1251,10 +1231,10 @@ uint8_t dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
if ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
if (res==modify || ip6hdr)
|
||||||
#else
|
#else
|
||||||
// if original packet was tampered earlier it needs checksum fixed
|
// if original packet was tampered earlier it needs checksum fixed
|
||||||
if ((res & VERDICT_MASK)==VERDICT_MODIFY)
|
if (res==modify)
|
||||||
#endif
|
#endif
|
||||||
udp_fix_checksum(udphdr,sizeof(struct udphdr)+len_payload,ip,ip6hdr);
|
udp_fix_checksum(udphdr,sizeof(struct udphdr)+len_payload,ip,ip6hdr);
|
||||||
|
|
||||||
@ -1272,14 +1252,14 @@ uint8_t dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
if (ip6hdr && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT))
|
if (ip6hdr && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT))
|
||||||
{
|
{
|
||||||
pkt_orig_len = sizeof(pkt3);
|
pkt_orig_len = sizeof(pkt3);
|
||||||
if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, data_pkt, *len_pkt, pkt3, &pkt_orig_len))
|
if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, data_pkt, len_pkt, pkt3, &pkt_orig_len))
|
||||||
return res;
|
return res;
|
||||||
pkt_orig = pkt3;
|
pkt_orig = pkt3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pkt_orig = data_pkt;
|
pkt_orig = data_pkt;
|
||||||
pkt_orig_len = *len_pkt;
|
pkt_orig_len = len_pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ip_frag(pkt_orig, pkt_orig_len, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len))
|
if (!ip_frag(pkt_orig, pkt_orig_len, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len))
|
||||||
@ -1295,7 +1275,7 @@ uint8_t dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_
|
|||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
return ct_new_postnat_fix_udp(ctrack, ip, ip6hdr, udphdr, len_pkt);
|
return ct_new_postnat_fix(ctrack, ip, frag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,5 +51,5 @@ bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode);
|
|||||||
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode);
|
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode);
|
||||||
|
|
||||||
void desync_init(void);
|
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);
|
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);
|
||||||
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);
|
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);
|
||||||
|
65
nfq/nfqws.c
65
nfq/nfqws.c
@ -80,15 +80,15 @@ static void onusr2(int sig)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt)
|
static packet_process_result processPacketData(uint32_t *mark, const char *ifout, uint8_t *data_pkt, size_t len_pkt)
|
||||||
{
|
{
|
||||||
struct ip *ip = NULL;
|
struct ip *ip = NULL;
|
||||||
struct ip6_hdr *ip6hdr = NULL;
|
struct ip6_hdr *ip6hdr = NULL;
|
||||||
struct tcphdr *tcphdr = NULL;
|
struct tcphdr *tcphdr = NULL;
|
||||||
struct udphdr *udphdr = NULL;
|
struct udphdr *udphdr = NULL;
|
||||||
size_t len = *len_pkt, len_with_th;
|
size_t len = len_pkt, len_with_th;
|
||||||
uint8_t *data = data_pkt;
|
uint8_t *data = data_pkt;
|
||||||
uint8_t res = VERDICT_PASS;
|
packet_process_result res = pass;
|
||||||
uint8_t proto;
|
uint8_t proto;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@ -146,9 +146,9 @@ static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *dat
|
|||||||
// ipv6 packets were with incorrect checksum
|
// ipv6 packets were with incorrect checksum
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
if (!(res & VERDICT_NOCSUM) && ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr && (res & VERDICT_MASK)==VERDICT_PASS))
|
if (res==modify || res!=frag && res!=modfrag && ip6hdr)
|
||||||
#else
|
#else
|
||||||
if (!(res & VERDICT_NOCSUM) && (res & VERDICT_MASK)==VERDICT_MODIFY)
|
if (res==modify)
|
||||||
#endif
|
#endif
|
||||||
tcp_fix_checksum(tcphdr,len_with_th,ip,ip6hdr);
|
tcp_fix_checksum(tcphdr,len_with_th,ip,ip6hdr);
|
||||||
}
|
}
|
||||||
@ -169,9 +169,9 @@ static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *dat
|
|||||||
res = dpi_desync_udp_packet(*mark, ifout, 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__
|
#ifdef __FreeBSD__
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
if (!(res & VERDICT_NOCSUM) && ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr && (res & VERDICT_MASK)==VERDICT_PASS))
|
if (res==modify || res!=frag && res!=modfrag && ip6hdr)
|
||||||
#else
|
#else
|
||||||
if (!(res & VERDICT_NOCSUM) && (res & VERDICT_MASK)==VERDICT_MODIFY)
|
if (res==modify)
|
||||||
#endif
|
#endif
|
||||||
udp_fix_checksum(udphdr,len_with_th,ip,ip6hdr);
|
udp_fix_checksum(udphdr,len_with_th,ip,ip6hdr);
|
||||||
}
|
}
|
||||||
@ -187,8 +187,8 @@ static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *dat
|
|||||||
#ifdef __linux__
|
#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, ilen;
|
int id;
|
||||||
size_t len;
|
int len;
|
||||||
struct nfqnl_msg_packet_hdr *ph;
|
struct nfqnl_msg_packet_hdr *ph;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
uint32_t ifidx;
|
uint32_t ifidx;
|
||||||
@ -198,7 +198,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
|
|||||||
id = ph ? ntohl(ph->packet_id) : 0;
|
id = ph ? ntohl(ph->packet_id) : 0;
|
||||||
|
|
||||||
uint32_t mark = nfq_get_nfmark(nfa);
|
uint32_t mark = nfq_get_nfmark(nfa);
|
||||||
ilen = nfq_get_payload(nfa, &data);
|
len = nfq_get_payload(nfa, &data);
|
||||||
|
|
||||||
*ifout=0;
|
*ifout=0;
|
||||||
if (params.bind_fix4 || params.bind_fix6)
|
if (params.bind_fix4 || params.bind_fix6)
|
||||||
@ -206,21 +206,21 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
|
|||||||
ifidx = nfq_get_outdev(nfa);
|
ifidx = nfq_get_outdev(nfa);
|
||||||
if (ifidx) if_indextoname(ifidx,ifout);
|
if (ifidx) if_indextoname(ifidx,ifout);
|
||||||
|
|
||||||
DLOG("packet: id=%d len=%d mark=%08X ifout=%s(%u)\n", id, ilen, mark, ifout, ifidx)
|
DLOG("packet: id=%d len=%d ifout=%s(%u)\n", id, len, ifout, ifidx)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// save some syscalls
|
// save some syscalls
|
||||||
DLOG("packet: id=%d len=%d mark=%08X\n", id, ilen, mark)
|
DLOG("packet: id=%d len=%d\n", id, len)
|
||||||
if (ilen >= 0)
|
if (len >= 0)
|
||||||
{
|
{
|
||||||
len = ilen;
|
switch (processPacketData(&mark, ifout, data, len))
|
||||||
uint8_t res = processPacketData(&mark, ifout, data, &len);
|
|
||||||
switch(res & VERDICT_MASK)
|
|
||||||
{
|
{
|
||||||
case VERDICT_MODIFY:
|
case modify:
|
||||||
DLOG("packet: id=%d pass modified. len=%zu\n", id, len);
|
case modfrag:
|
||||||
return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, (uint32_t)len, data);
|
DLOG("packet: id=%d pass modified\n", id);
|
||||||
case VERDICT_DROP:
|
return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, len, data);
|
||||||
|
case drop:
|
||||||
|
case frag:
|
||||||
DLOG("packet: id=%d drop\n", id);
|
DLOG("packet: id=%d drop\n", id);
|
||||||
return nfq_set_verdict2(qh, id, NF_DROP, mark, 0, NULL);
|
return nfq_set_verdict2(qh, id, NF_DROP, mark, 0, NULL);
|
||||||
}
|
}
|
||||||
@ -343,6 +343,7 @@ static int dvt_main(void)
|
|||||||
unsigned int id=0;
|
unsigned int id=0;
|
||||||
socklen_t socklen;
|
socklen_t socklen;
|
||||||
ssize_t rd,wr;
|
ssize_t rd,wr;
|
||||||
|
packet_process_result ppr;
|
||||||
fd_set fdset;
|
fd_set fdset;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -438,24 +439,18 @@ static int dvt_main(void)
|
|||||||
else if (rd>0)
|
else if (rd>0)
|
||||||
{
|
{
|
||||||
uint32_t mark=0;
|
uint32_t mark=0;
|
||||||
uint8_t res;
|
DLOG("packet: id=%u len=%zd\n", id, rd)
|
||||||
size_t len = rd;
|
ppr = processPacketData(&mark, NULL, buf, rd);
|
||||||
|
switch (ppr)
|
||||||
DLOG("packet: id=%u len=%zu\n", id, len)
|
|
||||||
res = processPacketData(&mark, NULL, buf, &len);
|
|
||||||
switch (res & VERDICT_MASK)
|
|
||||||
{
|
{
|
||||||
case VERDICT_PASS:
|
case pass:
|
||||||
case VERDICT_MODIFY:
|
case modify:
|
||||||
if ((res & VERDICT_MASK)==VERDICT_PASS)
|
DLOG(ppr==pass ? "packet: id=%u reinject unmodified\n" : "packet: id=%u reinject modified\n", id);
|
||||||
DLOG("packet: id=%u reinject unmodified\n", id)
|
wr = sendto(fd[i], buf, rd, 0, (struct sockaddr*)&sa_from, socklen);
|
||||||
else
|
|
||||||
DLOG("packet: id=%u reinject modified len=%zu\n", id, len)
|
|
||||||
wr = sendto(fd[i], buf, len, 0, (struct sockaddr*)&sa_from, socklen);
|
|
||||||
if (wr<0)
|
if (wr<0)
|
||||||
perror("reinject sendto");
|
perror("reinject sendto");
|
||||||
else if (wr!=len)
|
else if (wr!=rd)
|
||||||
fprintf(stderr,"reinject sendto: not all data was reinjected. received %zu, sent %zd\n", len, wr);
|
fprintf(stderr,"reinject sendto: not all data was reinjected. received %zd, sent %zd\n", rd, wr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DLOG("packet: id=%u drop\n", id);
|
DLOG("packet: id=%u drop\n", id);
|
||||||
|
10
nfq/nfqws.h
10
nfq/nfqws.h
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VERDICT_PASS 0
|
typedef enum
|
||||||
#define VERDICT_MODIFY 1
|
{
|
||||||
#define VERDICT_DROP 2
|
// frag=drop but do not fix checksum
|
||||||
#define VERDICT_MASK 3
|
pass = 0, modify, drop, frag, modfrag
|
||||||
#define VERDICT_NOCSUM 4
|
} packet_process_result;
|
||||||
|
Loading…
Reference in New Issue
Block a user