initial commit.
This commit is contained in:
45
.gitignore
vendored
Normal file
45
.gitignore
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
41
README.md
Normal file
41
README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# gfw-pac
|
||||
|
||||
通过 gfwlist 和中国 IP 地址生成 PAC(Proxy auto-config) 文件。对存在于 gfwlist 的域名和解析出的 IP 在国外的域名使用代理。
|
||||
|
||||
基于 [GFWList2PAC](https://github.com/clowwindy/gfwlist2pac) 和 [Flora PAC](https://github.com/Leask/Flora_Pac)
|
||||
|
||||
## 特性
|
||||
* 速度快,优先按域名匹配,再按 IP 匹配
|
||||
* 可自定义需要代理的域名
|
||||
* 可自定义不需要代理的域名
|
||||
* 如果访问的域名不在列表里,但是 IP 在国外,也返回代理服务器
|
||||
|
||||
## 用法
|
||||
|
||||
直接使用 `gfw.pac`,或者手工运行 `gfw-pac.py` 生成自己的 pac 文件。
|
||||
|
||||
## gfw-pac.py 使用说明
|
||||
|
||||
usage: gfw-pac.py [-h] [-i GFWLIST] -f PAC -p PROXY [--user-rule USER_RULE]
|
||||
[--direct-rule DIRECT_RULE] [--ip-file IP_FILE]
|
||||
|
||||
参数说明:
|
||||
|
||||
-h 显示帮助
|
||||
-i 指定本地 gfwlist 文件,若不指定则自动从 googlecode 下载
|
||||
-f (必须)输出的 pac 文件
|
||||
-p (必须)指定代理服务器
|
||||
--user-rule 自定义使用代理的域名文件,文件里每行一个域名
|
||||
--direct-rule 自定义不使用代理的域名文件,文件里每行一个域名
|
||||
--ip-file 指定本地的从 apnic 下载的 IP 分配文件。若不指定则自动从 apnic 下载
|
||||
|
||||
举例:
|
||||
|
||||
./gfw-pac.py -i gfwlist.txt \
|
||||
-f gfw.pac \
|
||||
-p "PROXY 192.168.1.200:3128; DIRECT" \
|
||||
--user-rule=custom-domains.txt \
|
||||
--direct-rule=direct-domains.txt \
|
||||
--ip-file=delegated-apnic-latest.txt
|
||||
|
||||
[一路凯歌 技术博客](http://zhiyi.us)
|
||||
55
custom-domains.txt
Normal file
55
custom-domains.txt
Normal file
@@ -0,0 +1,55 @@
|
||||
google.com
|
||||
google.com.hk
|
||||
ggpht.com
|
||||
googleapis.com
|
||||
google-analytics.com
|
||||
googleadservices.com
|
||||
googlesyndication.com
|
||||
googleadsserving.cn
|
||||
doubleclick.net
|
||||
wikipedia.org
|
||||
stackoverflow.com
|
||||
sstatic.net
|
||||
imgur.com
|
||||
github.com
|
||||
githubusercontent.com
|
||||
github.io
|
||||
googlecode.com
|
||||
docker.io
|
||||
docker.com
|
||||
angularjs.org
|
||||
rsyslog.com
|
||||
gerhards.net
|
||||
chrome.com
|
||||
digicert.com
|
||||
typekit.net
|
||||
wordpress.com
|
||||
aolcdn.com
|
||||
wp.com
|
||||
ifixit.com
|
||||
atlassian.com
|
||||
amazonaws.com
|
||||
cloudfront.net
|
||||
trello.com
|
||||
appelsiini.net
|
||||
angularjs.org
|
||||
mplxtms.com
|
||||
slack.com
|
||||
fastly.net
|
||||
edgekey.net
|
||||
discussions.apple.com
|
||||
disquscdn.com
|
||||
wenzhixin.net.cn
|
||||
last.fm
|
||||
scdn.co
|
||||
spotify.com
|
||||
spotilocal.com
|
||||
music.126.net
|
||||
laravel.com
|
||||
youbma.com
|
||||
youb99.com
|
||||
youb88.com
|
||||
youb77.com
|
||||
youb66.com
|
||||
youb11.com
|
||||
qiporn.com
|
||||
38084
delegated-apnic-latest.txt
Normal file
38084
delegated-apnic-latest.txt
Normal file
File diff suppressed because it is too large
Load Diff
368
direct-domains.txt
Normal file
368
direct-domains.txt
Normal file
@@ -0,0 +1,368 @@
|
||||
10010.com
|
||||
115.com
|
||||
123u.com
|
||||
126.com
|
||||
126.net
|
||||
163.com
|
||||
17173.com
|
||||
178.com
|
||||
17cdn.com
|
||||
21cn.com
|
||||
2288.org
|
||||
3322.org
|
||||
360buy.com
|
||||
360buyimg.com
|
||||
360doc.com
|
||||
360safe.com
|
||||
36kr.com
|
||||
400gb.com
|
||||
4399.com
|
||||
51.la
|
||||
51buy.com
|
||||
51cto.com
|
||||
51job.com
|
||||
51jobcdn.com
|
||||
5d6d.com
|
||||
5d6d.net
|
||||
61.com
|
||||
6600.org
|
||||
6rooms.com
|
||||
7766.org
|
||||
7k7k.com
|
||||
8800.org
|
||||
8866.org
|
||||
90g.org
|
||||
91.com
|
||||
9966.org
|
||||
acfun.tv
|
||||
aicdn.com
|
||||
ali213.net
|
||||
alibaba.com
|
||||
alicdn.com
|
||||
aliexpress.com
|
||||
aliimg.com
|
||||
alikunlun.com
|
||||
alimama.com
|
||||
alipay.com
|
||||
alipayobjects.com
|
||||
alisoft.com
|
||||
aliyun.com
|
||||
aliyuncdn.com
|
||||
aliyuncs.com
|
||||
anzhi.com
|
||||
appinn.com
|
||||
apple.com
|
||||
appsina.com
|
||||
archlinuxcn.org
|
||||
atpanel.com
|
||||
baidu.com
|
||||
baidupcs.com
|
||||
baidustatic.com
|
||||
baifendian.com
|
||||
baihe.com
|
||||
baixing.com
|
||||
bdimg.com
|
||||
bdstatic.com
|
||||
bilibili.tv
|
||||
blogbus.com
|
||||
blueidea.com
|
||||
ccb.com
|
||||
cctv.com
|
||||
cctvpic.com
|
||||
cdn20.com
|
||||
china.com
|
||||
chinabyte.com
|
||||
chinacache.com
|
||||
chinacache.net
|
||||
chinacaipu.com
|
||||
chinagba.com
|
||||
chinahr.com
|
||||
chinajoy.net
|
||||
chinamobile.com
|
||||
chinanetcenter.com
|
||||
chinanews.com
|
||||
chinapnr.com
|
||||
chinaren.com
|
||||
chinaspeeds.net
|
||||
chinaunix.net
|
||||
chinaz.com
|
||||
chint.com
|
||||
chiphell.com
|
||||
chuangxin.com
|
||||
ci123.com
|
||||
ciku5.com
|
||||
citysbs.com
|
||||
class.coursera.org
|
||||
cloudcdn.net
|
||||
cmbchina.com
|
||||
cmfu.com
|
||||
cmread.com
|
||||
cmwb.com
|
||||
cn.archive.ubuntu.com
|
||||
cn.bing.com
|
||||
cn.coremetrics.com
|
||||
cn.debian.org
|
||||
cn.msn.com
|
||||
cn
|
||||
cnak2.englishtown.com
|
||||
cnbeta.com
|
||||
cnbetacdn.com
|
||||
cnblogs.com
|
||||
cnepub.com
|
||||
cnzz.com
|
||||
comsenz.com
|
||||
csdn.net
|
||||
ct10000.com
|
||||
ctdisk.com
|
||||
dangdang.com
|
||||
dbank.com
|
||||
dedecms.com
|
||||
diandian.com
|
||||
dianping.com
|
||||
discuz.com
|
||||
discuz.net
|
||||
dl.google.com
|
||||
docin.com
|
||||
donews.com
|
||||
dospy.com
|
||||
douban.com
|
||||
douban.fm
|
||||
duapp.com
|
||||
duba.net
|
||||
duomi.com
|
||||
duote.com
|
||||
duowan.com
|
||||
egou.com
|
||||
et8.org
|
||||
etao.com
|
||||
f3322.org
|
||||
fantong.com
|
||||
fenzhi.com
|
||||
fhldns.com
|
||||
ganji.com
|
||||
gaopeng.com
|
||||
geekpark.net
|
||||
gfan.com
|
||||
gtimg.com
|
||||
hacdn.net
|
||||
hadns.net
|
||||
hao123.com
|
||||
hao123img.com
|
||||
hc360.com
|
||||
hdslb.com
|
||||
hexun.com
|
||||
hiapk.com
|
||||
hichina.com
|
||||
hoopchina.com
|
||||
huanqiu.com
|
||||
hudong.com
|
||||
huochepiao.com
|
||||
hupu.com
|
||||
iask.com
|
||||
iciba.com
|
||||
idqqimg.com
|
||||
ifanr.com
|
||||
ifeng.com
|
||||
ifengimg.com
|
||||
ijinshan.com
|
||||
iqiyi.com
|
||||
it168.com
|
||||
itcpn.net
|
||||
iteye.com
|
||||
itouzi.com
|
||||
jandan.net
|
||||
jd.com
|
||||
jiashule.com
|
||||
jiasule.com
|
||||
jiathis.com
|
||||
jiayuan.com
|
||||
jiepang.com
|
||||
jing.fm
|
||||
jobbole.com
|
||||
jstv.com
|
||||
jumei.com
|
||||
kaixin001.com
|
||||
kandian.com
|
||||
kandian.net
|
||||
kanimg.com
|
||||
kankanews.com
|
||||
kdnet.net
|
||||
koudai8.com
|
||||
ku6.com
|
||||
ku6cdn.com
|
||||
ku6img.com
|
||||
kuaidi100.com
|
||||
kugou.com
|
||||
lashou.com
|
||||
letao.com
|
||||
letv.com
|
||||
lietou.com
|
||||
linezing.com
|
||||
loli.mg
|
||||
loli.vg
|
||||
lvping.com
|
||||
lxdns.com
|
||||
mangocity.com
|
||||
mapbar.com
|
||||
mcbbs.net
|
||||
mediav.com
|
||||
meilishuo.com
|
||||
meituan.com
|
||||
meituan.net
|
||||
meizu.com
|
||||
microsoft.com
|
||||
miui.com
|
||||
moe123.com
|
||||
moegirl.org
|
||||
mop.com
|
||||
mtime.com
|
||||
my-card.in
|
||||
mydrivers.com
|
||||
mzstatic.com
|
||||
netease.com
|
||||
newsmth.net
|
||||
ngacn.cc
|
||||
nuomi.com
|
||||
okbuy.com
|
||||
optaim.com
|
||||
oschina.net
|
||||
paipai.com
|
||||
pcbeta.com
|
||||
pchome.net
|
||||
pcpop.com
|
||||
pengyou.com
|
||||
phoenixlzx.com
|
||||
phpwind.net
|
||||
pingan.com
|
||||
pool.ntp.org
|
||||
pplive.com
|
||||
pps.tv
|
||||
ppstream.com
|
||||
pptv.com
|
||||
pubyun.com
|
||||
qhimg.com
|
||||
qianlong.com
|
||||
qidian.com
|
||||
qingdaonews.com
|
||||
qiniu.com
|
||||
qiniudn.com
|
||||
qiushibaike.com
|
||||
qiyi.com
|
||||
qiyipic.com
|
||||
qq.com
|
||||
qqmail.com
|
||||
qstatic.com
|
||||
qunar.com
|
||||
qunarzz.com
|
||||
qvbuy.com
|
||||
renren.com
|
||||
renrendai.com
|
||||
rrfmn.com
|
||||
rrimg.com
|
||||
sanguosha.com
|
||||
sdo.com
|
||||
sina.com
|
||||
sinaapp.com
|
||||
sinaedge.com
|
||||
sinaimg.com
|
||||
sinajs.com
|
||||
skycn.com
|
||||
smzdm.com
|
||||
sogou.com
|
||||
sohu.com
|
||||
soku.com
|
||||
solidot.org
|
||||
soso.com
|
||||
soufun.com
|
||||
soufunimg.com
|
||||
staticfile.org
|
||||
staticsdo.com
|
||||
steamcn.com
|
||||
suning.com
|
||||
szzfgjj.com
|
||||
tanx.com
|
||||
taobao.com
|
||||
taobaocdn.com
|
||||
tbcache.com
|
||||
tdimg.com
|
||||
tencent.com
|
||||
tenpay.com
|
||||
tgbus.com
|
||||
thawte.com
|
||||
tiancity.com
|
||||
tianyaui.com
|
||||
tiexue.net
|
||||
tmall.com
|
||||
tmcdn.net
|
||||
tom.com
|
||||
tomonline-inc.com
|
||||
tuan800.com
|
||||
tuan800.net
|
||||
tuanimg.com
|
||||
tudou.com
|
||||
tudouui.com
|
||||
tuniu.com
|
||||
u148.net
|
||||
u17.com
|
||||
ubuntu.com
|
||||
ucjoy.com
|
||||
uni-marketers.com
|
||||
unionpay.com
|
||||
unionpaysecure.com
|
||||
upaiyun.com
|
||||
upyun.com
|
||||
uusee.com
|
||||
uuu9.com
|
||||
vaikan.com
|
||||
vancl.com
|
||||
vcimg.com
|
||||
verycd.com
|
||||
wandoujia.com
|
||||
wdjimg.com
|
||||
weibo.com
|
||||
weiphone.com
|
||||
weiyun.com
|
||||
west263.com
|
||||
wrating.com
|
||||
wscdns.com
|
||||
wumii.com
|
||||
xdcdn.net
|
||||
xiachufang.com
|
||||
xiami.com
|
||||
xiami.net
|
||||
xiaomi.com
|
||||
xiaonei.com
|
||||
xiazaiba.com
|
||||
xici.net
|
||||
xilu.com
|
||||
xinhuanet.com
|
||||
xinnet.com
|
||||
xlpan.com
|
||||
xn--fiqs8s
|
||||
xnpic.com
|
||||
xungou.com
|
||||
xunlei.com
|
||||
ydstatic.com
|
||||
yesky.com
|
||||
yeyou.com
|
||||
yihaodian.com
|
||||
yihaodianimg.com
|
||||
yingjiesheng.com
|
||||
yintai.com
|
||||
yinyuetai.com
|
||||
yiqifa.com
|
||||
yixun.com
|
||||
ykimg.com
|
||||
ynet.com
|
||||
youdao.com
|
||||
yougou.com
|
||||
youku.com
|
||||
yupoo.com
|
||||
yy.com
|
||||
zbjimg.com
|
||||
zhaopin.com
|
||||
zhi.hu
|
||||
zhihu.com
|
||||
zhimg.com
|
||||
zhubajie.com
|
||||
zongheng.com
|
||||
289
gfw-pac.py
Executable file
289
gfw-pac.py
Executable file
@@ -0,0 +1,289 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
import math
|
||||
import socket
|
||||
import struct
|
||||
import pkgutil
|
||||
import urlparse
|
||||
import json
|
||||
import logging
|
||||
import urllib2
|
||||
from argparse import ArgumentParser
|
||||
|
||||
gfwlist_url = 'https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt'
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('-i', '--input', dest='input',
|
||||
help='path to gfwlist', metavar='GFWLIST')
|
||||
parser.add_argument('-f', '--file', dest='output', required=True,
|
||||
help='path to output pac', metavar='PAC')
|
||||
parser.add_argument('-p', '--proxy', dest='proxy', required=True,
|
||||
help='the proxy parameter in the pac file, '
|
||||
'for example, "SOCKS5 127.0.0.1:1080;"',
|
||||
metavar='PROXY')
|
||||
parser.add_argument('--user-rule', dest='user_rule',
|
||||
help='user rule file, which will be appended to'
|
||||
' gfwlist')
|
||||
parser.add_argument('--direct-rule', dest='direct_rule',
|
||||
help='user rule file, contains domains not bypass proxy')
|
||||
parser.add_argument('--ip-file', dest='ip_file',
|
||||
help='delegated-apnic-latest from apnic.net')
|
||||
return parser.parse_args()
|
||||
|
||||
#from https://github.com/Leask/Flora_Pac
|
||||
def ip2long(ip):
|
||||
packedIP = socket.inet_aton(ip)
|
||||
return struct.unpack("!L", packedIP)[0]
|
||||
|
||||
#from https://github.com/Leask/Flora_Pac
|
||||
def fetch_ip_data():
|
||||
args = parse_args()
|
||||
if (args.ip_file):
|
||||
with open(args.ip_file, 'rb') as f:
|
||||
data = f.read()
|
||||
else:
|
||||
#fetch data from apnic
|
||||
print "Fetching data from apnic.net, it might take a few minutes, please wait..."
|
||||
url=r'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest'
|
||||
# url=r'http://flora/delegated-apnic-latest' #debug
|
||||
data=urllib2.urlopen(url).read()
|
||||
|
||||
cnregex=re.compile(r'apnic\|cn\|ipv4\|[0-9\.]+\|[0-9]+\|[0-9]+\|a.*',re.IGNORECASE)
|
||||
cndata=cnregex.findall(data)
|
||||
|
||||
results=[]
|
||||
prev_net=''
|
||||
|
||||
for item in cndata:
|
||||
unit_items=item.split('|')
|
||||
starting_ip=unit_items[3]
|
||||
num_ip=int(unit_items[4])
|
||||
|
||||
imask=0xffffffff^(num_ip-1)
|
||||
#convert to string
|
||||
imask=hex(imask)[2:]
|
||||
mask=[0]*4
|
||||
mask[0]=imask[0:2]
|
||||
mask[1]=imask[2:4]
|
||||
mask[2]='0' #imask[4:6]
|
||||
mask[3]='0' #imask[6:8]
|
||||
|
||||
#convert str to int
|
||||
mask=[ int(i,16 ) for i in mask]
|
||||
mask="%d.%d.%d.%d"%tuple(mask)
|
||||
|
||||
#mask in *nix format
|
||||
mask2=32-int(math.log(num_ip,2))
|
||||
|
||||
ip=starting_ip.split('.')
|
||||
ip[2] = '0'
|
||||
ip[3] = '0'
|
||||
starting_ip = '.'.join(ip)
|
||||
if starting_ip != prev_net:
|
||||
results.append((ip2long(starting_ip), ip2long(mask), mask2))
|
||||
prev_net = starting_ip
|
||||
|
||||
results.insert(0, (ip2long('127.0.0.1'), ip2long('255.0.0.0'), 0))
|
||||
results.insert(1, (ip2long('10.0.0.0'), ip2long('255.0.0.0'), 0))
|
||||
results.insert(2, (ip2long('172.16.0.0'), ip2long('255.240.0.0'), 0))
|
||||
results.insert(3, (ip2long('192.168.0.0'), ip2long('255.255.0.0'), 0))
|
||||
def ip(item):
|
||||
return item[0]
|
||||
|
||||
results = sorted(results, key = ip)
|
||||
return results
|
||||
|
||||
def decode_gfwlist(content):
|
||||
# decode base64 if have to
|
||||
try:
|
||||
if '.' in content:
|
||||
raise Exception()
|
||||
return content.decode('base64')
|
||||
except:
|
||||
return content
|
||||
|
||||
|
||||
def get_hostname(something):
|
||||
try:
|
||||
# quite enough for GFW
|
||||
if not something.startswith('http:'):
|
||||
something = 'http://' + something
|
||||
r = urlparse.urlparse(something)
|
||||
return r.hostname
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
return None
|
||||
|
||||
|
||||
def add_domain_to_set(s, something):
|
||||
hostname = get_hostname(something)
|
||||
if hostname is not None:
|
||||
s.add(hostname)
|
||||
|
||||
|
||||
def combine_lists(content, user_rule=None):
|
||||
gfwlist = content.splitlines(False)
|
||||
if user_rule:
|
||||
gfwlist.extend(user_rule.splitlines(False))
|
||||
return gfwlist
|
||||
|
||||
|
||||
def parse_gfwlist(gfwlist):
|
||||
domains = set()
|
||||
for line in gfwlist:
|
||||
if line.find('.*') >= 0:
|
||||
continue
|
||||
elif line.find('*') >= 0:
|
||||
line = line.replace('*', '/')
|
||||
if line.startswith('||'):
|
||||
line = line.lstrip('||')
|
||||
elif line.startswith('|'):
|
||||
line = line.lstrip('|')
|
||||
elif line.startswith('.'):
|
||||
line = line.lstrip('.')
|
||||
if line.startswith('!'):
|
||||
continue
|
||||
elif line.startswith('['):
|
||||
continue
|
||||
elif line.startswith('@'):
|
||||
# ignore white list
|
||||
continue
|
||||
add_domain_to_set(domains, line)
|
||||
return domains
|
||||
|
||||
|
||||
def reduce_domains(domains):
|
||||
# reduce 'www.google.com' to 'google.com'
|
||||
# remove invalid domains
|
||||
with open('./tld.txt', 'rb') as f:
|
||||
tld_content = f.read()
|
||||
tlds = set(tld_content.splitlines(False))
|
||||
new_domains = set()
|
||||
for domain in domains:
|
||||
domain_parts = domain.split('.')
|
||||
last_root_domain = None
|
||||
for i in xrange(0, len(domain_parts)):
|
||||
root_domain = '.'.join(domain_parts[len(domain_parts) - i - 1:])
|
||||
if i == 0:
|
||||
if not tlds.__contains__(root_domain):
|
||||
# root_domain is not a valid tld
|
||||
break
|
||||
last_root_domain = root_domain
|
||||
if tlds.__contains__(root_domain):
|
||||
continue
|
||||
else:
|
||||
break
|
||||
if last_root_domain is not None:
|
||||
new_domains.add(last_root_domain)
|
||||
|
||||
uni_domains = set()
|
||||
for domain in new_domains:
|
||||
domain_parts = domain.split('.')
|
||||
for i in xrange(0, len(domain_parts)-1):
|
||||
root_domain = '.'.join(domain_parts[len(domain_parts) - i - 1:])
|
||||
if domains.__contains__(root_domain):
|
||||
break
|
||||
else:
|
||||
uni_domains.add(domain)
|
||||
return uni_domains
|
||||
|
||||
|
||||
def generate_pac_fast(domains, proxy, direct_domains, cnips):
|
||||
# render the pac file
|
||||
with open('./pac-template', 'rb') as f:
|
||||
proxy_content = f.read()
|
||||
domains_dict = {}
|
||||
for domain in domains:
|
||||
domains_dict[domain] = 1
|
||||
proxy_content = proxy_content.replace('__PROXY__', json.dumps(str(proxy)))
|
||||
proxy_content = proxy_content.replace(
|
||||
'__DOMAINS__',
|
||||
json.dumps(domains_dict, indent=2, sort_keys=True)
|
||||
)
|
||||
|
||||
direct_domains_dict = {}
|
||||
for domain in direct_domains:
|
||||
direct_domains_dict[domain] = 1
|
||||
proxy_content = proxy_content.replace(
|
||||
'__DIRECT_DOMAINS__',
|
||||
json.dumps(direct_domains_dict, indent=2, sort_keys=True)
|
||||
)
|
||||
|
||||
proxy_content = proxy_content.replace(
|
||||
'__CN_IPS__',
|
||||
json.dumps(cnips, indent=2, sort_keys=False)
|
||||
)
|
||||
|
||||
return proxy_content
|
||||
|
||||
|
||||
def generate_pac_precise(rules, proxy):
|
||||
def grep_rule(rule):
|
||||
if rule:
|
||||
if rule.startswith('!'):
|
||||
return None
|
||||
if rule.startswith('['):
|
||||
return None
|
||||
return rule
|
||||
return None
|
||||
# render the pac file
|
||||
proxy_content = pkgutil.get_data('gfwlist2pac', './abp.js')
|
||||
rules = filter(grep_rule, rules)
|
||||
proxy_content = proxy_content.replace('__PROXY__', json.dumps(str(proxy)))
|
||||
proxy_content = proxy_content.replace('__RULES__',
|
||||
json.dumps(rules, indent=2))
|
||||
return proxy_content
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
user_rule = None
|
||||
direct_rule = None
|
||||
if (args.input):
|
||||
with open(args.input, 'rb') as f:
|
||||
content = f.read()
|
||||
else:
|
||||
print 'Downloading gfwlist from %s' % gfwlist_url
|
||||
content = urllib2.urlopen(gfwlist_url, timeout=10).read()
|
||||
if args.user_rule:
|
||||
userrule_parts = urlparse.urlsplit(args.user_rule)
|
||||
if not userrule_parts.scheme or not userrule_parts.netloc:
|
||||
# It's not an URL, deal it as local file
|
||||
with open(args.user_rule, 'rb') as f:
|
||||
user_rule = f.read()
|
||||
else:
|
||||
# Yeah, it's an URL, try to download it
|
||||
print 'Downloading user rules file from %s' % args.user_rule
|
||||
user_rule = urllib2.urlopen(args.user_rule, timeout=10).read()
|
||||
|
||||
if args.direct_rule:
|
||||
directrule_parts = urlparse.urlsplit(args.direct_rule)
|
||||
if not directrule_parts.scheme or not directrule_parts.netloc:
|
||||
# It's not an URL, deal it as local file
|
||||
with open(args.direct_rule, 'rb') as f:
|
||||
direct_rule = f.read()
|
||||
else:
|
||||
# Yeah, it's an URL, try to download it
|
||||
print 'Downloading user rules file from %s' % args.user_rule
|
||||
direct_rule = urllib2.urlopen(args.direct_rule, timeout=10).read()
|
||||
direct_rule = direct_rule.splitlines(False)
|
||||
|
||||
cnips = fetch_ip_data()
|
||||
|
||||
content = decode_gfwlist(content)
|
||||
gfwlist = combine_lists(content, user_rule)
|
||||
|
||||
domains = parse_gfwlist(gfwlist)
|
||||
domains = reduce_domains(domains)
|
||||
pac_content = generate_pac_fast(domains, args.proxy, direct_rule, cnips)
|
||||
|
||||
with open(args.output, 'wb') as f:
|
||||
f.write(pac_content)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
2244
gfwlist.txt
Normal file
2244
gfwlist.txt
Normal file
File diff suppressed because it is too large
Load Diff
91
pac-template
Normal file
91
pac-template
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
var cnips = __CN_IPS__;
|
||||
|
||||
var directDomains = __DIRECT_DOMAINS__;
|
||||
|
||||
var domains = __DOMAINS__;
|
||||
|
||||
var proxy = __PROXY__;
|
||||
|
||||
var direct = 'DIRECT;';
|
||||
|
||||
var hasOwnProperty = Object.hasOwnProperty;
|
||||
|
||||
function convertAddress(ipchars) {
|
||||
var bytes = ipchars.split('.');
|
||||
var result = ((bytes[0] & 0xff) << 24) |
|
||||
((bytes[1] & 0xff) << 16) |
|
||||
((bytes[2] & 0xff) << 8) |
|
||||
(bytes[3] & 0xff);
|
||||
return result;
|
||||
}
|
||||
|
||||
function match(ip) {
|
||||
var left = 0, right = cnips.length;
|
||||
do {
|
||||
var mid = Math.floor((left + right) / 2),
|
||||
ipf = (ip & cnips[mid][1]) >>> 0,
|
||||
m = (cnips[mid][0] & cnips[mid][1]) >>> 0;
|
||||
if (ipf == m) {
|
||||
return true;
|
||||
} else if (ipf > m) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid;
|
||||
}
|
||||
} while (left + 1 <= right)
|
||||
return false;
|
||||
}
|
||||
|
||||
function testDomain(target, domains, cnRootIncluded) {
|
||||
var idxA = target.lastIndexOf('.');
|
||||
var idxB = target.lastIndexOf('.', idxA - 1);
|
||||
var hasOwnProperty = Object.hasOwnProperty;
|
||||
var suffix = cnRootIncluded ? target.substring(idxA + 1) : '';
|
||||
if (suffix === 'cn') {
|
||||
return true;
|
||||
}
|
||||
while (true) {
|
||||
if (idxB === -1) {
|
||||
if (hasOwnProperty.call(domains, target)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
suffix = target.substring(idxB + 1);
|
||||
if (hasOwnProperty.call(domains, suffix)) {
|
||||
return true;
|
||||
}
|
||||
idxB = target.lastIndexOf('.', idxB - 1);
|
||||
}
|
||||
}
|
||||
|
||||
function FindProxyForURL(url, host) {
|
||||
if (isPlainHostName(host)
|
||||
|| host === '127.0.0.1'
|
||||
|| host === 'localhost') {
|
||||
return direct;
|
||||
}
|
||||
|
||||
if (testDomain(host, directDomains, true)) {
|
||||
return direct
|
||||
}
|
||||
|
||||
if (testDomain(host, domains)) {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
var strIp = dnsResolve(host);
|
||||
|
||||
if (!strIp) {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
var intIp = convertAddress(strIp);
|
||||
if (match(intIp)) {
|
||||
return direct;
|
||||
}
|
||||
|
||||
return proxy;
|
||||
}
|
||||
Reference in New Issue
Block a user