Browse Source

nfqws: fix posnat initial packet handling

pull/181/head
bol-van 1 year ago
parent
commit
99c6014adb
  1. BIN
      binaries/aarch64/nfqws
  2. BIN
      binaries/arm/nfqws
  3. BIN
      binaries/mips32r1-lsb/nfqws
  4. BIN
      binaries/mips32r1-msb/nfqws
  5. BIN
      binaries/mips64r2-msb/nfqws
  6. BIN
      binaries/ppc/nfqws
  7. BIN
      binaries/x86/nfqws
  8. BIN
      binaries/x86_64/nfqws
  9. 60
      nfq/desync.c
  10. 5
      nfq/nfqws.c
  11. 2
      nfq/nfqws.h

BIN
binaries/aarch64/nfqws

Binary file not shown.

BIN
binaries/arm/nfqws

Binary file not shown.

BIN
binaries/mips32r1-lsb/nfqws

Binary file not shown.

BIN
binaries/mips32r1-msb/nfqws

Binary file not shown.

BIN
binaries/mips64r2-msb/nfqws

Binary file not shown.

BIN
binaries/ppc/nfqws

Binary file not shown.

BIN
binaries/x86/nfqws

Binary file not shown.

BIN
binaries/x86_64/nfqws

Binary file not shown.

60
nfq/desync.c

@ -321,6 +321,35 @@ static void reasm_orig_fin(t_ctrack *ctrack)
} }
static packet_process_result ct_new_postnat_fix(const t_ctrack *ctrack, struct ip *ip, packet_process_result res)
{
#ifdef __linux__
// if used in postnat chain, dropping initial packet will cause conntrack connection teardown
// so we need to workaround this.
// 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 TCP fooling because DPI would accept fooled packets
if (ip && ctrack && ctrack->pcounter_orig==1)
{
// routers will drop IP frames with invalid checksum
if (ip->ip_p==IPPROTO_TCP)
{
// linux recalc ip checksum in tcp
// need another limiter
ip->ip_ttl=1;
}
else
ip->ip_sum ^= htons(0xBEAF);
return res==frag ? modfrag : modify;
}
else
#endif
// ipv6 does not have checksum
// consider we are free of NAT in ipv6 case. just drop
// BSDs also do not need this
return drop;
}
// result : true - drop original packet, false = dont drop // result : true - drop original packet, false = dont drop
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_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)
@ -479,26 +508,11 @@ packet_process_result dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout,
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;
#ifdef __linux__ res = ct_new_postnat_fix(ctrack, ip, drop);
// if used in postnat chain, dropping SYN will cause conntrack connection teardown
// so we need to workaround this.
// we can't use low ttl because TCP/IP stack listens to ttl expired ICMPs in response to SYN and reset connection
// we also can't use TCP fooling because DPI would accept fooled packets
if (ip)
{
// routers will drop IP frames with invalid checksum
ip->ip_sum ^= htons(0xBEAF);
res=modify;
}
else
// ipv6 does not have checksum
// consider we are free of NAT in ipv6 case. just drop
res=drop;
#else
res=drop;
#endif
break; break;
} }
// can do nothing else with SYN packet
return res;
} }
if (params.desync_cutoff) if (params.desync_cutoff)
@ -1142,7 +1156,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout,
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 drop; return ct_new_postnat_fix(ctrack, ip, drop);
} }
desync_mode = params.desync_mode2; desync_mode = params.desync_mode2;
break; break;
@ -1163,7 +1177,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout,
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 drop; return ct_new_postnat_fix(ctrack, ip, drop);
} }
desync_mode = params.desync_mode2; desync_mode = params.desync_mode2;
} }
@ -1180,7 +1194,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout,
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 drop; 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))
{ {
@ -1205,7 +1219,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout,
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 drop; return ct_new_postnat_fix(ctrack, ip, drop);
} }
else else
{ {
@ -1261,7 +1275,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout,
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 frag; return ct_new_postnat_fix(ctrack, ip, frag);
} }
} }

5
nfq/nfqws.c

@ -146,7 +146,7 @@ static packet_process_result processPacketData(uint32_t *mark, const char *ifout
// 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==modify || res!=frag && ip6hdr) if (res==modify || res!=frag && res!=modfrag && ip6hdr)
#else #else
if (res==modify) if (res==modify)
#endif #endif
@ -169,7 +169,7 @@ static packet_process_result processPacketData(uint32_t *mark, const char *ifout
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==modify || res!=frag && ip6hdr) if (res==modify || res!=frag && res!=modfrag && ip6hdr)
#else #else
if (res==modify) if (res==modify)
#endif #endif
@ -216,6 +216,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
switch (processPacketData(&mark, ifout, data, len)) switch (processPacketData(&mark, ifout, data, len))
{ {
case modify: case modify:
case modfrag:
DLOG("packet: id=%d pass modified\n", id); DLOG("packet: id=%d pass modified\n", id);
return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, len, data); return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, len, data);
case drop: case drop:

2
nfq/nfqws.h

@ -3,5 +3,5 @@
typedef enum typedef enum
{ {
// frag=drop but do not fix checksum // frag=drop but do not fix checksum
pass = 0, modify, drop, frag pass = 0, modify, drop, frag, modfrag
} packet_process_result; } packet_process_result;

Loading…
Cancel
Save