XMC finalmask: Add default directional padding/keep-alive packets, matching Minecraft 26.1.2 login/join/etc traffic shapes (#6487)

https://github.com/XTLS/Xray-core/pull/6487#issuecomment-5092235757

---------

Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
This commit is contained in:
Sparrow
2026-07-28 06:45:36 +00:00
committed by GitHub
co-authored by 风扇滑翔翼
parent 4aba687dd3
commit 6ab123bf8f
21 changed files with 2853 additions and 178 deletions
+48 -6
View File
@@ -11,6 +11,7 @@ import (
"regexp"
"strings"
googleuuid "github.com/google/uuid"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/transport/internet/finalmask/fragment"
@@ -720,14 +721,46 @@ func (c *Xdns) Build() (proto.Message, error) {
}
type XMC struct {
Hostname string `json:"hostname"`
Usernames []string `json:"usernames"`
Password string `json:"password"`
Hostname string `json:"hostname"`
Profiles []XMCProfile `json:"profiles"`
Password string `json:"password"`
}
type XMCProfile struct {
// Resolve the UUID by username, then request the session profile with
// unsigned=false. Client and server must use the same signed profile.
Username string `json:"username"`
UUID string `json:"uuid"`
TexturesValue string `json:"texturesValue"`
TexturesSignature string `json:"texturesSignature"`
}
var xmcUsernamePattern = regexp.MustCompile(`^[A-Za-z0-9_]{3,16}$`)
func (c *XMCProfile) Build() (*xmc.Profile, error) {
if !xmcUsernamePattern.MatchString(c.Username) {
return nil, fmt.Errorf("invalid minecraft profile username: %q", c.Username)
}
profileUUID, err := googleuuid.Parse(c.UUID)
if err != nil {
return nil, fmt.Errorf("invalid minecraft profile UUID: %w", err)
}
if c.TexturesValue == "" || c.TexturesSignature == "" {
return nil, fmt.Errorf("incomplete minecraft profile textures")
}
return &xmc.Profile{
Username: c.Username,
Uuid: append([]byte(nil), profileUUID[:]...),
TexturesValue: c.TexturesValue,
TexturesSignature: c.TexturesSignature,
}, nil
}
func (c *XMC) Build() (proto.Message, error) {
if len(c.Usernames) == 0 {
c.Usernames = []string{"Dream"}
if len(c.Profiles) == 0 {
return nil, fmt.Errorf("minecraft profiles are required")
}
if c.Password == "" {
@@ -744,12 +777,21 @@ func (c *XMC) Build() (proto.Message, error) {
return nil, fmt.Errorf("marshal minecraft rsa public key: %w", err)
}
profiles := make([]*xmc.Profile, 0, len(c.Profiles))
for i := range c.Profiles {
profile, err := c.Profiles[i].Build()
if err != nil {
return nil, fmt.Errorf("build minecraft profile %d: %w", i, err)
}
profiles = append(profiles, profile)
}
return &xmc.Config{
Password: c.Password,
Usernames: c.Usernames,
Hostname: c.Hostname,
RsaPrivateKey: x509.MarshalPKCS1PrivateKey(rsaPrivateKey),
RsaPublicKey: rsaPublicKey,
Profiles: profiles,
}, nil
}
@@ -0,0 +1,36 @@
package conf
import (
"strings"
"testing"
"github.com/xtls/xray-core/transport/internet/finalmask/xmc"
)
func TestXMCBuildProfile(t *testing.T) {
built, err := (&XMC{
Password: "test-password",
Profiles: []XMCProfile{
{
Username: "TestUser",
UUID: "00112233-4455-6677-8899-aabbccddeeff",
TexturesValue: "textures-value",
TexturesSignature: "textures-signature",
},
},
}).Build()
if err != nil {
t.Fatalf("build XMC config: %v", err)
}
config := built.(*xmc.Config)
if len(config.Profiles) != 1 || len(config.Profiles[0].Uuid) != 16 {
t.Fatalf("unexpected profiles: %+v", config.Profiles)
}
}
func TestXMCBuildRequiresProfile(t *testing.T) {
_, err := (&XMC{Password: "test-password"}).Build()
if err == nil || !strings.Contains(err.Error(), "profiles are required") {
t.Fatalf("expected required profiles error, got %v", err)
}
}