From 059cc65b559f70d797897c3a1bfe2f5266ee1070 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Fri, 4 Dec 2015 16:52:02 +0000 Subject: [PATCH] Fallback to encrypted sleeve on a per-connection basis If overlay encryption is required between peers, the fast datapath forwarder returns an error rather than aborting the process, allowing the overlay switch to fall back gracefully to an encrypted sleeve overlay connection. --- mesh/connection.go | 2 +- mesh/router.go | 15 +++++++++++++++ prog/weaver/main.go | 30 ++++++++++++++++++++++++++---- router/fastdp.go | 5 ++--- router/overlay_switch.go | 12 ++++++++++-- weave | 3 ++- 6 files changed, 56 insertions(+), 11 deletions(-) diff --git a/mesh/connection.go b/mesh/connection.go index b2c09139..ae03017d 100644 --- a/mesh/connection.go +++ b/mesh/connection.go @@ -96,7 +96,7 @@ func StartLocalConnection(connRemote *RemoteConnection, tcpConn *net.TCPConn, ro RemoteConnection: *connRemote, // NB, we're taking a copy of connRemote here. Router: router, TCPConn: tcpConn, - TrustRemote: false, + TrustRemote: router.Trusts(connRemote), uid: randUint64(), actionChan: actionChan, errorChan: errorChan, diff --git a/mesh/router.go b/mesh/router.go index 5f51cc87..598e485d 100644 --- a/mesh/router.go +++ b/mesh/router.go @@ -37,6 +37,7 @@ type Config struct { Password []byte ConnLimit int PeerDiscovery bool + TrustedSubnets []*net.IPNet } type Router struct { @@ -181,3 +182,17 @@ func (router *Router) applyTopologyUpdate(update []byte) (PeerNameSet, PeerNameS } return origUpdate, newUpdate, nil } + +func (router *Router) Trusts(remote *RemoteConnection) bool { + if tcpAddr, err := net.ResolveTCPAddr("tcp4", remote.remoteTCPAddr); err == nil { + for _, trustedSubnet := range router.TrustedSubnets { + if trustedSubnet.Contains(tcpAddr.IP) { + return true + } + } + } else { + // Should not happen as remoteTCPAddr was obtained from TCPConn + log.Errorf("Unable to parse remote TCP addr: %s", err) + } + return false +} diff --git a/prog/weaver/main.go b/prog/weaver/main.go index d5fb2553..51acd0c3 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -69,6 +69,7 @@ func main() { dnsEffectiveListenAddress string iface *net.Interface datapathName string + trustedSubnetStr string ) mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit") @@ -101,6 +102,8 @@ func main() { mflag.StringVar(&dnsEffectiveListenAddress, []string{"-dns-effective-listen-address"}, "", "address DNS will actually be listening, after Docker port mapping") mflag.StringVar(&datapathName, []string{"-datapath"}, "", "ODP datapath name") + mflag.StringVar(&trustedSubnetStr, []string{"-trusted-subnets"}, "", "Command separated list of trusted subnets in CIDR notation") + // crude way of detecting that we probably have been started in a // container, with `weave launch` --> suppress misleading paths in // mflags error messages. @@ -193,10 +196,7 @@ func main() { Log.Println("Communication between peers is unencrypted.") } else { config.Password = []byte(password) - Log.Println("Communication between peers is encrypted.") - - // fastdp doesn't support encryption - fastDPOverlay = nil + Log.Println("Communication between peers via untrusted networks is encrypted.") } overlays := weave.NewOverlaySwitch() @@ -237,6 +237,10 @@ func main() { networkConfig.PacketLogging = nopPacketLogging{} } + if config.TrustedSubnets, err = parseTrustedSubnets(trustedSubnetStr); err != nil { + Log.Fatal("Unable to parse trusted subnets: ", err) + } + router := weave.NewNetworkRouter(config, networkConfig, name, nickName, overlays) Log.Println("Our name is", router.Ourself) @@ -405,6 +409,24 @@ func determineQuorum(initPeerCountFlag int, peers []string) uint { return quorum } +func parseTrustedSubnets(trustedSubnetStr string) ([]*net.IPNet, error) { + trustedSubnets := []*net.IPNet{} + + if trustedSubnetStr == "" { + return trustedSubnets, nil + } + + for _, subnetStr := range strings.Split(trustedSubnetStr, ",") { + _, subnet, err := net.ParseCIDR(subnetStr) + if err != nil { + return nil, err + } + trustedSubnets = append(trustedSubnets, subnet) + } + + return trustedSubnets, nil +} + func listenAndServeHTTP(httpAddr string, muxRouter *mux.Router) { protocol := "tcp" if strings.HasPrefix(httpAddr, "/") { diff --git a/router/fastdp.go b/router/fastdp.go index 571fb10c..0fee5205 100644 --- a/router/fastdp.go +++ b/router/fastdp.go @@ -515,9 +515,8 @@ type fastDatapathForwarder struct { func (fastdp fastDatapathOverlay) PrepareConnection(params mesh.OverlayConnectionParams) (mesh.OverlayConnection, error) { if params.SessionKey != nil { - // No encryption suport in fastdp. The weaver main.go - // is responsible for ensuring this doesn't happen. - log.Fatal("Attempt to use FastDatapath with encryption") + // No encryption support in fastdp + return nil, fmt.Errorf("encryption not supported") } vxlanVportID := fastdp.mainVxlanVportID diff --git a/router/overlay_switch.go b/router/overlay_switch.go index 9e6efd00..da4bab78 100644 --- a/router/overlay_switch.go +++ b/router/overlay_switch.go @@ -204,8 +204,16 @@ func (osw *OverlaySwitch) PrepareConnection(params mesh.OverlayConnectionParams) subConn, err := overlay.PrepareConnection(params) if err != nil { - fwd.stopFrom(0) - return nil, err + log.Infof("Unable to use %s for connection to %s(%s): %s", + overlay.name, + params.RemotePeer.Name, + params.RemotePeer.NickName, + err) + // failed to start subforwarder - record overlay name and continue + fwd.forwarders[i] = subForwarder{ + overlayName: overlay.name, + } + continue } subFwd := subConn.(OverlayForwarder) diff --git a/weave b/weave index bd3c49dc..feca703d 100755 --- a/weave +++ b/weave @@ -42,7 +42,8 @@ weave setup weave version weave launch [--password ] [--nickname ] [--ipalloc-range [--ipalloc-default-subnet ]] - [--no-discovery] [--init-peer-count ] ... + [--no-discovery] [--init-peer-count ] + [--trusted-subnets ,...] ... weave launch-router [--password ] [--nickname ] [--ipalloc-range [--ipalloc-default-subnet ]] [--no-discovery] [--init-peer-count ] ...