nfqws: synack desync mode

This commit is contained in:
bol-van 2021-04-07 12:13:46 +03:00
parent 8229bcc98b
commit fe8cada8ae
14 changed files with 99 additions and 23 deletions

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.

View File

@ -244,11 +244,27 @@ mark is needed to keep away generated packets from NFQUEUE. nfqws sets fwmark wh
nfqws can internally filter marked packets. but when connbytes filter is used without mark filter
packet ordering can be changed breaking the whole idea of desync attack.
DESYNC COMBOS
dpi-desync parameter can take 2 comma separated arguments.
DPI DESYNC COMBOS
dpi-desync parameter takes up to 3 comma separated arguments.
zero phase means tcp connection establishement (before sending data payload). Mode can be "synack".
Hostlist filter is not applicable to the zero phase.
Next phases work on packets with data payload.
1st phase mode can be fake,rst,rstack, 2nd phase mode - disorder,disorder2,split,split2.
Can be useful for ISPs with more than one DPI.
SYNACK MODE
In geneva docs it's called "TCP turnaround". Attempt to make the DPI believe the roles of client and server are reversed.
!!! This mode breaks NAT operation and can be used only from devices with external IP address !
In linux it's required to remove standard firewall rule dropping INVALID packets, for example :
-A FORWARD -m state --state INVALID -j DROP
In openwrt it can be done in /etc/config/firewall :
config zone
option name 'wan'
.........
option masq_allow_invalid '1'
Otherwise raw sending SYN,ACK frame will cause error stopping the further processing.
If you realize you don't need the synack mode it's highly suggested to restore drop INVALID rule.
VIRTUAL MACHINES
Most of nfqws packet magic does not work from VMs powered by virtualbox and vmware when network is NATed.
Hypervisor forcibly changes ttl and does not forward fake packets.

View File

@ -187,7 +187,7 @@ nfqws
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
--domcase ; домен после Host: сделать таким : TeSt.cOm
--dpi-desync=<mode>[,<mode2] ; атака по десинхронизации DPI. mode : fake rst rstack disorder disorder2 split split2
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack fake rst rstack disorder disorder2 split split2
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
--dpi-desync-fooling=none|md5sig|ts|badseq|badsum ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера
@ -297,16 +297,33 @@ mark нужен, чтобы сгенерированный поддельный
Но лучше его все же оставить для увеличения скорости.
Почему --connbytes 1:4 :
1 - для работы параметра wssize. scaling factor обычно устанавливается инициатором соединения в SYN пакете
1 - для работы методов десинхронизации 0-й фазы и wssize
2 - иногда данные идут в 3-м пакете 3-way handshake
3 - стандартная ситуация
4 - для надежности. на случай, если выполнялась одна ретрансмиссия
КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ
В параметре dpi-desync можно указать 2 режима через запятую.
В параметре dpi-desync можно указать до 3 режимов через запятую.
0 фаза предполагает работу на этапе установления соединения. Может быть synack.
На 0 фазу не действует фильтр по hostlist.
Последующие режимы отрабатывают на пакетах с данными.
Режим 1-й фазы может быть fake,rst,rstack. Режим 2-й фазы может быть disorder,disorder2,split,split2.
Может быть полезно, когда у провайдера стоит не один DPI.
РЕЖИМ SYNACK
В документации по geneva это называется "TCB turnaround". Попытка ввести DPI в заблуждение относительно
ролей клиента и сервера.
!!! Поскольку режим нарушает работу NAT, техника может сработать только с устройства с внешним IP адресом.
Для реализации атаки в linux обязательно требуется отключить стандартное правило firewall,
дропающие инвалидные пакеты. Например : -A FORWARD -m state --state INVALID -j DROP
В openwrt это делается через опцию в /etc/config/firewall :
config zone
option name 'wan'
.........
option masq_allow_invalid '1'
В противном случае попытка отослать SYN,ACK сегмент вызовет ошибку и операция будет прервана.
Остальные режимы тоже не сработают. Если поймете, что вам synack не нужен, обязательно верните правило дропа INVALID.
ВИРТУАЛЬНЫЕ МАШИНЫ
Изнутри VM от virtualbox и vmware в режиме NAT не работают многие техники пакетной магии nfqws.
Принудительно заменяется ttl, не проходят фейк пакеты. Необходимо настроить сеть в режиме bridge.

View File

