Compare commits

..

No commits in common. "6e1e7e43bce542e06d8ee6e029bdebde9bb3784f" and "7272b243cbc2cd8c15cd5775be9f352500cbc7b0" have entirely different histories.

9 changed files with 51 additions and 84 deletions

View File

@ -478,6 +478,5 @@ nfqws: detect Discord Voice IP discovery packets
nfqws: detect STUN message packets
nfqws: change SNI to specified value tls mod : --dpi-desync-fake-tls-mod sni=<sni>
nfqws: update default TLS ClientHello fake. firefox 136.0.4 finger, no kyber, SNI=microsoft.com
nfqws: multiple mods for multiple TLS fakes
init.d: remove 50-discord
blockcheck: use tpws --fix-seg on linux for multiple splits

View File

@ -291,13 +291,9 @@ It's possible to use TLS Client Hello with any fingerprint and any SNI.
By default if custom fake is not defined `rnd,rndsni,dupsid` mods are applied. If defined - `none`.
This behaviour is compatible with previous versions with addition of `dupsid`.
If multiple TLS fakes are present each one takes the last mod.
If a mod is specified after fake it replaces previous mod.
This way it's possible to use different mods for every TLS fake.
If TLS mod is enabled and there're multiple TLS fakes, all valid TLS Client Hello fakes are modified.
If there's no TLS Client Hello program exits with error.
If a mod is set to non-TLS fake it causes error. Use `--dpi-desync-fake-tls-mod=none'.
Example : `--dpi-desync-fake-tls=iana_org.bin --dpi-desync-fake-tls-mod=rndsni --dpi-desync-fake-tls=0xaabbccdd --dpi-desync-fake-tls-mod=none'
### TCP segmentation

View File

