From 44848fb670ade6a20bbd8896d5ce3e669583c767 Mon Sep 17 00:00:00 2001 From: wits-fe <58023436+wits-fe@users.noreply.github.com> Date: Thu, 27 Apr 2023 02:54:44 +0800 Subject: [PATCH 1/7] add ipv6 support --- build.py | 96 ++++++++++++++++++++++++++++++++++++- code.js | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 234 insertions(+), 5 deletions(-) diff --git a/build.py b/build.py index 802d7a3..07e71dc 100755 --- a/build.py +++ b/build.py @@ -13,6 +13,9 @@ 'ipdeny.com': 'http://www.ipdeny.com/ipblocks/data/aggregated/cn-aggregated.zone', '17mon': 'https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt', } +SOURCES2 = { + 'gaoyifan': 'https://gaoyifan.github.io/china-operator-ip/china6.txt', +} OUT_DIR = "dist" # Stub content to disable GFWList check @@ -34,6 +37,89 @@ def fetch_and_convert(src): return template.format("\n".join(lines)) +def fetch_and_convert_ip6(src): + response = requests.get(src) + response.raise_for_status() + text = response.text + + template = "var CHINA6_F = [\n{}\n];\n\n" + template2 = "var CHINA6_S = [\n{}\n];\n" + lines = [] + lines2 = [] + lastnum = 0 + count = 0 + begins = False + ends = False + lower = 0 + upper = 0 + networkstr_b = "" + iprangestr_b = "" + fixlen = len(f" [0xFFFFFFFF, -1, 0xFFFFFFFF],") + + for iprange in text.strip().split("\n"): + ipnet = ipaddress.IPv6Network(iprange) + prefixlen = ipnet.prefixlen + fulladdr = str(ipnet.exploded).replace(':', '') + num1 = int(fulladdr[0:8], 16) + num2 = int(fulladdr[8:16], 16) + fullmask = f"{ipnet.netmask:X}" + mask1 = fullmask[0:8] + mask2 = fullmask[8:16] + + if lastnum != num1 and begins: + ends = True + + if ends: + begins = False + ends = False + upper = count - 1 + s2 = networkstr_b + if upper == lower: + s2 = iprangestr_b + s = f" [0x{lastnum:08X}, {lower}, {upper}]," + len1 = len(s) + if len1 < fixlen: + s = s + " " * (fixlen - len1) + s = f"{s} // {s2}" + lines.append(s) + + if prefixlen <= 32: + if begins: + raise NameError(f"Invalid list order: \n{iprange}") + s = f" [0x{num1:08X}, -1, 0x{mask1}], // {iprange}" + lines.append(s) + else: + if not begins: + begins = True + lower = count + networkstr_b = str(ipnet.exploded)[0:10] + iprangestr_b = iprange + + s = f" [0x{num2:08X}, 0x{mask2}], // {count}, {iprange}" + lines2.append(s) + count = count + 1 + lastnum = num1 + + if begins: + begins = False + ends = False + upper = count - 1 + s2 = networkstr_b + if upper == lower: + s2 = iprangestr_b + s = f" [0x{lastnum:08X}, {lower}, {upper}]," + len1 = len(s) + if len1 < fixlen: + s = s + " " * (fixlen - len1) + s = f"{s} // {s2}" + lines.append(s) + + lines.append(" [0xFFFFFFFF, -1, 0xFFFFFFFF] // ffff:ffff::/32 placeholder") + lines2.append(f" [0xFFFFFFFF, 0xFFFFFFFF] // {count}, placeholder, not in use") + + return template.format("\n".join(lines)) + template2.format("\n".join(lines2)) + + def main(): now = datetime.utcnow() date = now.strftime("%Y%m%d") @@ -49,22 +135,28 @@ def main(): print(f"Generating PAC script from source {key}") try: data = fetch_and_convert(SOURCES[key]) + key2 = list(SOURCES2)[0] + data2 = fetch_and_convert_ip6(SOURCES2[key2]) except RequestException: continue except HTTPError: continue - filename = f"pac-{key}.txt" - filename_gfwlist = f"pac-gfwlist-{key}.txt" + filename = f"pac-{key}-{key2}.txt" + filename_gfwlist = f"pac-gfwlist-{key}-{key2}.txt" with open(os.path.join(OUT_DIR, filename), "w") as f: f.write(code) f.write(data) f.write("\n") + f.write(data2) + f.write("\n") f.write(gfwlist_stub) with open(os.path.join(OUT_DIR, filename_gfwlist), "w") as f: f.write(code) f.write(data) f.write("\n") + f.write(data2) + f.write("\n") f.write(gfwlist_part) diff --git a/code.js b/code.js index 06c3388..7d3de02 100644 --- a/code.js +++ b/code.js @@ -5,6 +5,102 @@ var proxy = __PROXY__; var direct = "DIRECT"; +// lower: lower_index +// upper: (upper_index + 1) / (array_length if upper_index = last) +function binarySearch(list, num, lower, upper) { + var x = lower, y = upper, middle; + while (y - x > 1) { + middle = Math.floor((x + y) / 2); + if (list[middle][0] > num) + y = middle; + else + x = middle; + } + return x; +} + +function fixLength(text) { + if (text.length == 1) return "000" + text; + if (text.length == 2) return "00" + text; + if (text.length == 3) return "0" + text; + return text; +} + +function convertToInt(high, low) { + if (low.length != 4) + return parseInt(high + fixLength(low), 16); + return parseInt(high + low, 16); +} + +function isLan_Internal6(parts) { + var num = convertToInt(parts[0], parts[1]); + var list = LAN6; + var x = binarySearch(list, num, 0, list.length); + + return ((num & list[x][1]) === list[x][0]); +} + +function isInNet6(parts, list, list2) { + var num = convertToInt(parts[0], parts[1]); + var x = binarySearch(list, num, 0, list.length); + + if (list[x][1] == -1) + return ((num & list[x][2]) === list[x][0]); + + // not in net (/33 - /64) + if (num !== list[x][0]) + return false; + + var num2 = convertToInt(parts[2], parts[3]); + var x2 = binarySearch(list2, num2, list[x][1], list[x][2] + 1); + + return ((num2 & list2[x2][1]) === list2[x2][0]); +} + +function isLanOrChina6(host) { + if (host.indexOf("::") === -1) { + var groups = host.split(":"); + if (groups.length != 8) + return false; // invalid ipv6 format + return isInNet6(groups, CHINA6_F, CHINA6_S) || isInNet6(groups, LAN6_F, LAN6_S); + } + + var halfs = host.split("::"); + var left = halfs[0]; + var right = halfs[1]; + if (left.length < 1) left = "0000"; + if (right.length < 1) right = "0000"; + + var groups1 = left.split(":"); + if (groups1.length > 3) + return isInNet6(groups1, CHINA6_F, CHINA6_S) || isInNet6(groups1, LAN6_F, LAN6_S); + + var groups2 = right.split(":"); + var zeros = 8 - (groups1.length + groups2.length); + if (zeros < 2) + return false; // invalid ipv6 format + + var parts = ["0", "0", "0", "0"]; + parts[0] = groups1[0]; + var i = 1; + for (var j = 1; j < groups1.length; j++) { + parts[i] = groups1[j]; + i = i + 1; + if (i == 4) break; + } + + if (i < 4) { + for (var k = 0; k < zeros; k++) { + parts[i] = "0000"; + i = i + 1; + if (i == 4) break; + } + } + if (i == 3) parts[3] = groups2[0]; + + return isInNet6(parts, CHINA6_F, CHINA6_S) || isInNet6(parts, LAN6_F, LAN6_S); +} + function belongsToSubnet(host, list) { var ip = convert_addr(host) >>> 0; @@ -83,11 +179,34 @@ function FindProxyForURL(url, host) { } // Fallback to IP whitelist - var remote = dnsResolve(host); - if (!remote || remote.indexOf(":") !== -1) { - // resolution failed or is IPv6 addr + + // if host is IPv6 + if (host.indexOf(":") !== -1) { + if (isLanOrChina6(host)) { + return direct; + } return proxy; } + + // default resolve IPv4 + // var remote = dnsResolve(host); + // if (!remote) { + // // resolution failed + // return proxy; + // } + + // method for IPv6 + var ips = dnsResolveEx(host); + if (!ips) + return proxy; + var remote = ips.split(";")[0]; + if (remote.indexOf(":") !== -1) { + if (isLanOrChina6(remote)) { + return direct; + } + return proxy; + } + if (isLan(remote) || isChina(remote)) { return direct; } @@ -104,3 +223,21 @@ var LAN = [ [0xC0A80000, 0xFFFF0000] // 192.168.0.0/16 ]; +// not support /65 - /128 +var LAN6_F = [ + [0x00000000, 0, 0], // ::/64 + [0x0064FF9B, 1, 2], // 64:ff9b: + [0x01000000, 3, 3], // 100::/64 + [0x20010000, -1, 0xFFFFFFFF], // 2001::/32 - teredo, may remove + [0xFC000000, -1, 0xFE000000], // fc00::/7 + [0xFE800000, -1, 0xFFC00000], // fe80::/10 + [0xFF000000, -1, 0xFF000000] // ff00::/8 +]; + +var LAN6_S = [ + [0x00000000, 0xFFFFFFFF], // 0, ::/64 - catch {::, ::1, ::ffff:0:0/96, ::ffff:0:0:0/96}, may remove + [0x00000000, 0xFFFFFFFF], // 1, 64:ff9b::/64 - catch {64:ff9b::/96, NAT64}, may remove + [0x00010000, 0xFFFF0000], // 2, 64:ff9b:1::/48 - NAT64, may remove + [0x00000000, 0xFFFFFFFF] // 3, 100::/64 +]; + From 659711aa0d7cb8bde3ea36afde7d0d49ec39a418 Mon Sep 17 00:00:00 2001 From: wits-fe <58023436+wits-fe@users.noreply.github.com> Date: Thu, 27 Apr 2023 03:14:24 +0800 Subject: [PATCH 2/7] remove unused code --- code.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/code.js b/code.js index 7d3de02..b74ce9a 100644 --- a/code.js +++ b/code.js @@ -32,14 +32,6 @@ function convertToInt(high, low) { return parseInt(high + low, 16); } -function isLan_Internal6(parts) { - var num = convertToInt(parts[0], parts[1]); - var list = LAN6; - var x = binarySearch(list, num, 0, list.length); - - return ((num & list[x][1]) === list[x][0]); -} - function isInNet6(parts, list, list2) { var num = convertToInt(parts[0], parts[1]); var x = binarySearch(list, num, 0, list.length); From b42f8e2ca59a5806abf2a336f4c28e5983a06889 Mon Sep 17 00:00:00 2001 From: wits-fe <58023436+wits-fe@users.noreply.github.com> Date: Thu, 27 Apr 2023 16:10:13 +0800 Subject: [PATCH 3/7] IE11 compatible & bug fix --- code.js | 68 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/code.js b/code.js index b74ce9a..452761b 100644 --- a/code.js +++ b/code.js @@ -19,45 +19,43 @@ function binarySearch(list, num, lower, upper) { return x; } -function fixLength(text) { - if (text.length == 1) return "000" + text; - if (text.length == 2) return "00" + text; - if (text.length == 3) return "0" + text; - return text; -} - -function convertToInt(high, low) { - if (low.length != 4) - return parseInt(high + fixLength(low), 16); - return parseInt(high + low, 16); +function convertToInt6(high, low) { + var num1 = parseInt(high, 16) & 0xFFFF; + var num2 = parseInt(low, 16) & 0xFFFF; + return (((num1 << 16) | num2) >>> 0); } function isInNet6(parts, list, list2) { - var num = convertToInt(parts[0], parts[1]); + var num = convertToInt6(parts[0], parts[1]); var x = binarySearch(list, num, 0, list.length); if (list[x][1] == -1) - return ((num & list[x][2]) === list[x][0]); + return (((num & list[x][2]) ^ list[x][0]) === 0); // not in net (/33 - /64) if (num !== list[x][0]) return false; - var num2 = convertToInt(parts[2], parts[3]); + var num2 = convertToInt6(parts[2], parts[3]); var x2 = binarySearch(list2, num2, list[x][1], list[x][2] + 1); - return ((num2 & list2[x2][1]) === list2[x2][0]); + return (((num2 & list2[x2][1]) ^ list2[x2][0]) === 0); } function isLanOrChina6(host) { - if (host.indexOf("::") === -1) { - var groups = host.split(":"); + var addr = host; + if (addr.indexOf("[") !== -1) { + addr = addr.substring(1, addr.length - 1); + } + + if (addr.indexOf("::") === -1) { + var groups = addr.split(":"); if (groups.length != 8) return false; // invalid ipv6 format return isInNet6(groups, CHINA6_F, CHINA6_S) || isInNet6(groups, LAN6_F, LAN6_S); } - var halfs = host.split("::"); + var halfs = addr.split("::"); var left = halfs[0]; var right = halfs[1]; if (left.length < 1) left = "0000"; @@ -93,8 +91,14 @@ function isLanOrChina6(host) { return isInNet6(parts, CHINA6_F, CHINA6_S) || isInNet6(parts, LAN6_F, LAN6_S); } +function convertToInt(host) { + var bytes = host.split("."); + var result = ((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16) | ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF); + return (result >>> 0); +} + function belongsToSubnet(host, list) { - var ip = convert_addr(host) >>> 0; + var ip = convertToInt(host); if (list.length === 0 || ip < list[0][0]) return false; @@ -171,7 +175,7 @@ function FindProxyForURL(url, host) { } // Fallback to IP whitelist - + // if host is IPv6 if (host.indexOf(":") !== -1) { if (isLanOrChina6(host)) { @@ -179,26 +183,26 @@ function FindProxyForURL(url, host) { } return proxy; } - - // default resolve IPv4 - // var remote = dnsResolve(host); - // if (!remote) { - // // resolution failed - // return proxy; - // } // method for IPv6 - var ips = dnsResolveEx(host); - if (!ips) - return proxy; - var remote = ips.split(";")[0]; + var remote = dnsResolveEx(host); + if (!remote) { + // fallback to legacy method + remote = dnsResolve(host); + if (!remote) + return proxy; + } + else { + remote = remote.split(";")[0]; + } + if (remote.indexOf(":") !== -1) { if (isLanOrChina6(remote)) { return direct; } return proxy; } - + if (isLan(remote) || isChina(remote)) { return direct; } From 713f5e397bd1797bd2b6aa46d0f51aab09e0429d Mon Sep 17 00:00:00 2001 From: wits-fe <58023436+wits-fe@users.noreply.github.com> Date: Fri, 28 Apr 2023 23:58:48 +0800 Subject: [PATCH 4/7] add Maxmind-GeoLite2 & naming --- build.py | 58 ++++++++++++++++++++++++++++++++++++++++++++------------ code.js | 10 +++++----- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/build.py b/build.py index 07e71dc..fc0f967 100755 --- a/build.py +++ b/build.py @@ -8,14 +8,16 @@ import gfwlist - -SOURCES = { +SOURCES_4 = { 'ipdeny.com': 'http://www.ipdeny.com/ipblocks/data/aggregated/cn-aggregated.zone', '17mon': 'https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt', } -SOURCES2 = { +SOURCES_6 = { 'gaoyifan': 'https://gaoyifan.github.io/china-operator-ip/china6.txt', } +SOURCES_46 = { + 'maxmind': 'https://github.com/v2fly/geoip/raw/release/text/cn.txt', +} OUT_DIR = "dist" # Stub content to disable GFWList check @@ -28,6 +30,8 @@ def fetch_and_convert(src): template = "var CHINA = [\n{}\n];\n" lines = [] for iprange in response.text.strip().split("\n"): + if iprange.find(":") != -1: + break ipnet = ipaddress.IPv4Network(iprange) netaddr = int(ipnet.network_address) netmask = int(ipnet.netmask) @@ -57,6 +61,8 @@ def fetch_and_convert_ip6(src): fixlen = len(f" [0xFFFFFFFF, -1, 0xFFFFFFFF],") for iprange in text.strip().split("\n"): + if iprange.find(":") == -1: + continue ipnet = ipaddress.IPv6Network(iprange) prefixlen = ipnet.prefixlen fulladdr = str(ipnet.exploded).replace(':', '') @@ -131,34 +137,62 @@ def main(): 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}") + for key in SOURCES_4: + key_6 = list(SOURCES_6)[0] + print(f"Generating PAC script from source {key}(IPv4) & {key_6}(IPv6)") try: - data = fetch_and_convert(SOURCES[key]) - key2 = list(SOURCES2)[0] - data2 = fetch_and_convert_ip6(SOURCES2[key2]) + data = fetch_and_convert(SOURCES_4[key]) + data_6 = fetch_and_convert_ip6(SOURCES_6[key_6]) except RequestException: continue except HTTPError: continue - filename = f"pac-{key}-{key2}.txt" - filename_gfwlist = f"pac-gfwlist-{key}-{key2}.txt" + filename = f"pac-IPv4_{key}--IPv6_{key_6}.txt" + filename_gfwlist = f"pac-gfwlist-IPv4_{key}--IPv6_{key_6}.txt" with open(os.path.join(OUT_DIR, filename), "w") as f: f.write(code) f.write(data) f.write("\n") - f.write(data2) + f.write(data_6) f.write("\n") f.write(gfwlist_stub) with open(os.path.join(OUT_DIR, filename_gfwlist), "w") as f: f.write(code) f.write(data) f.write("\n") - f.write(data2) + f.write(data_6) f.write("\n") f.write(gfwlist_part) + for key in SOURCES_46: + print(f"Generating PAC script from source {key}(IPv4v6)") + try: + data = fetch_and_convert(SOURCES_46[key]) + data_6 = fetch_and_convert_ip6(SOURCES_46[key]) + except RequestException: + continue + except HTTPError: + continue + + filename = f"pac-IPv4v6_{key}.txt" + filename_gfwlist = f"pac-gfwlist-IPv4v6_{key}.txt" + with open(os.path.join(OUT_DIR, filename), "w") as f: + f.write(code) + f.write(data) + f.write("\n") + f.write(data_6) + f.write("\n") + f.write(gfwlist_stub) + with open(os.path.join(OUT_DIR, filename_gfwlist), "w") as f: + f.write(code) + f.write(data) + f.write("\n") + f.write(data_6) + f.write("\n") + f.write(gfwlist_part) + + if __name__ == '__main__': main() diff --git a/code.js b/code.js index 452761b..66f1d57 100644 --- a/code.js +++ b/code.js @@ -19,14 +19,14 @@ function binarySearch(list, num, lower, upper) { return x; } -function convertToInt6(high, low) { +function convertToUInt6(high, low) { var num1 = parseInt(high, 16) & 0xFFFF; var num2 = parseInt(low, 16) & 0xFFFF; return (((num1 << 16) | num2) >>> 0); } function isInNet6(parts, list, list2) { - var num = convertToInt6(parts[0], parts[1]); + var num = convertToUInt6(parts[0], parts[1]); var x = binarySearch(list, num, 0, list.length); if (list[x][1] == -1) @@ -36,7 +36,7 @@ function isInNet6(parts, list, list2) { if (num !== list[x][0]) return false; - var num2 = convertToInt6(parts[2], parts[3]); + var num2 = convertToUInt6(parts[2], parts[3]); var x2 = binarySearch(list2, num2, list[x][1], list[x][2] + 1); return (((num2 & list2[x2][1]) ^ list2[x2][0]) === 0); @@ -91,14 +91,14 @@ function isLanOrChina6(host) { return isInNet6(parts, CHINA6_F, CHINA6_S) || isInNet6(parts, LAN6_F, LAN6_S); } -function convertToInt(host) { +function convertToUInt(host) { var bytes = host.split("."); var result = ((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16) | ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF); return (result >>> 0); } function belongsToSubnet(host, list) { - var ip = convertToInt(host); + var ip = convertToUInt(host); if (list.length === 0 || ip < list[0][0]) return false; From b4672cad565248e18d8092232d424c588997ed0d Mon Sep 17 00:00:00 2001 From: wits-fe <58023436+wits-fe@users.noreply.github.com> Date: Sat, 29 Apr 2023 01:13:02 +0800 Subject: [PATCH 5/7] fix code Now checks if function "dnsResolveEx" exist. --- code.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/code.js b/code.js index 66f1d57..ebedab0 100644 --- a/code.js +++ b/code.js @@ -184,15 +184,16 @@ function FindProxyForURL(url, host) { return proxy; } - // method for IPv6 - var remote = dnsResolveEx(host); - if (!remote) { - // fallback to legacy method + var remote; + if(typeof dnsResolveEx == 'function') { + remote = dnsResolveEx(host); + } else { remote = dnsResolve(host); - if (!remote) - return proxy; } - else { + + if (!remote) { + return proxy; + } else { remote = remote.split(";")[0]; } From 3c8310f20335e19730979c044eb586bb3ec62908 Mon Sep 17 00:00:00 2001 From: wits-fe <58023436+wits-fe@users.noreply.github.com> Date: Sat, 20 May 2023 16:40:08 +0800 Subject: [PATCH 6/7] refactor, nothing changed --- build.py | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/build.py b/build.py index fc0f967..a970214 100755 --- a/build.py +++ b/build.py @@ -126,6 +126,16 @@ def fetch_and_convert_ip6(src): return template.format("\n".join(lines)) + template2.format("\n".join(lines2)) +def write_pac(filename, code, data, data_6, tail): + with open(os.path.join(OUT_DIR, filename), "w") as f: + f.write(code) + f.write(data) + f.write("\n") + f.write(data_6) + f.write("\n") + f.write(tail) + + def main(): now = datetime.utcnow() date = now.strftime("%Y%m%d") @@ -150,20 +160,8 @@ def main(): filename = f"pac-IPv4_{key}--IPv6_{key_6}.txt" filename_gfwlist = f"pac-gfwlist-IPv4_{key}--IPv6_{key_6}.txt" - with open(os.path.join(OUT_DIR, filename), "w") as f: - f.write(code) - f.write(data) - f.write("\n") - f.write(data_6) - f.write("\n") - f.write(gfwlist_stub) - with open(os.path.join(OUT_DIR, filename_gfwlist), "w") as f: - f.write(code) - f.write(data) - f.write("\n") - f.write(data_6) - f.write("\n") - f.write(gfwlist_part) + write_pac(filename, code, data, data_6, gfwlist_stub) + write_pac(filename_gfwlist, code, data, data_6, gfwlist_part) for key in SOURCES_46: print(f"Generating PAC script from source {key}(IPv4v6)") @@ -177,20 +175,8 @@ def main(): filename = f"pac-IPv4v6_{key}.txt" filename_gfwlist = f"pac-gfwlist-IPv4v6_{key}.txt" - with open(os.path.join(OUT_DIR, filename), "w") as f: - f.write(code) - f.write(data) - f.write("\n") - f.write(data_6) - f.write("\n") - f.write(gfwlist_stub) - with open(os.path.join(OUT_DIR, filename_gfwlist), "w") as f: - f.write(code) - f.write(data) - f.write("\n") - f.write(data_6) - f.write("\n") - f.write(gfwlist_part) + write_pac(filename, code, data, data_6, gfwlist_stub) + write_pac(filename_gfwlist, code, data, data_6, gfwlist_part) From f74bf55dc3880a225ec44bd05e70b72db6f9350e Mon Sep 17 00:00:00 2001 From: wits-fe <58023436+wits-fe@users.noreply.github.com> Date: Wed, 24 May 2023 13:34:12 +0800 Subject: [PATCH 7/7] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 98fbe6e..82e276d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ PAC scripts for proxies ## 特点 -基于 IP 地址白名单设计,位于白名单中的 IP 地址走直连,白名单以外的 IP 地址走代理(暂不支持 IPv6)。 +基于 IP 地址白名单设计,位于白名单中的 IP 地址走直连,白名单以外的 IP 地址走代理。 另有 GFWList 版本从 [gfwlist/gfwlist](https://github.com/gfwlist/gfwlist) 获取域名及 URL 列表,优先匹配列表中的黑白名单,有效防止 DNS 污染。 @@ -12,7 +12,7 @@ PAC scripts for proxies ## 使用 -获取方式:[本仓库的 Releases](https://github.com/iBug/pac/releases/latest) +获取方式:[本仓库的 Releases](https://github.com/wits-fe/pac/releases/latest) - `pac-.txt` 包含从数据源 `` 获取的 IP 地址列表(白名单) - `pac-gfwlist-.txt` 在 IP 白名单的基础上添加了 GFWList 的匹配