Add domain checking and pattern matching

This commit is contained in:
iBug 2020-07-27 03:00:37 +08:00
parent 12304fe245
commit cf08e0d840
2 changed files with 66 additions and 3 deletions

View File

@ -6,6 +6,8 @@ import ipaddress
import requests
from requests.exceptions import RequestException, HTTPError
import gfwlist
SOURCES = {
'ipdeny.com': 'http://www.ipdeny.com/ipblocks/data/aggregated/cn-aggregated.zone',
@ -13,6 +15,9 @@ SOURCES = {
}
OUT_DIR = "dist"
# Stub content to disable GFWList check
GFWLIST_STUB = "var DOMAINS = {};\nvar BLACKPAT = [];\nvar WHITEPAT = [];\n"
def fetch_and_convert(src):
response = requests.get(src)
@ -36,6 +41,9 @@ def main():
code = f.read()
code = code.replace("@@TIME@@", now.isoformat()[:-7])
gfwlist_part = gfwlist.generate_pac_partial()
gfwlist_stub = GFWLIST_STUB
os.makedirs(OUT_DIR, mode=0o755, exist_ok=True)
for key in SOURCES:
print(f"Generating PAC script from source {key}")
@ -45,10 +53,19 @@ def main():
continue
except HTTPError:
continue
filename = f"pac-{key}.txt"
filename_gfwlist = f"pac-gfwlist-{key}.txt"
with open(os.path.join(OUT_DIR, filename), "w") as f:
f.write(code)
f.write(data)
f.write("\n")
f.write(gfwlist_stub)
with open(os.path.join(OUT_DIR, filename), "w") as f:
f.write(code)
f.write(data)
f.write("\n")
f.write(gfwlist_part)
if __name__ == '__main__':

52
code.js
View File

@ -1,6 +1,9 @@
// Author: iBug <ibugone.com>
// Time: @@TIME@@
var proxy = __PROXY__;
var direct = "DIRECT";
function belongsToSubnet(host, list) {
var ip = host.split(".").map(Number);
ip = 0x1000000 * ip[0] + 0x10000 * ip[1] + 0x100 * ip[2] + ip[3];
@ -23,6 +26,38 @@ function belongsToSubnet(host, list) {
return (masked ^ list[x][0]) == 0;
}
function hasMatchedPattern(text, patterns) {
for (var i = 0; i < patterns.length; i++) {
if (shExpMatch(text, patterns[i])
return true;
}
return false;
}
function checkDomainType(host) {
// Check if a domain is blacklisted or whitelisted
var segments = host.split(".").reverse();
var ptr = DOMAINS;
var type = DOMAINS["@"];
for (var i = 0; i < segments.length; i++) {
var segment = segments[i];
ptr = ptr[segment];
if (ptr === undefined)
break;
if (ptr["@"] !== undefined)
type = ptr["@"];
}
return type;
}
function hasWhitelistedPattern(url) {
return hasMatchedPattern(url, WHITEPAT);
}
function hasBlacklistedPattern(url) {
return hasMatchedPattern(url, BLACKPAT);
}
function isChina(host) {
return belongsToSubnet(host, CHINA);
}
@ -31,10 +66,21 @@ function isLan(host) {
return belongsToSubnet(host, LAN);
}
var proxy = "__PROXY__";
var direct = "DIRECT";
function FindProxyForURL(url, host) {
if (hasWhitelistedPattern(url)) {
return direct;
}
if (hasBlacklistedPattern(url)) {
return proxy;
}
var domainType = checkDomainType(host);
if (domainType === 0) {
return proxy;
} else if (domainType === 1) {
return direct;
}
// Fallback to IP whitelist
var remote = dnsResolve(host);
if (!remote || remote.indexOf(":") !== -1) {
// resolution failed or is IPv6 addr