diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index dcc6361f..98280cad 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "log" + "math/rand" "net" "net/http" _ "net/http/pprof" @@ -103,7 +104,7 @@ func main() { fatalErr(err) } - myID = string(certID(cert.Certificate[0])) + myID = certID(cert.Certificate[0]) log.SetPrefix("[" + myID[0:5] + "] ") logger.SetPrefix("[" + myID[0:5] + "] ") @@ -235,6 +236,9 @@ func main() { var externalPort = 0 if cfg.Options.UPnPEnabled { + // We seed the random number generator with the node ID to get a + // repeatable sequence of random external ports. + rand.Seed(certSeed(cert.Certificate[0])) externalPort = setupUPnP() } @@ -278,9 +282,10 @@ func setupUPnP() int { igd, err := upnp.Discover() if err == nil { for i := 0; i < 10; i++ { - err := igd.AddPortMapping(upnp.TCP, port+i, port, "syncthing", 0) + r := 1024 + rand.Intn(65535-1024) + err := igd.AddPortMapping(upnp.TCP, r, port, "syncthing", 0) if err == nil { - externalPort = port + i + externalPort = r infoln("Created UPnP port mapping - external port", externalPort) break } diff --git a/cmd/syncthing/tls.go b/cmd/syncthing/tls.go index cfc1ce5b..72e7509f 100644 --- a/cmd/syncthing/tls.go +++ b/cmd/syncthing/tls.go @@ -8,6 +8,7 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/base32" + "encoding/binary" "encoding/pem" "math/big" "os" @@ -32,6 +33,13 @@ func certID(bs []byte) string { return strings.Trim(base32.StdEncoding.EncodeToString(id), "=") } +func certSeed(bs []byte) int64 { + hf := sha256.New() + hf.Write(bs) + id := hf.Sum(nil) + return int64(binary.BigEndian.Uint64(id)) +} + func newCertificate(dir string) { infoln("Generating RSA certificate and key...")