ipcenter/switch.go

254 lines
5.5 KiB
Go
Raw Permalink Normal View History

2018-12-16 18:58:52 +00:00
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")
2018-12-24 08:58:01 +00:00
err := cmd.Run()
2018-12-16 18:58:52 +00:00
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)
2019-03-14 06:46:44 +00:00
http.HandleFunc("/ippool/switch/allproxies", swi.allProxies)
2018-12-16 18:58:52 +00:00
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")
2018-12-17 16:42:59 +00:00
cmd.Run()
if err := cmd.Process.Release(); err != nil {
panic(err)
}
2018-12-16 18:58:52 +00:00
cmd = exec.Command("/bin/sh", "-c", "sudo iptables -t nat -F IPSWITCH")
2018-12-17 16:42:59 +00:00
cmd.Run()
if err := cmd.Process.Release(); err != nil {
panic(err)
}
2018-12-16 18:58:52 +00:00
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")
2018-12-17 16:42:59 +00:00
err := cmd.Run()
2018-12-16 18:58:52 +00:00
if err != nil {
panic(err)
}
2018-12-17 16:42:59 +00:00
if err := cmd.Process.Release(); err != nil {
panic(err)
}
2018-12-16 18:58:52 +00:00
}
2018-12-17 18:53:09 +00:00
server := &http.Server{Addr: addr, Handler: nil}
server.SetKeepAlivesEnabled(false)
server.ListenAndServe()
2018-12-16 18:58:52 +00:00
}
// 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)
}
}
}
}
2018-12-21 19:30:25 +00:00
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)
}
}
}
2018-12-16 18:58:52 +00:00
// checkInReady 签到的IP(vps的vpn节点IP))
func (swi *Switch) checkInReady(ip string, now int64) {
if dipg, ok := swi.Worker.ForMatch[ip]; ok {
2018-12-16 19:22:25 +00:00
if dh, ok := dipg.Waitor[ip]; ok {
2018-12-17 06:51:43 +00:00
if dh.OverTime(now, 20) > 0 {
2018-12-16 19:22:25 +00:00
delete(dipg.Waitor, ip)
} else {
return
}
}
2018-12-24 08:58:01 +00:00
dipg.Group[ip].ActiveTime = now
2018-12-16 18:58:52 +00:00
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 子节点访问 证明自己是活跃
2018-12-17 02:25:09 +00:00
func (swi *Switch) imActive(w http.ResponseWriter, req *http.Request) {
defer req.Body.Close()
2018-12-16 18:58:52 +00:00
w.Write([]byte("ok"))
2018-12-17 02:25:09 +00:00
ip := strings.Split(req.RemoteAddr, ":")[0]
2018-12-16 18:58:52 +00:00
// log.Println(ip) // 后续可以把这些节点, 自动活跃与更新
swi.Worker.Mutex.Lock()
defer swi.Worker.Mutex.Unlock()
now := time.Now().Unix()
// 60秒show一次日志
if now >= swi.lastShow+60 {
2018-12-21 19:30:25 +00:00
swi.clearReady(now)
2018-12-16 18:58:52 +00:00
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) {
2018-12-17 02:25:09 +00:00
defer req.Body.Close()
2018-12-16 18:58:52 +00:00
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) {
2018-12-17 02:25:09 +00:00
defer req.Body.Close()
2018-12-16 18:58:52 +00:00
swi.Worker.Mutex.Lock()
defer swi.Worker.Mutex.Unlock()
now := time.Now().Unix()
2018-12-17 02:25:09 +00:00
content := make(map[string]map[string]interface{})
2018-12-16 18:58:52 +00:00
for addr, group := range swi.Worker.ForLoop {
2018-12-17 02:25:09 +00:00
addrmap := make(map[string]interface{})
isappend := int64(0)
var hosts []string
2018-12-16 18:58:52 +00:00
for _, dhost := range group.Group {
2018-12-17 02:25:09 +00:00
if dhost.OverTime(now, 150) == 0 {
isappend++
}
hosts = append(hosts, dhost.Host)
2018-12-16 18:58:52 +00:00
}
2018-12-17 02:25:09 +00:00
if isappend > 1 {
2018-12-28 03:16:50 +00:00
content[addr] = addrmap
2018-12-17 02:25:09 +00:00
addrmap["group"] = hosts
addrmap["city"] = group.City
2018-12-16 18:58:52 +00:00
}
}
jdata, err := json.Marshal(content)
ErrorLog(err)
_, err = w.Write(jdata)
ErrorLog(err)
}
2019-03-14 06:46:44 +00:00
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)
}