Skip to content

Commit

Permalink
[routing] Add custom blocking & bypass sites routing rules
Browse files Browse the repository at this point in the history
There are conditions the site not matches the rules from the ready-up ruleSets, or we need different behaviour. We can add via custom blocking & bypass routing rules now.

NOTE: DNS rule not handled.
  • Loading branch information
dexfire committed Oct 27, 2024
1 parent b0a7c3e commit f3adeee
Showing 1 changed file with 84 additions and 21 deletions.
105 changes: 84 additions & 21 deletions src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,8 @@ async function updateDataset (env, newSettings, resetSettings) {
customCdnHost: validateField('customCdnHost')?.trim() ?? currentSettings?.customCdnHost ?? '',
customCdnSni: validateField('customCdnSni')?.trim() ?? currentSettings?.customCdnSni ?? '',
bestVLESSTrojanInterval: validateField('bestVLESSTrojanInterval') ?? currentSettings?.bestVLESSTrojanInterval ?? '30',
customRuleBlockSites: validateField("customRuleBlockSites")?.trim() ?? currentSettings?.customRuleBlockSites ?? "",
customRuleBypassSites: validateField("customRuleBypassSites")?.trim() ?? currentSettings?.customRuleBypassSites ?? "",
vlessConfigs: validateField('vlessConfigs') ?? currentSettings?.vlessConfigs ?? true,
trojanConfigs: validateField('trojanConfigs') ?? currentSettings?.trojanConfigs ?? false,
ports: validateField('ports')?.split(',') ?? currentSettings?.ports ?? ['443'],
Expand Down Expand Up @@ -1373,6 +1375,8 @@ function renderHomePage (request, proxySettings, hostName, isPassSet) {
customCdnHost,
customCdnSni,
bestVLESSTrojanInterval,
customRuleBlockSites,
customRuleBypassSites,
vlessConfigs,
trojanConfigs,
ports,
Expand Down Expand Up @@ -1791,6 +1795,14 @@ function renderHomePage (request, proxySettings, hostName, isPassSet) {
<label for="bestVLESSTrojanInterval">🔄 Best Interval</label>
<input type="number" id="bestVLESSTrojanInterval" name="bestVLESSTrojanInterval" min="10" max="90" value="${bestVLESSTrojanInterval}">
</div>
<div class="form-control">
<label for="customRuleBlockSites">🟠 Custom Rules: Block Sites</label>
<input type="text" id="customRuleBlockSites" name="customRuleBlockSites" value="${customRuleBlockSites}">
</div>
<div class="form-control">
<label for="customRuleBypassSites">🟢 Custom Rules: Bypass Sites</label>
<input type="text" id="customRuleBypassSites" name="customRuleBypassSites" value="${customRuleBypassSites}">
</div>
<div class="form-control" style="padding-top: 10px;">
<label for="vlessConfigs">⚙️ Protocols</label>
<div style="width: 100%; display: grid; grid-template-columns: 1fr 1fr; align-items: baseline; margin-top: 10px;">
Expand Down Expand Up @@ -2694,6 +2706,8 @@ function renderHomePage (request, proxySettings, hostName, isPassSet) {
const customCdnHost = document.getElementById('customCdnHost').value;
const customCdnSni = document.getElementById('customCdnSni').value;
const isCustomCdn = customCdnAddrs.length > 0 || customCdnHost !== '' || customCdnSni !== '';
const customRuleBlockSites = document.getElementById('customRuleBlockSites').value?.split(',').filter(addr => addr !== '');
const customRuleBypassSites = document.getElementById('customRuleBypassSites').value?.split(',').filter(addr => addr !== '');
const warpEndpoints = document.getElementById('warpEndpoints').value?.replaceAll(' ', '').split(',');
const noiseCountMin = getValue('noiseCountMin');
const noiseCountMax = getValue('noiseCountMax');
Expand Down Expand Up @@ -3290,7 +3304,9 @@ function buildXrayRoutingRules (proxySettings, outboundAddrs, isChain, isBalance
bypassRussia,
blockAds,
blockPorn,
blockUDP443
blockUDP443,
customRuleBlockSites,
customRuleBypassSites
} = proxySettings;

const isBlock = blockAds || blockPorn;
Expand Down Expand Up @@ -3331,33 +3347,51 @@ function buildXrayRoutingRules (proxySettings, outboundAddrs, isChain, isBalance
type: "field"
});

if (isBypass || isBlock) {
if (isBypass || isBlock || customRuleBlockSites || customRuleBypassSites) {
const createRule = (type, outbound) => ({
[type]: [],
outboundTag: outbound,
type: "field"
});

let geositeDirectRule, geoipDirectRule;
if (!isWorkerLess) {
geositeDirectRule = createRule("domain", "direct");
geoipDirectRule = createRule("ip", "direct");
if (customRuleBlockSites) {
let customSiteBlockRule = createRule("domain", "block");
customRuleBlockSites.split(",").forEach(
domainName => customSiteBlockRule.domain.push(domainName.trim())
);
rules.push(customSiteBlockRule);
}

let geositeBlockRule = createRule("domain", "block");
geoRules.forEach(({ rule, type, domain, ip }) => {
if (rule) {
if (type === 'direct') {
geositeDirectRule?.domain.push(domain);
geoipDirectRule?.ip?.push(ip);
} else {
geositeBlockRule.domain.push(domain);
}
if (customRuleBypassSites) {
let customSiteBypassRule = createRule("domain", "direct");
customRuleBypassSites.split(",").forEach(
domainName => customSiteBypassRule.domain.push(domainName.trim())
);
rules.push(customSiteBypassRule);
}

if (isBypass || isBlock) {
let geositeDirectRule, geoipDirectRule;
if (!isWorkerLess) {
geositeDirectRule = createRule("domain", "direct");
geoipDirectRule = createRule("ip", "direct");
}
});

!isWorkerLess && isBypass && rules.push(geositeDirectRule, geoipDirectRule);
isBlock && rules.push(geositeBlockRule);

let geositeBlockRule = createRule("domain", "block");
geoRules.forEach(({ rule, type, domain, ip }) => {
if (rule) {
if (type === 'direct') {
geositeDirectRule?.domain.push(domain);
geoipDirectRule?.ip?.push(ip);
} else {
geositeBlockRule.domain.push(domain);
}
}
});

!isWorkerLess && isBypass && rules.push(geositeDirectRule, geoipDirectRule);
isBlock && rules.push(geositeBlockRule);
}
}

blockUDP443 && rules.push({
Expand Down Expand Up @@ -4007,11 +4041,26 @@ function buildClashRoutingRules (proxySettings) {
bypassRussia,
blockAds,
blockPorn,
blockUDP443
blockUDP443,
customRuleBlockSites,
customRuleBypassSites
} = proxySettings;

const isBypass = bypassIran || bypassChina || bypassLAN || bypassRussia;
const isBlock = blockAds || blockPorn;

let customSiteBlockRules = [], customSiteBypassRules = [];
if (customRuleBlockSites) {
customRuleBlockSites.split(",").forEach(
domainName => customSiteBlockRules.push(`DOMAIN-SUFFIX,${domainName},REJECT`)
);
}
if (customRuleBypassSites) {
customRuleBypassSites.split(",").forEach(
domainName => customSiteBypassRules.push(`DOMAIN-SUFFIX,${domainName},DIRECT`)
);
}

let geositeDirectRules = [], geoipDirectRules = [], geositeBlockRules = [];
const geoRules = [
{ rule: bypassLAN, type: 'direct', geosite: "private", geoip: "private" },
Expand All @@ -4038,6 +4087,8 @@ function buildClashRoutingRules (proxySettings) {

let rules = [
`AND,((IP-CIDR,${localDNS}/32),(DST-PORT,53)),DIRECT`,
...customSiteBlockRules,
...customSiteBypassRules,
...geositeDirectRules,
...geoipDirectRules,
...geositeBlockRules
Expand Down Expand Up @@ -4478,7 +4529,9 @@ function buildSingBoxRoutingRules (proxySettings) {
bypassRussia,
blockAds,
blockPorn,
blockUDP443
blockUDP443,
customRuleBlockSites,
customRuleBypassSites
} = proxySettings;

const isBypass = bypassIran || bypassChina || bypassRussia;
Expand Down Expand Up @@ -4588,6 +4641,16 @@ function buildSingBoxRoutingRules (proxySettings) {
outbound: "direct"
});

customRuleBlockSites &&rules.push({
domain_suffix: customRuleBlockSites.split(',').trim(),
outbound: "block"
});

customRuleBypassSites && rules.push({
domain_suffix: customRuleBypassSites.split(',').trim(),
outbound: "direct"
});

const createRule = (outbound) => ({
rule_set: [],
outbound
Expand Down

0 comments on commit f3adeee

Please sign in to comment.