From 9dc6d6db7c5e10818643e8adbe0e98711a8c54d9 Mon Sep 17 00:00:00 2001 From: mpl Date: Thu, 15 Dec 2016 00:23:43 +0100 Subject: [PATCH] pkg/gpgchallenge: more paranoia against clients -check claimed IP is a global unicast one -set timeout on requests, so they don't make us create long-lived connections for nothing -prevent redirects -disable keepalive connections Change-Id: Ibdbdd9916ddc93eb58505b04b4f21de60e37c745 --- pkg/gpgchallenge/gpg.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/pkg/gpgchallenge/gpg.go b/pkg/gpgchallenge/gpg.go index ff58e07ec..3503cda35 100644 --- a/pkg/gpgchallenge/gpg.go +++ b/pkg/gpgchallenge/gpg.go @@ -100,6 +100,7 @@ const ( forgetSeen = time.Minute // anyone being quiet for that long is taken off the "potential spammer" list queriesRate = 10 // max concurrent (non-whitelisted) clients minKeySize = 2048 // in bits. to force potential attackers to generate GPG keys at least this expensive. + requestTimeout = 3 * time.Second // so a client does not make use create many long-lived connections ) // Server sends a challenge when a client that wants to claim ownership of an IP @@ -246,6 +247,19 @@ func (cs *Server) handleClaim(w http.ResponseWriter, r *http.Request) { return } + // Verify claimedIP looks ok + ip := net.ParseIP(claimedIP) + if ip == nil { + http.Error(w, "nope", http.StatusBadRequest) + log.Printf("%q does not look like a valid IP address", claimedIP) + return + } + if !ip.IsGlobalUnicast() { + http.Error(w, "nope", http.StatusBadRequest) + log.Printf("%q does not look like a nice IP", claimedIP) + return + } + keyID := pk.KeyIdShortString() if isSpammer := cs.rateLimit(keyID, claimedIP); isSpammer { http.Error(w, "don't be a spammer", http.StatusTooManyRequests) @@ -262,9 +276,16 @@ func (cs *Server) handleClaim(w http.ResponseWriter, r *http.Request) { } tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + DisableKeepAlives: true, + } + cl := &http.Client{ + Transport: tr, + Timeout: requestTimeout, + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + }, } - cl := &http.Client{Transport: tr} resp, err := cl.Post(fmt.Sprintf("https://%s:%d/%s", claimedIP, ClientChallengedPort, clientEndPointChallenge), "text/plain", strings.NewReader(nonce)) if err != nil {