mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-17 15:47:14 +00:00
fix(xray): stop a lone dns qType 0 from matching every query
The core reads a dns rule's qType as a PortList, which drops a bare numeric 0 (infra/conf/common.go: `if number != 0`), and a rule with no qTypes matches every query. A stored `"qType": 0` therefore does not target query type 0: it drops, refuses or hijacks all DNS through that outbound. A qType the panel writes has to be read by the core as exactly the query types it names. Four writers broke that: - DNSOutboundLegacyKeysFix rewrote a lone blockTypes [0] into "qType": 0, so "block type 0" became "block everything" on upgrade. - That seeder shipped in v3.8.0 and is recorded as done, so fixing it does not reach installs that already ran it. DNSOutboundQTypeZeroFix spells any stored numeric qType 0 as "0" once, protocol id matched like the core. - The outbound form adapter turned a typed "0" into the number 0. - The Xray template editor saves raw JSON past that adapter; the save now applies the same rewrite. Each writer is pinned by a test that fails without its part. The rewrite and the repair compare policies as the pinned core builds them, and the repair runs through runSeeders over a database whose legacy-keys seeder already ran, on SQLite and PostgreSQL 16.
This commit is contained in:
@@ -786,7 +786,8 @@ function dnsRuleToWire(r: DnsRuleForm) {
|
||||
const result: Raw = { action };
|
||||
const qType = r.qType.trim();
|
||||
if (qType) {
|
||||
result.qType = /^\d+$/.test(qType) ? Number(qType) : qType;
|
||||
// The core reads a numeric 0 as no qType at all, which matches every query.
|
||||
result.qType = /^\d+$/.test(qType) && Number(qType) > 0 ? Number(qType) : qType;
|
||||
}
|
||||
const domains = r.domain
|
||||
.split(',')
|
||||
|
||||
@@ -336,6 +336,19 @@ describe('outbound-form-adapter: round-trip', () => {
|
||||
expect(rules[1]).toEqual({ action: 'return', qType: 28, domain: ['blocked.com'], rCode: 3 });
|
||||
});
|
||||
|
||||
it('dns rules keep qType 0 a string, since the core reads a numeric 0 as every query', () => {
|
||||
const back = formValuesToWirePayload(
|
||||
rawOutboundToFormValues({
|
||||
protocol: 'dns',
|
||||
settings: { rules: [{ action: 'drop', qType: 0 }] },
|
||||
}),
|
||||
);
|
||||
const rules = (back.settings as Record<string, unknown>).rules as Array<
|
||||
Record<string, unknown>
|
||||
>;
|
||||
expect(rules[0]).toEqual({ action: 'drop', qType: '0' });
|
||||
});
|
||||
|
||||
it('dns rules read the legacy qtype wire key for back-compat', () => {
|
||||
const wire = {
|
||||
protocol: 'dns',
|
||||
|
||||
Reference in New Issue
Block a user