package main import ( "fmt" "io" "io/ioutil" mu "mfw/util" "net" "net/http" "os/exec" "strings" "time" ) //检测端口是否可用 func checkPort() (sPorts, fPorts []string) { output, err := exec.Command("netstat", "-tuln").Output() if err != nil { fmt.Println("执行netstat命令时出错:", err) return } lines := strings.Split(string(output), "\n") for _, port := range config.Ports { portOk := false for _, line := range lines { if line == "" { continue } fields := strings.Fields(line) if len(fields) >= 4 && strings.Contains(fields[3], fmt.Sprint(port)) { //端口存活 portOk = true } } if portOk { sPorts = append(sPorts, fmt.Sprint(port)) } else { fPorts = append(fPorts, fmt.Sprint(port)) } } return } //测速 func checkSpeed(addr string, updatename bool) (float64, float64) { conn, err := net.Dial("tcp", addr) if err != nil { return 0, 0 } defer conn.Close() t1 := time.Now() buf := make([]byte, 1024) for i := 0; i < 50; i++ { io.ReadFull(conn, buf) } dd := time.Since(t1) t1 = time.Now() for i := 0; i < 50; i++ { conn.Write(buf) } for { _, err := conn.Write(buf) if err != nil { break } time.Sleep(10 * time.Millisecond) } ud := time.Since(t1) dp, up := float64(0.05)/dd.Seconds(), float64(0.05)/ud.Seconds() msg := fmt.Sprintf(MSG_TPL, config.VpsName, float64(0.05)/dd.Seconds(), float64(0.05)/ud.Seconds()) fmt.Println("网速测试,", msg) if updatename { client.WriteObj("", "", mu.EVENT_UPDATE_MYNAME, mu.SENDTO_TYPE_P2P, []byte(msg)) } return dp, up } //切换IP func changeIP() { sendMessageBeforChangeIp() defer sendMessageAfterChangeIp() for { fmt.Println("start change ip...") exec.Command("pppoe-stop").Run() exec.Command("pppoe-start").Run() fmt.Println("wait...") time.Sleep(10 * time.Second) //避免换IP后无法获取IP newIp := getMyIp() //获取新IP fmt.Println("newIp:", newIp) if newIp != "" && newIp != myoldip { fmt.Println("公网IP由", myoldip, "换为", newIp) ds, us := checkSpeed(config.CheckSpeedAddr, true) //测速 if ds >= config.DownSpeedLimit && us >= config.UploadSpeedLimit { //网速达标 fmt.Println("IP测速通过", newIp) myoldip = newIp break } } time.Sleep(5 * time.Second) } } func sendMessageBeforChangeIp() { fmt.Println("切换IP前发送消息...") bs := []byte{} for _, v := range cache { udpclient.WriteUdp([]byte{}, mu.OP_WILLCHANGEIP, v.Addr) //udp通知本服务器的下载器节点要切换ip,下掉所有服务 bs = append(bs, []byte(v.Code)...) } client.WriteObj("", "", mu.SERVICE_DOWNLOAD_DELETE_NODE, mu.SENDTO_TYPE_ALL_RECIVER, bs) } func sendMessageAfterChangeIp() { fmt.Println("切换IP后发送消息...") cacheLock.Lock() for k, v := range cache { //告诉下载器重连 udpclient.WriteUdp([]byte{}, mu.OP_NEWCLIENT, v.Addr) delete(cache, k) } cacheLock.Unlock() go func() { for i := 1; i <= 5; i++ { time.Sleep(5 * time.Second) if len(cache) > 0 { bs := []byte{} for k, v := range cache { fmt.Println("本机下载器机器码:", k, v.Code) bs = append(bs, []byte(v.Code)...) } client.WriteObj("", "", mu.SERVICE_DOWNLOAD_APPEND_NODE, mu.SENDTO_TYPE_ALL_RECIVER, bs) return } } }() } //获取IP func getMyIp() (ip string) { for i := 1; i <= 3; i++ { client := &http.Client{ Timeout: 5 * time.Second, // 设置超时时间为5秒 } resp, err := client.Get("https://api.ipify.org") // 使用ipify.org提供的IP查询API if err != nil { fmt.Println("获取公网IP失败:", err) continue } ipByte, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("获取公网IP失败:", err) continue } resp.Body.Close() ip = string(ipByte) return } return } func checkIpAndPort() (sPorts, fPorts []string) { //检测IP if !changing { //正在切换IP,不做测速检测 fmt.Println("测速...") ds, us := checkSpeed(config.CheckSpeedAddr, false) //测速 if ds < config.DownSpeedLimit || us < config.UploadSpeedLimit { //网速不达标,切换IP go runChangeIP() //重新切换IP } } fmt.Println("检测端口...") //检测端口 sPorts, fPorts = checkPort() if len(fPorts) == len(config.Ports) { //端口都不可用,重启端口 go reStartPorts() //本轮检测重启,不可用 } time.Sleep(1 * time.Second) return } //端口重启 func reStartPorts() { tmpPort := []string{} for _, port := range config.Ports { tmpPort = append(tmpPort, ":"+fmt.Sprint(port)) } exec.Command("/bin/sh", "-c", `kill -9 $(pidof "proxy")`).Run() //杀proxy exec.Command("proxy", "socks", "-t", "tcp", "-p", strings.Join(tmpPort, ","), "--forever", "--nolog", "--daemon").Run() //启动proxy }