Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new generator for routeros #53

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b2816ac
Add new generator for routeros
tomasen Jan 6, 2016
d61beaa
merge golang version from https://github.com/kumakichi/chnroutes
tomasen Feb 14, 2016
ccf3ffd
find the IP not in Aisa
zhaoshengzhe Mar 10, 2016
ee18a68
test for route.go
zhaoshengzhe Mar 10, 2016
062ac7e
test
zhaoshengzhe Mar 10, 2016
2119b90
test
zhaoshengzhe Mar 10, 2016
28e2a4a
go version to find the public IP not in Asia
zhaoshengzhe Mar 10, 2016
2d1b658
Merge pull request #1 from zhaoshengzhe/master
tomasen Mar 11, 2016
19b7c99
添加README文档说明
zhaoshengzhe Mar 15, 2016
25261b1
增加了命令行参数r,用来选择所需要的地区IP。同时对README文档进行了修改
zhaoshengzhe Mar 17, 2016
0740bdb
add support to routeros
tomasen Mar 23, 2016
005dcbb
add comment about private network
tomasen Mar 23, 2016
7d60ee2
初步修改了-r not-asia
zhaoshengzhe Apr 1, 2016
e1fb572
对于-r命令行的asia和china参数获得的Ip进行整合
zhaoshengzhe Apr 5, 2016
9cd42bc
完成了对cidr整合的修改
zhaoshengzhe Apr 14, 2016
dd3f041
根据gometalinter对代码进行了初步的优化和修改,并替换了函数init和main的部分内容。还需要对代码的重复性进行改进。
zhaoshengzhe Apr 25, 2016
3c13f7e
完成了对代码重复的修改,现在用gometalinter进行检查只剩余一项函数的圈复杂度过高的问题。(关键函数的圈复杂度为28)
zhaoshengzhe Apr 28, 2016
f4932d9
完成了根据gometalinter的修改,在目录下输入gometalinter --deadline 100s不再出现警告。
zhaoshengzhe Apr 28, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
在命令行里执行 python chnroutes.py, 这将生成一个名为 routes.txt 的文本文件. 对于不想安装python的用户, 可以直接从项目下来列表里下载该文件. 它将会每月更新一次.
2. 使用你喜欢的文本编辑器打开上述文件, 并把内容复制粘贴到openvpn配置文件的末尾
3. 同时在openvpn配置文件的头部添加一句 max-routes num, 其中num是一个不小于文件routes.txt的行数的数字, 实际上因为还有一些服务器端push过来的路由信息, 所以保险起见可以用 routes.txt的行数加上50, 比如目前得到的routes.txt的行数是940, 你可以把数字设置为1000: max-routes 1000
4. 修改完之后, 重新进行openvpn连接, 你可以用之前描述过的方法进行测试是否成功
4. 修改完之后, 重新进行openvpn连接, 你可以用之前描述过的方法进行测试是否成功

以上方法在Mac OSX, Linux 和 Windows上测试通过. 但需要注意的是, 这里用到一个net_gateway的变量表示未连接openvpn前的网关地址, 但openvpn的文档里有说明这个不是所有系统都支持的, 如果发生这个情况, 可以修改一下生成脚本, 把net_gateway修改为你的局域网的网关地址. 对于windows 7 和 vista, OpenVPN的windows客户端可能需要设置Windows XP兼容模式才能使用, 安装文件要在属性选择中的兼容性选择Windows XP和以管理员的身份运行,安装好的运行文件也同样选择这两个选项。如果还是不能连接到VPN的网络,可以尝试在配置文件中加入:

Expand All @@ -30,7 +30,7 @@ route-delay 2
### 注意事项

* 因为这些ip数据不是固定不变的, 尽管变化不大, 但还是建议每隔两三个月更新一次
* 使用此法之后, 可能会导致google music无法访问, 这个其实是因为连上vpn之后, 使用的dns也是国外的, 国外dns对google.cn 解析出来的是国外的ip, 所以一个简单的解决方法是修改本机的hosts文件, 把国内dns解析出来的google.cn的地址写上去: 203.208.39.99 www.google.cn google.cn
* 使用此法之后, 可能会导致google music无法访问, 这个其实是因为连上vpn之后, 使用的dns也是国外的, 国外dns对google.cn 解析出来的是国外的ip, 所以一个简单的解决方法是修改本机的hosts文件, 把国内dns解析出来的google.cn的地址写上去: 203.208.39.99 www.google.cn google.cn

## PPTP

Expand All @@ -39,23 +39,30 @@ route-delay 2
* 下载 chnroutes.py
* 从终端进入下载目录, 执行 `python chnroutes.py -p mac`, 执行完毕之后同一目录下将生成两个新文件'ip-up'和'ip-down'
* 把这两个文件copy到 `/etc/ppp` 目录, 并使用 `sudo chmod a+x ip-up ip-down` 命令把它们设置为可执行
* 设置完毕, 重新连接vpn. 测试步骤同上.
* 设置完毕, 重新连接vpn. 测试步骤同上.

### Linux

