From 76f56fa0e09dd06878554ccddaac8d3ea284f442 Mon Sep 17 00:00:00 2001 From: SukkaW Date: Sat, 3 May 2025 22:54:25 +0800 Subject: [PATCH] Protocol/Network rule support --- Build/lib/rules/base.ts | 7 +++++++ Build/lib/writing-strategy/adguardhome.ts | 1 + Build/lib/writing-strategy/base.ts | 1 + Build/lib/writing-strategy/clash.ts | 14 ++++++++++++++ Build/lib/writing-strategy/singbox.ts | 14 +++++++++++++- Build/lib/writing-strategy/surge.ts | 6 ++++++ 6 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Build/lib/rules/base.ts b/Build/lib/rules/base.ts index 67e8bd56..3558c64c 100644 --- a/Build/lib/rules/base.ts +++ b/Build/lib/rules/base.ts @@ -34,6 +34,7 @@ export class FileOutput { protected sourceIpOrCidr = new Set(); protected sourcePort = new Set(); protected destPort = new Set(); + protected protocol = new Set(); protected otherRules: string[] = []; @@ -199,6 +200,9 @@ export class FileOutput { case 'DEST-PORT': this.destPort.add(value); break; + case 'PROTOCOL': + this.protocol.add(value.toUpperCase()); + break; default: this.otherRules.push(line); break; @@ -327,6 +331,9 @@ export class FileOutput { if (this.domainWildcard.size) { strategy.writeDomainWildcards(this.domainWildcard); } + if (this.protocol.size) { + strategy.writeProtocols(this.protocol); + } if (this.userAgent.size) { strategy.writeUserAgents(this.userAgent); } diff --git a/Build/lib/writing-strategy/adguardhome.ts b/Build/lib/writing-strategy/adguardhome.ts index 0f25a0fb..37792ee2 100644 --- a/Build/lib/writing-strategy/adguardhome.ts +++ b/Build/lib/writing-strategy/adguardhome.ts @@ -105,5 +105,6 @@ export class AdGuardHome extends BaseWriteStrategy { writeSourceIpCidrs = notSupported('writeSourceIpCidrs'); writeSourcePorts = notSupported('writeSourcePorts'); writeDestinationPorts = noop; + writeProtocols = noop; writeOtherRules = noop; } diff --git a/Build/lib/writing-strategy/base.ts b/Build/lib/writing-strategy/base.ts index 58ae2d07..d1639365 100644 --- a/Build/lib/writing-strategy/base.ts +++ b/Build/lib/writing-strategy/base.ts @@ -42,6 +42,7 @@ export abstract class BaseWriteStrategy { abstract writeSourceIpCidrs(sourceIpCidr: string[]): void; abstract writeSourcePorts(port: Set): void; abstract writeDestinationPorts(port: Set): void; + abstract writeProtocols(protocol: Set): void; abstract writeOtherRules(rule: string[]): void; protected abstract withPadding(title: string, description: string[] | readonly string[], date: Date, content: string[]): string[]; diff --git a/Build/lib/writing-strategy/clash.ts b/Build/lib/writing-strategy/clash.ts index 9456d95f..2f5373d5 100644 --- a/Build/lib/writing-strategy/clash.ts +++ b/Build/lib/writing-strategy/clash.ts @@ -41,6 +41,7 @@ export class ClashDomainSet extends BaseWriteStrategy { writeSourceIpCidrs = noop; writeSourcePorts = noop; writeDestinationPorts = noop; + writeProtocols = noop; writeOtherRules = noop; } @@ -80,6 +81,7 @@ export class ClashIPSet extends BaseWriteStrategy { writeSourceIpCidrs = notSupported('writeSourceIpCidrs'); writeSourcePorts = notSupported('writeSourcePorts'); writeDestinationPorts = noop; + writeProtocols = noop; writeOtherRules = noop; } @@ -171,5 +173,17 @@ export class ClashClassicRuleSet extends BaseWriteStrategy { appendSetElementsToArray(this.result, port, i => `DST-PORT,${i}`); } + writeProtocols(protocol: Set): void { + // Mihomo only matches UDP/TCP: https://wiki.metacubex.one/en/config/rules/#network + + // protocol has already be normalized and will only contain upppercase + if (protocol.has('UDP')) { + this.result.push('NETWORK,UDP'); + } + if (protocol.has('TCP')) { + this.result.push('NETWORK,TCP'); + } + } + writeOtherRules = noop; } diff --git a/Build/lib/writing-strategy/singbox.ts b/Build/lib/writing-strategy/singbox.ts index b6296f40..da79c195 100644 --- a/Build/lib/writing-strategy/singbox.ts +++ b/Build/lib/writing-strategy/singbox.ts @@ -17,7 +17,8 @@ interface SingboxHeadlessRule { port?: number[], port_range?: string[], process_name?: string[], - process_path?: string[] + process_path?: string[], + network?: string[] } export interface SingboxSourceFormat { @@ -154,5 +155,16 @@ export class SingboxSource extends BaseWriteStrategy { } } + writeProtocols(protocol: Set): void { + this.singbox.network ??= []; + // protocol has already be normalized and will only be uppercase + if (protocol.has('UDP')) { + this.singbox.network.push('udp'); + } + if (protocol.has('TCP')) { + this.singbox.network.push('tcp'); + } + } + writeOtherRules = noop; } diff --git a/Build/lib/writing-strategy/surge.ts b/Build/lib/writing-strategy/surge.ts index a19c629c..1f6f765b 100644 --- a/Build/lib/writing-strategy/surge.ts +++ b/Build/lib/writing-strategy/surge.ts @@ -44,6 +44,7 @@ export class SurgeDomainSet extends BaseWriteStrategy { writeSourceIpCidrs = noop; writeSourcePorts = noop; writeDestinationPorts = noop; + writeProtocols = noop; writeOtherRules = noop; } @@ -130,6 +131,10 @@ export class SurgeRuleSet extends BaseWriteStrategy { appendSetElementsToArray(this.result, port, i => `DEST-PORT,${i}`); } + writeProtocols(protocol: Set): void { + appendSetElementsToArray(this.result, protocol, i => `PROTOCOL,${i}`); + } + writeOtherRules(rule: string[]): void { appendArrayInPlace(this.result, rule); } @@ -268,5 +273,6 @@ export class SurgeMitmSgmodule extends BaseWriteStrategy { writeSourceIpCidrs = noop; writeSourcePorts = noop; writeDestinationPorts = noop; + writeProtocols = noop; writeOtherRules = noop; }