Skip to content

Commit 20394a4

Browse files
committed
feat: add PAC file execution test script and improve PAC logic #41
- Added a new script `test_pac_execution.js` to validate the functionality of the PAC file. - Enhanced the `pac-template` to maintain leading zeros in binary strings for CIDR matching. - Updated the logic for handling CIDR prefixes to support decompression. - Changed file permissions for `local-tlds.txt` and `proxy-domains.txt` to executable.
1 parent 59ec1a0 commit 20394a4

12 files changed

Lines changed: 293 additions & 24 deletions

.github/workflows/auto-generate-pac.yml

100644100755
File mode changed.

.github/workflows/auto-release.yml

100644100755
File mode changed.

.gitignore

100644100755
File mode changed.

LICENSE.txt

100644100755
File mode changed.

README.md

100644100755
File mode changed.

direct-domains.txt

100644100755
File mode changed.

gfw-pac.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,27 @@ def parse_args():
2525
return parser.parse_args()
2626

2727
def convert_cidr(cidr):
28+
"""将CIDR转换为二进制字符串(根据掩码长度)"""
2829
if '/' in cidr:
2930
network = ipaddress.ip_network(cidr.strip(), strict=False)
30-
network_address = int(network.network_address) >> (network.max_prefixlen - network.prefixlen)
31+
# 获取网络地址和前缀长度
32+
network_address = int(network.network_address)
33+
prefix_len = network.prefixlen
34+
# 转换为二进制字符串,根据前缀长度截取
35+
if network.version == 4:
36+
# IPv4: 最多32位
37+
binary = bin(network_address)[2:].zfill(32)[:prefix_len]
38+
else:
39+
# IPv6: 最多128位
40+
binary = bin(network_address)[2:].zfill(128)[:prefix_len]
3141
else:
32-
network = ipaddress.ip_address(cidr.strip())
33-
network_address = network
34-
return hex(int(network_address))[2:]
42+
# 单个IP地址,使用完整长度
43+
ip = ipaddress.ip_address(cidr.strip())
44+
if ip.version == 4:
45+
binary = bin(int(ip))[2:].zfill(32)
46+
else:
47+
binary = bin(int(ip))[2:].zfill(128)
48+
return binary
3549

3650
def longest_common_prefix(str1, str2):
3751
min_length = min(len(str1), len(str2))
@@ -47,8 +61,11 @@ def generate_cnip_cidrs():
4761
cidrs = file.read().splitlines()
4862
converted_cidrs = []
4963
for cidr in cidrs:
50-
converted_cidrs.append(convert_cidr(cidr))
64+
binary = convert_cidr(cidr)
65+
if binary: # 忽略空字符串
66+
converted_cidrs.append(binary)
5167

68+
# 按长度和字典序排序
5269
converted_cidrs.sort(key=lambda x: (len(x), x), reverse=False)
5370
converted_cidrs_clone = converted_cidrs[:]
5471

@@ -60,9 +77,11 @@ def generate_cnip_cidrs():
6077
lastFullCidr = currentCidr
6178
continue
6279
prefix = longest_common_prefix(lastFullCidr, currentCidr)
63-
if len(prefix) < len(lastFullCidr)//1.2:
80+
# 只有当前缀足够长时才压缩(至少80%相同)
81+
if len(prefix) < len(lastFullCidr) * 0.8:
6482
lastFullCidr = currentCidr
6583
continue
84+
# 使用~前缀表示压缩的部分
6685
converted_cidrs[i] = '~' + currentCidr[len(prefix):]
6786

6887
cidr_list = ','.join(converted_cidrs)

gfw.pac

Lines changed: 15 additions & 10 deletions
Large diffs are not rendered by default.

local-tlds.txt

100644100755
File mode changed.

pac-template

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ function ipToBinary(ip) {
6868
return ("0000000000000000" + parseInt(group || '0', 16).toString(2)).slice(-16);
6969
}).join('');
7070
}
71-
return bin.replace(/^0+/, '');
71+
// 不要删除前导零!保持完整的二进制字符串以便与CIDR前缀匹配
72+
return bin;
7273
}
7374

7475
function isInDirectDomain(host) {
@@ -163,16 +164,20 @@ var radixTree = new RadixTree();
163164

164165
(function () {
165166
debug('开始生成 Radix Tree', 'PAC文件载入开始');
166-
lastFullPrefix = ''
167-
for (let i=0; i<cidrs.length; i++) {
167+
var lastFullPrefix = '';
168+
for (var i = 0; i < cidrs.length; i++) {
168169
var prefix = cidrs[i];
170+
// 解压缩:如果以~开头,则从lastFullPrefix中还原
169171
if (prefix.substring(0, 1) !== '~') {
170-
lastFullPrefix = prefix
172+
lastFullPrefix = prefix;
171173
} else {
172-
prefix = lastFullPrefix.substring(0, lastFullPrefix.length-prefix.length+1) + prefix.substring(1)
174+
// 计算公共前缀长度
175+
var suffix = prefix.substring(1);
176+
var prefixLen = lastFullPrefix.length - suffix.length;
177+
prefix = lastFullPrefix.substring(0, prefixLen) + suffix;
173178
}
174-
var bits = (parseInt(prefix, 16)).toString(2);
175-
radixTree.insert(bits);
179+
// 直接使用二进制字符串插入(无需转换)
180+
radixTree.insert(prefix);
176181
}
177-
debug('Radix Tree 已生成', 'PAC文件载入完毕', cidrs.length.toString()+'个CIDR条目');
182+
debug('Radix Tree 已生成', 'PAC文件载入完毕', cidrs.length.toString() + '个CIDR条目');
178183
})();

0 commit comments

Comments
 (0)