commit f990e92a9de4a2d0d8750e9f238f4a13bc90fc3c Author: Blallo Date: Mon Oct 12 00:50:07 2020 +0200 Init diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c1c8599 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +output/arm64/probe: + cd probe \ + && GOOS=linux GOARCH=arm64 go build -tags netgo -o ../output/arm64/probe + +output/amd64/probe: + cd probe \ + && GOOS=linux GOARCH=amd64 go build -tags netgo -o ../output/amd64/probe + +output/arm64/probe-server: + cd probe-server \ + && GOOS=linux GOARCH=arm64 go build -tags netgo -o ../output/arm64/probe-server + +output/amd64/probe-server: + cd probe-server \ + && GOOS=linux GOARCH=amd64 go build -tags netgo -o ../output/amd64/probe-server + +build-arm64: output/arm64/probe output/arm64/probe-server + +build-amd64: output/amd64/probe output/amd64/probe-server + +build-all: build-arm64 build-amd64 + +clean-arm64: + rm -f output/arm64/probe* + +clean-amd64: + rm -f output/amd64/probe* + +clean-all: clean-arm64 clean-amd64 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0a7c4ff --- /dev/null +++ b/go.mod @@ -0,0 +1,4 @@ +module git.abbiamoundominio.org/blallo/go-prober + +go 1.15 + diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..47e94a0 --- /dev/null +++ b/go.sum @@ -0,0 +1,12 @@ +github.com/mozilla/mig v0.0.0-20190913234010-9e7e4f525805 h1:aR0FDMk+x7dz50dqbvd5EPobe2cCHvRbUKGD6HhSXhk= +github.com/mozilla/mig v0.0.0-20190913234010-9e7e4f525805/go.mod h1:2c03209qVdj62h4aUMg8KfnbIGC83caKZB8/4F/7YV4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/output/amd64/probe b/output/amd64/probe new file mode 100755 index 0000000..64112de Binary files /dev/null and b/output/amd64/probe differ diff --git a/output/amd64/probe-server b/output/amd64/probe-server new file mode 100755 index 0000000..bf2f0c8 Binary files /dev/null and b/output/amd64/probe-server differ diff --git a/output/arm64/probe b/output/arm64/probe new file mode 100755 index 0000000..ec6fd00 Binary files /dev/null and b/output/arm64/probe differ diff --git a/output/arm64/probe-server b/output/arm64/probe-server new file mode 100755 index 0000000..4756ef5 Binary files /dev/null and b/output/arm64/probe-server differ diff --git a/probe-server/main.go b/probe-server/main.go new file mode 100644 index 0000000..17f01e3 --- /dev/null +++ b/probe-server/main.go @@ -0,0 +1,89 @@ +package main + +import ( + "bufio" + "errors" + "flag" + "log" + "net" + "strconv" + "strings" + "time" +) + +var PortOutOfRange = errors.New("Port out of allowed range 1-65535") +var isDebug bool + +func init() { + isDebug = false +} + +func debug(v ...interface{}) { + if isDebug { + msg := make([]interface{}, len(v)+1) + msg[0] = "[DEBUG]" + for i, el := range v { + msg[i+1] = el + } + log.Println(msg...) + } +} + +func handleConn(c net.Conn) { + defer c.Close() + debug("connection established:", c) + reader := bufio.NewReader(c) + + for { + data, err := reader.ReadString('\n') + debug("Data =>", data) + if err != nil { + log.Fatal(err) + } + cleanData := strings.TrimSpace(string(data)) + duration, err := time.ParseDuration(cleanData) + if err != nil { + log.Fatal(err) + } + debug("Duration =>", duration) + c.Write([]byte("ACK\n")) + time.Sleep(duration) + } + + log.Println("connection closed:", c) +} + +func parsePort(port int) (string, error) { + if port < 1 || port > 65535 { + return "", PortOutOfRange + } + return strconv.Itoa(port), nil +} + +func main() { + var address string + var port int + flag.StringVar(&address, "addr", "", "The target address or ip") + flag.IntVar(&port, "port", 0, "The target port") + flag.BoolVar(&isDebug, "debug", false, "Enable debug logging") + flag.Parse() + + parsedPort, err := parsePort(port) + if err != nil { + log.Fatal(err) + } + host := net.JoinHostPort(address, parsedPort) + server, err := net.Listen("tcp4", host) + if err != nil { + log.Fatal(err) + } + defer server.Close() + + for { + c, err := server.Accept() + if err != nil { + log.Fatal(err) + } + go handleConn(c) + } +} diff --git a/probe/main.go b/probe/main.go new file mode 100644 index 0000000..141836f --- /dev/null +++ b/probe/main.go @@ -0,0 +1,130 @@ +package main + +import ( + "bufio" + "errors" + "flag" + "fmt" + "io" + "log" + "net" + "os" + "strconv" + "time" +) + +var PortNotInRange = errors.New("the port number is not in the 0-65535 range") +var ServiceNotFound = errors.New("the service is not known") +var isDebug bool + +func init() { + isDebug = false +} + +func debug(v ...interface{}) { + if isDebug { + msg := make([]interface{}, len(v)+1) + msg[0] = "[DEBUG]" + for i, el := range v { + msg[i+1] = el + } + log.Println(msg...) + } +} + +func connect(addr, port string) net.Conn { + target := net.JoinHostPort(addr, port) + conn, err := net.Dial("tcp", target) + if err != nil { + log.Fatal(err) + } + zero := time.Time{} + if err = conn.SetDeadline(zero); err != nil { + log.Fatal(err) + } + return conn +} + +func validatePort(port int) error { + if port < 1 || port > 65535 { + return PortNotInRange + } + return nil +} + +func getPort(srv string, port int) (string, error) { + if port != 0 { + return strconv.Itoa(port), nil + } + return srv, nil +} + +func initLogger(logFile string) (*os.File, error) { + f, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + return nil, err + } + wrt := io.MultiWriter(os.Stdout, f) + log.SetOutput(wrt) + return f, nil +} + +// TODO: planned function that should do some ping measurement and return +// the highest value found. +func findLatency(address string) (time.Duration, error) { + return time.Second, nil +} + +func main() { + var address, srv, logFile string + var port int + var interval, latency, zero time.Duration + flag.StringVar(&address, "addr", "", "The target address or ip") + flag.IntVar(&port, "port", 0, "The target port") + flag.StringVar(&srv, "srv", "", "The target service (will be translated to default port, if -port not provided)") + flag.StringVar(&logFile, "log-file", "", "The file path to log to") + flag.DurationVar(&interval, "interval", time.Second, "Internal refresh duration (defaults to 1s)") + flag.DurationVar(&latency, "latency", zero, "Internal refresh duration (defaults to 1s)") + flag.BoolVar(&isDebug, "debug", false, "Enable debug logging") + flag.Parse() + if port != 0 { + validatePort(port) + } + if logFile == "" { + log.Println("Logging only to stdout") + } else if f, err := initLogger(logFile); err != nil { + log.Fatalf("error opening file: %v", err) + f.Close() + } else { + defer f.Close() + } + parsedPort, err := getPort(srv, port) + if err != nil { + log.Fatal(err) + } + if latency == zero { + latency, err = findLatency(address) + if err != nil { + log.Fatal(err) + } + } + log.Printf("Logging every %v\n", interval) + log.Printf("Latency is %v\n", latency) + conn := connect(address, parsedPort) + intervalStr := fmt.Sprintf("%v\n", interval) + for conn != nil { + conn.Write([]byte(intervalStr)) + conn.SetReadDeadline(time.Now().Add(latency)) + if data, err := bufio.NewReader(conn).ReadString('\n'); err != nil { + log.Print(err) + conn.Close() + conn = nil + } else { + debug("Data =>", data) + conn.SetReadDeadline(time.Now().Add(interval + latency)) + } + time.Sleep(interval) + } + + log.Println("Connection closed") +} diff --git a/units/probe-server.service b/units/probe-server.service new file mode 100644 index 0000000..55a04fa --- /dev/null +++ b/units/probe-server.service @@ -0,0 +1,7 @@ +[Unit] +Description=Probe server to allow testing of long-lived connections + +[Service] +Type=simple +ExecStart=/usr/local/bin/probe-server -port ${PROBE_PORT} +Restart=always diff --git a/units/probe.service b/units/probe.service new file mode 100644 index 0000000..fceca93 --- /dev/null +++ b/units/probe.service @@ -0,0 +1,8 @@ +[Unit] +Description=Probe network for disconnections on long-lived connections + +[Service] +Type=simple +ExecStart=/usr/local/bin/probe -addr ${PROBE_HOST} -port ${PROBE_PORT} -log-file /var/log/probe/probe.log +Restart=always +RestartSec=60