diff --git a/docs/manual.md b/docs/manual.md index 58963b0..9081d41 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -3524,6 +3524,7 @@ function tls_client_hello_clone(ctx, desync) - arg: [standard direction](#standard-direction) - arg: blob - имя блоба, получающего результат +- arg: fallback - имя блоба, который копируется в результат, если пейлоад неверного типа или невалидный - arg: sni_del_ext - удалить sni extension. остальные параметры не используются - arg: sni_del - удалить все хосты - arg: sni_snt - заменить на всех уже имеющихся хостах поле "server name type" diff --git a/lua/zapret-antidpi.lua b/lua/zapret-antidpi.lua index f3d9321..7e142e1 100644 --- a/lua/zapret-antidpi.lua +++ b/lua/zapret-antidpi.lua @@ -289,7 +289,8 @@ end -- nfqws1 : not available -- standard args : direction --- arg: blob = blob name to store cloned tls client hello (stored in desync, not global) +-- arg: blob - blob name to store cloned tls client hello (stored in desync, not global) +-- arg: fallback - copy this blob if could not clone -- arg: sni_snt - server name type value in existing names -- arg: sni_snt_new - server name type value for new names -- arg: sni_del_ext - delete sni extension @@ -302,50 +303,19 @@ function tls_client_hello_clone(ctx, desync) return end direction_cutoff_opposite(ctx, desync) - if desync.l7payload=="tls_client_hello" and direction_check(desync) then + if direction_check(desync) then if not desync.arg.blob then error("fake: 'blob' arg required") end - local tdis = tls_dissect(desync.reasm_data or desync.dis.payload) - if not tdis then - DLOG("tls_client_hello_clone: could not dissect tls") - return - end - if not tdis.handshake or not tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT] then - DLOG("tls_client_hello_clone: handshake not dissected") - return - end - local idx_sni - if desync.arg.sni_snt or desync.arg.sni_del_ext or desync.arg.sni_del or desync.arg.sni_first or desync.arg.sni_last then - idx_sni = array_field_search(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext, "type", TLS_EXT_SERVER_NAME) - if not idx_sni then - DLOG("tls_client_hello_clone: no SNI extension. adding") - table.insert(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext, 1, { type = TLS_EXT_SERVER_NAME, dis = { list = {} } } ) - idx_sni = 1 + if desync.l7payload=="tls_client_hello" then + desync[desync.arg.blob] = tls_client_hello_mod(desync.reasm_data or desync.dis.payload, desync.arg) + if desync[desync.arg.blob] then + DLOG("tls_client_hello_clone: cloned to desync."..desync.arg.blob) end end - if desync.arg.sni_del_ext then - table.remove(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext, idx_sni) - else - if desync.arg.sni_del then - tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext[idx_sni].dis.list = {} - elseif desync.arg.sni_snt then - for i,v in pairs(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext[idx_sni].dis.list) do - v.type = desync.arg.sni_snt - end - end - if desync.arg.sni_first then - table.insert(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext[idx_sni].dis.list, 1, { name = desync.arg.sni_first, type = desync.arg.sni_snt_new } ) - end - if desync.arg.sni_last then - table.insert(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext[idx_sni].dis.list, { name = desync.arg.sni_last, type = desync.arg.sni_snt_new } ) - end - end - desync[desync.arg.blob] = tls_reconstruct(tdis) - if desync[desync.arg.blob] then - DLOG("tls_client_hello_clone: cloned to desync."..desync.arg.blob) - else - DLOG_ERR("tls_client_hello_clone: reconstruct error") + if not desync[desync.arg.blob] and desync.arg.fallback then + DLOG("tls_client_hello_clone: desync."..desync.arg.blob.."="..desync.arg.fallback) + desync[desync.arg.blob] = blob(desync, desync.arg.fallback) end end end diff --git a/lua/zapret-lib.lua b/lua/zapret-lib.lua index 8ec21bd..0b76fd6 100644 --- a/lua/zapret-lib.lua +++ b/lua/zapret-lib.lua @@ -1361,6 +1361,55 @@ function ipfrag2(dis, ipfrag_options) end +-- option: sni_snt - server name type value in existing names +-- option: sni_snt_new - server name type value for new names +-- option: sni_del_ext - delete sni extension +-- option: sni_del - delete all names +-- option: sni_first - add name to the beginning +-- option: sni_last - add name to the end +function tls_client_hello_mod(tls, options) + local tdis = tls_dissect(tls) + if not tdis then + DLOG("tls_client_hello_mod: could not dissect tls") + return + end + if not tdis.handshake or not tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT] then + DLOG("tls_client_hello_mod: handshake not dissected") + return + end + local idx_sni + if options.sni_snt or options.sni_del_ext or options.sni_del or options.sni_first or options.sni_last then + idx_sni = array_field_search(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext, "type", TLS_EXT_SERVER_NAME) + if not idx_sni then + DLOG("tls_client_hello_mod: no SNI extension. adding") + table.insert(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext, 1, { type = TLS_EXT_SERVER_NAME, dis = { list = {} } } ) + idx_sni = 1 + end + end + if options.sni_del_ext then + table.remove(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext, idx_sni) + else + if options.sni_del then + tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext[idx_sni].dis.list = {} + elseif options.sni_snt then + for i,v in pairs(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext[idx_sni].dis.list) do + v.type = options.sni_snt + end + end + if options.sni_first then + table.insert(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext[idx_sni].dis.list, 1, { name = options.sni_first, type = options.sni_snt_new } ) + end + if options.sni_last then + table.insert(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext[idx_sni].dis.list, { name = options.sni_last, type = options.sni_snt_new } ) + end + end + local tls = tls_reconstruct(tdis) + if not tls then + DLOG_ERR("tls_client_hello_mod: reconstruct error") + end + return tls +end + -- DISSECTORS function http_dissect_header(header)