Added support for custom gTLDs; Updated gfwlist and CNIP to the latest.
This commit is contained in:
14
README.md
14
README.md
@@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
通过 gfwlist 和中国 IP 地址生成 PAC(Proxy auto-config) 文件。对存在于 gfwlist 的域名和解析出的 IP 在国外的域名使用代理。
|
通过 gfwlist 和中国 IP 地址生成 PAC(Proxy auto-config) 文件。对存在于 gfwlist 的域名和解析出的 IP 在国外的域名使用代理。
|
||||||
|
|
||||||
基于 [GFWList2PAC](https://github.com/clowwindy/gfwlist2pac) 和 [Flora PAC](https://github.com/Leask/Flora_Pac)
|
|
||||||
|
|
||||||
## 特性
|
## 特性
|
||||||
* 速度快,优先按域名匹配,再按 IP 匹配
|
* 速度快,优先按域名匹配,再按 IP 匹配
|
||||||
* 可自定义需要代理的域名
|
* 可自定义需要代理的域名
|
||||||
|
* 可自定义本地开发 TLD 域名,例如 .test
|
||||||
* 可自定义不需要代理的域名
|
* 可自定义不需要代理的域名
|
||||||
* 如果访问的域名不在列表里,但是 IP 在国外,也返回代理服务器
|
* 如果访问的域名不在列表里,但是 IP 在国外,也返回代理服务器
|
||||||
|
|
||||||
@@ -16,17 +15,21 @@
|
|||||||
|
|
||||||
## gfw-pac.py 使用说明
|
## gfw-pac.py 使用说明
|
||||||
|
|
||||||
usage: gfw-pac.py [-h] [-i GFWLIST] -f PAC -p PROXY [--user-rule USER_RULE]
|
usage: gfw-pac.py -f PAC -p PROXY [-h] [-i GFWLIST_FILE]
|
||||||
[--direct-rule DIRECT_RULE] [--ip-file IP_FILE]
|
[--user-rule USER_RULE_FILE]
|
||||||
|
[--direct-rule DIRECT_RULE_FILE]
|
||||||
|
[--localtld-rule LOCAL_TLD_RULE_FILE]
|
||||||
|
[--ip-file IP_FILE]
|
||||||
|
|
||||||
参数说明:
|
参数说明:
|
||||||
|
|
||||||
-h 显示帮助
|
-h 显示帮助
|
||||||
-i 指定本地 gfwlist 文件,若不指定则自动从 googlecode 下载
|
-i 指定本地 gfwlist 文件,若不指定则自动下载
|
||||||
-f (必须)输出的 pac 文件
|
-f (必须)输出的 pac 文件
|
||||||
-p (必须)指定代理服务器
|
-p (必须)指定代理服务器
|
||||||
--user-rule 自定义使用代理的域名文件,文件里每行一个域名
|
--user-rule 自定义使用代理的域名文件,文件里每行一个域名
|
||||||
--direct-rule 自定义不使用代理的域名文件,文件里每行一个域名
|
--direct-rule 自定义不使用代理的域名文件,文件里每行一个域名
|
||||||
|
--localtld-rule 自定义不使用代理的顶级域,文件里每行一个域名,必须带前导圆点(例如 .test)
|
||||||
--ip-file 指定本地的从 apnic 下载的 IP 分配文件。若不指定则自动从 apnic 下载
|
--ip-file 指定本地的从 apnic 下载的 IP 分配文件。若不指定则自动从 apnic 下载
|
||||||
|
|
||||||
举例:
|
举例:
|
||||||
@@ -36,6 +39,7 @@
|
|||||||
-p "PROXY 192.168.1.200:3128; DIRECT" \
|
-p "PROXY 192.168.1.200:3128; DIRECT" \
|
||||||
--user-rule=custom-domains.txt \
|
--user-rule=custom-domains.txt \
|
||||||
--direct-rule=direct-domains.txt \
|
--direct-rule=direct-domains.txt \
|
||||||
|
--localtld-rule=local-tlds.txt \
|
||||||
--ip-file=delegated-apnic-latest.txt
|
--ip-file=delegated-apnic-latest.txt
|
||||||
|
|
||||||
[一路凯歌 技术博客](http://zhiyi.us)
|
[一路凯歌 技术博客](http://zhiyi.us)
|
||||||
@@ -11,9 +11,6 @@ wikipedia.org
|
|||||||
stackoverflow.com
|
stackoverflow.com
|
||||||
sstatic.net
|
sstatic.net
|
||||||
imgur.com
|
imgur.com
|
||||||
github.com
|
|
||||||
githubusercontent.com
|
|
||||||
github.io
|
|
||||||
googlecode.com
|
googlecode.com
|
||||||
docker.io
|
docker.io
|
||||||
docker.com
|
docker.com
|
||||||
@@ -43,13 +40,4 @@ wenzhixin.net.cn
|
|||||||
last.fm
|
last.fm
|
||||||
scdn.co
|
scdn.co
|
||||||
spotify.com
|
spotify.com
|
||||||
spotilocal.com
|
spotilocal.com
|
||||||
music.126.net
|
|
||||||
laravel.com
|
|
||||||
youbma.com
|
|
||||||
youb99.com
|
|
||||||
youb88.com
|
|
||||||
youb77.com
|
|
||||||
youb66.com
|
|
||||||
youb11.com
|
|
||||||
qiporn.com
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -365,4 +365,7 @@ zhi.hu
|
|||||||
zhihu.com
|
zhihu.com
|
||||||
zhimg.com
|
zhimg.com
|
||||||
zhubajie.com
|
zhubajie.com
|
||||||
zongheng.com
|
zongheng.com
|
||||||
|
github.com
|
||||||
|
githubusercontent.com
|
||||||
|
github.io
|
||||||
29
gfw-pac.py
29
gfw-pac.py
@@ -30,6 +30,8 @@ def parse_args():
|
|||||||
' gfwlist')
|
' gfwlist')
|
||||||
parser.add_argument('--direct-rule', dest='direct_rule',
|
parser.add_argument('--direct-rule', dest='direct_rule',
|
||||||
help='user rule file, contains domains not bypass proxy')
|
help='user rule file, contains domains not bypass proxy')
|
||||||
|
parser.add_argument('--localtld-rule', dest='localtld_rule',
|
||||||
|
help='local TLD rule file, contains TLDs with a leading dot not bypass proxy')
|
||||||
parser.add_argument('--ip-file', dest='ip_file',
|
parser.add_argument('--ip-file', dest='ip_file',
|
||||||
help='delegated-apnic-latest from apnic.net')
|
help='delegated-apnic-latest from apnic.net')
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
@@ -192,7 +194,7 @@ def reduce_domains(domains):
|
|||||||
return uni_domains
|
return uni_domains
|
||||||
|
|
||||||
|
|
||||||
def generate_pac_fast(domains, proxy, direct_domains, cnips):
|
def generate_pac_fast(domains, proxy, direct_domains, cnips, local_tlds):
|
||||||
# render the pac file
|
# render the pac file
|
||||||
with open('./pac-template', 'rb') as f:
|
with open('./pac-template', 'rb') as f:
|
||||||
proxy_content = f.read()
|
proxy_content = f.read()
|
||||||
@@ -218,6 +220,14 @@ def generate_pac_fast(domains, proxy, direct_domains, cnips):
|
|||||||
json.dumps(cnips, indent=2, sort_keys=False)
|
json.dumps(cnips, indent=2, sort_keys=False)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tlds_dict = {}
|
||||||
|
for domain in local_tlds:
|
||||||
|
tlds_dict[domain] = 1
|
||||||
|
proxy_content = proxy_content.replace(
|
||||||
|
'__LOCAL_TLDS__',
|
||||||
|
json.dumps(tlds_dict, indent=2, sort_keys=True)
|
||||||
|
)
|
||||||
|
|
||||||
return proxy_content
|
return proxy_content
|
||||||
|
|
||||||
|
|
||||||
@@ -243,6 +253,7 @@ def main():
|
|||||||
args = parse_args()
|
args = parse_args()
|
||||||
user_rule = None
|
user_rule = None
|
||||||
direct_rule = None
|
direct_rule = None
|
||||||
|
localtld_rule = None
|
||||||
if (args.input):
|
if (args.input):
|
||||||
with open(args.input, 'rb') as f:
|
with open(args.input, 'rb') as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
@@ -274,6 +285,20 @@ def main():
|
|||||||
else:
|
else:
|
||||||
direct_rule = []
|
direct_rule = []
|
||||||
|
|
||||||
|
if args.localtld_rule:
|
||||||
|
tldrule_parts = urlparse.urlsplit(args.localtld_rule)
|
||||||
|
if not tldrule_parts.scheme or not tldrule_parts.netloc:
|
||||||
|
# It's not an URL, deal it as local file
|
||||||
|
with open(args.localtld_rule, 'rb') as f:
|
||||||
|
localtld_rule = f.read()
|
||||||
|
else:
|
||||||
|
# Yeah, it's an URL, try to download it
|
||||||
|
print 'Downloading local tlds rules file from %s' % args.user_rule
|
||||||
|
localtld_rule = urllib2.urlopen(args.localtld_rule, timeout=10).read()
|
||||||
|
localtld_rule = localtld_rule.splitlines(False)
|
||||||
|
else:
|
||||||
|
localtld_rule = []
|
||||||
|
|
||||||
cnips = fetch_ip_data()
|
cnips = fetch_ip_data()
|
||||||
|
|
||||||
content = decode_gfwlist(content)
|
content = decode_gfwlist(content)
|
||||||
@@ -281,7 +306,7 @@ def main():
|
|||||||
|
|
||||||
domains = parse_gfwlist(gfwlist)
|
domains = parse_gfwlist(gfwlist)
|
||||||
domains = reduce_domains(domains)
|
domains = reduce_domains(domains)
|
||||||
pac_content = generate_pac_fast(domains, args.proxy, direct_rule, cnips)
|
pac_content = generate_pac_fast(domains, args.proxy, direct_rule, cnips, localtld_rule)
|
||||||
|
|
||||||
with open(args.output, 'wb') as f:
|
with open(args.output, 'wb') as f:
|
||||||
f.write(pac_content)
|
f.write(pac_content)
|
||||||
|
|||||||
4439
gfwlist.txt
4439
gfwlist.txt
File diff suppressed because it is too large
Load Diff
2
local-tlds.txt
Normal file
2
local-tlds.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.test
|
||||||
|
.localhost
|
||||||
36
pac-template
36
pac-template
@@ -1,13 +1,14 @@
|
|||||||
|
var proxy = __PROXY__;
|
||||||
|
|
||||||
|
var direct = 'DIRECT;';
|
||||||
|
|
||||||
var cnips = __CN_IPS__;
|
var cnips = __CN_IPS__;
|
||||||
|
|
||||||
var directDomains = __DIRECT_DOMAINS__;
|
var directDomains = __DIRECT_DOMAINS__;
|
||||||
|
|
||||||
var domains = __DOMAINS__;
|
var domainsUsingProxy = __DOMAINS__;
|
||||||
|
|
||||||
var proxy = __PROXY__;
|
var localTlds = __LOCAL_TLDS__;
|
||||||
|
|
||||||
var direct = 'DIRECT;';
|
|
||||||
|
|
||||||
var hasOwnProperty = Object.hasOwnProperty;
|
var hasOwnProperty = Object.hasOwnProperty;
|
||||||
|
|
||||||
@@ -63,9 +64,32 @@ function testDomain(target, domains, cnRootIncluded) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isLocalTestDomain(domain) {
|
||||||
|
// Chrome uses .test as testing gTLD.
|
||||||
|
var tld = domain.substring(domain.lastIndexOf('.'));
|
||||||
|
if (tld === domain) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Object.hasOwnProperty.call(localTlds, tld);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* https://github.com/frenchbread/private-ip */
|
||||||
|
function isPrivateIp(ip) {
|
||||||
|
return /^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
||||||
|
/^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
||||||
|
/^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
||||||
|
/^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
||||||
|
/^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
||||||
|
/^f[cd][0-9a-f]{2}:/i.test(ip) ||
|
||||||
|
/^fe80:/i.test(ip) ||
|
||||||
|
/^::1$/.test(ip) ||
|
||||||
|
/^::$/.test(ip);
|
||||||
|
}
|
||||||
|
|
||||||
function FindProxyForURL(url, host) {
|
function FindProxyForURL(url, host) {
|
||||||
if (isPlainHostName(host)
|
if (isPlainHostName(host)
|
||||||
|| host === '127.0.0.1'
|
|| isPrivateIp(host)
|
||||||
|
|| isLocalTestDomain(host)
|
||||||
|| host === 'localhost') {
|
|| host === 'localhost') {
|
||||||
return direct;
|
return direct;
|
||||||
}
|
}
|
||||||
@@ -75,7 +99,7 @@ function FindProxyForURL(url, host) {
|
|||||||
return direct
|
return direct
|
||||||
}
|
}
|
||||||
|
|
||||||
if (testDomain(host, domains)) {
|
if (testDomain(host, domainsUsingProxy)) {
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
strIp = dnsResolve(host);
|
strIp = dnsResolve(host);
|
||||||
|
|||||||
Reference in New Issue
Block a user