diff --git a/Dockerfile b/Dockerfile index f1813d4eaf7c1f3ea5344c80eec1bee8f0144e67..ef2b410cbff3af4743a6eb7fe473232baf728d3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,7 @@ RUN wget https://www.musl-libc.org/releases/musl-${MUSL_VERSION}.tar.gz && \ COPY . /build RUN cd /build; CGO_ENABLED=1 CC=/usr/local/musl/bin/musl-gcc go build --ldflags '-linkmode external -extldflags=-static' +RUN strip /build/gocanary FROM scratch WORKDIR /canary diff --git a/server/dns/dns.go b/server/dns/dns.go index 2de3be7f75de99a48a97ac5b4a8bd8442518e20b..167d13dc43302ba1af0f62b65021e05a480446ef 100644 --- a/server/dns/dns.go +++ b/server/dns/dns.go @@ -34,7 +34,7 @@ func getCanaryInfo(t tokens.CanaryRecord, w dns.ResponseWriter, r *dns.Msg) aler } // Check if the DNS query contains a token and trigger the alert if it does -func checkAndAlert(q dns.Question, w dns.ResponseWriter, r *dns.Msg) { +func checkAndAlert(q dns.Question, w dns.ResponseWriter, r *dns.Msg) bool { qComponents := strings.Split(q.Name, ".") qFirst := qComponents[0] qDomain := q.Name[len(qFirst)+1:] @@ -43,15 +43,24 @@ func checkAndAlert(q dns.Question, w dns.ResponseWriter, r *dns.Msg) { canary, err := tokens.GetToken(qFirst) if err == nil { alert.DNSAlert(getCanaryInfo(canary, w, r), canary.Alert) + return true } } + return false +} + +func logRequest(q dns.Question, w dns.ResponseWriter) { + slog.Info("dns-request", + "Type", "dns-request", + "Query", q.Name, + "RemoteAddr": w.RemoteAddr().String(), + ) } // Builds the A record, can be NXDOMAIN or a fixed answer from config -func buildAnswer(q dns.Question, m *dns.Msg) { - log.Printf("hello3 ") +func buildAnswer(q dns.Question, m *dns.Msg, canaryTriggered bool) { //Fixed answer - if serverConfig.AnswerWith != "" { + if serverConfig.AnswerWith != "" && canaryTriggered { rr, err := dns.NewRR(fmt.Sprintf("%s A %s", q.Name, serverConfig.AnswerWith)) if err == nil { m.Answer = append(m.Answer, rr) @@ -77,9 +86,9 @@ func handleDNS(w dns.ResponseWriter, r *dns.Msg) { for _, q := range m.Question { switch q.Qtype { case dns.TypeA: - buildAnswer(q, m) // Check if question contains canary - checkAndAlert(q, w, r) + canaryTriggered := checkAndAlert(q, w, r) + buildAnswer(q, m, canaryTriggered) } } } diff --git a/server/http/http.go b/server/http/http.go index 456202f4716cce104c9e74f4e27aa101c27a85bf..4f4beb0ac0ecebd5a89b4bb19db7b04fae7759c8 100644 --- a/server/http/http.go +++ b/server/http/http.go @@ -37,7 +37,7 @@ func getFullUrl(r *http.Request) string { return fmt.Sprintf("%s://%s%s", schema, r.Host, r.URL.Path) } -func getCanaryInfo(t tokens.CanaryRecord, w http.ResponseWriter, r *http.Request) alert.HTTPCanary { +func getCanaryInfo(t tokens.CanaryRecord, r *http.Request) alert.HTTPCanary { return alert.HTTPCanary{ Canary: alert.Canary{ @@ -93,13 +93,13 @@ func handleRequest(w http.ResponseWriter, r *http.Request) { //Look for the last url path as a token canary, err := tokens.GetToken(lastPath) if err == nil { - alert.HTTPAlert(getCanaryInfo(canary, w, r), canary.Alert) + alert.HTTPAlert(getCanaryInfo(canary, r), canary.Alert) return } // Get Host path and look for a token canary, err = tokens.GetToken(hFirst) if err == nil { - alert.HTTPAlert(getCanaryInfo(canary, w, r), canary.Alert) + alert.HTTPAlert(getCanaryInfo(canary, r), canary.Alert) return } } diff --git a/utils/harden/harden.go b/utils/harden/harden.go index bce8c0a5592033b57e09c9fd22fdf30bc4f06162..05397a14c69389e7517542f34cc4a476db9067d1 100644 --- a/utils/harden/harden.go +++ b/utils/harden/harden.go @@ -27,7 +27,7 @@ func ShowCaps() { } // As soon as possible drop root capabilities only to be able to bind and change user/group -func MinCapabilities() { +func MinCapabilities(hardeningEnabled bool) { // Keep the ability to bind to lower ports and drop privs // NewPid(0) means current process caps, err := capability.NewPid(0) @@ -36,14 +36,15 @@ func MinCapabilities() { } caps.Clear(capability.CAPS) caps.Set(capability.CAPS, capability.CAP_NET_BIND_SERVICE) - caps.Set(capability.CAPS, capability.CAP_SETUID) - caps.Set(capability.CAPS, capability.CAP_SETGID) + //Only if hardening enabled, we will need to change user/group later on + if hardeningEnabled { + caps.Set(capability.CAPS, capability.CAP_SETUID) + caps.Set(capability.CAPS, capability.CAP_SETGID) + } if err := caps.Apply(capability.CAPS); err != nil { log.Fatalf("could not apply caps: %v", err) } - - log.Printf("now: %+v", caps) } // Drop to another user/group and clean supplementary groups