package main import ( "encoding/json" "log" "net/http" "os/exec" "regexp" "strings" "time" ) // Switch 轮换IP相关类 type Switch struct { // config map[string]interface{} // configMutex sync.Mutex ipregion *regexp.Regexp lastShow int64 lastSwitch int64 Worker *DIPWorker AO *AlertOver } // SetAddrForward 设置当前ip 转发的节点 func SetAddrForward(num, addr, ip string) { port := strings.Split(addr, ":")[1] cmd := exec.Command("/bin/sh", "-c", "sudo iptables -t nat -R IPSWITCH "+num+" -p tcp --dport "+port+" -j DNAT --to "+ip+":8885") err := cmd.Run() if err != nil { panic(err) } } // NewSwitch 初始化默认 func NewSwitch() *Switch { swi := Switch{} swi.Worker = NewDipWorker("actives.yaml") swi.AO = &AlertOver{} swi.AO.SetDefaultSetting() log.Println(swi.Worker.ShowGroupInfo()) http.HandleFunc("/ippool/switch/imactive", swi.imActive) http.HandleFunc("/ippool/switch/update", swi.updateActives) http.HandleFunc("/ippool/switch/actives", swi.switchActives) http.HandleFunc("/ippool/switch/allproxies", swi.allProxies) return &swi } // Run addr 监听的地址addr // ipregion 匹配adsl的规则, 作为ping服务器并且控制网络转发的调度 func (swi *Switch) Run(addr string, ipregion string) { swi.ipregion = regexp.MustCompile(ipregion) cmd := exec.Command("/bin/sh", "-c", "sudo iptables -t nat -N IPSWITCH") cmd.Run() if err := cmd.Process.Release(); err != nil { panic(err) } cmd = exec.Command("/bin/sh", "-c", "sudo iptables -t nat -F IPSWITCH") cmd.Run() if err := cmd.Process.Release(); err != nil { panic(err) } for range swi.Worker.ForLoop { cmd := exec.Command("/bin/sh", "-c", "sudo iptables -t nat -A IPSWITCH -p icmp -s 1.1.1.1 -j DNAT --to 1.1.1.1:8885") err := cmd.Run() if err != nil { panic(err) } if err := cmd.Process.Release(); err != nil { panic(err) } } server := &http.Server{Addr: addr, Handler: nil} server.SetKeepAlivesEnabled(false) server.ListenAndServe() } // timeToSwitch 计算是否到切换时间 func (swi *Switch) timeToSwitch(now int64) { for addr, group := range swi.Worker.ForLoop { if group.Current == nil { group.Choose(addr) } else { if now >= group.Current.ActiveTime+swi.Worker.Restart { // log.Println(now, group.Current.ActiveTime, swi.Worker.Restart) group.Choose(addr) } } } } func (swi *Switch) clearReady(now int64) { for _, dipg := range swi.Worker.ForMatch { var delIPList []string for ip, dhost := range dipg.Ready { if now >= dhost.ActiveTime+150 { delIPList = append(delIPList, ip) } } for _, ip := range delIPList { delete(dipg.Ready, ip) } } } // checkInReady 签到的IP(vps的vpn节点IP)) func (swi *Switch) checkInReady(ip string, now int64) { if dipg, ok := swi.Worker.ForMatch[ip]; ok { if dh, ok := dipg.Waitor[ip]; ok { if dh.OverTime(now, 20) > 0 { delete(dipg.Waitor, ip) } else { return } } dipg.Group[ip].ActiveTime = now if dipg.Current == nil { dhost := NewDHost(ip) dhost.ActiveTime = now dipg.Ready[ip] = dhost } else { if dipg.Current.Host != ip { if v, ok := dipg.Ready[ip]; ok { v.ActiveTime = now } else { dhost := NewDHost(ip) dhost.ActiveTime = now dipg.Ready[ip] = dhost } } } } } // imActive 子节点访问 证明自己是活跃 func (swi *Switch) imActive(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() w.Write([]byte("ok")) ip := strings.Split(req.RemoteAddr, ":")[0] // log.Println(ip) // 后续可以把这些节点, 自动活跃与更新 swi.Worker.Mutex.Lock() defer swi.Worker.Mutex.Unlock() now := time.Now().Unix() // 60秒show一次日志 if now >= swi.lastShow+60 { swi.clearReady(now) swi.lastShow = now log.Println("\n" + swi.Worker.ShowGroupInfo()) } // 5秒一次检测 if now >= swi.lastSwitch+5 { swi.lastSwitch = now swi.timeToSwitch(now) } swi.checkInReady(ip, now) } // updateActives 更新最新配置 func (swi *Switch) updateActives(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() swi.Worker.Mutex.Lock() defer swi.Worker.Mutex.Unlock() swi.Worker = NewDipWorker("actives.yaml") w.Write([]byte("update success!")) } func (swi *Switch) switchActives(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() swi.Worker.Mutex.Lock() defer swi.Worker.Mutex.Unlock() now := time.Now().Unix() content := make(map[string]map[string]interface{}) for addr, group := range swi.Worker.ForLoop { addrmap := make(map[string]interface{}) isappend := int64(0) var hosts []string for _, dhost := range group.Group { if dhost.OverTime(now, 150) == 0 { isappend++ } hosts = append(hosts, dhost.Host) } if isappend > 1 { content[addr] = addrmap addrmap["group"] = hosts addrmap["city"] = group.City } } jdata, err := json.Marshal(content) ErrorLog(err) _, err = w.Write(jdata) ErrorLog(err) } func (swi *Switch) allProxies(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() swi.Worker.Mutex.Lock() defer swi.Worker.Mutex.Unlock() now := time.Now().Unix() content := make(map[string]map[string]interface{}) for addr, group := range swi.Worker.ForLoop { addrmap := make(map[string]interface{}) content[addr] = addrmap isappend := int64(0) var hosts []string for _, dhost := range group.Group { hosts = append(hosts, dhost.Host) } addrmap["group"] = hosts addrmap["city"] = group.City } jdata, err := json.Marshal(content) ErrorLog(err) _, err = w.Write(jdata) ErrorLog(err) }