-
Notifications
You must be signed in to change notification settings - Fork 2
/
monitor.go
91 lines (87 loc) · 2.56 KB
/
monitor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package main
import (
"net"
"os/exec"
"strconv"
"time"
)
func generator() {
generatorLock.Lock()
defer generatorLock.Unlock()
logger.Debug("updating new list...")
for _, tunnel := range tunnels {
ipt.ClearChain("mangle", tunnel.ChainName)
}
var chainSerials map[string]int
var chainSerialsTotal map[string]int
chainSerials = make(map[string]int)
chainSerialsTotal = make(map[string]int)
for _, tunnel := range tunnels {
if tunnel.status {
for j := 0; j < tunnel.Weight; j++ {
_, exists := chainSerialsTotal[tunnel.ChainName]
if !exists {
chainSerialsTotal[tunnel.ChainName] = 0
}
chainSerialsTotal[tunnel.ChainName]++
}
}
}
for _, tunnel := range tunnels {
if tunnel.status {
for j := 0; j < tunnel.Weight; j++ {
_, exists := chainSerials[tunnel.ChainName]
if !exists {
chainSerials[tunnel.ChainName] = 0
}
logger.Debug("iptables -t mangle -A %s -m statistic --mode nth --every %s --packet %s -j MARK --set-xmark %s", tunnel.ChainName, strconv.Itoa(chainSerialsTotal[tunnel.ChainName]), strconv.Itoa(chainSerials[tunnel.ChainName]), tunnel.Mark)
ipt.Append("mangle", tunnel.ChainName, "-m", "statistic", "--mode", "nth", "--every", strconv.Itoa(chainSerialsTotal[tunnel.ChainName]), "--packet", strconv.Itoa(chainSerials[tunnel.ChainName]), "-j", "MARK", "--set-xmark", tunnel.Mark)
chainSerials[tunnel.ChainName]++
}
}
}
logger.Trace("updating finished")
}
func monitor() {
pin.OnRecv = func(addr *net.IPAddr, rtt time.Duration) {
logger.Trace("ping %s %f ms", addr.String(), rtt.Seconds())
tunInfo := tunnels[ip2tunnel[addr.String()]]
tunInfo.lastlive = time.Now()
if tunInfo.status == false {
logger.Info("connection recover %s(%s)", ip2tunnel[addr.String()], tunInfo.Ip)
tunInfo.status = true
if tunInfo.RecoverCommand != "" {
exec.Command("bash", "-c", tunInfo.RecoverCommand)
}
generator()
}
}
pin.OnIdle = func() {}
pin.MaxRTT = time.Second * time.Duration(rtt)
go func() {
for {
pin.Run()
time.Sleep(time.Second * time.Duration(rtt))
<-pin.Done()
}
}()
for {
regenerate := false
for tunName, tunInfo := range tunnels {
if tunInfo.lastlive.Add(time.Second * time.Duration(determineTime)).Before(time.Now()) {
if tunInfo.status {
logger.Info("connection lost %s(%s)", tunName, tunInfo.Ip)
tunInfo.status = false
regenerate = true
if tunInfo.DownCommand != "" {
exec.Command("bash", "-c", tunInfo.DownCommand)
}
}
}
}
if regenerate {
generator()
}
time.Sleep(time.Second * time.Duration(detectingDuration))
}
}