diff --git a/alpine/Dockerfile b/alpine/Dockerfile index f7e8e1900..10a8f16a2 100644 --- a/alpine/Dockerfile +++ b/alpine/Dockerfile @@ -40,7 +40,6 @@ COPY packages/docker/bin/* /usr/bin/ COPY packages/docker/etc /etc/ COPY packages/diagnostics/diagnostics /usr/bin/ COPY packages/diagnostics/diagnostics-server /usr/bin/ -COPY packages/diagnostics/diagnostics-download /usr/bin/ COPY packages/diagnostics/etc /etc/ COPY packages/automount/etc /etc/ COPY packages/ntp15m/etc /etc/ diff --git a/alpine/packages/Makefile b/alpine/packages/Makefile index f611e7d87..8b1d41a27 100644 --- a/alpine/packages/Makefile +++ b/alpine/packages/Makefile @@ -1,5 +1,6 @@ all: $(MAKE) -C proxy OS=linux + $(MAKE) -C diagnostics OS=linux $(MAKE) -C transfused OS=linux $(MAKE) -C mdnstool OS=linux $(MAKE) -C hupper OS=linux @@ -11,6 +12,7 @@ all: arm: $(MAKE) -C proxy OS=linux ARCH=arm + $(MAKE) -C diagnostics OS=linux ARCH=arm $(MAKE) -C transfused OS=linux ARCH=arm $(MAKE) -C mdnstool OS=linux ARCH=arm $(MAKE) -C hupper OS=linux ARCH=arm @@ -20,6 +22,7 @@ arm: clean: $(MAKE) -C proxy clean + $(MAKE) -C diagnostics clean $(MAKE) -C transfused clean $(MAKE) -C mdnstool clean $(MAKE) -C docker clean diff --git a/alpine/packages/diagnostics/.gitignore b/alpine/packages/diagnostics/.gitignore new file mode 100644 index 000000000..4c3c66566 --- /dev/null +++ b/alpine/packages/diagnostics/.gitignore @@ -0,0 +1 @@ +diagnostics-server diff --git a/alpine/packages/diagnostics/Dockerfile b/alpine/packages/diagnostics/Dockerfile new file mode 100644 index 000000000..3d4add408 --- /dev/null +++ b/alpine/packages/diagnostics/Dockerfile @@ -0,0 +1,15 @@ +FROM golang:alpine + +RUN apk update && apk add alpine-sdk + +RUN mkdir -p /go/src/diagnostics +WORKDIR /go/src/diagnostics + +COPY . /go/src/diagnostics + +ARG GOARCH +ARG GOOS + +RUN go install --ldflags '-extldflags "-fno-PIC"' + +RUN [ -f /go/bin/*/diagnostics ] && mv /go/bin/*/diagnostics /go/bin/ || true diff --git a/alpine/packages/diagnostics/Makefile b/alpine/packages/diagnostics/Makefile new file mode 100644 index 000000000..8d0ed40f5 --- /dev/null +++ b/alpine/packages/diagnostics/Makefile @@ -0,0 +1,10 @@ +all: diagnostics-server + +diagnostics-server: Dockerfile main.go + docker build --build-arg GOOS=$(OS) --build-arg GOARCH=$(ARCH) -t diagnostics:build . + docker run --rm diagnostics:build cat /go/bin/diagnostics > diagnostics-server + chmod 755 diagnostics-server + +clean: + rm -f diagnostics-server + docker images -q diagnostics:build | xargs docker rmi -f diff --git a/alpine/packages/diagnostics/diagnostics-download b/alpine/packages/diagnostics/diagnostics-download deleted file mode 100755 index 79ced7887..000000000 --- a/alpine/packages/diagnostics/diagnostics-download +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -# Gather diagnostic data and write a .tar file to stdout - -TEMP=$(mktemp -d diagnoseXXXXXXX) -trap 'rm -rf "$TEMP"' EXIT -mkdir $TEMP/moby -cd $TEMP/moby - -# gather diagnostic data -timeout -t 2 date > "date" -timeout -t 2 uname -a > "uname -a" -timeout -t 2 ps uax > "ps -aux" -timeout -t 2 netstat -tulpn > "netstat -tulpn" -timeout -t 2 iptables-save > "iptables-save" -timeout -t 2 ifconfig -a > "ifconfig -a" -timeout -t 2 route -n > "route -n" -timeout -t 2 brctl show > "brctl show" -timeout -t 2 dmesg > dmesg -timeout -t 2 docker ps > "docker ps" -timeout -t 2 tail /var/log/docker.log > "docker.log" -timeout -t 2 mount > "mount" -timeout -t 2 df > "df" -timeout -t 2 ls -l /var &> "ls -l var" -timeout -t 2 ls -l /var/lib &> "ls -l var_lib" -timeout -t 2 ls -l /var/lib/docker &> "ls -l var_lib_docker" -timeout -t 2 /usr/bin/diagnostics > "diagnostics" -timeout -t 2 ping -w 5 8.8.8.8 &> "ping -w 5 8.8.8.8" -timeout -t 2 cp /etc/resolv.conf . -timeout -t 2 dig docker.com > "dig docker.com" -timeout -t 2 wget -O - http://www.docker.com/ &> "wget docker.com" - -# send everything to the client -cd .. -tar -c . diff --git a/alpine/packages/diagnostics/diagnostics-server b/alpine/packages/diagnostics/diagnostics-server deleted file mode 100755 index 611b0f28c..000000000 --- a/alpine/packages/diagnostics/diagnostics-server +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -# Allow clients (e.g. pinata diagnose) to download diagnostic data - -while /bin/true; do - nc -l -p 62374 -e /usr/bin/diagnostics-download 2>> /var/log/diagnostics-server.log -done diff --git a/alpine/packages/diagnostics/main.go b/alpine/packages/diagnostics/main.go new file mode 100644 index 000000000..ae6dbc502 --- /dev/null +++ b/alpine/packages/diagnostics/main.go @@ -0,0 +1,133 @@ +package main + +import ( + "archive/tar" + "bytes" + "io" + "log" + "net" + "os/exec" + "path" + "strings" + "time" +) + +func run(timeout time.Duration, w *tar.Writer, command string, args ...string) { + log.Printf("Running %s", command) + c := exec.Command(command, args...) + stdoutPipe, err := c.StdoutPipe() + if err != nil { + log.Fatalf("Failed to create stdout pipe: %#v", err) + } + stderrPipe, err := c.StderrPipe() + if err != nil { + log.Fatalf("Failed to create stderr pipe: %#v", err) + } + var stdoutBuffer bytes.Buffer + var stderrBuffer bytes.Buffer + done := make(chan int) + go func() { + io.Copy(&stdoutBuffer, stdoutPipe) + done <- 0 + }() + go func() { + io.Copy(&stderrBuffer, stderrPipe) + done <- 0 + }() + var timer *time.Timer + timer = time.AfterFunc(timeout, func() { + timer.Stop() + if c.Process != nil { + c.Process.Kill() + } + }) + _ = c.Run() + <-done + <-done + timer.Stop() + + name := strings.Join(append([]string{path.Base(command)}, args...), " ") + + hdr := &tar.Header{ + Name: name + ".stdout", + Mode: 0644, + Size: int64(stdoutBuffer.Len()), + } + if err = w.WriteHeader(hdr); err != nil { + log.Fatalln(err) + } + if _, err = w.Write(stdoutBuffer.Bytes()); err != nil { + log.Fatalln(err) + } + hdr = &tar.Header{ + Name: name + ".stderr", + Mode: 0644, + Size: int64(stderrBuffer.Len()), + } + if err = w.WriteHeader(hdr); err != nil { + log.Fatalln(err) + } + if _, err = w.Write(stderrBuffer.Bytes()); err != nil { + log.Fatalln(err) + } + +} + +func capture(w *tar.Writer) { + t := 2 * time.Second + + run(t, w, "/bin/date") + run(t, w, "/bin/uname", "-a") + run(t, w, "/bin/ps", "uax") + run(t, w, "/bin/netstat", "-tulpn") + run(t, w, "/sbin/iptables-save") + run(t, w, "/sbin/ifconfig", "-a") + run(t, w, "/sbin/route", "-n") + run(t, w, "/usr/sbin/brctl", "show") + run(t, w, "/bin/dmesg") + run(t, w, "/usr/bin/docker", "ps") + run(t, w, "/usr/bin/tail", "/var/log/docker.log") + run(t, w, "/bin/mount") + run(t, w, "/bin/df") + run(t, w, "/bin/ls", "-l", "/var") + run(t, w, "/bin/ls", "-l", "/var/lib") + run(t, w, "/bin/ls", "-l", "/var/lib/docker") + run(t, w, "/usr/bin/diagnostics") + run(t, w, "/bin/ping", "-w", "5", "8.8.8.8") + run(t, w, "/bin/cp", "/etc/resolv.conf", ".") + run(t, w, "/usr/bin/dig", "docker.com") + run(t, w, "/usr/bin/wget", "-O", "-", "http://www.docker.com/") +} + +func main() { + listeners := make([]net.Listener, 0) + + ip, err := net.Listen("tcp", ":62374") + if err != nil { + log.Printf("Failed to bind to TCP port 62374: %#v", err) + } else { + listeners = append(listeners, ip) + } + + for _, l := range listeners { + go func(l net.Listener) { + for { + conn, err := l.Accept() + if err != nil { + log.Printf("Error accepting connection: %#v", err) + return // no more listening + } + go func(conn net.Conn) { + w := tar.NewWriter(conn) + capture(w) + if err := w.Close(); err != nil { + log.Println(err) + } + conn.Close() + }(conn) + } + }(l) + } + forever := make(chan int) + <-forever +}