Finalmask header-custom: add programmable handshake templates and runtime core#5920
Finalmask header-custom: add programmable handshake templates and runtime core#5920
Conversation
|
Thanks. This PR intentionally focuses on the schema/evaluator layer only, so I avoided adding transport-specific runtime examples to keep the review scope narrow. The corresponding runtime-oriented config usage is split into the follow-up stacked PRs:
If it helps the review, I can also add a small generic |
|
算了这太复杂了 最后加一坨都没人知道怎么用 感觉没有现实意义 |
But Xray-core was never meant to be the simplest solution in the first place. And if we are talking about censorship resistance, then I think this is actually a meaningful step. Not every feature has to be for everyone. |
|
可以接受但设计需要简单通俗些,让大多数人知道该怎么用 |
I think there are two different ways to simplify this, and they have very different trade-offs. If the concern is mainly about UX and how the feature is presented, then I can simplify the surface without really losing capability: But if the expectation is to actually remove syntax/operations from the design itself, then we would start losing generality. So I want to clarify which direction you mean by “make it simpler”:
Those two lead to very different designs. |
|
1 刚刚才看到 @iambabyninja 也发邮件说了这个, 目前可以先把代理和加密的部分完全交给 VLESS Encryption random,然后 finalmask 做外部流量包装和整形,弄成任何东西
|
Yes, I agree. I’ll think about how to make the design simpler and easier to understand, while keeping the underlying flexibility. |
|
I agree with the concern about making the design easier to understand. I have reworked the user-facing config surface in this PR to make it read more like programmable handshake packet templates, instead of a mini-language:
The underlying capability is intentionally unchanged:
So the goal of this update is to simplify the UX and mental model, without reducing the flexibility needed for programmable handshake shaping. If you think the public model should be simplified even further, I can continue iterating in that direction. |
The rename was intentional, not arbitrary. The earlier feedback was that the design should be simpler and easier to understand, so I adjusted the user-facing terminology to make it read less like a mini-DSL and more like packet-template fields. I agree that changing naming during review adds churn, so I should stabilize the vocabulary more carefully. But the goal of the rename was to improve UX, not to change the underlying model. As for fallback, I agree it is useful, but it solves a different problem. |
Good catch. In the current implementation, unresolved reuse is not rejected at config-build time. It is only rejected later at runtime evaluation, where it fails with an unknown variable error. So this test was only meant to validate the parser/config shape, not to imply that an uncaptured field can actually be reused successfully. That said, I agree this is a poor example for a user-facing review context, because it makes the model look more confusing than it should. I’ll adjust the test case to use a properly captured field instead. Also, this is my first PR in Xray-core, and I’m glad to have the opportunity to communicate with the maintainers and contributors here while iterating on the design. |
我自己搓个格式用标准语言还得写一堆函数和变量呢 用这抽象玩意得多难写啊 |
Sure, writing this is harder than writing a normal program directly. But the goal here is not to replace a real programming language. The goal is to provide a bounded in-config mechanism for programmable handshake shaping inside Xray itself. So I do not expect it to be “easy” in the same sense as a simple config. |
|
|
yeah, sorry about that i pushed it once it was working and already usable for me, and only later realized i had not thought enough about the UX side i’m probably not the pickiest user myself :) will try to keep it less vibe and more polished from here |
f622ca1 to
479ca44
Compare
479ca44 to
7fb158c
Compare
|
I restacked the series and rebased it onto current There were two reasons for this:
So this PR now represents the self-contained
The remaining follow-up PR is now only for detached UDP standalone mode. After the restack, I reran the focused tests and local live smoke checks for both TCP and UDP paths. |



Summary
finalmask/header-customwith programmable handshake templates for both TCP and UDPcapture,reuse, andtransformfields together with flow-scoped state and runtime-derived metadataheader-customruntime while keeping existingpacket/randbehavior workingWhy
header-customcurrently supports fixed bytes and random bytes only. That is enough for static wrappers, but not for handshakes that need captured fields, reused values, deterministic derived fields, or request/response correlation.This PR keeps the template/config layer and the corresponding runtime core together so the feature is self-contained.
Scope
header-customconfig with captured, reused, and transformed fieldsconcat,slice,xor16,xor32,be16, andbe32header-customheader-customruntimepacket/randconfigsNon-Goals
Test Plan
go test ./infra/conf -run 'Test(HeaderCustomUDPBuild|HeaderCustomTCPBuildRejectsMixedItemKinds|HeaderCustomUDPBuildRejectsInvalidVariableNames|HeaderCustomUDPBuildRejectsExprWithoutArgs)' -count=1go test ./transport/internet/finalmask/header/custom -run 'Test(Evaluator.*|Metadata.*|State.*|DSLTCP.*|DSLUDP.*)' -count=1go test ./transport/internet/finalmask -run 'Test(ConnReadWrite|PacketConnReadWrite|TCPcustomStaticHandshakeRoundTrip|TCPcustomClientRejectsMismatchedServerSequence|UDPcustomStaticHeaderWireShape|UDPcustomServerRejectsMismatchedStaticHeader)' -count=1