@ -346,15 +346,8 @@ dvtws, собираемый из тех же исходников (см. [док
По умолчанию если не задан собственный фейк для TLS используются модификации `rnd,rndsni,dupsid`. Если фейк задан, используется `none`.
Это соответствует поведению программы более старых версий с добавлением функции `dupsid`.
Если задан режим модификации и имеется множество TLS фейков, к каждому из них применяется последний режим модификации.
Если режим модификации задан после фейка, то он замещает предыдущий режим.
Таким образом можно использовать разные режимы модификации для разных фейков.
При невозможности модифицировать фейк на этапе запуска программа завершается с ошибкой.
Если сначала идет TLS фейк, для него задан режим однократной модификации, затем идет не TLS фейк, то будет ошибка.
Нужно использовать `--dpi-desync-fake-tls-mod=none'.
Пример : `--dpi-desync-fake-tls=iana_org.bin --dpi-desync-fake-tls-mod=rndsni --dpi-desync-fake-tls=0xaabbccdd --dpi-desync-fake-tls-mod=none'
Если задан режим модификации и имеется множество TLS фейков, модифицируются все фейки, являющиеся TLS Client Hello.
Если нет ни одного TLS Client Hello фейка, программа завершается с ошибкой.
### TCP СЕГМЕНТАЦИЯ

View File

@ -623,12 +623,12 @@ static uint16_t IP4_IP_ID_FIX(const struct ip *ip)
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
// size does not change
// return : true - altered, false - not altered
static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache, const struct fake_tls_mod *tls_mod, const uint8_t *fake_data, size_t fake_data_size, const uint8_t *payload, size_t payload_len, uint8_t *fake_mod)
static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache, uint32_t fake_tls_mod, const uint8_t *fake_data, size_t fake_data_size, const uint8_t *payload, size_t payload_len, uint8_t *fake_mod)
{
bool b=false;
if (modcache) // it's filled only if it's TLS
{
if (tls_mod->mod & FAKE_TLS_MOD_PADENCAP)
if (fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
{
size_t sz_rec = pntoh16(fake_data+3) + payload_len;
size_t sz_handshake = pntoh24(fake_data+6) + payload_len;
@ -647,7 +647,7 @@ static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache
DLOG("fake[%d] applied padencap tls mod. sizes increased by %zu bytes.\n", fake_n, payload_len);
}
}
if (tls_mod->mod & FAKE_TLS_MOD_RND)
if (fake_tls_mod & FAKE_TLS_MOD_RND)
{
if (!b) memcpy(fake_mod,fake_data,fake_data_size);
fill_random_bytes(fake_mod+11,32); // random
@ -655,11 +655,9 @@ static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache
b=true;
DLOG("fake[%d] applied rnd tls mod\n", fake_n);
}
if (tls_mod->mod & FAKE_TLS_MOD_DUP_SID)
if (fake_tls_mod & FAKE_TLS_MOD_DUP_SID)
{
if (payload_len<44)
DLOG("fake[%d] cannot apply dupsid tls mod. data payload is too short.\n",fake_n);
else if (fake_data[43]!=payload[43])
if (fake_data[43]!=payload[43])
DLOG("fake[%d] cannot apply dupsid tls mod. fake and orig session id length mismatch.\n",fake_n);
else if (payload_len<(44+payload[43]))
DLOG("fake[%d] cannot apply dupsid tls mod. data payload is not valid.\n",fake_n);
@ -1323,7 +1321,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
{
case TLS:
if ((fake_item->size <= sizeof(fake_data_buf)) &&
runtime_tls_mod(n,(struct fake_tls_mod_cache *)fake_item->extra,(struct fake_tls_mod *)fake_item->extra2, fake_item->data, fake_item->size, rdata_payload, rlen_payload, fake_data_buf))
runtime_tls_mod(n,(struct fake_tls_mod_cache *)fake_item->extra, dp->fake_tls_mod, fake_item->data, fake_item->size, rdata_payload, rlen_payload, fake_data_buf))
{
fake_data = fake_data_buf;
break;

View File

@ -950,12 +950,12 @@ static bool parse_ip_list(char *opt, ipset *pp)
return true;
}
static bool parse_tlsmod_list(char *opt, struct fake_tls_mod *tls_mod)
static bool parse_tlsmod_list(char *opt, uint32_t *mod, char *sni, size_t sni_buf_len)
{
char *e,*e2,*p,c,c2;
tls_mod->mod &= FAKE_TLS_MOD_SAVE_MASK;
tls_mod->mod |= FAKE_TLS_MOD_SET;
*mod &= FAKE_TLS_MOD_SAVE_MASK;
*mod |= FAKE_TLS_MOD_SET;
for (p=opt ; p ; )
{
for (e2=p ; *e2 && *e2!=',' && *e2!='=' ; e2++);
@ -975,20 +975,20 @@ static bool parse_tlsmod_list(char *opt, struct fake_tls_mod *tls_mod)
e2=NULL;
if (!strcmp(p,"rnd"))
tls_mod->mod |= FAKE_TLS_MOD_RND;
*mod |= FAKE_TLS_MOD_RND;
else if (!strcmp(p,"rndsni"))
tls_mod->mod |= FAKE_TLS_MOD_RND_SNI;
*mod |= FAKE_TLS_MOD_RND_SNI;
else if (!strcmp(p,"sni"))
{
tls_mod->mod |= FAKE_TLS_MOD_SNI;
*mod |= FAKE_TLS_MOD_SNI;
if (!e2 || !e2[1] || e2[1]==',') goto err;
strncpy(tls_mod->sni,e2+1,sizeof(tls_mod->sni)-1);
tls_mod->sni[sizeof(tls_mod->sni)-1-1]=0;
strncpy(sni,e2+1,sni_buf_len-1);
sni[sni_buf_len-1]=0;
}
else if (!strcmp(p,"padencap"))
tls_mod->mod |= FAKE_TLS_MOD_PADENCAP;
*mod |= FAKE_TLS_MOD_PADENCAP;
else if (!strcmp(p,"dupsid"))
tls_mod->mod |= FAKE_TLS_MOD_DUP_SID;
*mod |= FAKE_TLS_MOD_DUP_SID;
else if (strcmp(p,"none"))
goto err;
@ -1034,13 +1034,13 @@ static void SplitDebug(void)
static const char * tld[]={"com","org","net","edu","gov","biz"};
static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tls_mod *tls_mod, uint8_t *fake_tls, size_t *fake_tls_size, size_t fake_tls_buf_size, struct fake_tls_mod_cache *modcache)
static bool onetime_tls_mod_blob(int profile_n, int fake_n, uint32_t fake_tls_mod, const char *fake_tls_sni, uint8_t *fake_tls, size_t *fake_tls_size, size_t fake_tls_buf_size, struct fake_tls_mod_cache *modcache)
{
const uint8_t *ext;
size_t extlen;
modcache->extlen_offset = modcache->padlen_offset = 0;
if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI|FAKE_TLS_MOD_PADENCAP))
if (fake_tls_mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI|FAKE_TLS_MOD_PADENCAP))
{
if (!TLSFindExtLen(fake_tls,*fake_tls_size,&modcache->extlen_offset))
{
@ -1048,7 +1048,7 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl
return false;
}
DLOG("profile %d fake[%d] tls extensions length offset : %zu\n", profile_n, fake_n, modcache->extlen_offset);
if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI))
if (fake_tls_mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI))
{
size_t slen;
if (!TLSFindExt(fake_tls,*fake_tls_size,0,&ext,&extlen,false))
@ -1063,9 +1063,9 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl
return false;
}
uint8_t *sni = fake_tls + (ext - fake_tls);
if (tls_mod->mod & FAKE_TLS_MOD_SNI)
if (fake_tls_mod & FAKE_TLS_MOD_SNI)
{
size_t slen_new = strlen(tls_mod->sni);
size_t slen_new = strlen(fake_tls_sni);
ssize_t slen_delta = slen_new-slen;
char *s1=NULL;
if (params.debug)
@ -1093,12 +1093,12 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl
*fake_tls_size+=slen_delta;
slen = slen_new;
}
DLOG("profile %d fake[%d] change SNI : %s => %s size_delta=%zd\n", profile_n, fake_n, s1, tls_mod->sni, slen_delta);
DLOG("profile %d fake[%d] change SNI : %s => %s size_delta=%zd\n", profile_n, fake_n, s1, fake_tls_sni, slen_delta);
free(s1);
memcpy(sni,tls_mod->sni,slen_new);
memcpy(sni,fake_tls_sni,slen_new);
}
if (tls_mod->mod & FAKE_TLS_MOD_RND_SNI)
if (fake_tls_mod & FAKE_TLS_MOD_RND_SNI)
{
if (!slen)
{
@ -1136,7 +1136,7 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl
}
}
}
if (tls_mod->mod & FAKE_TLS_MOD_PADENCAP)
if (fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
{
if (TLSFindExt(fake_tls,*fake_tls_size,21,&ext,&extlen,false))
{
@ -1171,37 +1171,39 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl
}
static bool onetime_tls_mod(struct desync_profile *dp)
{
if (dp->n && !(dp->fake_tls_mod & (FAKE_TLS_MOD_SET|FAKE_TLS_MOD_CUSTOM_FAKE)))
dp->fake_tls_mod |= FAKE_TLS_MOD_RND|FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_DUP_SID; // old behavior compat + dup_sid
if (!(dp->fake_tls_mod & ~FAKE_TLS_MOD_SAVE_MASK))
return true; // nothing to do
struct blob_item *fake_tls;
struct fake_tls_mod *tls_mod;
int n=0;
bool bMod=false;
LIST_FOREACH(fake_tls, &dp->fake_tls, next)
{
++n;
tls_mod = (struct fake_tls_mod *)fake_tls->extra2;
if (!tls_mod) continue;
if (dp->n && !(tls_mod->mod & (FAKE_TLS_MOD_SET|FAKE_TLS_MOD_CUSTOM_FAKE)))
tls_mod->mod |= FAKE_TLS_MOD_RND|FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_DUP_SID; // old behavior compat + dup_sid
if (!(tls_mod->mod & ~FAKE_TLS_MOD_SAVE_MASK))
continue;
if (!IsTLSClientHello(fake_tls->data,fake_tls->size,false) || (fake_tls->size < (44+fake_tls->data[43]))) // has session id ?
{
DLOG("profile %d fake[%d] tls mod set but tls fake structure invalid.\n", dp->n, n);
return false;
DLOG("profile %d fake[%d] tls mod set but tls fake structure invalid. mod skipped.\n", dp->n, n);
continue;
}
bMod = true;
if (!fake_tls->extra)
{
fake_tls->extra = malloc(sizeof(struct fake_tls_mod_cache));
if (!fake_tls->extra) return false;
}
if (!onetime_tls_mod_blob(dp->n,n,tls_mod,fake_tls->data,&fake_tls->size,fake_tls->size_buf,(struct fake_tls_mod_cache*)fake_tls->extra))
if (!onetime_tls_mod_blob(dp->n,n,dp->fake_tls_mod,dp->fake_tls_sni,fake_tls->data,&fake_tls->size,fake_tls->size_buf,(struct fake_tls_mod_cache*)fake_tls->extra))
return false;
}
return true;
if (!bMod)
DLOG_ERR("profile %d tls fake list does not have any valid TLS ClientHello\n", dp->n);
return bMod;
}
static struct blob_item *load_blob_to_collection(const char *filename, struct blob_collection_head *blobs, size_t max_size, size_t size_reserve)
static void load_blob_to_collection(const char *filename, struct blob_collection_head *blobs, size_t max_size, size_t size_reserve)
{
struct blob_item *blob = blob_collection_add(blobs);
uint8_t *p;
@ -1220,7 +1222,6 @@ static struct blob_item *load_blob_to_collection(const char *filename, struct bl
}
blob->data = p;
blob->size_buf = blob->size+size_reserve;
return blob;
}
@ -2115,26 +2116,15 @@ int main(int argc, char **argv)
load_blob_to_collection(optarg, &dp->fake_http, FAKE_MAX_TCP,0);
break;
case 39: /* dpi-desync-fake-tls */
{
dp->tls_fake_last = load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP,4+sizeof(dp->tls_mod_last.sni));
if (!(dp->tls_fake_last->extra2 = malloc(sizeof(struct fake_tls_mod))))
{
DLOG_ERR("out of memory\n");
exit_clean(1);
}
struct fake_tls_mod *tls_mod = (struct fake_tls_mod*)dp->tls_fake_last->extra2;
*tls_mod = dp->tls_mod_last;
tls_mod->mod |= FAKE_TLS_MOD_CUSTOM_FAKE;
}
load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP,4+sizeof(dp->fake_tls_sni));
dp->fake_tls_mod |= FAKE_TLS_MOD_CUSTOM_FAKE;
break;
case 40: /* dpi-desync-fake-tls-mod */
if (!parse_tlsmod_list(optarg,&dp->tls_mod_last))
if (!parse_tlsmod_list(optarg,&dp->fake_tls_mod,dp->fake_tls_sni,sizeof(dp->fake_tls_sni)))
{
DLOG_ERR("Invalid tls mod : %s\n",optarg);
exit_clean(1);
}
if (dp->tls_fake_last)
*(struct fake_tls_mod*)dp->tls_fake_last->extra2 = dp->tls_mod_last;
break;
case 41: /* dpi-desync-fake-unknown */
load_blob_to_collection(optarg, &dp->fake_unknown, FAKE_MAX_TCP, 0);

