├── dist └── .gitignore ├── custom ├── direct.txt ├── reject.txt └── proxy.txt ├── .gitignore ├── surge_rules.txt ├── official ├── private.txt └── cn.txt ├── package.json ├── router.proto ├── LICENSE ├── README.md ├── geolite └── GeoLite2-Country-Locations-en.csv └── app.js /dist/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | * 3 | -------------------------------------------------------------------------------- /custom/direct.txt: -------------------------------------------------------------------------------- 1 | # baidu.com 2 | # 1.1.1.1/32 3 | -------------------------------------------------------------------------------- /custom/reject.txt: -------------------------------------------------------------------------------- 1 | # baidu.com 2 | # 1.1.1.1/32 3 | -------------------------------------------------------------------------------- /custom/proxy.txt: -------------------------------------------------------------------------------- 1 | # baidu.com 2 | # 1.1.1.1/32 3 | pixiv.net 4 | pixiv.org 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | package-lock.json 4 | geoip.dat 5 | geosite.dat 6 | -------------------------------------------------------------------------------- /surge_rules.txt: -------------------------------------------------------------------------------- 1 | https://github.com/lhie1/Surge/raw/master/Basics.conf 2 | https://github.com/lhie1/Surge/raw/master/DIRECT.conf 3 | https://github.com/lhie1/Surge/raw/master/PROXY.conf 4 | https://github.com/lhie1/Surge/raw/master/REJECT.conf 5 | -------------------------------------------------------------------------------- /official/private.txt: -------------------------------------------------------------------------------- 1 | 0.0.0.0/8 2 | 10.0.0.0/8 3 | 100.64.0.0/10 4 | 127.0.0.0/8 5 | 169.254.0.0/16 6 | 172.16.0.0/12 7 | 192.0.0.0/24 8 | 192.0.2.0/24 9 | 192.168.0.0/16 10 | 198.18.0.0/15 11 | 198.51.100.0/24 12 | 203.0.113.0/24 13 | ::1/128 14 | fc00::/7 15 | fe80::/10 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "v2raygeokit", 3 | "version": "0.0.3", 4 | "scripts": { 5 | "start": "node app.js" 6 | }, 7 | "dependencies": { 8 | "dedupe": "^2.1.0", 9 | "ip": "^1.1.5", 10 | "is-cidr": "^2.0.4", 11 | "neat-csv": "^2.1.0", 12 | "protobufjs": "^6.8.3", 13 | "request": "^2.83.0", 14 | "request-promise": "^4.2.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /router.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package router; 4 | 5 | // Domain for routing decision. 6 | message Domain { 7 | // Type of domain value. 8 | enum Type { 9 | // The value is used as is. 10 | Plain = 0; 11 | // The value is used as a regular expression. 12 | Regex = 1; 13 | // The value is a domain. 14 | Domain = 2; 15 | } 16 | 17 | // Domain matching type. 18 | Type type = 1; 19 | 20 | // Domain value. 21 | string value = 2; 22 | } 23 | 24 | message GeoSite { 25 | string country_code = 1; 26 | repeated Domain domain = 2; 27 | } 28 | 29 | message GeoSiteList { 30 | repeated GeoSite entry = 1; 31 | } 32 | 33 | // IP for routing decision, in CIDR form. 34 | message CIDR { 35 | // IP address, should be either 4 or 16 bytes. 36 | bytes ip = 1; 37 | 38 | // Number of leading ones in the network mask. 39 | uint32 prefix = 2; 40 | } 41 | 42 | message GeoIP { 43 | string country_code = 1; 44 | repeated CIDR cidr = 2; 45 | } 46 | 47 | message GeoIPList { 48 | repeated GeoIP entry = 1; 49 | } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 没有说明( 2 | 3 | npm i && npm run start 4 | 5 | example rules 6 | ``` 7 | "rules": [{ 8 | "type": "field", 9 | "ip": [ 10 | "geoip:custom:reject", 11 | "geoip:surge:reject" 12 | ], 13 | "outboundTag": "reject" 14 | }, 15 | { 16 | "type": "field", 17 | "domain": [ 18 | "geosite:custom:reject", 19 | "geosite:surge:reject" 20 | ], 21 | "outboundTag": "reject" 22 | }, 23 | { 24 | "type": "field", 25 | "ip": [ 26 | "geoip:custom:direct", 27 | "geoip:surge:direct", 28 | "geoip:private" 29 | ], 30 | "outboundTag": "direct" 31 | }, 32 | { 33 | "type": "field", 34 | "domain": [ 35 | "geosite:custom:direct", 36 | "geosite:surge:direct", 37 | "geosite:gfwlist:direct", 38 | "geosite:cn" 39 | ], 40 | "outboundTag": "direct" 41 | }, 42 | { 43 | "type": "field", 44 | "ip": [ 45 | "geoip:custom:proxy", 46 | "geoip:surge:proxy" 47 | ], 48 | "outboundTag": "proxy" 49 | }, 50 | { 51 | "type": "field", 52 | "domain": [ 53 | "geosite:custom:proxy", 54 | "geosite:surge:proxy", 55 | "geosite:gfwlist:proxy" 56 | ], 57 | "outboundTag": "proxy" 58 | } 59 | ] 60 | ``` 61 | -------------------------------------------------------------------------------- /official/cn.txt: -------------------------------------------------------------------------------- 1 | cn 2 | xn--fiqs8s 3 | 10010.com 4 | 100offer.com 5 | 115.com 6 | 123juzi.com 7 | 123juzi.net 8 | 123u.com 9 | 126.com 10 | 126.net 11 | 127.net 12 | 163.com 13 | 17173.com 14 | 17cdn.com 15 | 188.com 16 | 1905.com 17 | 21cn.com 18 | 2288.org 19 | 2345.com 20 | 263.net 21 | 2cto.com 22 | 3322.org 23 | 35.com 24 | 360doc.com 25 | 360buy.com 26 | 360buyimg.com 27 | 360safe.com 28 | 36kr.com 29 | 39.net 30 | 3dmgame.com 31 | 3conline.com 32 | 4399.com 33 | 500d.me 34 | 50bang.org 35 | 51.la 36 | 51credit.com 37 | 51cto.com 38 | 51jingying.com 39 | 51job.com 40 | 51jobcdn.com 41 | 51wendang.com 42 | 55.com 43 | 51yes.com 44 | 55bbs.com 45 | 58.com 46 | 6rooms.com 47 | 71.am 48 | 7k7k.com 49 | 900.la 50 | 9718.com 51 | 9xu.com 52 | abchina.com 53 | acfun.tv 54 | acgvideo.com 55 | agrantsem.com 56 | aicdn.com 57 | aixifan.com 58 | alibaba.com 59 | alibabaplanet.com 60 | alicdn.com 61 | aliimg.com.com 62 | alipay.com 63 | alipayobjects.com 64 | aliyun.com 65 | aliyuncdn.com 66 | aliyuncs.com 67 | allyes.com 68 | amap.com 69 | anjuke.com 70 | anquan.org 71 | appinn.com 72 | babytree.com 73 | babytreeimg.com 74 | baidu.com 75 | baiducontent.com 76 | baidupcs.com 77 | baidustatic.com 78 | baifendian.com 79 | baifubao.com 80 | baihe.com 81 | baike.com 82 | baixing.com 83 | baixing.net 84 | bankcomm.com 85 | bankofchina.com 86 | bcy.net 87 | bdimg.com 88 | bdstatic.com 89 | bilibili.com 90 | cn.bing.com 91 | bitauto.com 92 | bitautoimg.com 93 | bobo.com 94 | bootcss.com 95 | btcfans.com 96 | caiyunapp.com 97 | ccb.com 98 | cctv.com 99 | cctvpic.com 100 | cdn20.com 101 | cebbank.com 102 | ch.com 103 | chashebao.com 104 | che168.com 105 | china.com 106 | chinacache.com 107 | chinacache.net 108 | chinahr.com 109 | chinamobile.com 110 | chinapay.com 111 | chinatranslation.net 112 | chinaz.com 113 | chiphell.com 114 | chouti.com 115 | chuangxin.com 116 | chuansong.me 117 | clouddn.com 118 | cloudxns.com 119 | cmbchina.com 120 | cnbeta.com 121 | cnbetacdn.com 122 | cnblogs.com 123 | cnepub.com 124 | cnzz.com 125 | coding.net 126 | coolapk.com 127 | cqvip.com 128 | csbew.com 129 | csdn.net 130 | ctfile.com 131 | ctrip.com 132 | cubead.com 133 | dajie.com 134 | dajieimg.com 135 | dangdang.com 136 | daocloud.io 137 | daovoice.io 138 | dbank.com 139 | dedecms.com 140 | dgtle.com 141 | diandian.com 142 | dianping.com 143 | diopic.net 144 | docin.com 145 | dockerone.com 146 | dockone.io 147 | donews.com 148 | douban.com 149 | douban.fm 150 | doubanio.com 151 | dpfile.com 152 | duokanbox.com 153 | duomai.com 154 | duoshuo.com 155 | duowan.com 156 | dxpmedia.com 157 | eastday.com 158 | ecitic.com 159 | emarbox.com 160 | eoeandroid.com 161 | etao.com 162 | excelhome.net 163 | fanli.com 164 | feng.com 165 | fengniao.com 166 | fhldns.com 167 | foxmail.com 168 | geekpark.net 169 | geetest.com 170 | geilicdn.com 171 | getui.com 172 | google-analytics.com 173 | growingio.com 174 | gtags.net 175 | gwdang.com 176 | hao123.com 177 | hao123img.com 178 | haosou.com 179 | hdslb.com 180 | henha.com 181 | henkuai.com 182 | hexun.com 183 | hichina.com 184 | huanqiu.com 185 | hunantv.com 186 | huochepiao.com 187 | hupu.com 188 | hupucdn.com 189 | huxiu.com 190 | iask.com 191 | iciba.com 192 | idqqimg.com 193 | ifanr.com 194 | ifanrusercontent.com 195 | ifanrx.com 196 | ifeng.com 197 | ifengimg.com 198 | ijinshan.com 199 | ikafan.com 200 | imedao.com 201 | imgo.tv 202 | imooc.com 203 | infoq.com 204 | infoqstatic.com 205 | ip138.com 206 | ipinyou.com 207 | ipip.net 208 | ip-cdn.com 209 | iqiyi.com 210 | irs01.com 211 | it165.net 212 | it168.com 213 | it610.com 214 | iteye.com 215 | ithome.com 216 | itjuzi.com 217 | jandan.net 218 | jd.com 219 | jb51.com 220 | jia.com 221 | jianshu.com 222 | jianshu.io 223 | jiasuhui.com 224 | jiathis.com 225 | jiayuan.com 226 | jikexueyuan.com 227 | jisuanke.com 228 | jmstatic.com 229 | jsdelivr.net 230 | jstv.com 231 | jumei.com 232 | jyimg.com 233 | kaixin001.com 234 | kanimg.com 235 | kankanews.com 236 | kejet.net 237 | kf5.com 238 | kimiss.com 239 | kouclo.com 240 | koudai.com 241 | koudai8.com 242 | ku6.com 243 | ku6cdn.com 244 | ku6img.com 245 | kuqin.com 246 | lady8844.com 247 | lagou.com 248 | le.com 249 | leanote.com 250 | leiphone.com 251 | leju.com 252 | leturich.org 253 | letv.com 254 | letvcdn.com 255 | letvimg.com 256 | liantu.me 257 | liaoxuefeng.com 258 | liba.com 259 | libaclub.com 260 | liepin.com 261 | lietou.com 262 | lightonus.com 263 | linkvans.com 264 | linuxidc.com 265 | liuxiaoer.com 266 | lofter.com 267 | lu.com 268 | lufax.com 269 | lufaxcdn.com 270 | lvmama.com 271 | lxdns.com 272 | lxway.com 273 | ly.com 274 | mayihr.com 275 | mechina.org 276 | mediav.com 277 | meiqia.com 278 | meika360.com 279 | meilishuo.com 280 | meishij.net 281 | meituan.com 282 | meizu.com 283 | mgtv.com 284 | mi.com 285 | miaopai.com 286 | miaozhen.com 287 | miui.com 288 | mmbang.com 289 | mmbang.info 290 | mmstat.com 291 | mogucdn.com 292 | mogujie.com 293 | mop.com 294 | mscbsc.com 295 | mukewang.com 296 | mydrivers.com 297 | myshow360.net 298 | mzstatic.com 299 | netease.com 300 | newbandeng.com 301 | ngacn.cc 302 | ntalker.com 303 | nvsheng.com 304 | oeeee.com 305 | ol-img.com 306 | oneapm.com 307 | onlinedown.net 308 | onlinesjtu.com 309 | oschina.net 310 | paipai.com 311 | pcbeta.com 312 | pchome.net 313 | pingan.com 314 | pingplusplus.com 315 | pps.tv 316 | psbc.com 317 | pubyun.com 318 | qbox.me 319 | qcloud.com 320 | qhimg.com 321 | qhres.com 322 | qiaobutang.com 323 | qidian.com 324 | qie.tv 325 | qihucdn.com 326 | qingcloud.com 327 | qingsongchou.com 328 | qiniu.com 329 | qiniucdn.com 330 | qiniudn.com 331 | qiniudns.com 332 | qiyi.com 333 | qiyipic.com 334 | qtmojo.com 335 | qq.com 336 | qqmail.com 337 | qunar.com 338 | qunarzz.com 339 | qzone.com 340 | renren.com 341 | runoob.com 342 | ruanmei.com 343 | ruby-china.org 344 | sandai.net 345 | sanguosha.com 346 | sanwen.net 347 | segmentfault.com 348 | sf-express.com 349 | sharejs.com 350 | shmetro.com 351 | shutcm.com 352 | simei8.com 353 | sina.com 354 | sinaapp.com 355 | sinaedge.com 356 | sinaimg.com 357 | sinajs.com 358 | szzfgjj.com 359 | smzdm.com 360 | sohu.com 361 | sohucs.com 362 | sogou.com 363 | sogoucdn.com 364 | soso.com 365 | sspai.com 366 | ssports.com 367 | starbaby.cc 368 | starbaby.com 369 | staticfile.org 370 | stockstar.com 371 | suning.com 372 | szfw.org 373 | t1y5.com 374 | tanx.com 375 | tao123.com 376 | taobao.com 377 | taobaocdn.com 378 | tbcache.com 379 | tencent.com 380 | tenpay.com 381 | tenxcloud.com 382 | tiebaimg.com 383 | tietuku.com 384 | tiexue.net 385 | tmall.com 386 | tmcdn.net 387 | topthink.com 388 | ttpod.com 389 | tudou.com 390 | tudouui.com 391 | tuicool.com 392 | tuniu.com 393 | tutuapp.com 394 | u17.com 395 | useso.com 396 | unionpay.com 397 | unionpaysecure.com 398 | upyun.com 399 | upaiyun.com 400 | v2ex.com 401 | v5875.com 402 | vamaker.com 403 | vancl.com 404 | vcimg.com 405 | vip.com 406 | wallstreetcn.com 407 | wandoujia.com 408 | wdjimg.com 409 | weand.com 410 | webterren.com 411 | weibo.com 412 | weicaifu.com 413 | weidian.com 414 | weiphone.com 415 | weiphone.net 416 | weixing.com 417 | weiyun.com 418 | wonnder.com 419 | worktile.com 420 | wooyun.org 421 | wrating.com 422 | wscdns.com 423 | wumii.com 424 | xiachufang.com 425 | xiami.com 426 | xiaokaxiu.com 427 | xiaomi.com 428 | xitu.com 429 | xinhuanet.com 430 | xinshipu.com 431 | xiu8.com 432 | xnpic.com 433 | xueqiu.com 434 | xunlei.com 435 | xywy.com 436 | yaolan.com 437 | yccdn.com 438 | yeepay.com 439 | yesky.com 440 | yigao.com 441 | yihaodian.com 442 | yihaodianimg.com 443 | yingjiesheng.com 444 | yinxiang.com 445 | yinyuetai.com 446 | yixi.tv 447 | yjbys.com 448 | yhd.com 449 | youboy.com 450 | youku.com 451 | ysten.com 452 | yunba.io 453 | yundaex.com 454 | yunshipei.com 455 | yupoo.com 456 | yuzua.com 457 | yy.com 458 | yytcdn.com 459 | zampda.net 460 | zastatic.com 461 | zbjimg.com 462 | zdfans.com 463 | zdmimg.com 464 | zhenai.com 465 | zhanqi.tv 466 | zhaopin.com 467 | zhihu.com 468 | zhimg.com 469 | zhiziyun.com 470 | zjstv.com 471 | zhubajie.com 472 | zrblog.net 473 | zuche.com 474 | zuchecdn.com 475 | -------------------------------------------------------------------------------- /geolite/GeoLite2-Country-Locations-en.csv: -------------------------------------------------------------------------------- 1 | geoname_id,locale_code,continent_code,continent_name,country_iso_code,country_name 2 | 49518,en,AF,Africa,RW,Rwanda 3 | 51537,en,AF,Africa,SO,Somalia 4 | 69543,en,AS,Asia,YE,Yemen 5 | 99237,en,AS,Asia,IQ,Iraq 6 | 102358,en,AS,Asia,SA,"Saudi Arabia" 7 | 130758,en,AS,Asia,IR,Iran 8 | 146669,en,EU,Europe,CY,Cyprus 9 | 149590,en,AF,Africa,TZ,Tanzania 10 | 163843,en,AS,Asia,SY,Syria 11 | 174982,en,AS,Asia,AM,Armenia 12 | 192950,en,AF,Africa,KE,Kenya 13 | 203312,en,AF,Africa,CD,Congo 14 | 223816,en,AF,Africa,DJ,Djibouti 15 | 226074,en,AF,Africa,UG,Uganda 16 | 239880,en,AF,Africa,CF,"Central African Republic" 17 | 241170,en,AF,Africa,SC,Seychelles 18 | 248816,en,AS,Asia,JO,"Hashemite Kingdom of Jordan" 19 | 272103,en,AS,Asia,LB,Lebanon 20 | 285570,en,AS,Asia,KW,Kuwait 21 | 286963,en,AS,Asia,OM,Oman 22 | 289688,en,AS,Asia,QA,Qatar 23 | 290291,en,AS,Asia,BH,Bahrain 24 | 290557,en,AS,Asia,AE,"United Arab Emirates" 25 | 294640,en,AS,Asia,IL,Israel 26 | 298795,en,AS,Asia,TR,Turkey 27 | 337996,en,AF,Africa,ET,Ethiopia 28 | 338010,en,AF,Africa,ER,Eritrea 29 | 357994,en,AF,Africa,EG,Egypt 30 | 366755,en,AF,Africa,SD,Sudan 31 | 390903,en,EU,Europe,GR,Greece 32 | 433561,en,AF,Africa,BI,Burundi 33 | 453733,en,EU,Europe,EE,Estonia 34 | 458258,en,EU,Europe,LV,Latvia 35 | 587116,en,AS,Asia,AZ,Azerbaijan 36 | 597427,en,EU,Europe,LT,"Republic of Lithuania" 37 | 607072,en,EU,Europe,SJ,"Svalbard and Jan Mayen" 38 | 614540,en,AS,Asia,GE,Georgia 39 | 617790,en,EU,Europe,MD,"Republic of Moldova" 40 | 630336,en,EU,Europe,BY,Belarus 41 | 660013,en,EU,Europe,FI,Finland 42 | 661882,en,EU,Europe,AX,"Åland" 43 | 690791,en,EU,Europe,UA,Ukraine 44 | 718075,en,EU,Europe,MK,Macedonia 45 | 719819,en,EU,Europe,HU,Hungary 46 | 732800,en,EU,Europe,BG,Bulgaria 47 | 783754,en,EU,Europe,AL,Albania 48 | 798544,en,EU,Europe,PL,Poland 49 | 798549,en,EU,Europe,RO,Romania 50 | 831053,en,EU,Europe,XK,Kosovo 51 | 878675,en,AF,Africa,ZW,Zimbabwe 52 | 895949,en,AF,Africa,ZM,Zambia 53 | 921929,en,AF,Africa,KM,Comoros 54 | 927384,en,AF,Africa,MW,Malawi 55 | 932692,en,AF,Africa,LS,Lesotho 56 | 933860,en,AF,Africa,BW,Botswana 57 | 934292,en,AF,Africa,MU,Mauritius 58 | 934841,en,AF,Africa,SZ,Swaziland 59 | 935317,en,AF,Africa,RE,Réunion 60 | 953987,en,AF,Africa,ZA,"South Africa" 61 | 1024031,en,AF,Africa,YT,Mayotte 62 | 1036973,en,AF,Africa,MZ,Mozambique 63 | 1062947,en,AF,Africa,MG,Madagascar 64 | 1149361,en,AS,Asia,AF,Afghanistan 65 | 1168579,en,AS,Asia,PK,Pakistan 66 | 1210997,en,AS,Asia,BD,Bangladesh 67 | 1218197,en,AS,Asia,TM,Turkmenistan 68 | 1220409,en,AS,Asia,TJ,Tajikistan 69 | 1227603,en,AS,Asia,LK,"Sri Lanka" 70 | 1252634,en,AS,Asia,BT,Bhutan 71 | 1269750,en,AS,Asia,IN,India 72 | 1282028,en,AS,Asia,MV,Maldives 73 | 1282588,en,AS,Asia,IO,"British Indian Ocean Territory" 74 | 1282988,en,AS,Asia,NP,Nepal 75 | 1327865,en,AS,Asia,MM,"Myanmar [Burma]" 76 | 1512440,en,AS,Asia,UZ,Uzbekistan 77 | 1522867,en,AS,Asia,KZ,Kazakhstan 78 | 1527747,en,AS,Asia,KG,Kyrgyzstan 79 | 1546748,en,AN,Antarctica,TF,"French Southern Territories" 80 | 1547314,en,AN,Antarctica,HM,"Heard Island and McDonald Islands" 81 | 1547376,en,AS,Asia,CC,"Cocos [Keeling] Islands" 82 | 1559582,en,OC,Oceania,PW,Palau 83 | 1562822,en,AS,Asia,VN,Vietnam 84 | 1605651,en,AS,Asia,TH,Thailand 85 | 1643084,en,AS,Asia,ID,Indonesia 86 | 1655842,en,AS,Asia,LA,Laos 87 | 1668284,en,AS,Asia,TW,Taiwan 88 | 1694008,en,AS,Asia,PH,Philippines 89 | 1733045,en,AS,Asia,MY,Malaysia 90 | 1814991,en,AS,Asia,CN,China 91 | 1819730,en,AS,Asia,HK,"Hong Kong" 92 | 1820814,en,AS,Asia,BN,Brunei 93 | 1821275,en,AS,Asia,MO,Macao 94 | 1831722,en,AS,Asia,KH,Cambodia 95 | 1835841,en,AS,Asia,KR,"Republic of Korea" 96 | 1861060,en,AS,Asia,JP,Japan 97 | 1873107,en,AS,Asia,KP,"North Korea" 98 | 1880251,en,AS,Asia,SG,Singapore 99 | 1899402,en,OC,Oceania,CK,"Cook Islands" 100 | 1966436,en,OC,Oceania,TL,"East Timor" 101 | 2017370,en,EU,Europe,RU,Russia 102 | 2029969,en,AS,Asia,MN,Mongolia 103 | 2077456,en,OC,Oceania,AU,Australia 104 | 2078138,en,AS,Asia,CX,"Christmas Island" 105 | 2080185,en,OC,Oceania,MH,"Marshall Islands" 106 | 2081918,en,OC,Oceania,FM,"Federated States of Micronesia" 107 | 2088628,en,OC,Oceania,PG,"Papua New Guinea" 108 | 2103350,en,OC,Oceania,SB,"Solomon Islands" 109 | 2110297,en,OC,Oceania,TV,Tuvalu 110 | 2110425,en,OC,Oceania,NR,Nauru 111 | 2134431,en,OC,Oceania,VU,Vanuatu 112 | 2139685,en,OC,Oceania,NC,"New Caledonia" 113 | 2155115,en,OC,Oceania,NF,"Norfolk Island" 114 | 2186224,en,OC,Oceania,NZ,"New Zealand" 115 | 2205218,en,OC,Oceania,FJ,Fiji 116 | 2215636,en,AF,Africa,LY,Libya 117 | 2233387,en,AF,Africa,CM,Cameroon 118 | 2245662,en,AF,Africa,SN,Senegal 119 | 2260494,en,AF,Africa,CG,"Republic of the Congo" 120 | 2264397,en,EU,Europe,PT,Portugal 121 | 2275384,en,AF,Africa,LR,Liberia 122 | 2287781,en,AF,Africa,CI,"Ivory Coast" 123 | 2300660,en,AF,Africa,GH,Ghana 124 | 2309096,en,AF,Africa,GQ,"Equatorial Guinea" 125 | 2328926,en,AF,Africa,NG,Nigeria 126 | 2361809,en,AF,Africa,BF,"Burkina Faso" 127 | 2363686,en,AF,Africa,TG,Togo 128 | 2372248,en,AF,Africa,GW,Guinea-Bissau 129 | 2378080,en,AF,Africa,MR,Mauritania 130 | 2395170,en,AF,Africa,BJ,Benin 131 | 2400553,en,AF,Africa,GA,Gabon 132 | 2403846,en,AF,Africa,SL,"Sierra Leone" 133 | 2410758,en,AF,Africa,ST,"São Tomé and Príncipe" 134 | 2411586,en,EU,Europe,GI,Gibraltar 135 | 2413451,en,AF,Africa,GM,Gambia 136 | 2420477,en,AF,Africa,GN,Guinea 137 | 2434508,en,AF,Africa,TD,Chad 138 | 2440476,en,AF,Africa,NE,Niger 139 | 2453866,en,AF,Africa,ML,Mali 140 | 2461445,en,AF,Africa,EH,"Western Sahara" 141 | 2464461,en,AF,Africa,TN,Tunisia 142 | 2510769,en,EU,Europe,ES,Spain 143 | 2542007,en,AF,Africa,MA,Morocco 144 | 2562770,en,EU,Europe,MT,Malta 145 | 2589581,en,AF,Africa,DZ,Algeria 146 | 2622320,en,EU,Europe,FO,"Faroe Islands" 147 | 2623032,en,EU,Europe,DK,Denmark 148 | 2629691,en,EU,Europe,IS,Iceland 149 | 2635167,en,EU,Europe,GB,"United Kingdom" 150 | 2658434,en,EU,Europe,CH,Switzerland 151 | 2661886,en,EU,Europe,SE,Sweden 152 | 2750405,en,EU,Europe,NL,Netherlands 153 | 2782113,en,EU,Europe,AT,Austria 154 | 2802361,en,EU,Europe,BE,Belgium 155 | 2921044,en,EU,Europe,DE,Germany 156 | 2960313,en,EU,Europe,LU,Luxembourg 157 | 2963597,en,EU,Europe,IE,Ireland 158 | 2993457,en,EU,Europe,MC,Monaco 159 | 3017382,en,EU,Europe,FR,France 160 | 3041565,en,EU,Europe,AD,Andorra 161 | 3042058,en,EU,Europe,LI,Liechtenstein 162 | 3042142,en,EU,Europe,JE,Jersey 163 | 3042225,en,EU,Europe,IM,"Isle of Man" 164 | 3042362,en,EU,Europe,GG,Guernsey 165 | 3057568,en,EU,Europe,SK,Slovakia 166 | 3077311,en,EU,Europe,CZ,Czechia 167 | 3144096,en,EU,Europe,NO,Norway 168 | 3164670,en,EU,Europe,VA,"Vatican City" 169 | 3168068,en,EU,Europe,SM,"San Marino" 170 | 3175395,en,EU,Europe,IT,Italy 171 | 3190538,en,EU,Europe,SI,Slovenia 172 | 3194884,en,EU,Europe,ME,Montenegro 173 | 3202326,en,EU,Europe,HR,Croatia 174 | 3277605,en,EU,Europe,BA,"Bosnia and Herzegovina" 175 | 3351879,en,AF,Africa,AO,Angola 176 | 3355338,en,AF,Africa,NA,Namibia 177 | 3370751,en,AF,Africa,SH,"Saint Helena" 178 | 3374084,en,NA,"North America",BB,Barbados 179 | 3374766,en,AF,Africa,CV,"Cabo Verde" 180 | 3378535,en,SA,"South America",GY,Guyana 181 | 3381670,en,SA,"South America",GF,"French Guiana" 182 | 3382998,en,SA,"South America",SR,Suriname 183 | 3424932,en,NA,"North America",PM,"Saint Pierre and Miquelon" 184 | 3425505,en,NA,"North America",GL,Greenland 185 | 3437598,en,SA,"South America",PY,Paraguay 186 | 3439705,en,SA,"South America",UY,Uruguay 187 | 3469034,en,SA,"South America",BR,Brazil 188 | 3474414,en,SA,"South America",FK,"Falkland Islands" 189 | 3474415,en,AN,Antarctica,GS,"South Georgia and the South Sandwich Islands" 190 | 3489940,en,NA,"North America",JM,Jamaica 191 | 3508796,en,NA,"North America",DO,"Dominican Republic" 192 | 3562981,en,NA,"North America",CU,Cuba 193 | 3570311,en,NA,"North America",MQ,Martinique 194 | 3572887,en,NA,"North America",BS,Bahamas 195 | 3573345,en,NA,"North America",BM,Bermuda 196 | 3573511,en,NA,"North America",AI,Anguilla 197 | 3573591,en,NA,"North America",TT,"Trinidad and Tobago" 198 | 3575174,en,NA,"North America",KN,"St Kitts and Nevis" 199 | 3575830,en,NA,"North America",DM,Dominica 200 | 3576396,en,NA,"North America",AG,"Antigua and Barbuda" 201 | 3576468,en,NA,"North America",LC,"Saint Lucia" 202 | 3576916,en,NA,"North America",TC,"Turks and Caicos Islands" 203 | 3577279,en,NA,"North America",AW,Aruba 204 | 3577718,en,NA,"North America",VG,"British Virgin Islands" 205 | 3577815,en,NA,"North America",VC,"Saint Vincent and the Grenadines" 206 | 3578097,en,NA,"North America",MS,Montserrat 207 | 3578421,en,NA,"North America",MF,"Saint Martin" 208 | 3578476,en,NA,"North America",BL,Saint-Barthélemy 209 | 3579143,en,NA,"North America",GP,Guadeloupe 210 | 3580239,en,NA,"North America",GD,Grenada 211 | 3580718,en,NA,"North America",KY,"Cayman Islands" 212 | 3582678,en,NA,"North America",BZ,Belize 213 | 3585968,en,NA,"North America",SV,"El Salvador" 214 | 3595528,en,NA,"North America",GT,Guatemala 215 | 3608932,en,NA,"North America",HN,Honduras 216 | 3617476,en,NA,"North America",NI,Nicaragua 217 | 3624060,en,NA,"North America",CR,"Costa Rica" 218 | 3625428,en,SA,"South America",VE,Venezuela 219 | 3658394,en,SA,"South America",EC,Ecuador 220 | 3686110,en,SA,"South America",CO,Colombia 221 | 3703430,en,NA,"North America",PA,Panama 222 | 3723988,en,NA,"North America",HT,Haiti 223 | 3865483,en,SA,"South America",AR,Argentina 224 | 3895114,en,SA,"South America",CL,Chile 225 | 3923057,en,SA,"South America",BO,Bolivia 226 | 3932488,en,SA,"South America",PE,Peru 227 | 3996063,en,NA,"North America",MX,Mexico 228 | 4030656,en,OC,Oceania,PF,"French Polynesia" 229 | 4030699,en,OC,Oceania,PN,"Pitcairn Islands" 230 | 4030945,en,OC,Oceania,KI,Kiribati 231 | 4031074,en,OC,Oceania,TK,Tokelau 232 | 4032283,en,OC,Oceania,TO,Tonga 233 | 4034749,en,OC,Oceania,WF,"Wallis and Futuna" 234 | 4034894,en,OC,Oceania,WS,Samoa 235 | 4036232,en,OC,Oceania,NU,Niue 236 | 4041468,en,OC,Oceania,MP,"Northern Mariana Islands" 237 | 4043988,en,OC,Oceania,GU,Guam 238 | 4566966,en,NA,"North America",PR,"Puerto Rico" 239 | 4796775,en,NA,"North America",VI,"U.S. Virgin Islands" 240 | 5854968,en,OC,Oceania,UM,"U.S. Minor Outlying Islands" 241 | 5880801,en,OC,Oceania,AS,"American Samoa" 242 | 6251999,en,NA,"North America",CA,Canada 243 | 6252001,en,NA,"North America",US,"United States" 244 | 6254930,en,AS,Asia,PS,Palestine 245 | 6255147,en,AS,Asia,, 246 | 6255148,en,EU,Europe,, 247 | 6290252,en,EU,Europe,RS,Serbia 248 | 6697173,en,AN,Antarctica,AQ,Antarctica 249 | 7609695,en,NA,"North America",SX,"Sint Maarten" 250 | 7626836,en,NA,"North America",CW,Curaçao 251 | 7626844,en,NA,"North America",BQ,"Bonaire, Sint Eustatius, and Saba" 252 | 7909807,en,AF,Africa,SS,"South Sudan" 253 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const protobuf = require("protobufjs"); 4 | const fs = require('fs'); 5 | const request = require('request-promise'); 6 | const neatCsv = require('neat-csv'); 7 | const IP = require('ip'); 8 | const isCidr = require('is-cidr'); 9 | const dedupe = require('dedupe'); 10 | 11 | const rule_urls = fs.readFileSync('./surge_rules.txt').toString().split('\n'); 12 | 13 | const gfwlist_url = 'https://github.com/gfwlist/gfwlist/raw/master/gfwlist.txt'; 14 | 15 | const site_rules = {}, ip_rules = {}; 16 | 17 | function pushSiteRules(country_code, rules) { 18 | if (rules.length > 0) { 19 | if (!!site_rules[country_code]) { 20 | rules.push(...site_rules[country_code]); 21 | rules = dedupe(rules.sort((a, b) => a.value.localeCompare(b.value)), a => a.value); 22 | } 23 | site_rules[country_code] = rules 24 | } 25 | } 26 | 27 | function pushIPRules(country_code, rules) { 28 | if (rules.length > 0) { 29 | if (!!ip_rules[country_code]) { 30 | rules.push(...ip_rules[country_code]); 31 | rules = dedupe(rules.sort((a, b) => a.localeCompare(b)), a => a); 32 | } 33 | ip_rules[country_code] = rules 34 | } 35 | } 36 | 37 | function getType(type_str) { 38 | type_str = type_str.toLowerCase(); 39 | if (type_str.includes('reject')) { 40 | return 'reject' 41 | } else if (type_str.includes('proxy')) { 42 | return 'proxy' 43 | } else if (type_str.includes('direct') || type_str.includes('domestic') || type_str.includes('other') || type_str.includes('🍎')) { 44 | return 'direct' 45 | } else { 46 | return 'direct' 47 | } 48 | } 49 | 50 | function getDomain(url) { 51 | url = url.trim(); 52 | url = decodeURIComponent(url); 53 | url = url.replace(/https?:\/\//g, ''); 54 | let i = url.indexOf(':') > 1 ? url.indexOf(':') : url.indexOf('/'); 55 | if (i > 1) { 56 | url = url.substr(0, i); 57 | } 58 | if (!url.includes('.')) { 59 | return null; 60 | } 61 | return url; 62 | } 63 | 64 | function parseIP(ip) { 65 | ip = ip.split('/'); 66 | let addr = ip[0], mask = ip[1]; 67 | return { 68 | ip: IP.toBuffer(addr), 69 | prefix: parseInt(mask) 70 | } 71 | } 72 | 73 | function formatDomain(domain) { 74 | let {value, type} = domain; 75 | if (type === 'suffix') { 76 | if (value.startsWith('.')) { 77 | type = 1; 78 | value = value.replace(/\./g, '\\.'); 79 | value = value.replace('*', '.*'); 80 | } else { 81 | type = 2 82 | } 83 | } else if (type === 'full') { 84 | type = 1; 85 | value = value.replace(/\./g, '\\.'); 86 | value = value.replace('*', '.*'); 87 | value = '^' + value + '$'; 88 | } else if (type === 'keyword') { 89 | type = 0; 90 | } else { 91 | type = 1; 92 | } 93 | return {type, value}; 94 | } 95 | 96 | function parseRulesFromUrl(url) { 97 | let domains = {reject: [], direct: [], proxy: []}, ipcidrs = {reject: [], direct: [], proxy: []}; 98 | return request(url).then(body => { 99 | let lines = body.split('\n'); 100 | lines.map(line => { 101 | line = line.trim(); 102 | if (!!line) { 103 | if (line.toUpperCase().startsWith('DOMAIN')) { 104 | line = line.split(','); 105 | let opt = line[0], domain = line[1], type = line[2]; 106 | if (opt.endsWith('KEYWORD')) { 107 | domains[getType(type)].push({value: domain, type: 'keyword'}) 108 | } else if (opt.endsWith('SUFFIX')) { 109 | domains[getType(type)].push({value: domain, type: 'suffix'}) 110 | } else { 111 | domains[getType(type)].push({value: domain, type: 'full'}) 112 | } 113 | } else if (line.toUpperCase().startsWith('IP-CIDR')) { 114 | line = line.split(','); 115 | let ip = line[1], type = line[2]; 116 | ipcidrs[getType(type)].push(ip) 117 | } 118 | } 119 | }); 120 | return {domains, ipcidrs} 121 | }) 122 | } 123 | 124 | function parseGFWListRules() { 125 | let direct = [], proxy = []; 126 | return request(gfwlist_url).then(body => { 127 | body = new Buffer(body, 'base64').toString(); 128 | let lines = body.split('\n'); 129 | let supplemental = false; 130 | lines.map(line => { 131 | if (!!line) { 132 | if (!(line.startsWith('!') || line.startsWith('['))) { 133 | if (line.startsWith('||')) { 134 | line = getDomain(line.substr(2)); 135 | if (!!line && proxy.filter(p => p.value === line).length === 0) { 136 | proxy.push({value: line, type: 'suffix'}) 137 | } 138 | } else if (line.startsWith('|')) { 139 | line = getDomain(line.substr(1)); 140 | if (!!line && proxy.filter(p => p.value === line).length === 0) { 141 | proxy.push({value: line, type: 'full'}) 142 | } 143 | } else if (line.startsWith('@@')) { 144 | line = line.substr(2); 145 | let type = 'suffix'; 146 | if (line[1] !== '|') { 147 | type = 'full' 148 | } 149 | line = getDomain(line.replace(/\|{1,2}/, '')); 150 | if (!!line) { 151 | if (proxy.filter(p => p.value === line).length === 0) { 152 | proxy = proxy.filter(p => p.value !== line) 153 | } 154 | if (direct.filter(p => p.value === line).length === 0) { 155 | direct.push({value: line, type}) 156 | } 157 | } 158 | } else { 159 | if (!line.startsWith('/') && !supplemental) { 160 | line = getDomain(line); 161 | if (!!line && proxy.filter(p => p.value === line).length === 0) { 162 | proxy.push({value: line, type: 'suffix'}) 163 | } 164 | } else if (line.startsWith('/')) { 165 | // regex 166 | // console.log(line) 167 | } 168 | } 169 | } else if (line.includes('Supplemental List Start')) { 170 | supplemental = true; 171 | } else if (supplemental && line.includes('Supplemental List End')) { 172 | supplemental = false; 173 | } 174 | } 175 | }); 176 | proxy.sort((a, b) => a.value.localeCompare(b.value)); 177 | direct.sort((a, b) => a.value.localeCompare(b.value)); 178 | return {proxy, direct} 179 | }) 180 | } 181 | 182 | async function parseGeoLite() { 183 | let country_codes = {}; 184 | let cidrs = []; 185 | let country_csv = fs.readFileSync('./geolite/GeoLite2-Country-Locations-en.csv'); 186 | await neatCsv(country_csv).then(rows => { 187 | rows.map(row => { 188 | country_codes[row.geoname_id] = row.country_iso_code.toUpperCase() 189 | }) 190 | }); 191 | 192 | let ipv4_csv = fs.readFileSync('./geolite/GeoLite2-Country-Blocks-IPv4.csv'); 193 | await neatCsv(ipv4_csv).then(rows => { 194 | rows.map(row => { 195 | if (!!country_codes[row.geoname_id]) { 196 | let country_code = country_codes[row.geoname_id]; 197 | let cidr = parseIP(row.network); 198 | if (cidrs.filter(cidr => cidr.countryCode === country_code).length > 0) { 199 | cidrs.find(cidr => cidr.countryCode === country_code).cidr.push(cidr) 200 | } else { 201 | cidrs.push({ 202 | countryCode: country_code, 203 | cidr: [cidr] 204 | }) 205 | } 206 | } 207 | }) 208 | }); 209 | 210 | let ipv6_csv = fs.readFileSync('./geolite/GeoLite2-Country-Blocks-IPv6.csv'); 211 | await neatCsv(ipv6_csv).then(rows => { 212 | rows.map(row => { 213 | if (!!country_codes[row.geoname_id]) { 214 | let country_code = country_codes[row.geoname_id]; 215 | let cidr = parseIP(row.network); 216 | if (cidrs.filter(cidr => cidr.countryCode === country_code).length > 0) { 217 | cidrs.find(cidr => cidr.countryCode === country_code).cidr.push(cidr) 218 | } else { 219 | cidrs.push({ 220 | countryCode: country_code, 221 | cidr: [cidr] 222 | }) 223 | } 224 | } 225 | }) 226 | }); 227 | 228 | cidrs.sort((a, b) => a.countryCode.localeCompare(b.countryCode)); 229 | return cidrs; 230 | } 231 | 232 | function loadCustomRules(filename, is_official = false) { 233 | let domains = [], ipcidrs = []; 234 | let lines = fs.readFileSync(filename).toString(); 235 | lines = lines.split('\n'); 236 | lines.map(line => { 237 | line = line.trim(); 238 | if (!!line) { 239 | line = line.replace('\r', ''); 240 | if (!line.startsWith('#')) { 241 | if (isCidr(line)) { 242 | if (!ip_rules.includes(line)) { 243 | ipcidrs.push(line) 244 | } 245 | } else { 246 | if (domains.filter(domain => domain.value === line).length === 0) { 247 | domains.push({value: line, type: 'suffix'}) 248 | } 249 | } 250 | } 251 | } 252 | }); 253 | if (!is_official && domains.length === 0) { 254 | domains.push({value: '�', type: 'full'}) 255 | } 256 | domains = domains.sort((a, b) => a.value.localeCompare(b.value)); 257 | if (!is_official && ipcidrs.length === 0) { 258 | ipcidrs.push('233.333.333.333/33') 259 | } 260 | return {domains, ipcidrs} 261 | } 262 | 263 | async function main() { 264 | try { 265 | let proto_root = await protobuf.load("router.proto"); 266 | let GeoSiteList = proto_root.lookupType("router.GeoSiteList"); 267 | let GeoIPList = proto_root.lookupType("router.GeoIPList"); 268 | 269 | // load official rules 270 | console.log('loading official rules..'); 271 | let official_filenames = fs.readdirSync('./official'); 272 | for (let official_filename of official_filenames) { 273 | let country_code = official_filename.substr(0, official_filename.indexOf('.')); 274 | let {domains, ipcidrs} = loadCustomRules('./official/' + official_filename, true); 275 | pushSiteRules(country_code, domains); 276 | pushIPRules(country_code, ipcidrs); 277 | } 278 | // load official rules 279 | 280 | // load custom rules 281 | console.log('loading custom rules..'); 282 | let custom_filenames = fs.readdirSync('./custom'); 283 | for (let custom_filename of custom_filenames) { 284 | let country_code = custom_filename.substr(0, custom_filename.indexOf('.')); 285 | let {domains, ipcidrs} = loadCustomRules('./custom/' + custom_filename); 286 | pushSiteRules('custom:' + country_code, domains); 287 | pushIPRules('custom:' + country_code, ipcidrs); 288 | } 289 | // load custom rules 290 | 291 | console.log('loading geolite ip datas..'); 292 | let geo_ips = await parseGeoLite(); 293 | 294 | console.log('loading gfwlist rules..'); 295 | let {proxy, direct} = await parseGFWListRules(); 296 | pushSiteRules('gfwlist:proxy', proxy); 297 | pushSiteRules('gfwlist:direct', direct); 298 | 299 | console.log('loading surge style rules..'); 300 | for (let url of rule_urls) { 301 | if (!url) continue; 302 | let {domains, ipcidrs} = await parseRulesFromUrl(url); 303 | for (let key in domains) { 304 | if (domains.hasOwnProperty(key)) { 305 | pushSiteRules('surge:' + key, domains[key]); 306 | } 307 | } 308 | for (let key in ipcidrs) { 309 | if (ipcidrs.hasOwnProperty(key)) { 310 | pushIPRules('surge:' + key, ipcidrs[key]); 311 | } 312 | } 313 | } 314 | 315 | let site_list = GeoSiteList.create({ 316 | entry: Object.keys(site_rules).map(key => { 317 | let rules = site_rules[key]; 318 | rules = rules.map(domain => formatDomain(domain)); 319 | return {countryCode: key.toUpperCase(), domain: rules} 320 | }) 321 | }); 322 | let buffer = GeoSiteList.encode(site_list).finish(); 323 | fs.writeFileSync('./dist/geosite.dat', buffer); 324 | 325 | buffer = fs.readFileSync('./dist/geosite.dat'); 326 | GeoSiteList.decode(buffer); 327 | console.log('write geosite.dat'); 328 | 329 | let ip_list = GeoIPList.create({ 330 | entry: [...geo_ips, 331 | ...Object.keys(ip_rules).map(key => { 332 | let rules = ip_rules[key]; 333 | rules = rules.map(ip => parseIP(ip)); 334 | return {countryCode: key.toUpperCase(), cidr: rules} 335 | }) 336 | ] 337 | }); 338 | 339 | buffer = GeoIPList.encode(ip_list).finish(); 340 | fs.writeFileSync('./dist/geoip.dat', buffer); 341 | 342 | buffer = fs.readFileSync('./dist/geoip.dat'); 343 | GeoIPList.decode(buffer); 344 | console.log('write geoip.dat'); 345 | } catch (error) { 346 | console.error(error) 347 | } 348 | } 349 | 350 | main(); 351 | --------------------------------------------------------------------------------