Commit 929df3f0 authored by bol-van's avatar bol-van
Browse files

nfqws: support different tls mods for every tls fake

parent 7272b243
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -291,9 +291,13 @@ 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 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 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 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

+9 −2
Original line number Diff line number Diff line
@@ -346,8 +346,15 @@ dvtws, собираемый из тех же исходников (см. [док
По умолчанию если не задан собственный фейк для TLS используются модификации `rnd,rndsni,dupsid`. Если фейк задан, используется `none`.
Это соответствует поведению программы более старых версий с добавлением функции `dupsid`.

Если задан режим модификации и имеется множество TLS фейков, модифицируются все фейки, являющиеся TLS Client Hello.
Если нет ни одного TLS Client Hello фейка, программа завершается с ошибкой.
Если задан режим модификации и имеется множество 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'

### TCP СЕГМЕНТАЦИЯ

+5 −5
Original line number Diff line number Diff line
@@ -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, 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)
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)
{
	bool b=false;
	if (modcache) // it's filled only if it's TLS
	{
		if (fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
		if (tls_mod->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 (fake_tls_mod & FAKE_TLS_MOD_RND)
		if (tls_mod->mod & FAKE_TLS_MOD_RND)
		{
			if (!b)	memcpy(fake_mod,fake_data,fake_data_size);
			fill_random_bytes(fake_mod+11,32); // random
@@ -655,7 +655,7 @@ 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 (fake_tls_mod & FAKE_TLS_MOD_DUP_SID)
		if (tls_mod->mod & FAKE_TLS_MOD_DUP_SID)
		{
			if (fake_data[43]!=payload[43])
				DLOG("fake[%d] cannot apply dupsid tls mod. fake and orig session id length mismatch.\n",fake_n);
@@ -1321,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, dp->fake_tls_mod, 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,(struct fake_tls_mod *)fake_item->extra2, fake_item->data, fake_item->size, rdata_payload, rlen_payload, fake_data_buf))
								{
									fake_data = fake_data_buf;
									break;
+37 −27
Original line number Diff line number Diff line
@@ -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, 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)
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)
{
	const uint8_t *ext;
	size_t extlen;

	modcache->extlen_offset = modcache->padlen_offset = 0;
	if (fake_tls_mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI|FAKE_TLS_MOD_PADENCAP))
	if (tls_mod->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, uint32_t fake_tls_mo
			return false;
		}
		DLOG("profile %d fake[%d] tls extensions length offset : %zu\n", profile_n, fake_n, modcache->extlen_offset);
		if (fake_tls_mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI))
		if (tls_mod->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, uint32_t fake_tls_mo
				return false;
			}
			uint8_t *sni = fake_tls + (ext - fake_tls);
			if (fake_tls_mod & FAKE_TLS_MOD_SNI)
			if (tls_mod->mod & FAKE_TLS_MOD_SNI)
			{
				size_t slen_new = strlen(fake_tls_sni);
				size_t slen_new = strlen(tls_mod->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, uint32_t fake_tls_mo
					*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, fake_tls_sni, slen_delta);
				DLOG("profile %d fake[%d] change SNI : %s => %s size_delta=%zd\n", profile_n, fake_n, s1, tls_mod->sni, slen_delta);
				free(s1);

				memcpy(sni,fake_tls_sni,slen_new);
				memcpy(sni,tls_mod->sni,slen_new);
			}
			if (fake_tls_mod & FAKE_TLS_MOD_RND_SNI)
			if (tls_mod->mod & FAKE_TLS_MOD_RND_SNI)
			{
				if (!slen)
				{
@@ -1136,7 +1136,7 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, uint32_t fake_tls_mo
				}
			}
		}
		if (fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
		if (tls_mod->mod & FAKE_TLS_MOD_PADENCAP)
		{
			if (TLSFindExt(fake_tls,*fake_tls_size,21,&ext,&extlen,false))
			{
@@ -1171,39 +1171,37 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, uint32_t fake_tls_mo
}
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;
		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. mod skipped.\n", dp->n, 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;
		}
		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,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))
		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))
			return false;
	}
	if (!bMod)
		DLOG_ERR("profile %d tls fake list does not have any valid TLS ClientHello\n", dp->n);
	return bMod;
	return true;
}

static void load_blob_to_collection(const char *filename, struct blob_collection_head *blobs, size_t max_size, size_t size_reserve)
static struct blob_item *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;
@@ -1222,6 +1220,7 @@ static void load_blob_to_collection(const char *filename, struct blob_collection
	}
	blob->data = p;
	blob->size_buf = blob->size+size_reserve;
	return blob;
}


@@ -2116,15 +2115,26 @@ 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 */
			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;
			{
				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;
			}
			break;
		case 40: /* dpi-desync-fake-tls-mod */
			if (!parse_tlsmod_list(optarg,&dp->fake_tls_mod,dp->fake_tls_sni,sizeof(dp->fake_tls_sni)))
			if (!parse_tlsmod_list(optarg,&dp->tls_mod_last.mod,dp->tls_mod_last.sni,sizeof(dp->tls_mod_last.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);
+4 −2
Original line number Diff line number Diff line
@@ -185,7 +185,6 @@ 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
@@ -206,8 +205,11 @@ bool dp_fake_defaults(struct desync_profile *dp)
			return false;
	if (blob_collection_empty(&dp->fake_tls))
	{
		if (!blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(dp->fake_tls_sni)))
		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))))
			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))
	{
Loading