Created
April 27, 2020 13:38
-
-
Save sotex/73201e0c3ee9267ad637a07ee13d2919 to your computer and use it in GitHub Desktop.
自动更新hosts加速github访问
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************************************************************************** | |
文件: github_hosts_speed.go | |
描述: 获取 github 相关域名的 ip 地址 | |
作者: solym [email protected] | |
版本: 2020.04.27 | |
日期: 2020年4月27日 | |
历史: | |
*****************************************************************************/ | |
package main | |
import ( | |
"bufio" | |
"bytes" | |
"fmt" | |
"io/ioutil" | |
"net/http" | |
"os" | |
"runtime" | |
json "github.com/json-iterator/go" | |
) | |
func httpGetRequest(url string) ([]byte, error) { | |
// 创建一个请求 | |
req, err := http.NewRequest("GET", url, nil) | |
if err != nil { | |
return nil, err | |
} | |
// 设置头,模拟火狐浏览器 | |
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0") | |
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") | |
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2") | |
req.Header.Set("Connection", "keep-alive") | |
req.Header.Set("Upgrade-Insecure-Requests", "1") | |
req.Header.Set("Pragma", "no-cache") | |
req.Header.Set("Cache-Control", "no-cache") | |
// 执行请求结果 | |
resp, err := http.DefaultClient.Do(req) | |
if err != nil { | |
return nil, err | |
} | |
defer resp.Body.Close() | |
// 获取返回结果 | |
data, err := ioutil.ReadAll(resp.Body) | |
if resp.StatusCode != 200 || err != nil { | |
return nil, fmt.Errorf("请求失败:[%d] %v", resp.StatusCode, err) | |
} | |
return data, nil | |
} | |
func getPublicIP() (string, error) { | |
// 通过访问 http://pv.sohu.com/cityjson 来获取 | |
// var returnCitySN = {"cip": "111.196.240.67", "cid": "110000", "cname": "北京市"}; | |
data, err := httpGetRequest("http://pv.sohu.com/cityjson") | |
if err != nil { | |
return "", err | |
} | |
if i := bytes.IndexByte(data, '{'); i > 0 { | |
data = data[i:] | |
any := json.Get(data, "cip") | |
return any.ToString(), nil | |
} else { | |
return "", fmt.Errorf("格式不正确:%s", string(data)) | |
} | |
} | |
func getIPAddressOfDomain(domain, myip string) (string, error) { | |
// 通过 119.29.29.29 的 接口获取最合适的 IP | |
url := "http://119.29.29.29/d?dn=" + domain + "&ip=" + myip | |
data, err := httpGetRequest(url) | |
if err != nil { | |
return "", err | |
} | |
// 可能会有多个 IP 返回,只要第一个 | |
// 185.199.109.154;185.199.110.154;185.199.111.154;185.199.108.154 | |
if i := bytes.IndexByte(data, ';'); i > 6 { | |
data = data[0:i] | |
} | |
return string(data), nil | |
} | |
func main() { | |
// 1、获取本机的公网IP | |
myip, err := getPublicIP() | |
if err != nil { | |
fmt.Println("获取公网 IP 地址失败:", err) | |
return | |
} | |
// 2、获取域名对应的IP地址 | |
domainlist := []string{ | |
"github.global.ssl.fastly.net", | |
"github.com", | |
"assets-cdn.github.com", | |
"documentcloud.github.com", | |
"gist.github.com", | |
"help.github.com", | |
"nodeload.github.com", | |
"raw.github.com", | |
"status.github.com", | |
"training.github.com", | |
"www.github.com", | |
"avatars0.githubusercontent.com", | |
"avatars1.githubusercontent.com", | |
"github.githubassets.com", | |
"github-production-release-asset-2e65be.s3.amazonaws.com", | |
"api.github.com", | |
"user-images.githubusercontent.com", | |
"raw.githubusercontent.com", | |
"gist.githubusercontent.com", | |
"camo.githubusercontent.com", | |
"avatars2.githubusercontent.com", | |
"avatars3.githubusercontent.com", | |
"avatars4.githubusercontent.com", | |
"avatars5.githubusercontent.com", | |
"avatars6.githubusercontent.com", | |
"avatars8.githubusercontent.com", | |
"github.io", | |
"avatars7.githubusercontent.com", | |
} | |
// 域名IP映射表 | |
domaintoipaddr := make(map[string]string) | |
for _, domain := range domainlist { | |
ipaddr, err := getIPAddressOfDomain(domain, myip) | |
if err != nil { | |
fmt.Println("错误:", err, domain) | |
continue | |
} | |
fmt.Println(ipaddr, domain) | |
domaintoipaddr[domain] = ipaddr | |
} | |
// 3、更新 hosts 文件 | |
hostspath := "/etc/hosts" | |
if runtime.GOOS == "windows" { | |
// 这里应该先通过环境变量 windir 或 SystemRoot 获取路径 | |
hostspath = "C:/Windows/System32/drivers/etc/hosts" | |
} | |
// 读取 hosts 文件 | |
hostsdata, err := ioutil.ReadFile(hostspath) | |
if err != nil { | |
fmt.Println(err) | |
return | |
} | |
// 逐行读取并更新 | |
hostsreader := bufio.NewReader(bytes.NewReader(hostsdata)) | |
hostsbuffer := bytes.NewBuffer(nil) | |
hostswriter := bufio.NewWriter(hostsbuffer) | |
line, err := hostsreader.ReadSlice('\n') | |
for ; err == nil; line, err = hostsreader.ReadSlice('\n') { | |
// 分割为多个部分 | |
fields := bytes.Fields(line) | |
// 可能是 # xxx xxxx | |
// 127.0.0.1 localhost # xxxxx | |
// 等多种形势 | |
if len(fields) < 2 || fields[0][0] == byte('#') { | |
hostswriter.Write(line) | |
continue | |
} | |
// 如果域名存在,则替换 | |
domain := string(fields[1]) | |
if ipaddr, ok := domaintoipaddr[domain]; ok { | |
fields[0] = []byte(ipaddr) | |
line = bytes.Join(fields, []byte(" ")) | |
line = append(line, byte('\n')) | |
// 将映射表内的删除 | |
delete(domaintoipaddr, domain) | |
} | |
hostswriter.Write(line) | |
} | |
// 将不存在 Hosts 中的加入 | |
hostswriter.WriteString("\n# github speed\n") | |
for domain := range domaintoipaddr { | |
hostswriter.WriteString(fmt.Sprintln(domaintoipaddr[domain], domain)) | |
} | |
hostswriter.Flush() | |
// 写入到 hosts 文件,这里应该需要管理员权限 | |
err = ioutil.WriteFile(hostspath, hostsbuffer.Bytes(), os.ModePerm) | |
if err != nil { | |
fmt.Println("写入更新失败:", err) | |
return | |
} | |
// 还需要刷新下 DNS 缓存,这里就直接给个提示好了 | |
fmt.Println("更新 hosts 文件完成,需要刷新 DNS 缓存请参考下面命令") | |
fmt.Println("Windows 请执行命令: ipconfig /flushdns") | |
fmt.Println("Linux 请执行命令: sudo service nscd restart") | |
fmt.Println(" 或: sudo service restart") | |
fmt.Println(" 或: sudo systemctl restart network") | |
fmt.Println(" 或: sudo /etc/init.d/networking restart") | |
fmt.Println("MacOS 请执行命令: sudo killall -HUP mDNSResponder") | |
fmt.Println(" Yosemite: sudo discoveryutil udnsflushcaches") | |
fmt.Println(" Snow Leopard: sudo dscacheutil -flushcache") | |
fmt.Println("Leopard and below: sudo lookupd -flushcache") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment