mirror of
https://github.com/bol-van/zapret.git
synced 2025-04-19 21:42:59 +03:00
tpws: memmem nfqws: memmem, nfqws check hostlist in hostcase and hostnospace options
This commit is contained in:
parent
487fe25e25
commit
b430221cd6
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.
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.
@ -135,7 +135,7 @@ It takes the following parameters:
|
|||||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not apply desync to requests without hostname in the SNI
|
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not apply desync to requests without hostname in the SNI
|
||||||
--dpi-desync-split-pos=<1..1500> ; (for disorder only) split TCP packet at specified position
|
--dpi-desync-split-pos=<1..1500> ; (for disorder only) split TCP packet at specified position
|
||||||
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
|
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
|
||||||
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply)
|
--hostlist=<filename> ; apply fooling only to the listed hosts (one host per line, subdomains auto apply)
|
||||||
|
|
||||||
The manipulation parameters can be combined in any way.
|
The manipulation parameters can be combined in any way.
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ Split mode is very similar to disorder but without segment reordering :
|
|||||||
4. 2nd segment
|
4. 2nd segment
|
||||||
Mode 'split2' disables sending of fake segments. It can be used as a faster alternative to --wsize.
|
Mode 'split2' disables sending of fake segments. It can be used as a faster alternative to --wsize.
|
||||||
|
|
||||||
In disorder2 and split2 modes no fake packets are sent, so no fooling options are required.
|
In disorder2 and split2 modes no fake packets are sent, so ttl and fooling options are not required.
|
||||||
|
|
||||||
There are DPIs that analyze responses from the server, particularly the certificate from the ServerHello
|
There are DPIs that analyze responses from the server, particularly the certificate from the ServerHello
|
||||||
that contain domain name(s). The ClientHello delivery confirmation is an ACK packet from the server
|
that contain domain name(s). The ClientHello delivery confirmation is an ACK packet from the server
|
||||||
@ -204,7 +204,6 @@ doing something about it is hardly possible without the help of the server.
|
|||||||
The best solution is to enable TLS 1.3 support on the server. TLS 1.3 sends the server certificate in encrypted form.
|
The best solution is to enable TLS 1.3 support on the server. TLS 1.3 sends the server certificate in encrypted form.
|
||||||
This is recommendation to all admins of blocked sites. Enable TLS 1.3. You will give more opportunities to overcome DPI.
|
This is recommendation to all admins of blocked sites. Enable TLS 1.3. You will give more opportunities to overcome DPI.
|
||||||
|
|
||||||
Hostlist is applicable only to desync attack. It does not work for other options.
|
|
||||||
Hosts are extracted from plain http request Host: header and SNI of ClientHelllo TLS message.
|
Hosts are extracted from plain http request Host: header and SNI of ClientHelllo TLS message.
|
||||||
Subdomains are applied automatically. gzip lists are supported.
|
Subdomains are applied automatically. gzip lists are supported.
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ nfqws
|
|||||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
||||||
--dpi-desync-split-pos=<1..1500> ; (только для disorder) разбивать пакет на указанной позиции
|
--dpi-desync-split-pos=<1..1500> ; (только для disorder) разбивать пакет на указанной позиции
|
||||||
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
||||||
--hostlist=<filename> ; применять dpi-desync только к хостам из листа
|
--hostlist=<filename> ; применять дурение только к хостам из листа
|
||||||
|
|
||||||
Параметры манипуляции могут сочетаться в любых комбинациях.
|
Параметры манипуляции могут сочетаться в любых комбинациях.
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ nfqws
|
|||||||
Режим split2 отключает отправку поддельных частей.
|
Режим split2 отключает отправку поддельных частей.
|
||||||
Он может быть использован как более быстрая альтернатива --wsize.
|
Он может быть использован как более быстрая альтернатива --wsize.
|
||||||
|
|
||||||
disorder2 и split2 не предполагают отсылку фейк пакетов, поэтому опции дурения неактуальны.
|
disorder2 и split2 не предполагают отсылку фейк пакетов, поэтому опции ttl и fooling неактуальны.
|
||||||
|
|
||||||
Есть DPI, которые анализируют ответы от сервера, в частности сертификат из ServerHello, где прописаны домены.
|
Есть DPI, которые анализируют ответы от сервера, в частности сертификат из ServerHello, где прописаны домены.
|
||||||
Подтверждением доставки ClientHello является ACK пакет от сервера с номером ACK sequence, соответствующим длине ClientHello+1.
|
Подтверждением доставки ClientHello является ACK пакет от сервера с номером ACK sequence, соответствующим длине ClientHello+1.
|
||||||
@ -239,7 +239,6 @@ DPI может отстать от потока, если ClientHello его у
|
|||||||
Лучшее решение - включить на сервере поддержку TLS 1.3. В нем сертификат сервера передается в зашифрованном виде.
|
Лучшее решение - включить на сервере поддержку TLS 1.3. В нем сертификат сервера передается в зашифрованном виде.
|
||||||
Это рекомендация ко всем админам блокируемых сайтов. Включайте TLS 1.3. Так вы дадите больше возможностей преодолеть DPI.
|
Это рекомендация ко всем админам блокируемых сайтов. Включайте TLS 1.3. Так вы дадите больше возможностей преодолеть DPI.
|
||||||
|
|
||||||
hostlist относится только к атаке desync. он не работает для других параметров. при попытке запустить nfqws с hostlist и без dpi-desync будет ошибка.
|
|
||||||
Хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
Хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
||||||
Субдомены учитываются автоматически. Поддерживаются листы gzip.
|
Субдомены учитываются автоматически. Поддерживаются листы gzip.
|
||||||
|
|
||||||
|
@ -76,6 +76,11 @@ bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *ip
|
|||||||
fake = (uint8_t*)fake_http_request;
|
fake = (uint8_t*)fake_http_request;
|
||||||
fake_size = sizeof(fake_http_request);
|
fake_size = sizeof(fake_http_request);
|
||||||
if (params.hostlist || params.debug) bHaveHost=HttpExtractHost(data_payload,len_payload,host,sizeof(host));
|
if (params.hostlist || params.debug) bHaveHost=HttpExtractHost(data_payload,len_payload,host,sizeof(host));
|
||||||
|
if (params.hostlist && !bHaveHost)
|
||||||
|
{
|
||||||
|
DLOG("not applying dpi-desync to HTTP without Host:\n")
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (IsTLSClientHello(data_payload,len_payload))
|
else if (IsTLSClientHello(data_payload,len_payload))
|
||||||
{
|
{
|
||||||
|
@ -1,29 +1,9 @@
|
|||||||
#include "helpers.h"
|
#define _GNU_SOURCE
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
const uint8_t *find_bin_const(const uint8_t *data, size_t len, const void *blk, size_t blk_len)
|
#include "helpers.h"
|
||||||
{
|
#include <stdio.h>
|
||||||
while (len >= blk_len)
|
#include <string.h>
|
||||||
{
|
#include <ctype.h>
|
||||||
if (!memcmp(data, blk, blk_len))
|
|
||||||
return data;
|
|
||||||
data++;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
uint8_t *find_bin(uint8_t *data, size_t len, const void *blk, size_t blk_len)
|
|
||||||
{
|
|
||||||
while (len >= blk_len)
|
|
||||||
{
|
|
||||||
if (!memcmp(data, blk, blk_len))
|
|
||||||
return data;
|
|
||||||
data++;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_sockaddr(const struct sockaddr *sa)
|
void print_sockaddr(const struct sockaddr *sa)
|
||||||
{
|
{
|
||||||
@ -42,3 +22,24 @@ void print_sockaddr(const struct sockaddr *sa)
|
|||||||
printf("UNKNOWN_FAMILY_%d", sa->sa_family);
|
printf("UNKNOWN_FAMILY_%d", sa->sa_family);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *strncasestr(const char *s,const char *find, size_t slen)
|
||||||
|
{
|
||||||
|
char c, sc;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if ((c = *find++) != '\0')
|
||||||
|
{
|
||||||
|
len = strlen(find);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (slen-- < 1 || (sc = *s++) == '\0') return NULL;
|
||||||
|
} while (toupper(c) != toupper(sc));
|
||||||
|
if (len > slen) return NULL;
|
||||||
|
} while (strncasecmp(s, find, len) != 0);
|
||||||
|
s--;
|
||||||
|
}
|
||||||
|
return (char *)s;
|
||||||
|
}
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
const uint8_t *find_bin_const(const uint8_t *data, size_t len, const void *blk, size_t blk_len);
|
|
||||||
uint8_t *find_bin(uint8_t *data, size_t len, const void *blk, size_t blk_len);
|
|
||||||
void print_sockaddr(const struct sockaddr *sa);
|
void print_sockaddr(const struct sockaddr *sa);
|
||||||
|
char *strncasestr(const char *s,const char *find, size_t slen);
|
||||||
|
66
nfq/nfqws.c
66
nfq/nfqws.c
@ -5,6 +5,7 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "checksum.h"
|
#include "checksum.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
#include "protocol.h"
|
||||||
#include "hostlist.h"
|
#include "hostlist.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -165,34 +166,57 @@ static bool modify_tcp_packet(uint8_t *data, size_t len, struct tcphdr *tcphdr)
|
|||||||
uint8_t *phost, *pua;
|
uint8_t *phost, *pua;
|
||||||
bool bRet = false;
|
bool bRet = false;
|
||||||
|
|
||||||
if (params.wsize && tcp_synack_segment(tcphdr))
|
if (tcp_synack_segment(tcphdr))
|
||||||
{
|
{
|
||||||
tcp_rewrite_winsize(tcphdr, (uint16_t)params.wsize);
|
if (params.wsize)
|
||||||
bRet = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((params.hostcase || params.hostnospace) && (phost = find_bin(data, len, "\r\nHost: ", 8)))
|
|
||||||
{
|
|
||||||
if (params.hostcase)
|
|
||||||
{
|
{
|
||||||
DLOG("modifying Host: => %c%c%c%c:\n", params.hostspell[0], params.hostspell[1], params.hostspell[2], params.hostspell[3])
|
tcp_rewrite_winsize(tcphdr, (uint16_t)params.wsize);
|
||||||
memcpy(phost + 2, params.hostspell, 4);
|
|
||||||
bRet = true;
|
bRet = true;
|
||||||
}
|
}
|
||||||
if (params.hostnospace && (pua = find_bin(data, len, "\r\nUser-Agent: ", 14)) && (pua = find_bin(pua + 1, len - (pua - data) - 1, "\r\n", 2)))
|
}
|
||||||
|
else if ((params.hostcase || params.hostnospace) && IsHttp(data,len))
|
||||||
|
{
|
||||||
|
if (params.hostlist)
|
||||||
{
|
{
|
||||||
DLOG("removing space after Host: and adding it to User-Agent:\n")
|
char host[256];
|
||||||
if (pua > phost)
|
if (HttpExtractHost(data,len,host,sizeof(host)))
|
||||||
{
|
{
|
||||||
memmove(phost + 7, phost + 8, pua - phost - 8);
|
DLOG("hostname: %s\n",host)
|
||||||
phost[pua - phost - 1] = ' ';
|
if (!SearchHostList(params.hostlist,host,params.debug))
|
||||||
|
{
|
||||||
|
DLOG("not applying tampering to this request\n")
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memmove(pua + 1, pua, phost - pua + 7);
|
DLOG("could not extract host from http request. not applying tampering\n")
|
||||||
*pua = ' ';
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (phost = (uint8_t*)memmem(data, len, "\r\nHost: ", 8))
|
||||||
|
{
|
||||||
|
if (params.hostcase)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
bRet = true;
|
||||||
|
}
|
||||||
|
if (params.hostnospace && (pua = (uint8_t*)memmem(data, len, "\r\nUser-Agent: ", 14)) && (pua = (uint8_t*)memmem(pua + 1, len - (pua - data) - 1, "\r\n", 2)))
|
||||||
|
{
|
||||||
|
DLOG("removing space after Host: and adding it to User-Agent:\n")
|
||||||
|
if (pua > phost)
|
||||||
|
{
|
||||||
|
memmove(phost + 7, phost + 8, pua - phost - 8);
|
||||||
|
phost[pua - phost - 1] = ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memmove(pua + 1, pua, phost - pua + 7);
|
||||||
|
*pua = ' ';
|
||||||
|
}
|
||||||
|
bRet = true;
|
||||||
}
|
}
|
||||||
bRet = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bRet;
|
return bRet;
|
||||||
@ -531,12 +555,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.desync_mode==DESYNC_NONE && params.hostlist)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "hostlist is applicable only to dpi-desync\n");
|
|
||||||
exit_clean(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon) daemonize();
|
if (daemon) daemonize();
|
||||||
|
|
||||||
h = NULL;
|
h = NULL;
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL };
|
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL };
|
||||||
bool IsHttp(const char *data, size_t len)
|
bool IsHttp(const char *data, size_t len)
|
||||||
@ -21,7 +24,7 @@ bool HttpExtractHost(const uint8_t *data, size_t len, char *host, size_t len_hos
|
|||||||
{
|
{
|
||||||
const uint8_t *p, *s, *e=data+len;
|
const uint8_t *p, *s, *e=data+len;
|
||||||
|
|
||||||
p = find_bin_const(data, len, "\nHost:", 6);
|
p = (uint8_t*)strncasestr((char*)data, "\nHost:", len);
|
||||||
if (!p) return false;
|
if (!p) return false;
|
||||||
p+=6;
|
p+=6;
|
||||||
while(p<e && (*p==' ' || *p=='\t')) p++;
|
while(p<e && (*p==' ' || *p=='\t')) p++;
|
||||||
|
@ -1,27 +1,17 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include "tamper.h"
|
#include "tamper.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
#include "hostlist.h"
|
#include "hostlist.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
char *find_bin(void *data, size_t len, const void *blk, size_t blk_len)
|
|
||||||
{
|
|
||||||
while (len >= blk_len)
|
|
||||||
{
|
|
||||||
if (!memcmp(data, blk, blk_len))
|
|
||||||
return data;
|
|
||||||
data = (char*)data + 1;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pHost points to "Host: ..."
|
// pHost points to "Host: ..."
|
||||||
bool find_host(char **pHost,char *buf,size_t bs)
|
bool find_host(char **pHost,char *buf,size_t bs)
|
||||||
{
|
{
|
||||||
if (!*pHost)
|
if (!*pHost)
|
||||||
{
|
{
|
||||||
*pHost = find_bin(buf, bs, "\nHost:", 6);
|
*pHost = memmem(buf, bs, "\nHost:", 6);
|
||||||
if (*pHost)
|
if (*pHost)
|
||||||
{
|
{
|
||||||
(*pHost)++;
|
(*pHost)++;
|
||||||
@ -74,7 +64,7 @@ void modify_tcp_segment(char *segment,size_t segment_buffer_size,size_t *size,si
|
|||||||
if (params.unixeol)
|
if (params.unixeol)
|
||||||
{
|
{
|
||||||
p = pp = segment;
|
p = pp = segment;
|
||||||
while (p = find_bin(p, segment + *size - p, "\r\n", 2))
|
while (p = memmem(p, segment + *size - p, "\r\n", 2))
|
||||||
{
|
{
|
||||||
*p = '\n'; p++;
|
*p = '\n'; p++;
|
||||||
memmove(p, p + 1, segment + *size - p - 1);
|
memmove(p, p + 1, segment + *size - p - 1);
|
||||||
|
@ -3,6 +3,5 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
char *find_bin(void *data, size_t len, const void *blk, size_t blk_len);
|
|
||||||
bool find_host(char **pHost,char *buf,size_t bs);
|
bool find_host(char **pHost,char *buf,size_t bs);
|
||||||
void modify_tcp_segment(char *segment,size_t segment_buffer_size,size_t *size,size_t *split_pos);
|
void modify_tcp_segment(char *segment,size_t segment_buffer_size,size_t *size,size_t *split_pos);
|
||||||
|
@ -98,7 +98,6 @@ static int get_so_error(int fd)
|
|||||||
socklen_t optlen = sizeof(errn);
|
socklen_t optlen = sizeof(errn);
|
||||||
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &errn, &optlen) == -1)
|
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &errn, &optlen) == -1)
|
||||||
errn=errno;
|
errn=errno;
|
||||||
|
|
||||||
return errn;
|
return errn;
|
||||||
}
|
}
|
||||||
static bool proxy_remote_conn_ack(tproxy_conn_t *conn, int sock_err)
|
static bool proxy_remote_conn_ack(tproxy_conn_t *conn, int sock_err)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user