mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-05 13:42:07 +03:00
62423cacd1
Bump xtls/xray-core to b26a91de4f (v26.9.30) and the three binary pins (DockerInit.sh, release.yml Linux + Windows) in lockstep. No deleted symbols; the sing and sing-shadowsocks indirect deps drop out with the SS2022 rewrite. XDNS finalmask (#6718) replaced its string lists with objects: domains are {name, types, edns0, lenLimit, labelLimit} and client resolvers {type, settings.addr}. The loader no longer parses the old lists, so a single stored xdns mask keeps the whole core from starting. The new leaf package internal/util/maskcompat converts them: "name[:type]" becomes a domain and "name[:type]+udp://addr" a domain plus a udp resolver. A bare name maps to TXT, the type legacy clients queried by default, and each converted domain keeps the 1232-byte EDNS0 the old code always used (without it the server caps answers at 512). It runs from: - the XdnsFinalmaskObjectsFix seeder, over inbound streams, hosts, the xray template, the global sub-JSON mask and cached subscription outbounds; - inbound save (normalizeStreamSettings) and GetXrayConfig, for rows that never went through the seeder; - both link importers, since fm= from an older panel carries the lists. The finalmask form edits the object shape (every key needs a registered field, or the finalmask watch drops it on save) and lifts legacy masks on open. The udp-mask golden fixture moves to the object shape, which TestGoldenStreamFixturesBuildInXray now builds through the core. The wire format changed as well, so pre-upgrade clients need the new core. WireGuard outbound (#6771) dropped settings.domainStrategy and the remoteDNS "local" mode. The endpoint lookup now follows sockopt.domainStrategy and in-tunnel targets the outbound's targetStrategy. The old key is silently ignored, which undid the IPv4-first endpoint lookup the WARP outbound depends on (#5205), and "local" now panics the core at startup because remoteDNS goes through netip.MustParseAddr. The WireguardDomainStrategyFix seeder moves a stored family preference to both keys (a value already set wins) and turns "local" into targetStrategy; the outbound form lifts legacy rows the same way and drops its select, the WARP modal writes the new placement, and the inbound form loses a field the server never read. ValidateOutboundConfig now refuses a non-IP remoteDNS entry, which conf.Build() lets through, on template save and for outbound subscriptions. Noise finalmask items accept type "exp" (#6862), a tag expression. The form offers it for noise items only: header-custom items go through the core's PraseByteSlice, which refuses it. TUN gained autoSystemDnsToGateway (Linux) and autoSystemWfpBlockLeak (Windows). Both pass through the settings schema so a value set in JSON survives the next form save. MASQUE (inbound, outbound, transport) and the XDRIVE transport are new protocols the panel does not offer yet; their new loader refusals only cover configs the panel never generates. The FakeDNS IPv6 pool default, the SS2022 rewrite (same gRPC account; emails are now deduped case-insensitively, as the panel already does), the restored udphop interval default and the rest change no panel-facing config.
102 lines
3.8 KiB
Go
102 lines
3.8 KiB
Go
package maskcompat
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/xtls/xray-core/infra/conf"
|
|
)
|
|
|
|
// buildXdnsSettings runs an xdns mask's settings through conf.XDNS, the loader
|
|
// the core calls at startup, so the test's verdict is the core's verdict.
|
|
func buildXdnsSettings(t *testing.T, settings any) error {
|
|
t.Helper()
|
|
raw, err := json.Marshal(settings)
|
|
if err != nil {
|
|
t.Fatalf("marshal xdns settings: %v", err)
|
|
}
|
|
var mask conf.XDNS
|
|
if err := json.Unmarshal(raw, &mask); err != nil {
|
|
return err
|
|
}
|
|
_, err = mask.Build()
|
|
return err
|
|
}
|
|
|
|
func TestUpgradeLegacyXdns(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
mask string
|
|
want string
|
|
}{
|
|
{
|
|
name: "bare server domain becomes TXT with the legacy EDNS0 size",
|
|
mask: `{"type":"xdns","settings":{"domains":["t.example.com"]}}`,
|
|
want: `{"domains":[{"edns0":1232,"name":"t.example.com","types":[16]}]}`,
|
|
},
|
|
{
|
|
name: "method suffixes map to their record types",
|
|
mask: `{"type":"xdns","settings":{"domains":["a.example.com:a","q.example.com:AAAA","t.example.com:txt"]}}`,
|
|
want: `{"domains":[{"edns0":1232,"name":"a.example.com","types":[1]},{"edns0":1232,"name":"q.example.com","types":[28]},{"edns0":1232,"name":"t.example.com","types":[16]}]}`,
|
|
},
|
|
{
|
|
name: "client resolver splits into its domain and a udp resolver",
|
|
mask: `{"type":"XDNS","settings":{"resolvers":["t.example.com:a+udp://8.8.8.8:53"]}}`,
|
|
want: `{"domains":[{"edns0":1232,"name":"t.example.com","types":[1]}],"resolvers":[{"settings":{"addr":"8.8.8.8:53"},"type":"udp"}]}`,
|
|
},
|
|
{
|
|
name: "a resolver for an already listed domain adds no duplicate",
|
|
mask: `{"type":"xdns","settings":{"domains":["t.example.com"],"resolvers":["T.example.com+udp://1.1.1.1:53"]}}`,
|
|
want: `{"domains":[{"edns0":1232,"name":"t.example.com","types":[16]}],"resolvers":[{"settings":{"addr":"1.1.1.1:53"},"type":"udp"}]}`,
|
|
},
|
|
{
|
|
name: "entries the old core refused are dropped",
|
|
mask: `{"type":"xdns","settings":{"domains":["t.example.com","m.example.com:mx"],"resolvers":["1.1.1.1:53"]}}`,
|
|
want: `{"domains":[{"edns0":1232,"name":"t.example.com","types":[16]}]}`,
|
|
},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
var mask map[string]any
|
|
if err := json.Unmarshal([]byte(tc.mask), &mask); err != nil {
|
|
t.Fatalf("unmarshal mask: %v", err)
|
|
}
|
|
if err := buildXdnsSettings(t, mask["settings"]); err == nil {
|
|
t.Fatal("the core accepted the legacy string shape; the upgrade is no longer needed")
|
|
}
|
|
finalmask := map[string]any{"udp": []any{mask}}
|
|
if !UpgradeLegacyXdns(finalmask) {
|
|
t.Fatal("UpgradeLegacyXdns reported no change for a legacy mask")
|
|
}
|
|
got, err := json.Marshal(mask["settings"])
|
|
if err != nil {
|
|
t.Fatalf("marshal upgraded settings: %v", err)
|
|
}
|
|
if string(got) != tc.want {
|
|
t.Fatalf("upgraded settings\n got: %s\nwant: %s", got, tc.want)
|
|
}
|
|
if err := buildXdnsSettings(t, mask["settings"]); err != nil {
|
|
t.Fatalf("the core refuses the upgraded settings: %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpgradeLegacyXdnsLeavesCurrentShapeAlone(t *testing.T) {
|
|
const current = `{"udp":[{"type":"xdns","settings":{"domains":[{"name":"t.example.com","types":[16,28],"edns0":1232}],"resolvers":[{"type":"tcp","settings":{"addr":"8.8.8.8:53"}}],"extraPoll":2}},{"type":"salamander","settings":{"password":"x"}}]}`
|
|
var finalmask map[string]any
|
|
if err := json.Unmarshal([]byte(current), &finalmask); err != nil {
|
|
t.Fatalf("unmarshal finalmask: %v", err)
|
|
}
|
|
if UpgradeLegacyXdns(finalmask) {
|
|
t.Fatal("UpgradeLegacyXdns rewrote a mask that is already in the object shape")
|
|
}
|
|
var want map[string]any
|
|
_ = json.Unmarshal([]byte(current), &want)
|
|
got, _ := json.Marshal(finalmask)
|
|
wantJSON, _ := json.Marshal(want)
|
|
if string(got) != string(wantJSON) {
|
|
t.Fatalf("finalmask changed\n got: %s\nwant: %s", got, wantJSON)
|
|
}
|
|
}
|