* 下载 chnroutes.py
* 从终端进入下载目录, 执行 `python chnroutes.py -p linux`, 执行完毕之后同一目录下将生成两个新文件'ip-pre-up'和'ip-down'.
* 把 `ip-pre-up` 拷贝到 `/etc/ppp` 目录, `ip-down` 拷贝到 `/etc/ppp/ip-down.d` 目录. 测试步骤同上.
* 把 `ip-pre-up` 拷贝到 `/etc/ppp` 目录, `ip-down` 拷贝到 `/etc/ppp/ip-down.d` 目录. 测试步骤同上.

### Windows

* 下载 chnroutes.py
* 从终端进入下载目录, 执行 `python chnroutes.py -p win`, 执行之后会生成vpnup.bat和vpndown.bat两个文件.
* 从终端进入下载目录, 执行 `python chnroutes.py -p win`, 执行之后会生成vpnup.bat和vpndown.bat两个文件.

由于windows上的pptp不支持拨号脚本, 所以也只能在进行拨号之前手动执行vpnup.bat文件以设置路由表. 而在断开vpn之后, 如果你觉得有必要, 可以运行vpndown.bat把这些路由信息给清理掉.

如果机器上没有安装python, 可以直接从下载页面上下载已经预生成的bat文件.

### routeros

* 下载 chnroutes.py
* 从终端进入下载目录, 执行 `python chnroutes.py -p routeros`, 执行之后会生成 router.txt.
* 粘贴 router.txt 中的脚本至 routeros 的命令行,会生成名为 chnroutes 的 address-list.


### Android

