Compare commits
72 Commits
v20241003.
...
v20250522.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5a92c3623 | ||
|
|
0d3a81c98a | ||
|
|
48b691f648 | ||
|
|
b08e659514 | ||
|
|
1a511c81ef | ||
|
|
e084116209 | ||
|
|
64f75179f5 | ||
|
|
948a002d73 | ||
|
|
046401ec20 | ||
|
|
9cf413c43c | ||
|
|
601b549b31 | ||
|
|
6b65baa275 | ||
|
|
8c52b77a03 | ||
|
|
02f24366f5 | ||
|
|
419485dde2 | ||
|
|
2a1c178d3a | ||
|
|
ab03a97789 | ||
|
|
ac4fb7b19b | ||
|
|
f810a66b0c | ||
|
|
e6129a6dd4 | ||
|
|
f1df8acaba | ||
|
|
7add95746e | ||
|
|
9622bd4456 | ||
|
|
3949a407b0 | ||
|
|
8b51175a34 | ||
|
|
bdc53dd5ca | ||
|
|
f3d1085c2d | ||
|
|
932d427c01 | ||
|
|
d554c444cc | ||
|
|
7b9fb28619 | ||
|
|
74e6d0aa47 | ||
|
|
509f516d1d | ||
|
|
4ae3541f20 | ||
|
|
58d793c13c | ||
|
|
340754f759 | ||
|
|
d36a5097f5 | ||
|
|
03998c2db0 | ||
|
|
bc33e69e7d | ||
|
|
fcd1ce19aa | ||
|
|
d923c54720 | ||
|
|
16f2713aa1 | ||
|
|
07a9e9773b | ||
|
|
f827e221e7 | ||
|
|
357bbd09bd | ||
|
|
a283940216 | ||
|
|
4a64f36f5c | ||
|
|
34b4cd9097 | ||
|
|
812b8e7d4c | ||
|
|
0ab915b467 | ||
|
|
87d75dba5f | ||
|
|
3027e9e6a7 | ||
|
|
b9032ea016 | ||
|
|
f7e2dd9dce | ||
|
|
41d62c40c6 | ||
|
|
bcabb05039 | ||
|
|
4ac16b533e | ||
|
|
bf629eb3f3 | ||
|
|
e6c2fd567a | ||
|
|
416f1dcf3b | ||
|
|
ec45c85714 | ||
|
|
fb5d8aa6d4 | ||
|
|
778963d00d | ||
|
|
f78408a67f | ||
|
|
48aa309ec3 | ||
|
|
555acef5c1 | ||
|
|
c6fdf656fd | ||
|
|
92a7e03482 | ||
|
|
2740c7a3ce | ||
|
|
a780ff9a2b | ||
|
|
9f2b1b5045 | ||
|
|
9ff1fa9969 | ||
|
|
ed194cb9d4 |
55
.github/workflows/auto-generate-pac.yml
vendored
Normal file
55
.github/workflows/auto-generate-pac.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
name: Auto Generate PAC File
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '10 0 * * 4'
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'gfw-pac.py'
|
||||||
|
- 'pac-template'
|
||||||
|
- 'local-tlds.txt'
|
||||||
|
- 'direct-domains.txt'
|
||||||
|
- 'proxy-domains.txt'
|
||||||
|
- 'cidrs-cn.txt'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-gfw-pac:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Check if gfw.pac is in the commit
|
||||||
|
id: check-file
|
||||||
|
run: |
|
||||||
|
if git diff --name-only HEAD^ HEAD | grep -q 'gfw\.pac'; then
|
||||||
|
echo "file-exists=true" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "file-exists=false" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Download the latest cn.txt
|
||||||
|
if: env.file-exists == 'false'
|
||||||
|
run: curl -L https://raw.githubusercontent.com/Loyalsoldier/geoip/release/text/cn.txt -o cidrs-cn.txt
|
||||||
|
|
||||||
|
- name: Run gfw-pac.py script
|
||||||
|
if: env.file-exists == 'false'
|
||||||
|
run: ./gfw-pac.py -f gfw.pac -p "PROXY 127.0.0.1:3128" --proxy-domains=proxy-domains.txt --direct-domains=direct-domains.txt --localtld-domains=local-tlds.txt --ip-file=cidrs-cn.txt
|
||||||
|
|
||||||
|
- name: Commit and push changes
|
||||||
|
if: env.file-exists == 'false'
|
||||||
|
run: |
|
||||||
|
last_commit_message=$(git log -1 --pretty=%B)
|
||||||
|
commit_message=$([[ "${{ github.event_name }}" == "schedule" ]] && echo "定期更新数据并生成 gfw.pac" || echo "自动生成 gfw.pac: $last_commit_message")
|
||||||
|
git config --local user.email "action@github.com"
|
||||||
|
git config --local user.name "GitHub Action"
|
||||||
|
git add -A
|
||||||
|
git commit -a -m "${commit_message}"
|
||||||
|
git push
|
||||||
|
|
||||||
|
- name: Trigger Auto-Release
|
||||||
|
if: env.file-exists == 'false'
|
||||||
|
uses: benc-uk/workflow-dispatch@v1
|
||||||
|
with:
|
||||||
|
workflow: Auto Generate Release
|
||||||
23
.github/workflows/auto-release.yml
vendored
23
.github/workflows/auto-release.yml
vendored
@@ -1,10 +1,10 @@
|
|||||||
name: Auto Generate Release
|
name: Auto Generate Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- 'gfw.pac' # 替换为你要监控的文件路径
|
- 'gfw.pac'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
generate-release:
|
generate-release:
|
||||||
@@ -12,20 +12,23 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Git
|
- name: Set up Git
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name "GitHub Actions"
|
git config --global user.name "GitHub Actions"
|
||||||
git config --global user.email "actions@github.com"
|
git config --global user.email "actions@github.com"
|
||||||
|
|
||||||
- name: Get commit count for today
|
- name: Generate Release Name
|
||||||
id: commit_count
|
id: commit_count
|
||||||
run: |
|
run: |
|
||||||
today=$(date +%Y%m%d)
|
today=$(TZ=Asia/Shanghai date +%Y%m%d)
|
||||||
commit_count=$(git log --since="$today 00:00:00" --until="$today 23:59:59" --pretty=format: --name-only | grep -c '^gfw.pac$')
|
commit_count=$(TZ=Asia/Shanghai git log --date=local --since="$today 00:00:00" --until="$today 23:59:59" --pretty=format: --name-only | grep -c '^gfw.pac$')
|
||||||
echo "COMMIT_COUNT=$commit_count" >> $GITHUB_ENV
|
echo "COMMIT_COUNT=$commit_count" >> $GITHUB_ENV
|
||||||
echo "RELEASE_NAME=v$(TZ='Asia/Shanghai' date +%Y%m%d).$commit_count" >> $GITHUB_ENV
|
echo "RELEASE_NAME=v$(TZ='Asia/Shanghai' date +%Y%m%d).$commit_count" >> $GITHUB_ENV
|
||||||
|
echo "COMMIT_MESSAGE=$(git log -1 --pretty=%B)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Create Tag
|
- name: Create Tag
|
||||||
id: create_tag
|
id: create_tag
|
||||||
@@ -39,11 +42,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
tag_name: "${{ env.RELEASE_NAME }}"
|
tag_name: "${{ env.RELEASE_NAME }}"
|
||||||
name: "${{ env.RELEASE_NAME }}"
|
name: "${{ env.RELEASE_NAME }}"
|
||||||
body: "Automatically generated release for pac file update"
|
body: "${{ env.COMMIT_MESSAGE }}"
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
files: gfw.pac # 替换为你要上传的文件路径
|
files: gfw.pac
|
||||||
|
|
||||||
- name: Verify Release
|
|
||||||
run: |
|
|
||||||
echo "Release created with name ${{ env.RELEASE_NAME }}"
|
|
||||||
32
.github/workflows/auto-update-gfw-pac.yml
vendored
32
.github/workflows/auto-update-gfw-pac.yml
vendored
@@ -1,32 +0,0 @@
|
|||||||
name: GFW PAC Update
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 */14 * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-gfw-pac:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Download delegated-apnic-latest
|
|
||||||
run: curl https://raw.githubusercontent.com/Loyalsoldier/geoip/refs/heads/release/text/cn.txt -o cidrs-cn.txt
|
|
||||||
|
|
||||||
- name: Run gfw-pac.py script
|
|
||||||
run: ./gfw-pac.py -f gfw.pac -p "PROXY 127.0.0.1:3128" --proxy-domains=proxy-domains.txt --direct-domains=direct-domains.txt --localtld-domains=local-tlds.txt --ip-file=cidrs-cn.txt
|
|
||||||
|
|
||||||
- name: Commit gfw.pac
|
|
||||||
run: |
|
|
||||||
git config --local user.email "action@github.com"
|
|
||||||
git config --local user.name "GitHub Action"
|
|
||||||
git add .
|
|
||||||
git commit -a -m "自动更新 gfw.pac"
|
|
||||||
|
|
||||||
- name: Push changes
|
|
||||||
uses: ad-m/github-push-action@master
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.PUSH_TOKEN }}
|
|
||||||
branch: master
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -43,3 +43,5 @@ $RECYCLE.BIN/
|
|||||||
|
|
||||||
# Windows shortcuts
|
# Windows shortcuts
|
||||||
*.lnk
|
*.lnk
|
||||||
|
|
||||||
|
test.js
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
科学上网 PAC 文件以及生成器。通过自定义域名和 CNIP 地址生成 PAC(Proxy auto-config) 文件。对存在于自定义域名和解析出的IP不是CNIP的域名使用代理,支持IPv6。
|
科学上网 PAC 文件以及生成器。通过自定义域名和 CNIP 地址生成 PAC(Proxy auto-config) 文件。对存在于自定义域名和解析出的IP不是CNIP的域名使用代理,支持IPv6。
|
||||||
|
|
||||||
**此仓库每 14 天自动通过 GitHub Action 从 `Loyalsoldier/geoip` 获取国内地址段并更新 `gfw.pac` 文件**
|
**此仓库每周四自动通过 GitHub Action 从 `Loyalsoldier/geoip` 同步数据并更新 `gfw.pac` 文件**
|
||||||
|
|
||||||
## 特性
|
## 特性
|
||||||
* 开箱即用,直接可用的 `gfw.pac` 包含了常用的直连域名和代理域名以及国内IPv4/IPv6地址段
|
* 开箱即用,直接可用的 `gfw.pac` 包含了常用的直连域名和代理域名以及国内IPv4/IPv6地址段
|
||||||
|
|||||||
8592
cidrs-cn.txt
8592
cidrs-cn.txt
File diff suppressed because it is too large
Load Diff
@@ -69,8 +69,18 @@ douyinstatic.com
|
|||||||
douyinvod.com
|
douyinvod.com
|
||||||
supercachenode.com
|
supercachenode.com
|
||||||
bytedance.com
|
bytedance.com
|
||||||
|
bytedanceapi.com
|
||||||
bytescm.com
|
bytescm.com
|
||||||
bytecdn.cn
|
bytecdn.cn
|
||||||
|
byteoc.com
|
||||||
|
bytednsdoc.com
|
||||||
|
bytetcc.com
|
||||||
|
feishu.cn
|
||||||
|
feishucdn.com
|
||||||
|
toutiao.com
|
||||||
|
toutiaoimg.com
|
||||||
|
toutiaostatic.com
|
||||||
|
yhgfb-cn-static.com
|
||||||
cmbchina.com
|
cmbchina.com
|
||||||
mi.com
|
mi.com
|
||||||
xiaomi.com
|
xiaomi.com
|
||||||
@@ -80,68 +90,39 @@ meituan.com
|
|||||||
meituan.net
|
meituan.net
|
||||||
sogou.com
|
sogou.com
|
||||||
dianping.com
|
dianping.com
|
||||||
o.pki.goog
|
|
||||||
www.googletagmanager.com
|
|
||||||
www.google-analytics.com
|
|
||||||
pagead2.googlesyndication.com
|
|
||||||
adservice.google.com
|
|
||||||
fonts.googleapis.com
|
|
||||||
fonts.gstatic.com
|
|
||||||
www.gstatic.com
|
|
||||||
ssl.gstatic.com
|
|
||||||
quark.cn
|
quark.cn
|
||||||
|
wps.cn
|
||||||
|
wpscdn.cn
|
||||||
|
xiaohongshu.com
|
||||||
|
xhscdn.com
|
||||||
push.apple.com
|
push.apple.com
|
||||||
time-ios.apple.com
|
|
||||||
time.apple.com
|
|
||||||
time-macos.apple.com
|
|
||||||
setup.icloud.com
|
setup.icloud.com
|
||||||
www.apple.com.cn
|
|
||||||
play.itunes.apple.com
|
|
||||||
appldnld.apple.com
|
appldnld.apple.com
|
||||||
configuration.apple.com
|
|
||||||
mesu.apple.com
|
|
||||||
oscdn.apple.com
|
oscdn.apple.com
|
||||||
osrecovery.apple.com
|
osrecovery.apple.com
|
||||||
skl.apple.com
|
|
||||||
swcdn.apple.com
|
swcdn.apple.com
|
||||||
swdist.apple.com
|
swdist.apple.com
|
||||||
swdownload.apple.com
|
swdownload.apple.com
|
||||||
swscan.apple.com
|
swscan.apple.com
|
||||||
updates-http.cdn-apple.com
|
updates-http.cdn-apple.com
|
||||||
updates.cdn-apple.com
|
updates.cdn-apple.com
|
||||||
xp.apple.com
|
|
||||||
audiocontentdownload.apple.com
|
audiocontentdownload.apple.com
|
||||||
devimages-cdn.apple.com
|
devimages-cdn.apple.com
|
||||||
devstreaming-cdn.apple.com
|
devstreaming-cdn.apple.com
|
||||||
icloud.cdn-apple.com
|
|
||||||
iosdm-cn.cdn-apple.com
|
|
||||||
js-cdn.music.apple.com
|
|
||||||
oscdn.apple.com
|
oscdn.apple.com
|
||||||
speed-test-cnc.cdn-apple.com
|
|
||||||
download.developer.apple.com
|
|
||||||
playgrounds-assets-cdn.apple.com
|
|
||||||
sylvan.apple.com
|
|
||||||
diagassets.apple.com
|
|
||||||
doh.dns.apple.com
|
|
||||||
certs.apple.com
|
certs.apple.com
|
||||||
crl.apple.com
|
|
||||||
ocsp.apple.com
|
ocsp.apple.com
|
||||||
ocsp2.apple.com
|
ocsp2.apple.com
|
||||||
valid.apple.com
|
valid.apple.com
|
||||||
appleid.cdn-apple.com
|
appleid.cdn-apple.com
|
||||||
apzones.com
|
|
||||||
icloud.com.cn
|
icloud.com.cn
|
||||||
guzzoni.apple.com
|
guzzoni.apple.com
|
||||||
app-site-association.cdn-apple.com
|
app-site-association.cdn-apple.com
|
||||||
smp-device-content.apple.com
|
smp-device-content.apple.com
|
||||||
idv.cdn-apple.com
|
idv.cdn-apple.com
|
||||||
weatherkit.apple.com
|
|
||||||
adcdownload.apple.com
|
adcdownload.apple.com
|
||||||
alpdownloadit.cdn-apple.com
|
alpdownloadit.cdn-apple.com
|
||||||
bricks.cdn-apple.com
|
bricks.cdn-apple.com
|
||||||
pancake.apple.com
|
|
||||||
storage.live.com
|
|
||||||
blob.core.windows.net
|
|
||||||
self.events.data.microsoft.com
|
self.events.data.microsoft.com
|
||||||
mobile.events.data.microsoft.com
|
mobile.events.data.microsoft.com
|
||||||
browser.events.data.microsoft.com
|
browser.events.data.microsoft.com
|
||||||
@@ -149,3 +130,10 @@ ocsp.globalsign.com
|
|||||||
ocsp2.globalsign.com
|
ocsp2.globalsign.com
|
||||||
ocsp.digicert.cn
|
ocsp.digicert.cn
|
||||||
ocsp.dcocsp.cn
|
ocsp.dcocsp.cn
|
||||||
|
api.onedrive.com
|
||||||
|
storage.live.com
|
||||||
|
gr.global.aa-rt.sharepoint.com
|
||||||
|
skyapi.live.net
|
||||||
|
roaming.officeapps.live.com
|
||||||
|
blob.core.windows.net
|
||||||
|
default.exp-tas.com
|
||||||
36
gfw-pac.py
36
gfw-pac.py
@@ -1,12 +1,10 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import urllib.parse
|
|
||||||
import json
|
import json
|
||||||
import urllib.request, urllib.error, urllib.parse
|
import urllib.request, urllib.error, urllib.parse
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import json
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
parser = ArgumentParser()
|
parser = ArgumentParser()
|
||||||
@@ -22,23 +20,25 @@ def parse_args():
|
|||||||
help='直连的域名文件,每行一个')
|
help='直连的域名文件,每行一个')
|
||||||
parser.add_argument('--localtld-domains', dest='localtld_rule',
|
parser.add_argument('--localtld-domains', dest='localtld_rule',
|
||||||
help='本地 TLD 规则文件, 不走代理, 每行一个,以 . 开头')
|
help='本地 TLD 规则文件, 不走代理, 每行一个,以 . 开头')
|
||||||
parser.add_argument('--ip-file', dest='ip_file',
|
parser.add_argument('--ip-file', dest='ip_file', required=True,
|
||||||
help='中国IP地址段文件')
|
help='中国IP地址段文件')
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
def convert_cidr(cidr):
|
def convert_cidr(cidr):
|
||||||
if '/' in cidr:
|
if '/' in cidr:
|
||||||
network = ipaddress.ip_network(cidr.strip(), strict=False)
|
network = ipaddress.ip_network(cidr.strip(), strict=False)
|
||||||
network_address = network.network_address
|
network_address = int(network.network_address) >> (network.max_prefixlen - network.prefixlen)
|
||||||
prefixlen = network.prefixlen
|
|
||||||
else:
|
else:
|
||||||
network = ipaddress.ip_address(cidr.strip())
|
network = ipaddress.ip_address(cidr.strip())
|
||||||
network_address = network
|
network_address = network
|
||||||
prefixlen = network.max_prefixlen
|
return hex(int(network_address))[2:]
|
||||||
if network.version == 4:
|
|
||||||
return hex(int(network_address))[2:] + '/' + str(prefixlen)
|
def longest_common_prefix(str1, str2):
|
||||||
else:
|
min_length = min(len(str1), len(str2))
|
||||||
return network.compressed
|
for i in range(min_length):
|
||||||
|
if str1[i] != str2[i]:
|
||||||
|
return str1[:i]
|
||||||
|
return str1[:min_length]
|
||||||
|
|
||||||
def generate_cnip_cidrs():
|
def generate_cnip_cidrs():
|
||||||
""" 从文件中读取CIDR地址 """
|
""" 从文件中读取CIDR地址 """
|
||||||
@@ -49,6 +49,22 @@ def generate_cnip_cidrs():
|
|||||||
for cidr in cidrs:
|
for cidr in cidrs:
|
||||||
converted_cidrs.append(convert_cidr(cidr))
|
converted_cidrs.append(convert_cidr(cidr))
|
||||||
|
|
||||||
|
converted_cidrs.sort(key=lambda x: (len(x), x), reverse=False)
|
||||||
|
converted_cidrs_clone = converted_cidrs[:]
|
||||||
|
|
||||||
|
lastFullCidr = ''
|
||||||
|
for i in range(len(converted_cidrs)):
|
||||||
|
prevCidr = converted_cidrs_clone[i-1] if i > 0 else ''
|
||||||
|
currentCidr = converted_cidrs[i]
|
||||||
|
if len(prevCidr) != len(currentCidr):
|
||||||
|
lastFullCidr = currentCidr
|
||||||
|
continue
|
||||||
|
prefix = longest_common_prefix(lastFullCidr, currentCidr)
|
||||||
|
if len(prefix) < len(lastFullCidr)//1.2:
|
||||||
|
lastFullCidr = currentCidr
|
||||||
|
continue
|
||||||
|
converted_cidrs[i] = '~' + currentCidr[len(prefix):]
|
||||||
|
|
||||||
cidr_list = ','.join(converted_cidrs)
|
cidr_list = ','.join(converted_cidrs)
|
||||||
return f"'{cidr_list}'.split(',')"
|
return f"'{cidr_list}'.split(',')"
|
||||||
|
|
||||||
|
|||||||
70
pac-template
70
pac-template
@@ -10,35 +10,45 @@ var localTlds = __LOCAL_TLDS__;
|
|||||||
|
|
||||||
var cidrs = __CIDRS__;
|
var cidrs = __CIDRS__;
|
||||||
|
|
||||||
var hasOwnProperty = Object.hasOwnProperty;
|
|
||||||
|
|
||||||
function isIpAddress(ip) {
|
function isIpAddress(ip) {
|
||||||
return /^\d{1,3}(\.\d{1,3}){3}$/.test(ip) || /^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$/.test(ip);
|
return /^\d{1,3}(\.\d{1,3}){3}$/.test(ip) || /^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$/.test(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
function RadixTree() {
|
function RadixTree() {
|
||||||
this.root = {};
|
this.root = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
RadixTree.prototype.insert = function(string) {
|
RadixTree.prototype.insert = function(string) {
|
||||||
var node = this.root;
|
var node = this.root;
|
||||||
for (var i = 0; i < string.length; i++) {
|
for (var i = 0; i < string.length; i++) {
|
||||||
var char = string[i];
|
var char = string[i];
|
||||||
if (!node[char]) {
|
if (!node.has(char)) {
|
||||||
node[char] = {};
|
node.set(char, new Map());
|
||||||
}
|
}
|
||||||
node = node[char];
|
node = node.get(char);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RadixTree.prototype.to_list = function() {
|
RadixTree.prototype.search = function(string) {
|
||||||
return this.root;
|
var currentNode = this.root;
|
||||||
};
|
var isLastNode = false;
|
||||||
|
for (var i=0; i < string.length; i++) {
|
||||||
|
var char = string[i];
|
||||||
|
if (currentNode.has(char)) {
|
||||||
|
currentNode = currentNode.get(char);
|
||||||
|
isLastNode = currentNode.size === 0;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isLastNode;
|
||||||
|
}
|
||||||
|
|
||||||
function ipToBinary(ip) {
|
function ipToBinary(ip) {
|
||||||
|
var bin = ''
|
||||||
// Check if it's IPv4
|
// Check if it's IPv4
|
||||||
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) {
|
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) {
|
||||||
return ip.split('.').map(function(num) {
|
bin = ip.split('.').map(function(num) {
|
||||||
return ("00000000" + parseInt(num, 10).toString(2)).slice(-8);
|
return ("00000000" + parseInt(num, 10).toString(2)).slice(-8);
|
||||||
}).join('');
|
}).join('');
|
||||||
} else if (/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$/.test(ip)) {
|
} else if (/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$/.test(ip)) {
|
||||||
@@ -54,25 +64,11 @@ function ipToBinary(ip) {
|
|||||||
var fullAddress = left.concat(Array(zeroGroups + 1).join('0').split('')).concat(right);
|
var fullAddress = left.concat(Array(zeroGroups + 1).join('0').split('')).concat(right);
|
||||||
|
|
||||||
// Convert each group to binary and pad to 16 bits
|
// Convert each group to binary and pad to 16 bits
|
||||||
return fullAddress.map(function(group) {
|
bin = fullAddress.map(function(group) {
|
||||||
return ("0000000000000000" + parseInt(group || '0', 16).toString(2)).slice(-16);
|
return ("0000000000000000" + parseInt(group || '0', 16).toString(2)).slice(-16);
|
||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
}
|
return bin.replace(/^0+/, '');
|
||||||
|
|
||||||
function searchRadixTree(bits) {
|
|
||||||
var currentNode = radixTree;
|
|
||||||
var isLastNode = false;
|
|
||||||
for (var i=0; i<bits.length; i++) {
|
|
||||||
var char = bits[i];
|
|
||||||
if (currentNode[char]) {
|
|
||||||
currentNode = currentNode[char];
|
|
||||||
isLastNode = Object.keys(currentNode).length === 0;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return isLastNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isInDirectDomain(host) {
|
function isInDirectDomain(host) {
|
||||||
@@ -142,7 +138,7 @@ function FindProxyForURL(url, host) {
|
|||||||
} else if (isPrivateIp(ip)) {
|
} else if (isPrivateIp(ip)) {
|
||||||
debug('域名解析后命中私有 IP 地址', host, ip);
|
debug('域名解析后命中私有 IP 地址', host, ip);
|
||||||
return direct;
|
return direct;
|
||||||
} else if (searchRadixTree(ipToBinary(ip))) {
|
} else if (radixTree.search(ipToBinary(ip))) {
|
||||||
debug('匹配到直连IP', host, ip);
|
debug('匹配到直连IP', host, ip);
|
||||||
return direct;
|
return direct;
|
||||||
}
|
}
|
||||||
@@ -152,7 +148,7 @@ function FindProxyForURL(url, host) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var allowAlert = true
|
var allowAlert = true
|
||||||
function debug(msg, host, ip) {
|
function debug(msg, host='', ip='') {
|
||||||
if (!allowAlert) {
|
if (!allowAlert) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -166,19 +162,17 @@ function debug(msg, host, ip) {
|
|||||||
var radixTree = new RadixTree();
|
var radixTree = new RadixTree();
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
var startTime = new Date().getMilliseconds();
|
debug('开始生成 Radix Tree', 'PAC文件载入开始');
|
||||||
debug('开始生成 Radix Tree', 'PAC文件载入开始', startTime.toString());
|
lastFullPrefix = ''
|
||||||
for (let i=0; i<cidrs.length; i++) {
|
for (let i=0; i<cidrs.length; i++) {
|
||||||
var cidr = cidrs[i];
|
var prefix = cidrs[i];
|
||||||
var [ip, prefixLen] = cidr.split('/');
|
if (prefix.substring(0, 1) !== '~') {
|
||||||
if (!cidr.includes(':')) {
|
lastFullPrefix = prefix
|
||||||
var ip = ip.match(/.{1,2}/g).map(function(byte) {
|
} else {
|
||||||
return parseInt(byte, 16);
|
prefix = lastFullPrefix.substring(0, lastFullPrefix.length-prefix.length+1) + prefix.substring(1)
|
||||||
}).join('.');
|
|
||||||
}
|
}
|
||||||
var bits = ipToBinary(ip).slice(0, prefixLen);
|
var bits = (parseInt(prefix, 16)).toString(2);
|
||||||
radixTree.insert(bits);
|
radixTree.insert(bits);
|
||||||
}
|
}
|
||||||
radixTree = radixTree.to_list();
|
|
||||||
debug('Radix Tree 已生成', 'PAC文件载入完毕', cidrs.length.toString()+'个CIDR条目');
|
debug('Radix Tree 已生成', 'PAC文件载入完毕', cidrs.length.toString()+'个CIDR条目');
|
||||||
})();
|
})();
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
google.com
|
|
||||||
google.com.hk
|
google.com.hk
|
||||||
googleapis.com
|
ent.com
|
||||||
gstatic.com
|
|
||||||
ggpht.com
|
|
||||||
googleusercontent.com
|
|
||||||
youtube.com
|
youtube.com
|
||||||
googlevideo.com
|
googlevideo.com
|
||||||
ytimg.com
|
ytimg.com
|
||||||
@@ -14,12 +10,14 @@ githubassets.com
|
|||||||
bing.com
|
bing.com
|
||||||
bing.cn
|
bing.cn
|
||||||
bing.net
|
bing.net
|
||||||
|
bingapis.com
|
||||||
live.com
|
live.com
|
||||||
stackoverflow.com
|
stackoverflow.com
|
||||||
wikipedia.org
|
wikipedia.org
|
||||||
godaddy.com
|
godaddy.com
|
||||||
cloudflare.com
|
cloudflare.com
|
||||||
twitter.com
|
twitter.com
|
||||||
|
x.com
|
||||||
twimg.com
|
twimg.com
|
||||||
docker.com
|
docker.com
|
||||||
facebook.com
|
facebook.com
|
||||||
@@ -29,3 +27,9 @@ segment.io
|
|||||||
unpkg.com
|
unpkg.com
|
||||||
jsdelivr.com
|
jsdelivr.com
|
||||||
tv.apple.com
|
tv.apple.com
|
||||||
|
instagram.com
|
||||||
|
cdninstagram.com
|
||||||
|
reddit.com
|
||||||
|
redd.it
|
||||||
|
whatsapp.com
|
||||||
|
whatsapp.net
|
||||||
Reference in New Issue
Block a user