mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-12 01:00:34 +08:00
Refactor: simplify build infra
This commit is contained in:
parent
8519b216cd
commit
9eda90e85b
@ -5,13 +5,16 @@ import { parseFelixDnsmasq } from './lib/parse-dnsmasq';
|
|||||||
import { task, traceAsync } from './lib/trace-runner';
|
import { task, traceAsync } from './lib/trace-runner';
|
||||||
import { SHARED_DESCRIPTION } from './lib/constants';
|
import { SHARED_DESCRIPTION } from './lib/constants';
|
||||||
import picocolors from 'picocolors';
|
import picocolors from 'picocolors';
|
||||||
|
import { createMemoizedPromise } from './lib/memo-promise';
|
||||||
|
|
||||||
|
export const getAppleCdnDomainsPromise = createMemoizedPromise(() => traceAsync(
|
||||||
|
picocolors.gray('download dnsmasq-china-list apple.china.conf'),
|
||||||
|
() => parseFelixDnsmasq('https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/apple.china.conf'),
|
||||||
|
picocolors.gray
|
||||||
|
));
|
||||||
|
|
||||||
export const buildAppleCdn = task(import.meta.path, async () => {
|
export const buildAppleCdn = task(import.meta.path, async () => {
|
||||||
const res = await traceAsync(
|
const res = await getAppleCdnDomainsPromise();
|
||||||
picocolors.gray('download dnsmasq-china-list apple.china.conf'),
|
|
||||||
() => parseFelixDnsmasq('https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/apple.china.conf'),
|
|
||||||
picocolors.gray
|
|
||||||
);
|
|
||||||
|
|
||||||
const description = [
|
const description = [
|
||||||
...SHARED_DESCRIPTION,
|
...SHARED_DESCRIPTION,
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { task, traceAsync, traceSync } from './lib/trace-runner';
|
|||||||
|
|
||||||
import { exclude } from 'fast-cidr-tools';
|
import { exclude } from 'fast-cidr-tools';
|
||||||
import picocolors from 'picocolors';
|
import picocolors from 'picocolors';
|
||||||
|
import { createMemoizedPromise } from './lib/memo-promise';
|
||||||
|
|
||||||
// https://github.com/misakaio/chnroutes2/issues/25
|
// https://github.com/misakaio/chnroutes2/issues/25
|
||||||
const EXCLUDE_CIDRS = [
|
const EXCLUDE_CIDRS = [
|
||||||
@ -17,17 +18,21 @@ const INCLUDE_CIDRS = [
|
|||||||
'211.99.96.0/19' // wy.com.cn
|
'211.99.96.0/19' // wy.com.cn
|
||||||
];
|
];
|
||||||
|
|
||||||
export const buildChnCidr = task(import.meta.path, async () => {
|
export const getChnCidrPromise = createMemoizedPromise(async () => {
|
||||||
const cidr = await traceAsync(
|
const cidr = await traceAsync(
|
||||||
picocolors.gray('download chnroutes2'),
|
picocolors.gray('download chnroutes2'),
|
||||||
async () => processLineFromReadline(await fetchRemoteTextAndReadByLine('https://raw.githubusercontent.com/misakaio/chnroutes2/master/chnroutes.txt')),
|
async () => processLineFromReadline(await fetchRemoteTextAndReadByLine('https://raw.githubusercontent.com/misakaio/chnroutes2/master/chnroutes.txt')),
|
||||||
picocolors.gray
|
picocolors.gray
|
||||||
);
|
);
|
||||||
const filteredCidr = traceSync(
|
return traceSync(
|
||||||
picocolors.gray('processing chnroutes2'),
|
picocolors.gray('processing chnroutes2'),
|
||||||
() => exclude([...cidr, ...INCLUDE_CIDRS], EXCLUDE_CIDRS, true),
|
() => exclude([...cidr, ...INCLUDE_CIDRS], EXCLUDE_CIDRS, true),
|
||||||
picocolors.gray
|
picocolors.gray
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const buildChnCidr = task(import.meta.path, async () => {
|
||||||
|
const filteredCidr = await getChnCidrPromise();
|
||||||
|
|
||||||
// Can not use SHARED_DESCRIPTION here as different license
|
// Can not use SHARED_DESCRIPTION here as different license
|
||||||
const description = [
|
const description = [
|
||||||
|
|||||||
@ -6,8 +6,9 @@ import { processLineFromReadline } from './lib/process-line';
|
|||||||
import { compareAndWriteFile, createRuleset } from './lib/create-file';
|
import { compareAndWriteFile, createRuleset } from './lib/create-file';
|
||||||
import { task } from './lib/trace-runner';
|
import { task } from './lib/trace-runner';
|
||||||
import { SHARED_DESCRIPTION } from './lib/constants';
|
import { SHARED_DESCRIPTION } from './lib/constants';
|
||||||
|
import { createMemoizedPromise } from './lib/memo-promise';
|
||||||
|
|
||||||
export const buildDomesticRuleset = task(import.meta.path, async () => {
|
export const getDomesticDomainsRulesetPromise = createMemoizedPromise(async () => {
|
||||||
const results = await processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/domestic.conf')));
|
const results = await processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/domestic.conf')));
|
||||||
|
|
||||||
results.push(
|
results.push(
|
||||||
@ -17,6 +18,10 @@ export const buildDomesticRuleset = task(import.meta.path, async () => {
|
|||||||
}, []).map((domain) => `DOMAIN-SUFFIX,${domain}`)
|
}, []).map((domain) => `DOMAIN-SUFFIX,${domain}`)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return results;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const buildDomesticRuleset = task(import.meta.path, async () => {
|
||||||
const rulesetDescription = [
|
const rulesetDescription = [
|
||||||
...SHARED_DESCRIPTION,
|
...SHARED_DESCRIPTION,
|
||||||
'',
|
'',
|
||||||
@ -28,7 +33,7 @@ export const buildDomesticRuleset = task(import.meta.path, async () => {
|
|||||||
'Sukka\'s Ruleset - Domestic Domains',
|
'Sukka\'s Ruleset - Domestic Domains',
|
||||||
rulesetDescription,
|
rulesetDescription,
|
||||||
new Date(),
|
new Date(),
|
||||||
results,
|
await getDomesticDomainsRulesetPromise(),
|
||||||
'ruleset',
|
'ruleset',
|
||||||
path.resolve(import.meta.dir, '../List/non_ip/domestic.conf'),
|
path.resolve(import.meta.dir, '../List/non_ip/domestic.conf'),
|
||||||
path.resolve(import.meta.dir, '../Clash/non_ip/domestic.txt')
|
path.resolve(import.meta.dir, '../Clash/non_ip/domestic.txt')
|
||||||
|
|||||||
184
Build/build-sspanel-appprofile.ts
Normal file
184
Build/build-sspanel-appprofile.ts
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import fsp from 'fs/promises';
|
||||||
|
|
||||||
|
import { getAppleCdnDomainsPromise } from './build-apple-cdn';
|
||||||
|
import { getDomesticDomainsRulesetPromise } from './build-domestic-ruleset';
|
||||||
|
import { surgeRulesetToClashClassicalTextRuleset } from './lib/clash';
|
||||||
|
import { readFileByLine } from './lib/fetch-text-by-line';
|
||||||
|
import { processLineFromReadline } from './lib/process-line';
|
||||||
|
import { task } from './lib/trace-runner';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
import { ALL as AllStreamServices } from '../Source/stream';
|
||||||
|
import { getChnCidrPromise } from './build-chn-cidr';
|
||||||
|
import { getTelegramCIDRPromise } from './build-telegram-cidr';
|
||||||
|
import { compareAndWriteFile } from './lib/create-file';
|
||||||
|
|
||||||
|
const POLICY_GROUPS: Array<[name: string, insertProxy: boolean, insertDirect: boolean]> = [
|
||||||
|
['Default Proxy', true, false],
|
||||||
|
['Global', true, true],
|
||||||
|
['Microsoft & Apple', true, true],
|
||||||
|
['Stream', true, false],
|
||||||
|
['Domestic', false, true],
|
||||||
|
['Final Match', true, true]
|
||||||
|
];
|
||||||
|
|
||||||
|
const removeNoResolved = (line: string) => line.replace(',no-resolve', '');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This only generates a simplified version, for under-used users only.
|
||||||
|
*/
|
||||||
|
export const buildSSPanelUIMAppProfile = task(import.meta.path, async () => {
|
||||||
|
const [
|
||||||
|
domesticDomains,
|
||||||
|
appleCdnDomains,
|
||||||
|
appleCnDomains,
|
||||||
|
neteaseMusicDomains,
|
||||||
|
microsoftDomains,
|
||||||
|
appleDomains,
|
||||||
|
streamDomains,
|
||||||
|
globalDomains,
|
||||||
|
globalPlusDomains,
|
||||||
|
telegramDomains,
|
||||||
|
domesticCidrs,
|
||||||
|
streamCidrs,
|
||||||
|
{ results: rawTelegramCidrs }
|
||||||
|
] = await Promise.all([
|
||||||
|
// domestic - domains
|
||||||
|
getDomesticDomainsRulesetPromise().then(surgeRulesetToClashClassicalTextRuleset),
|
||||||
|
getAppleCdnDomainsPromise().then(domains => domains.map(domain => `DOMAIN-SUFFIX,${domain}`)),
|
||||||
|
processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/apple_cn.conf'))),
|
||||||
|
processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/neteasemusic.conf'))).then(surgeRulesetToClashClassicalTextRuleset),
|
||||||
|
// microsoft & apple - domains
|
||||||
|
processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/internal_microsoft.conf'))),
|
||||||
|
(processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/apple_services.conf')))).then(surgeRulesetToClashClassicalTextRuleset),
|
||||||
|
// stream - domains
|
||||||
|
surgeRulesetToClashClassicalTextRuleset(AllStreamServices.flatMap((i) => i.rules)),
|
||||||
|
// global - domains
|
||||||
|
processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/global.conf'))).then(surgeRulesetToClashClassicalTextRuleset),
|
||||||
|
processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/global_plus.conf'))).then(surgeRulesetToClashClassicalTextRuleset),
|
||||||
|
processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/telegram.conf'))).then(surgeRulesetToClashClassicalTextRuleset),
|
||||||
|
// domestic - ip cidr
|
||||||
|
getChnCidrPromise().then(cidrs => cidrs.map(cidr => `IP-CIDR,${cidr}`)),
|
||||||
|
AllStreamServices.flatMap((i) => (
|
||||||
|
i.ip
|
||||||
|
? [
|
||||||
|
...i.ip.v4.map((ip) => `IP-CIDR,${ip}`),
|
||||||
|
...i.ip.v6.map((ip) => `IP-CIDR6,${ip}`)
|
||||||
|
]
|
||||||
|
: []
|
||||||
|
)),
|
||||||
|
// global - ip cidr
|
||||||
|
getTelegramCIDRPromise()
|
||||||
|
] as const);
|
||||||
|
|
||||||
|
const telegramCidrs = rawTelegramCidrs.map(removeNoResolved);
|
||||||
|
|
||||||
|
const output = generateAppProfile(
|
||||||
|
[
|
||||||
|
...domesticDomains,
|
||||||
|
...appleCdnDomains,
|
||||||
|
...appleCnDomains,
|
||||||
|
...neteaseMusicDomains
|
||||||
|
],
|
||||||
|
[
|
||||||
|
...microsoftDomains,
|
||||||
|
...appleDomains
|
||||||
|
],
|
||||||
|
streamDomains,
|
||||||
|
[
|
||||||
|
...globalDomains,
|
||||||
|
...globalPlusDomains,
|
||||||
|
...telegramDomains
|
||||||
|
],
|
||||||
|
domesticCidrs,
|
||||||
|
streamCidrs,
|
||||||
|
[
|
||||||
|
...telegramCidrs
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
await fsp.mkdir(path.resolve(import.meta.dir, '../List/internal'), { recursive: true });
|
||||||
|
|
||||||
|
await compareAndWriteFile(
|
||||||
|
output,
|
||||||
|
path.resolve(import.meta.dir, '../List/internal/appprofile.php')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (import.meta.main) {
|
||||||
|
buildSSPanelUIMAppProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
const isTruthy = <T>(i: T | 0 | '' | false | null | undefined): i is T => !!i;
|
||||||
|
|
||||||
|
function generateAppProfile(
|
||||||
|
directDomains: string[],
|
||||||
|
microsoftAppleDomains: string[],
|
||||||
|
streamDomains: string[],
|
||||||
|
globalDomains: string[],
|
||||||
|
directCidrs: string[],
|
||||||
|
streamCidrs: string[],
|
||||||
|
globalCidrs: string[]
|
||||||
|
) {
|
||||||
|
const result: string[] = [];
|
||||||
|
|
||||||
|
result.push(
|
||||||
|
'<?php',
|
||||||
|
'',
|
||||||
|
'declare(strict_types=1);',
|
||||||
|
'',
|
||||||
|
'$_ENV[\'Clash_Config\'] = [',
|
||||||
|
' \'port\' => 7890,',
|
||||||
|
' \'socks-port\' => 7891,',
|
||||||
|
' \'allow-lan\' => false,',
|
||||||
|
' \'mode\' => \'Rule\',',
|
||||||
|
' \'ipv6\' => true,',
|
||||||
|
' \'log-level\' => \'error\',',
|
||||||
|
' \'external-controller\' => \'0.0.0.0:9090\',',
|
||||||
|
'];',
|
||||||
|
'',
|
||||||
|
`$_ENV['Clash_Group_Indexes'] = [${JSON.stringify(POLICY_GROUPS.reduce<number[]>((acc, [, insertProxy], index) => {
|
||||||
|
if (insertProxy) {
|
||||||
|
acc.push(index);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, [])).slice(1, -1)}];`,
|
||||||
|
'$_ENV[\'Clash_Group_Config\'] = [',
|
||||||
|
' \'proxy-groups\' => [',
|
||||||
|
...POLICY_GROUPS.flatMap(([name, insertProxy, insertDirect]) => {
|
||||||
|
return [
|
||||||
|
' [',
|
||||||
|
` 'name' => '${name}',`,
|
||||||
|
' \'type\' => \'select\',',
|
||||||
|
' \'proxies\' => [',
|
||||||
|
insertProxy && name !== 'Default Proxy' && ' \'Default Proxy\',',
|
||||||
|
insertDirect && ' \'DIRECT\',',
|
||||||
|
' ],',
|
||||||
|
' ],'
|
||||||
|
].filter(isTruthy);
|
||||||
|
}),
|
||||||
|
' ],',
|
||||||
|
' \'rules\' => [',
|
||||||
|
// domestic - domains
|
||||||
|
...directDomains.map(line => ` '${line},Domestic',`),
|
||||||
|
// microsoft & apple - domains
|
||||||
|
...microsoftAppleDomains.map(line => ` '${line},Microsoft & Apple',`),
|
||||||
|
// stream - domains
|
||||||
|
...streamDomains.map(line => ` '${line},Stream',`),
|
||||||
|
// global - domains
|
||||||
|
...globalDomains.map(line => ` '${line},Global',`),
|
||||||
|
// domestic - ip cidr
|
||||||
|
...directCidrs.map(line => ` '${line},Domestic,no-resolve',`),
|
||||||
|
// microsoft & apple - ip cidr (nope)
|
||||||
|
// stream - ip cidr
|
||||||
|
...streamCidrs.map(line => ` '${line},Stream,no-resolve',`),
|
||||||
|
// global - ip cidr
|
||||||
|
...globalCidrs.map(line => ` '${line},Global,no-resolve',`),
|
||||||
|
// match
|
||||||
|
' \'MATCH,Final Match\',',
|
||||||
|
' ],',
|
||||||
|
'];'
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@ -7,7 +7,7 @@ import { createRuleset } from './lib/create-file';
|
|||||||
import { ALL, NORTH_AMERICA, EU, HK, TW, JP, KR } from '../Source/stream';
|
import { ALL, NORTH_AMERICA, EU, HK, TW, JP, KR } from '../Source/stream';
|
||||||
import { SHARED_DESCRIPTION } from './lib/constants';
|
import { SHARED_DESCRIPTION } from './lib/constants';
|
||||||
|
|
||||||
const createRulesetForStreamService = (fileId: string, title: string, streamServices: Array<import('../Source/stream').StreamService>) => {
|
export const createRulesetForStreamService = (fileId: string, title: string, streamServices: Array<import('../Source/stream').StreamService>) => {
|
||||||
return [
|
return [
|
||||||
// Domains
|
// Domains
|
||||||
...createRuleset(
|
...createRuleset(
|
||||||
|
|||||||
@ -7,8 +7,9 @@ import { processLine } from './lib/process-line';
|
|||||||
import { createRuleset } from './lib/create-file';
|
import { createRuleset } from './lib/create-file';
|
||||||
import { task } from './lib/trace-runner';
|
import { task } from './lib/trace-runner';
|
||||||
import { SHARED_DESCRIPTION } from './lib/constants';
|
import { SHARED_DESCRIPTION } from './lib/constants';
|
||||||
|
import { createMemoizedPromise } from './lib/memo-promise';
|
||||||
|
|
||||||
export const buildTelegramCIDR = task(import.meta.path, async () => {
|
export const getTelegramCIDRPromise = createMemoizedPromise(async () => {
|
||||||
const resp = await fetchWithRetry('https://core.telegram.org/resources/cidr.txt', defaultRequestInit) as Response;
|
const resp = await fetchWithRetry('https://core.telegram.org/resources/cidr.txt', defaultRequestInit) as Response;
|
||||||
const lastModified = resp.headers.get('last-modified');
|
const lastModified = resp.headers.get('last-modified');
|
||||||
const date = lastModified ? new Date(lastModified) : new Date();
|
const date = lastModified ? new Date(lastModified) : new Date();
|
||||||
@ -28,6 +29,12 @@ export const buildTelegramCIDR = task(import.meta.path, async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return { date, results };
|
||||||
|
});
|
||||||
|
|
||||||
|
export const buildTelegramCIDR = task(import.meta.path, async () => {
|
||||||
|
const { date, results } = await getTelegramCIDRPromise();
|
||||||
|
|
||||||
if (results.length === 0) {
|
if (results.length === 0) {
|
||||||
throw new Error('Failed to fetch data!');
|
throw new Error('Failed to fetch data!');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,8 @@ import { buildStreamService } from './build-stream-service';
|
|||||||
import { buildRedirectModule } from './build-redirect-module';
|
import { buildRedirectModule } from './build-redirect-module';
|
||||||
import { validate } from './validate-domainset';
|
import { validate } from './validate-domainset';
|
||||||
|
|
||||||
|
import { buildSSPanelUIMAppProfile } from './build-sspanel-appprofile';
|
||||||
|
|
||||||
import { buildPublic } from './build-public';
|
import { buildPublic } from './build-public';
|
||||||
// import type { TaskResult } from './lib/trace-runner';
|
// import type { TaskResult } from './lib/trace-runner';
|
||||||
|
|
||||||
@ -64,6 +66,10 @@ import { buildPublic } from './build-public';
|
|||||||
const buildRedirectModulePromise = downloadPreviousBuildPromise.then(() => buildRedirectModule());
|
const buildRedirectModulePromise = downloadPreviousBuildPromise.then(() => buildRedirectModule());
|
||||||
const buildStreamServicePromise = downloadPreviousBuildPromise.then(() => buildStreamService());
|
const buildStreamServicePromise = downloadPreviousBuildPromise.then(() => buildStreamService());
|
||||||
|
|
||||||
|
const buildSSPanelUIMAppProfilePromise = Promise.all([
|
||||||
|
downloadPreviousBuildPromise
|
||||||
|
]).then(() => buildSSPanelUIMAppProfile());
|
||||||
|
|
||||||
const stats = await Promise.all([
|
const stats = await Promise.all([
|
||||||
downloadPreviousBuildPromise,
|
downloadPreviousBuildPromise,
|
||||||
downloadPublicSuffixListPromise,
|
downloadPublicSuffixListPromise,
|
||||||
@ -80,7 +86,8 @@ import { buildPublic } from './build-public';
|
|||||||
// buildInternalChnDomainsPromise,
|
// buildInternalChnDomainsPromise,
|
||||||
buildDomesticRulesetPromise,
|
buildDomesticRulesetPromise,
|
||||||
buildRedirectModulePromise,
|
buildRedirectModulePromise,
|
||||||
buildStreamServicePromise
|
buildStreamServicePromise,
|
||||||
|
buildSSPanelUIMAppProfilePromise
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
|||||||
7
Build/lib/memo-promise.ts
Normal file
7
Build/lib/memo-promise.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export const createMemoizedPromise = <T>(fn: () => Promise<T>): () => Promise<T> => {
|
||||||
|
let promise: Promise<T> | null = null;
|
||||||
|
return () => {
|
||||||
|
promise ||= fn();
|
||||||
|
return promise;
|
||||||
|
};
|
||||||
|
};
|
||||||
76
Source/non_ip/internal_microsoft.conf
Normal file
76
Source/non_ip/internal_microsoft.conf
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# $ custom_build_script
|
||||||
|
|
||||||
|
DOMAIN,officecdn-microsoft-com.akamaized.net
|
||||||
|
DOMAIN-SUFFIX,aadrm.com
|
||||||
|
DOMAIN-SUFFIX,acompli.com
|
||||||
|
DOMAIN-SUFFIX,acompli.net
|
||||||
|
DOMAIN-SUFFIX,aka.ms
|
||||||
|
DOMAIN-SUFFIX,akadns.net
|
||||||
|
DOMAIN-SUFFIX,aspnetcdn.com
|
||||||
|
DOMAIN-SUFFIX,assets-yammer.com
|
||||||
|
DOMAIN-SUFFIX,azure.com
|
||||||
|
DOMAIN-SUFFIX,azure.net
|
||||||
|
DOMAIN-SUFFIX,azureedge.net
|
||||||
|
DOMAIN-SUFFIX,azurerms.com
|
||||||
|
DOMAIN-SUFFIX,bing.com
|
||||||
|
DOMAIN-SUFFIX,cloudapp.net
|
||||||
|
DOMAIN-SUFFIX,cloudappsecurity.com
|
||||||
|
DOMAIN-SUFFIX,edgesuite.net
|
||||||
|
DOMAIN-SUFFIX,gfx.ms
|
||||||
|
DOMAIN-SUFFIX,hotmail.com
|
||||||
|
DOMAIN-SUFFIX,live.com
|
||||||
|
DOMAIN-SUFFIX,live.net
|
||||||
|
DOMAIN-SUFFIX,lync.com
|
||||||
|
DOMAIN-SUFFIX,msappproxy.net
|
||||||
|
DOMAIN-SUFFIX,msauth.net
|
||||||
|
DOMAIN-SUFFIX,msauthimages.net
|
||||||
|
DOMAIN-SUFFIX,msecnd.net
|
||||||
|
DOMAIN-SUFFIX,msedge.net
|
||||||
|
DOMAIN-SUFFIX,msft.net
|
||||||
|
DOMAIN-SUFFIX,msftauth.net
|
||||||
|
DOMAIN-SUFFIX,msftauthimages.net
|
||||||
|
DOMAIN-SUFFIX,msftidentity.com
|
||||||
|
DOMAIN-SUFFIX,msidentity.com
|
||||||
|
DOMAIN-SUFFIX,msn.com
|
||||||
|
DOMAIN-SUFFIX,msocdn.com
|
||||||
|
DOMAIN-SUFFIX,msocsp.com
|
||||||
|
DOMAIN-SUFFIX,mstea.ms
|
||||||
|
DOMAIN-SUFFIX,o365weve.com
|
||||||
|
DOMAIN-SUFFIX,oaspapps.com
|
||||||
|
DOMAIN-SUFFIX,office.com
|
||||||
|
DOMAIN-SUFFIX,office.net
|
||||||
|
DOMAIN-SUFFIX,office365.com
|
||||||
|
DOMAIN-SUFFIX,officeppe.net
|
||||||
|
DOMAIN-SUFFIX,omniroot.com
|
||||||
|
DOMAIN-SUFFIX,onedrive.com
|
||||||
|
DOMAIN-SUFFIX,onenote.com
|
||||||
|
DOMAIN-SUFFIX,onenote.net
|
||||||
|
DOMAIN-SUFFIX,onestore.ms
|
||||||
|
DOMAIN-SUFFIX,outlook.com
|
||||||
|
DOMAIN-SUFFIX,outlookmobile.com
|
||||||
|
DOMAIN-SUFFIX,phonefactor.net
|
||||||
|
DOMAIN-SUFFIX,public-trust.com
|
||||||
|
DOMAIN-SUFFIX,sfbassets.com
|
||||||
|
DOMAIN-SUFFIX,sfx.ms
|
||||||
|
DOMAIN-SUFFIX,sharepoint.com
|
||||||
|
DOMAIN-SUFFIX,sharepointonline.com
|
||||||
|
DOMAIN-SUFFIX,skype.com
|
||||||
|
DOMAIN-SUFFIX,skypeassets.com
|
||||||
|
DOMAIN-SUFFIX,skypeforbusiness.com
|
||||||
|
DOMAIN-SUFFIX,staffhub.ms
|
||||||
|
DOMAIN-SUFFIX,svc.ms
|
||||||
|
DOMAIN-SUFFIX,sway-cdn.com
|
||||||
|
DOMAIN-SUFFIX,sway-extensions.com
|
||||||
|
DOMAIN-SUFFIX,sway.com
|
||||||
|
DOMAIN-SUFFIX,trafficmanager.net
|
||||||
|
DOMAIN-SUFFIX,uservoice.com
|
||||||
|
DOMAIN-SUFFIX,virtualearth.net
|
||||||
|
DOMAIN-SUFFIX,visualstudio.com
|
||||||
|
DOMAIN-SUFFIX,windows-ppe.net
|
||||||
|
DOMAIN-SUFFIX,windows.com
|
||||||
|
DOMAIN-SUFFIX,windows.net
|
||||||
|
DOMAIN-SUFFIX,windowsazure.com
|
||||||
|
DOMAIN-SUFFIX,windowsupdate.com
|
||||||
|
DOMAIN-SUFFIX,wunderlist.com
|
||||||
|
DOMAIN-SUFFIX,yammer.com
|
||||||
|
DOMAIN-SUFFIX,yammerusercontent.com
|
||||||
Loading…
x
Reference in New Issue
Block a user