View File

@ -185,6 +185,7 @@ void dp_init(struct desync_profile *dp)
dp->desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT;
dp->desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT;
dp->desync_repeats = 1;
dp->fake_tls_mod = 0;
dp->fake_syndata_size = 16;
dp->wscale=-1; // default - dont change scale factor (client)
dp->desync_ttl6 = 0xFF; // unused
@ -205,11 +206,8 @@ bool dp_fake_defaults(struct desync_profile *dp)
return false;
if (blob_collection_empty(&dp->fake_tls))
{
if (!(item=blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(((struct fake_tls_mod*)0)->sni))))
if (!blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(dp->fake_tls_sni)))
return false;
if (!(item->extra2 = malloc(sizeof(struct fake_tls_mod))))
return false;
*(struct fake_tls_mod*)item->extra2 = dp->tls_mod_last;
}
if (blob_collection_empty(&dp->fake_unknown))
{

View File

@ -56,11 +56,6 @@ struct fake_tls_mod_cache
{
size_t extlen_offset, padlen_offset;
};
struct fake_tls_mod
{
char sni[64];
uint32_t mod;
};
struct desync_profile
{
@ -93,8 +88,8 @@ struct desync_profile
uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],fsplit_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP];
size_t fake_syndata_size;
struct fake_tls_mod tls_mod_last;
struct blob_item *tls_fake_last;
uint32_t fake_tls_mod;
char fake_tls_sni[64];
int udplen_increment;

View File

@ -570,7 +570,6 @@ void blob_collection_destroy(struct blob_collection_head *head)
{
LIST_REMOVE(entry, next);
free(entry->extra);
free(entry->extra2);
free(entry->data);
free(entry);
}

View File

@ -153,7 +153,6 @@ struct blob_item {
size_t size; // main data blob size
size_t size_buf;// main data blob allocated size
void *extra; // any data without size
void *extra2; // any data without size
LIST_ENTRY(blob_item) next;
};
LIST_HEAD(blob_collection_head, blob_item);