prober: icmp: Initialize ID and sequence to random values (#412)
authorBenoît Knecht <benoit.knecht@fsfe.org>
Wed, 30 Jan 2019 10:57:57 +0000 (11:57 +0100)
committerBrian Brazil <brian.brazil@robustperception.io>
Wed, 30 Jan 2019 10:57:57 +0000 (10:57 +0000)
This should help preventing issues with some network devices that have
trouble NATing ICMP packets with the same ID and sequence nubmer but a
different source IP address.

Currently, this can happen if the blackbox_exporter runs in a container
(the ID is set to the PID, which is typically 1 in a container), and
serveral blackbox_exporters are restarted at the same time (the sequence
numbers are reset to zero and stay in sync).

This commit sets the ICMP echo ID to a random value if the PID is 1, and
initializes the sequence number at a random offset.

See #411 for details.

Signed-off-by: Benoît Knecht <benoit.knecht@fsfe.org>
prober/icmp.go

index 330ae9d327806c5e2cbf662662a52d2dce684a35..0f1c819847460176ee61c514b614f7244545acc2 100644 (file)
@@ -16,6 +16,7 @@ package prober
 import (
        "bytes"
        "context"
+       "math/rand"
        "net"
        "os"
        "sync"
@@ -32,10 +33,27 @@ import (
 )
 
 var (
+       icmpID            int
        icmpSequence      uint16
        icmpSequenceMutex sync.Mutex
 )
 
+func init() {
+       // PID is typically 1 when running in a container; in that case, set
+       // the ICMP echo ID to a random value to avoid potential clashes with
+       // other blackbox_exporter instances. See #411.
+       if pid := os.Getpid(); pid == 1 {
+               icmpID = rand.Intn(1 << 16)
+       } else {
+               icmpID = pid & 0xffff
+       }
+
+       // Start the ICMP echo sequence at a random offset to prevent them from
+       // being in sync when several blackbox_exporter instances are restarted
+       // at the same time. See #411.
+       icmpSequence = uint16(rand.Intn(1 << 16))
+}
+
 func getICMPSequence() uint16 {
        icmpSequenceMutex.Lock()
        defer icmpSequenceMutex.Unlock()
@@ -129,7 +147,7 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr
        }
 
        body := &icmp.Echo{
-               ID:   os.Getpid() & 0xffff,
+               ID:   icmpID,
                Seq:  int(getICMPSequence()),
                Data: data,
        }