@ -60,6 +60,10 @@ void desync_init()
}
bool desync_valid_zero_stage(enum dpi_desync_mode mode)
{
return mode==DESYNC_SYNACK;
}
bool desync_valid_first_stage(enum dpi_desync_mode mode)
{
return mode==DESYNC_FAKE || mode==DESYNC_RST || mode==DESYNC_RSTACK;
@ -78,6 +82,8 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
return DESYNC_RST;
else if (!strcmp(s,"rstack"))
return DESYNC_RSTACK;
else if (!strcmp(s,"synack"))
return DESYNC_SYNACK;
else if (!strcmp(s,"disorder"))
return DESYNC_DISORDER;
else if (!strcmp(s,"disorder2"))
@ -126,6 +132,12 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
t_ctrack *ctrack=NULL;
bool bReverse=false;
struct sockaddr_storage src, dst;
uint8_t newdata[DPI_DESYNC_MAX_FAKE_LEN+100];
size_t newlen;
uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor;
uint32_t *timestamps;
if (!!ip == !!ip6hdr) return res; // one and only one must be present
if (CONNTRACK_REQUIRED)
@ -139,17 +151,44 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
tcp_rewrite_winsize(tcphdr, params.wsize, params.wscale);
res=modify;
}
if (params.wssize && !bReverse && (ctrack && !ctrack->b_wssize_cutoff))
if (bReverse) return res; // nothing to do. do not waste cpu
if (params.wssize && (ctrack && !ctrack->b_wssize_cutoff))
{
tcp_rewrite_winsize(tcphdr, params.wssize, params.wsscale);
res=modify;
}
if (bReverse || !params.wssize && params.desync_mode==DESYNC_NONE && !params.hostcase && !params.hostnospace && !params.domcase) return res; // nothing to do. do not waste cpu
if (params.desync_mode0!=DESYNC_NONE || params.desync_mode!=DESYNC_NONE) // save some cpu
{
ttl_orig = ip ? ip->ip_ttl : ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim;
ttl_fake = params.desync_ttl ? params.desync_ttl : ttl_orig;
flags_orig = *((uint8_t*)tcphdr+13);
scale_factor = tcp_find_scale_factor(tcphdr);
timestamps = tcp_find_timestamps(tcphdr);
extract_endpoints(ip, ip6hdr, tcphdr, &src, &dst);
}
if (params.desync_mode0==DESYNC_SYNACK && tcp_syn_segment(tcphdr))
{
newlen = sizeof(newdata);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_SYN|TH_ACK, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
ttl_fake,params.desync_tcp_fooling_mode,
NULL, 0, newdata, &newlen))
{
return res;
}
DLOG("sending fake SYNACK\n");
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
return res;
}
if (!params.wssize && params.desync_mode==DESYNC_NONE && !params.hostcase && !params.hostnospace && !params.domcase) return res; // nothing to do. do not waste cpu
if (!(tcphdr->th_flags & TH_SYN) && len_payload)
{
struct sockaddr_storage src, dst;
const uint8_t *fake;
size_t fake_size;
char host[256];
@ -251,7 +290,6 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
return res;
}
extract_endpoints(ip, ip6hdr, tcphdr, &src, &dst);
if (params.debug)
{
printf("dpi desync src=");
@ -261,14 +299,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
printf("\n");
}
uint8_t newdata[DPI_DESYNC_MAX_FAKE_LEN+100];
size_t newlen;
uint8_t ttl_orig = ip ? ip->ip_ttl : ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim;
uint8_t ttl_fake = params.desync_ttl ? params.desync_ttl : ttl_orig;
uint8_t flags_orig = *((uint8_t*)tcphdr+13);
uint32_t *timestamps = tcp_find_timestamps(tcphdr);
enum dpi_desync_mode desync_mode = params.desync_mode;
uint8_t scale_factor = tcp_find_scale_factor(tcphdr);
bool b;
newlen = sizeof(newdata);

View File

@ -24,6 +24,7 @@ enum dpi_desync_mode {
DESYNC_FAKE,
DESYNC_RST,
DESYNC_RSTACK,
DESYNC_SYNACK,
DESYNC_DISORDER,
DESYNC_DISORDER2,
DESYNC_SPLIT,
@ -34,6 +35,7 @@ extern const char *fake_http_request_default;
extern const uint8_t fake_tls_clienthello_default[517];
enum dpi_desync_mode desync_mode_from_string(const char *s);
bool desync_valid_zero_stage(enum dpi_desync_mode mode);
bool desync_valid_first_stage(enum dpi_desync_mode mode);
bool desync_valid_second_stage(enum dpi_desync_mode mode);

View File

@ -479,7 +479,7 @@ static void exithelp()
" --hostspell\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
" --hostnospace\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
" --domcase\t\t\t\t; mix domain case : Host: TeSt.cOm\n"
" --dpi-desync=<mode>[,<mode2>]\t\t; try to desync dpi state. modes : fake rst rstack disorder disorder2 split split2\n"
" --dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake rst rstack disorder disorder2 split split2\n"
#ifdef __linux__
" --dpi-desync-fwmark=<int|0xHEX>\t; override fwmark for desync packet. default = 0x%08X (%u)\n"
#elif defined(SO_USER_COOKIE)
@ -701,20 +701,30 @@ int main(int argc, char **argv)
break;
case 14: /* dpi-desync */
{
char *mode2;
mode2 = optarg ? strchr(optarg,',') : NULL;
char *mode=optarg,*mode2,*mode3;
mode2 = mode ? strchr(mode,',') : NULL;
if (mode2) *mode2++=0;
mode3 = mode2 ? strchr(mode2,',') : NULL;
if (mode3) *mode3++=0;
params.desync_mode = desync_mode_from_string(optarg);
params.desync_mode0 = desync_mode_from_string(mode);
if (desync_valid_zero_stage(params.desync_mode0))
{
mode = mode2;
mode2 = mode3;
}
else
params.desync_mode0 = DESYNC_NONE;
params.desync_mode = desync_mode_from_string(mode);
params.desync_mode2 = desync_mode_from_string(mode2);
if (params.desync_mode==DESYNC_NONE || params.desync_mode==DESYNC_INVALID || params.desync_mode2==DESYNC_INVALID)
if (params.desync_mode0==DESYNC_INVALID || params.desync_mode==DESYNC_INVALID || params.desync_mode2==DESYNC_INVALID)
{
fprintf(stderr, "invalid dpi-desync mode\n");
exit_clean(1);
}
if (params.desync_mode2 && !(desync_valid_first_stage(params.desync_mode) && desync_valid_second_stage(params.desync_mode2)))
{
fprintf(stderr, "invalid desync combo : %s+%s\n", optarg,mode2);
fprintf(stderr, "invalid desync combo : %s+%s\n", mode,mode2);
exit_clean(1);
}
}

View File

@ -30,7 +30,7 @@ struct params_s
#endif
bool hostcase, hostnospace, domcase;
char hostspell[4];
enum dpi_desync_mode desync_mode,desync_mode2;
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
bool desync_retrans,desync_skip_nosni,desync_any_proto;
int desync_repeats,desync_split_pos;
unsigned int desync_cutoff;