Add dynamic relay lookup (DDoS relays.syncthing.net!)

This commit is contained in:
Audrius Butkevicius 2015-07-23 20:39:44 +01:00
parent 687fbb0a7e
commit 6cccd9b6fc
3 changed files with 65 additions and 11 deletions

View File

@ -219,7 +219,7 @@ type OptionsConfiguration struct {
LocalAnnEnabled bool `xml:"localAnnounceEnabled" json:"localAnnounceEnabled" default:"true"`
LocalAnnPort int `xml:"localAnnouncePort" json:"localAnnouncePort" default:"21025"`
LocalAnnMCAddr string `xml:"localAnnounceMCAddr" json:"localAnnounceMCAddr" default:"[ff32::5222]:21026"`
RelayServers []string `xml:"relayServer" json:"relayServers" default:""`
RelayServers []string `xml:"relayServer" json:"relayServers" default:"dynamic+https://relays.syncthing.net"`
MaxSendKbps int `xml:"maxSendKbps" json:"maxSendKbps"`
MaxRecvKbps int `xml:"maxRecvKbps" json:"maxRecvKbps"`
ReconnectIntervalS int `xml:"reconnectionIntervalS" json:"reconnectionIntervalS" default:"60"`

View File

@ -37,6 +37,7 @@ func TestDefaultValues(t *testing.T) {
LocalAnnEnabled: true,
LocalAnnPort: 21025,
LocalAnnMCAddr: "[ff32::5222]:21026",
RelayServers: []string{"dynamic+https://relays.syncthing.net"},
MaxSendKbps: 0,
MaxRecvKbps: 0,
ReconnectIntervalS: 60,

View File

@ -8,7 +8,9 @@ package relay
import (
"crypto/tls"
"encoding/json"
"net"
"net/http"
"net/url"
"time"
@ -82,7 +84,8 @@ func (s *Svc) VerifyConfiguration(from, to config.Configuration) error {
}
func (s *Svc) CommitConfiguration(from, to config.Configuration) bool {
existing := make(map[string]struct{}, len(to.Options.RelayServers))
existing := make(map[string]*url.URL, len(to.Options.RelayServers))
for _, addr := range to.Options.RelayServers {
uri, err := url.Parse(addr)
if err != nil {
@ -91,32 +94,74 @@ func (s *Svc) CommitConfiguration(from, to config.Configuration) bool {
}
continue
}
existing[uri.String()] = uri
}
existing[uri.String()] = struct{}{}
// Expand dynamic addresses into a set of relays
for key, uri := range existing {
if uri.Scheme != "dynamic+http" && uri.Scheme != "dynamic+https" {
continue
}
delete(existing, key)
_, ok := s.tokens[uri.String()]
uri.Scheme = uri.Scheme[8:]
data, err := http.Get(uri.String())
if err != nil {
if debug {
l.Debugln("Failed to lookup dynamic relays", err)
}
continue
}
var ann dynamicAnnouncement
err = json.NewDecoder(data.Body).Decode(&ann)
data.Body.Close()
if err != nil {
if debug {
l.Debugln("Failed to lookup dynamic relays", err)
}
continue
}
for _, relayAnn := range ann.Relays {
ruri, err := url.Parse(relayAnn.URL)
if err != nil {
if debug {
l.Debugln("Failed to parse dynamic relay address", relayAnn.URL, err)
}
continue
}
if debug {
l.Debugln("Found", ruri, "via", uri)
}
existing[ruri.String()] = ruri
}
}
for key, uri := range existing {
_, ok := s.tokens[key]
if !ok {
if debug {
l.Debugln("Connecting to relay", uri)
}
c := client.NewProtocolClient(uri, s.tlsCfg.Certificates, s.invitations)
s.tokens[uri.String()] = s.Add(c)
s.tokens[key] = s.Add(c)
s.mut.Lock()
s.clients[uri.String()] = c
s.clients[key] = c
s.mut.Unlock()
}
}
for uri, token := range s.tokens {
_, ok := existing[uri]
for key, token := range s.tokens {
_, ok := existing[key]
if !ok {
err := s.Remove(token)
delete(s.tokens, uri)
delete(s.tokens, key)
s.mut.Lock()
delete(s.clients, uri)
delete(s.clients, key)
s.mut.Unlock()
if debug {
l.Debugln("Disconnecting from relay", uri, err)
l.Debugln("Disconnecting from relay", key, err)
}
}
}
@ -195,3 +240,11 @@ func (r *invitationReceiver) Stop() {
r.stop <- struct{}{}
r.stop = nil
}
type dynamicAnnouncement struct {
Relays []relayAnnouncement `json:"relays"`
}
type relayAnnouncement struct {
URL string `json:"url"`
}