mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-14 06:13:09 +00:00
zapret-obfs: ippxor
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,5 +1,7 @@
|
|||||||
* text=auto eol=lf
|
* text=auto eol=lf
|
||||||
*.cmd eol=crlf
|
*.cmd eol=crlf
|
||||||
*.bat eol=crlf
|
*.bat eol=crlf
|
||||||
|
*.manifest eol=crlf
|
||||||
|
*.rc eol=crlf
|
||||||
init.d/windivert.filter.examples/** eol=crlf
|
init.d/windivert.filter.examples/** eol=crlf
|
||||||
files/** binary
|
files/** binary
|
||||||
|
|||||||
@@ -175,6 +175,9 @@ end
|
|||||||
-- produce resulting verdict from 2 verdicts
|
-- produce resulting verdict from 2 verdicts
|
||||||
function verdict_aggregate(v1, v2)
|
function verdict_aggregate(v1, v2)
|
||||||
local v
|
local v
|
||||||
|
local vn = bitor(bitand(v1,VERDICT_PRESERVE_NEXT),bitand(v2,VERDICT_PRESERVE_NEXT))
|
||||||
|
v1 = bitand(v1, VERDICT_MASK)
|
||||||
|
v2 = bitand(v2, VERDICT_MASK)
|
||||||
v1 = v1 or VERDICT_PASS
|
v1 = v1 or VERDICT_PASS
|
||||||
v2 = v2 or VERDICT_PASS
|
v2 = v2 or VERDICT_PASS
|
||||||
if v1==VERDICT_DROP or v2==VERDICT_DROP then
|
if v1==VERDICT_DROP or v2==VERDICT_DROP then
|
||||||
@@ -184,7 +187,7 @@ function verdict_aggregate(v1, v2)
|
|||||||
else
|
else
|
||||||
v=VERDICT_PASS
|
v=VERDICT_PASS
|
||||||
end
|
end
|
||||||
return v
|
return bitor(v,vn)
|
||||||
end
|
end
|
||||||
function plan_instance_execute(desync, verdict, instance)
|
function plan_instance_execute(desync, verdict, instance)
|
||||||
apply_execution_plan(desync, instance)
|
apply_execution_plan(desync, instance)
|
||||||
@@ -751,6 +754,14 @@ function dis_reverse(dis)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function dis_reconstruct_l3(dis, options)
|
||||||
|
if dis.ip then
|
||||||
|
return csum_ip4_fix(reconstruct_iphdr(dis.ip))
|
||||||
|
elseif dis.ip6 then
|
||||||
|
return reconstruct_ip6hdr(dis.ip6, options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- parse autottl : delta,min-max
|
-- parse autottl : delta,min-max
|
||||||
function parse_autottl(s)
|
function parse_autottl(s)
|
||||||
if s then
|
if s then
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ function wgobfs(ctx, desync)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not desync.arg.secret or #desync.arg.secret==0 then
|
if not desync.arg.secret or #desync.arg.secret==0 then
|
||||||
error("wgobfs requires secret")
|
error("wgobfs: secret required")
|
||||||
end
|
end
|
||||||
if padmin>padmax then
|
if padmin>padmax then
|
||||||
error("wgobfs: padmin>padmax")
|
error("wgobfs: padmin>padmax")
|
||||||
@@ -78,3 +78,71 @@ function wgobfs(ctx, desync)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- test case :
|
||||||
|
-- endpoint1:
|
||||||
|
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:xor=192:dataxor=0xABCD
|
||||||
|
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
|
||||||
|
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp dport "{5001}" queue num 200 bypass
|
||||||
|
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp dport "{5001}" queue num 200 bypass
|
||||||
|
-- iperf -i 1 -c endpoint2
|
||||||
|
-- endpoint2:
|
||||||
|
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:xor=192:dataxor=0xABCD --server
|
||||||
|
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
|
||||||
|
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp sport "{5001}" queue num 200 bypass
|
||||||
|
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp sport "{5001}" queue num 200 bypass
|
||||||
|
-- iperf -s
|
||||||
|
-- xor ip protocol number and optionally xor tcp,udp,icmp payload with supplied blob pattern
|
||||||
|
-- arg : ippxor - value to xor ip protocol number
|
||||||
|
-- arg : dataxor - blob to xor tcp, udp or icmp payload
|
||||||
|
function ippxor(ctx, desync)
|
||||||
|
local dataxor
|
||||||
|
local function dxor(dis)
|
||||||
|
if dataxor and dis.payload and #dis.payload>0 and (dis.tcp or dis.udp or dis.icmp) then
|
||||||
|
dis.payload = bxor(dis.payload, pattern(dataxor,1,#dis.payload))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if not desync.arg.ippxor then
|
||||||
|
error("ippxor: ippxor value required")
|
||||||
|
end
|
||||||
|
local ippxor = tonumber(desync.arg.ippxor)
|
||||||
|
if ippxor<0 or ippxor>0xFF then
|
||||||
|
error("ippxor: invalid ippxor value. should be 0..255")
|
||||||
|
end
|
||||||
|
if desync.arg.dataxor then
|
||||||
|
dataxor = blob(desync,desync.arg.dataxor)
|
||||||
|
if #dataxor==0 then
|
||||||
|
error("ippxor: empty dataxor value")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local l3_from = ip_proto_l3(desync.dis)
|
||||||
|
local l3_to = bitxor(l3_from, ippxor)
|
||||||
|
|
||||||
|
local bdxor = dxor(desync.dis)
|
||||||
|
if bdxor then
|
||||||
|
DLOG("ippxor: dataxor out")
|
||||||
|
end
|
||||||
|
fix_ip_proto(desync.dis, l3_to)
|
||||||
|
|
||||||
|
local raw_ip = reconstruct_dissect(desync.dis, {ip6_preserve_next=true})
|
||||||
|
|
||||||
|
local dis = dissect(raw_ip)
|
||||||
|
if not dis.ip and not dis.ip6 then
|
||||||
|
DLOG_ERR("ippxor: could not rebuild packet")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not bdxor then
|
||||||
|
if dxor(dis) then
|
||||||
|
DLOG("ippxor: dataxor in")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desync.dis = dis
|
||||||
|
DLOG("ippxor: "..l3_from.." => "..l3_to)
|
||||||
|
return VERDICT_MODIFY + VERDICT_PRESERVE_NEXT
|
||||||
|
end
|
||||||
@@ -99,8 +99,10 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
|
|||||||
#define VERDICT_MODIFY 1
|
#define VERDICT_MODIFY 1
|
||||||
#define VERDICT_DROP 2
|
#define VERDICT_DROP 2
|
||||||
#define VERDICT_MASK 3
|
#define VERDICT_MASK 3
|
||||||
#define VERDICT_NOCSUM 4
|
#define VERDICT_PRESERVE_NEXT 4
|
||||||
#define VERDICT_MASK_VALID 7
|
#define VERDICT_MASK_VALID_LUA (VERDICT_MASK|VERDICT_PRESERVE_NEXT)
|
||||||
|
#define VERDICT_NOCSUM 8
|
||||||
|
#define VERDICT_MASK_VALID 15
|
||||||
|
|
||||||
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0)
|
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0)
|
||||||
#define IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0)
|
#define IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0)
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ static bool dp_match(
|
|||||||
if (!port_filters_match(&dp->pf_udp, port)) return false;
|
if (!port_filters_match(&dp->pf_udp, port)) return false;
|
||||||
break;
|
break;
|
||||||
case IPPROTO_ICMP:
|
case IPPROTO_ICMP:
|
||||||
|
case IPPROTO_ICMPV6:
|
||||||
if (!icmp_filters_match(&dp->icf, icmp_type, icmp_code)) return false;
|
if (!icmp_filters_match(&dp->icf, icmp_type, icmp_code)) return false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -821,7 +822,7 @@ static bool desync_get_result(uint8_t *verdict)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
lua_Integer lv = lua_tointeger(params.L, -1);
|
lua_Integer lv = lua_tointeger(params.L, -1);
|
||||||
if (lv & ~VERDICT_MASK)
|
if (lv & ~VERDICT_MASK_VALID_LUA)
|
||||||
{
|
{
|
||||||
DLOG_ERR("desync function returned bad int result\n");
|
DLOG_ERR("desync function returned bad int result\n");
|
||||||
goto err;
|
goto err;
|
||||||
@@ -836,6 +837,20 @@ err:
|
|||||||
lua_pop(params.L, rescount);
|
lua_pop(params.L, rescount);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
static uint8_t verdict_aggregate(uint8_t v1,uint8_t v2)
|
||||||
|
{
|
||||||
|
uint8_t verdict_action = v1 & VERDICT_MASK;
|
||||||
|
switch (v2 & VERDICT_MASK)
|
||||||
|
{
|
||||||
|
case VERDICT_MODIFY:
|
||||||
|
if (verdict_action == VERDICT_PASS) verdict_action = VERDICT_MODIFY;
|
||||||
|
break;
|
||||||
|
case VERDICT_DROP:
|
||||||
|
verdict_action = VERDICT_DROP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return v1 & ~VERDICT_MASK | verdict_action | v2 & VERDICT_PRESERVE_NEXT;
|
||||||
|
}
|
||||||
static uint8_t desync(
|
static uint8_t desync(
|
||||||
struct desync_profile *dp,
|
struct desync_profile *dp,
|
||||||
uint32_t fwmark,
|
uint32_t fwmark,
|
||||||
@@ -1031,14 +1046,8 @@ static uint8_t desync(
|
|||||||
}
|
}
|
||||||
if (!desync_get_result(&verdict_func))
|
if (!desync_get_result(&verdict_func))
|
||||||
goto err;
|
goto err;
|
||||||
switch (verdict_func & VERDICT_MASK)
|
|
||||||
{
|
verdict = verdict_aggregate(verdict, verdict_func);
|
||||||
case VERDICT_MODIFY:
|
|
||||||
if (verdict == VERDICT_PASS) verdict = VERDICT_MODIFY;
|
|
||||||
break;
|
|
||||||
case VERDICT_DROP:
|
|
||||||
verdict = VERDICT_DROP;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DLOG("* lua '%s' : payload_type '%s' does not satisfy filter\n", instance, l7payload_str(l7payload));
|
DLOG("* lua '%s' : payload_type '%s' does not satisfy filter\n", instance, l7payload_str(l7payload));
|
||||||
@@ -1057,7 +1066,7 @@ static uint8_t desync(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verdict == VERDICT_MODIFY)
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||||
{
|
{
|
||||||
// use same memory buffer to reduce memory copying
|
// use same memory buffer to reduce memory copying
|
||||||
// packet size cannot grow
|
// packet size cannot grow
|
||||||
@@ -1073,16 +1082,12 @@ static uint8_t desync(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b = lua_reconstruct_dissect(params.L, -1, mod_pkt, len_mod_pkt, false, false, IPPROTO_NONE, false);
|
b = lua_reconstruct_dissect(params.L, -1, mod_pkt, len_mod_pkt, false, false, IPPROTO_NONE, !!(verdict & VERDICT_PRESERVE_NEXT));
|
||||||
lua_pop(params.L, 2);
|
lua_pop(params.L, 2);
|
||||||
if (!b)
|
if (!b)
|
||||||
{
|
{
|
||||||
DLOG_ERR("failed to reconstruct packet after VERDICT_MODIFY\n");
|
DLOG_ERR("failed to reconstruct packet after VERDICT_MODIFY\n");
|
||||||
// to reduce memory copying we used original packet buffer for reconstruction.
|
verdict = VERDICT_PASS;
|
||||||
// it may have been modified. windows and BSD will send modified data despite of VERDICT_PASS.
|
|
||||||
// force same behavior on all OS
|
|
||||||
// it's LUA script error, they passed bad data
|
|
||||||
verdict = VERDICT_DROP;
|
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
DLOG("reconstructed packet due to VERDICT_MODIFY. size %zu => %zu\n", dis->len_pkt, *len_mod_pkt);
|
DLOG("reconstructed packet due to VERDICT_MODIFY. size %zu => %zu\n", dis->len_pkt, *len_mod_pkt);
|
||||||
|
|||||||
@@ -3827,6 +3827,8 @@ static void lua_init_const(void)
|
|||||||
{"VERDICT_PASS",VERDICT_PASS},
|
{"VERDICT_PASS",VERDICT_PASS},
|
||||||
{"VERDICT_MODIFY",VERDICT_MODIFY},
|
{"VERDICT_MODIFY",VERDICT_MODIFY},
|
||||||
{"VERDICT_DROP",VERDICT_DROP},
|
{"VERDICT_DROP",VERDICT_DROP},
|
||||||
|
{"VERDICT_MASK",VERDICT_MASK},
|
||||||
|
{"VERDICT_PRESERVE_NEXT",VERDICT_PRESERVE_NEXT},
|
||||||
|
|
||||||
{"DEFAULT_MSS",DEFAULT_MSS},
|
{"DEFAULT_MSS",DEFAULT_MSS},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user