由于没在android上进行过测试, 无法确定上文描述的openvpn v2.1的使用方法是否也在android手机上适用, 所以保留以下内容
Expand All @@ -66,16 +73,16 @@ route-delay 2
* 下载 chnroutes.py
* 从终端进入下载目录, 执行 `python chnroutes.py -p linux`, 这将成
'vpnup.sh'和'vpndown.sh'两个文件.
* 把步骤2生成的两个文件拷贝到 android 的 /sdcard/openvpn/目录下, 然后修改openvpn配置文件,
* 把步骤2生成的两个文件拷贝到 android 的 /sdcard/openvpn/目录下, 然后修改openvpn配置文件,
在文件中加上以上三句:
```

```
script-security 2
up "/system/bin/sh /sdcard/openvpn/vpnup.sh"
down "/system/bin/sh /sdcard/openvpn/vpndown.sh"
```
注意自行修改其中的路径以符合你的android rom的实际路径

注意自行修改其中的路径以符合你的android rom的实际路径

另外, 这里假定了你的android已经安装过busybox, 否则请先安装busybox再进行以上操作, 还需要知道的是, 这个脚本在手机上执行会花费比较长的时间, 如非必要, 就不要用了. 也许采用非redirect-gateway方式, 然后在ovpn配置文件里添加几条需要路由的ip段是比较快捷方便的做法.
基于Linux的第三方系统的路由器
Expand All @@ -84,4 +91,4 @@ route-delay 2

## 信息反馈

本项目的脚本都是在使用路由器进行拨号的情况下测试通过的, 如果在其它拨号方式下, 脚本不能运作, 请添加一个新的issue. 另外, 在配合openvpn使用的时候, 可能会出现一种情况是因为网络质量不好, openvpn非主动断开, 这时候vpndown脚本也会被自动调用, 但重新连上之后, 可能会找不到默认的路由而添加失败, 这时候你可以通过停止openvpn重连, 并手动设置好原来的默认路由再重新进行openvpn拨号.
本项目的脚本都是在使用路由器进行拨号的情况下测试通过的, 如果在其它拨号方式下, 脚本不能运作, 请添加一个新的issue. 另外, 在配合openvpn使用的时候, 可能会出现一种情况是因为网络质量不好, openvpn非主动断开, 这时候vpndown脚本也会被自动调用, 但重新连上之后, 可能会找不到默认的路由而添加失败, 这时候你可以通过停止openvpn重连, 并手动设置好原来的默认路由再重新进行openvpn拨号.
202 changes: 202 additions & 0 deletions chnroutes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
package main

import (
"bufio"
"encoding/binary"
"flag"
"fmt"
"io"
"math"
"net"
"net/http"
"os"
"regexp"
"strconv"
)

type apnicData struct {
startIp string
mask net.IP
maskNum int
}

var (
platform string
metric int
)

func init() {
flag.StringVar(&platform, "p", "openvpn", "Target platforms, it can be openvpn, mac, linux,win, android. openvpn by default.")
flag.IntVar(&metric, "m", 5, "Metric setting for the route rules")
}

func main() {
router := map[string]func([]apnicData){
"openvpn": generate_open,
"linux": generate_linux,
"mac": generate_mac,
"win": generate_win,
"android": generate_android,
}

flag.Parse()
if fun := router[platform]; fun != nil {
data := fetch_ip_data()
fun(data)
} else {
fmt.Printf("Platform %s is not supported.\n", platform)
}
}

func generate_open(data []apnicData) {
fp := safeCreateFile("routes.txt")
defer fp.Close()

for _, v := range data {
route_item := fmt.Sprintf("route %s %s net_gateway %d\n", v.startIp, v.mask.String(), metric)
fp.WriteString(route_item)
}

fmt.Printf("Usage: Append the content of the newly created routes.txt to your openvpn config file, and also add 'max-routes %d', which takes a line, to the head of the file.\n", len(data)+20)
}

func generate_linux(data []apnicData) {
upfile := safeCreateFile("ip-pre-up")
downfile := safeCreateFile("ip-down")
defer upfile.Close()
defer downfile.Close()

upfile.WriteString(linux_upscript_header)
downfile.WriteString(linux_downscript_header)

for _, v := range data {
upstr := fmt.Sprintf("route add -net %s netmask %s gw $OLDGW\n", v.startIp, v.mask.String())
upfile.WriteString(upstr)
dnstr := fmt.Sprintf("route del -net %s netmask %s\n", v.startIp, v.mask.String())
downfile.WriteString(dnstr)
}
downfile.WriteString("rm /tmp/vpn_oldgw\n")

fmt.Println("For pptp only, please copy the file ip-pre-up to the folder/etc/ppp, please copy the file ip-down to the folder /etc/ppp/ip-down.d.")
}

func generate_mac(data []apnicData) {
upfile := safeCreateFile("ip-up")
downfile := safeCreateFile("ip-down")
defer upfile.Close()
defer downfile.Close()

upfile.WriteString(mac_upscript_header)
downfile.WriteString(mac_downscript_header)

for _, v := range data {
upstr := fmt.Sprintf("route add %s/%d \"${OLDGW}\"\n", v.startIp, v.maskNum)
upfile.WriteString(upstr)
dnstr := fmt.Sprintf("route delete %s/%d ${OLDGW}\n", v.startIp, v.maskNum)
downfile.WriteString(dnstr)
}
downfile.WriteString("\n\nrm /tmp/pptp_oldgw\n")

fmt.Println("For pptp on mac only, please copy ip-up and ip-down to the /etc/ppp folder, don't forget to make them executable with the chmod command.")
}

func generate_win(data []apnicData) {
upfile := safeCreateFile("vpnup.bat")
downfile := safeCreateFile("vpndown.bat")
defer upfile.Close()
defer downfile.Close()

upfile.WriteString(ms_upscript_header)
upfile.WriteString("ipconfig /flushdns\n\n")
downfile.WriteString("@echo off\n")

for _, v := range data {
upstr := fmt.Sprintf("route add %s mask %s %%gw%% metric %d\n", v.startIp, v.mask.String(), metric)
upfile.WriteString(upstr)
dnstr := fmt.Sprintf("route delete %s\n", v.startIp)
downfile.WriteString(dnstr)
}

fmt.Println("For pptp on windows only, run vpnup.bat before dialing to vpn, and run vpndown.bat after disconnected from the vpn.")
}

func generate_android(data []apnicData) {
upfile := safeCreateFile("vpnup.sh")
downfile := safeCreateFile("vpndown.sh")
defer upfile.Close()
defer downfile.Close()

upfile.WriteString(android_upscript_header)
downfile.WriteString(android_downscript_header)

for _, v := range data {
upstr := fmt.Sprintf("route add -net %s netmask %s gw $OLDGW\n", v.startIp, v.mask.String())
upfile.WriteString(upstr)
dnstr := fmt.Sprintf("route del -net %s netmask %s\n", v.startIp, v.mask.String())
downfile.WriteString(dnstr)
}

fmt.Println("Old school way to call up/down script from openvpn client. use the regular openvpn 2.1 method to add routes if it's possible")
}

func fetch_ip_data() []apnicData {
// fetch data from apnic
fmt.Println("Fetching data from apnic.net, it might take a few minutes, please wait...")

url := "http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest"
resp, err := http.Get(url)
if err != nil {
fmt.Println(err.Error())
os.Exit(-1)
}
defer resp.Body.Close()

br := bufio.NewReader(resp.Body)
reg, _ := regexp.Compile(`(apnic\|CN\|ipv4\|)([0-9.]*)\|([0-9]*)\|([0-9]*)\|(a.*)`)
results := make([]apnicData, 0)

for {
line, isPrefix, err := br.ReadLine()
if err != nil {
if err != io.EOF {
fmt.Println(err.Error())
os.Exit(-1)
}
break
}

if isPrefix {
fmt.Println("You should not see this!")
return results
}

matches := reg.FindStringSubmatch(string(line))
if len(matches) != 6 {
continue
}

starting_ip := matches[2]
num_ip, _ := strconv.Atoi(matches[3])

imask := UintToIP(0xffffffff ^ uint32(num_ip-1))
imaskNum := 32 - int(math.Log2(float64(num_ip)))
// fmt.Printf("%s %v %d\n", starting_ip, imask, imaskNum)
results = append(results, apnicData{starting_ip, imask, imaskNum})
}
return results
}

func UintToIP(ip uint32) net.IP {
result := make(net.IP, 4)
binary.BigEndian.PutUint32([]byte(result), ip)
return result
}

func safeCreateFile(name string) *os.File {
fp, err := os.Create(name)
if err != nil {
fmt.Println(err.Error())
os.Exit(-1)
}
return fp
}
Loading