From d434b50dfcdd1da79a5316450499a8918a68da1d Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Fri, 4 Dec 2015 15:49:39 +0000 Subject: [PATCH 1/7] Include trust level in features exchange Add a 'Trusted' feature to the protocol exchange which indicates whether the remote considers us to be reachable via a secure network; overlay encryption will be disabled in the event that both peers agree. For backwards compatibility purposes a default value of untrusted is assumed if the feature is missing. --- mesh/connection.go | 47 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/mesh/connection.go b/mesh/connection.go index 7edb9253..b2c09139 100644 --- a/mesh/connection.go +++ b/mesh/connection.go @@ -40,17 +40,19 @@ type RemoteConnection struct { type LocalConnection struct { sync.RWMutex RemoteConnection - TCPConn *net.TCPConn - version byte - tcpSender TCPSender - SessionKey *[32]byte - heartbeatTCP *time.Ticker - Router *Router - uid uint64 - actionChan chan<- ConnectionAction - errorChan chan<- error - finished <-chan struct{} // closed to signal that actorLoop has finished - OverlayConn OverlayConnection + TCPConn *net.TCPConn + TrustRemote bool // is remote on a trusted subnet? + TrustedByRemote bool // does remote trust us? + version byte + tcpSender TCPSender + SessionKey *[32]byte + heartbeatTCP *time.Ticker + Router *Router + uid uint64 + actionChan chan<- ConnectionAction + errorChan chan<- error + finished <-chan struct{} // closed to signal that actorLoop has finished + OverlayConn OverlayConnection } type ConnectionAction func() error @@ -94,6 +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, uid: randUint64(), actionChan: actionChan, errorChan: errorChan, @@ -189,13 +192,19 @@ func (conn *LocalConnection) run(actionChan <-chan ConnectionAction, errorChan < conn.Log("connection ready; using protocol version", conn.version) + // only use negotiated session key for untrusted connections + var sessionKey *[32]byte + if conn.Untrusted() { + sessionKey = conn.SessionKey + } + params := OverlayConnectionParams{ RemotePeer: conn.remote, LocalAddr: conn.TCPConn.LocalAddr().(*net.TCPAddr), RemoteAddr: conn.TCPConn.RemoteAddr().(*net.TCPAddr), Outbound: conn.outbound, ConnUID: conn.uid, - SessionKey: conn.SessionKey, + SessionKey: sessionKey, SendControlMessage: conn.sendOverlayControlMessage, Features: intro.Features, } @@ -253,6 +262,7 @@ func (conn *LocalConnection) makeFeatures() map[string]string { "ShortID": fmt.Sprint(conn.local.ShortID), "UID": fmt.Sprint(conn.local.UID), "ConnID": fmt.Sprint(conn.uid), + "Trusted": fmt.Sprint(conn.TrustRemote), } conn.Router.Overlay.AddFeaturesTo(features) return features @@ -300,6 +310,15 @@ func (conn *LocalConnection) parseFeatures(features features) (*Peer, error) { } } + var trusted bool + if trustedStr, present := features["Trusted"]; present { + trusted, err = strconv.ParseBool(trustedStr) + if err != nil { + return nil, err + } + } + conn.TrustedByRemote = trusted + uid, err := ParsePeerUID(features.Get("UID")) if err != nil { return nil, err @@ -435,3 +454,7 @@ func (conn *LocalConnection) handleProtocolMsg(tag ProtocolTag, payload []byte) func (conn *LocalConnection) extendReadDeadline() { conn.TCPConn.SetReadDeadline(time.Now().Add(TCPHeartbeat * 2)) } + +func (conn *LocalConnection) Untrusted() bool { + return !conn.TrustRemote || !conn.TrustedByRemote +} From 059cc65b559f70d797897c3a1bfe2f5266ee1070 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Fri, 4 Dec 2015 16:52:02 +0000 Subject: [PATCH 2/7] 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 ] ... From 4e41d4d45125e13d923088b0e124639ac5d4423c Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Mon, 7 Dec 2015 14:54:42 +0000 Subject: [PATCH 3/7] Add trusted subnets to `weave status` `weave status` now displays the list of specified trusted subnets, and `weave staus connections` shows the encryption state of individual connections. --- mesh/status.go | 20 +++++++++++++++++++- prog/weaver/http.go | 9 +++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/mesh/status.go b/mesh/status.go index 0dce08bb..559dae66 100644 --- a/mesh/status.go +++ b/mesh/status.go @@ -2,6 +2,7 @@ package mesh import ( "fmt" + "net" ) type Status struct { @@ -19,6 +20,7 @@ type Status struct { Connections []LocalConnectionStatus Targets []string OverlayDiagnostics interface{} + TrustedSubnets []string } type PeerStatus struct { @@ -69,7 +71,8 @@ func NewStatus(router *Router) *Status { NewBroadcastRouteStatusSlice(router.Routes), NewLocalConnectionStatusSlice(router.ConnectionMaker), NewTargetSlice(router.ConnectionMaker), - router.Overlay.Diagnostics()} + router.Overlay.Diagnostics(), + NewTrustedSubnetsSlice(router.TrustedSubnets)} } func NewPeerStatusSlice(peers *Peers) []PeerStatus { @@ -147,6 +150,13 @@ func NewLocalConnectionStatusSlice(cm *ConnectionMaker) []LocalConnectionStatus } lc, _ := conn.(*LocalConnection) info := fmt.Sprintf("%-6v %v", lc.OverlayConn.DisplayName(), conn.Remote()) + if lc.Router.UsingPassword() { + if lc.Untrusted() { + info = fmt.Sprintf("%-11v %v", "encrypted", info) + } else { + info = fmt.Sprintf("%-11v %v", "unencrypted", info) + } + } slice = append(slice, LocalConnectionStatus{conn.RemoteTCPAddr(), conn.Outbound(), state, info}) } for address, target := range cm.targets { @@ -191,3 +201,11 @@ func NewTargetSlice(cm *ConnectionMaker) []string { } return <-resultChan } + +func NewTrustedSubnetsSlice(trustedSubnets []*net.IPNet) []string { + trustedSubnetStrs := []string{} + for _, trustedSubnet := range trustedSubnets { + trustedSubnetStrs = append(trustedSubnetStrs, trustedSubnet.String()) + } + return trustedSubnetStrs +} diff --git a/prog/weaver/http.go b/prog/weaver/http.go index 1dc84925..2fed6787 100644 --- a/prog/weaver/http.go +++ b/prog/weaver/http.go @@ -27,11 +27,11 @@ var rootTemplate = template.New("root").Funcs(map[string]interface{}{ } return count }, - "upstreamServers": func(servers []string) string { - if len(servers) == 0 { + "printList": func(list []string) string { + if len(list) == 0 { return "none" } - return strings.Join(servers, ", ") + return strings.Join(list, ", ") }, "printIPAMRanges": func(router weave.NetworkRouterStatus, status ipam.Status) string { var buffer bytes.Buffer @@ -153,6 +153,7 @@ var statusTemplate = defTemplate("status", `\ Targets: {{len .Router.Targets}} Connections: {{len .Router.Connections}}{{with printConnectionCounts .Router.Connections}} ({{.}}){{end}} Peers: {{len .Router.Peers}}{{with printPeerConnectionCounts .Router.Peers}} (with {{.}} connections){{end}} +TrustedSubnets: {{printList .Router.TrustedSubnets}} {{if .IPAM}}\ Service: ipam @@ -176,7 +177,7 @@ var statusTemplate = defTemplate("status", `\ Service: dns Domain: {{.DNS.Domain}} - Upstream: {{upstreamServers .DNS.Upstream}} + Upstream: {{printList .DNS.Upstream}} TTL: {{.DNS.TTL}} Entries: {{countDNSEntries .DNS.Entries}} {{end}}\ From e0cb9cf24ddb59ea0db4899c79466a678a0e0a5f Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Mon, 7 Dec 2015 15:32:39 +0000 Subject: [PATCH 4/7] Restore leading whitespace to `weave status` --- prog/weaver/http.go | 46 ++++++++++++++++++++++----------------------- weave | 8 ++++---- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/prog/weaver/http.go b/prog/weaver/http.go index 2fed6787..a0cca5c8 100644 --- a/prog/weaver/http.go +++ b/prog/weaver/http.go @@ -138,48 +138,48 @@ func defTemplate(name string, text string) *template.Template { } var statusTemplate = defTemplate("status", `\ - Version: {{.Version}} + Version: {{.Version}} - Service: router - Protocol: {{.Router.Protocol}} \ + Service: router + Protocol: {{.Router.Protocol}} \ {{if eq .Router.ProtocolMinVersion .Router.ProtocolMaxVersion}}\ {{.Router.ProtocolMaxVersion}}\ {{else}}\ {{.Router.ProtocolMinVersion}}..{{.Router.ProtocolMaxVersion}}\ {{end}} - Name: {{.Router.Name}}({{.Router.NickName}}) - Encryption: {{printState .Router.Encryption}} - PeerDiscovery: {{printState .Router.PeerDiscovery}} - Targets: {{len .Router.Targets}} - Connections: {{len .Router.Connections}}{{with printConnectionCounts .Router.Connections}} ({{.}}){{end}} - Peers: {{len .Router.Peers}}{{with printPeerConnectionCounts .Router.Peers}} (with {{.}} connections){{end}} -TrustedSubnets: {{printList .Router.TrustedSubnets}} + Name: {{.Router.Name}}({{.Router.NickName}}) + Encryption: {{printState .Router.Encryption}} + PeerDiscovery: {{printState .Router.PeerDiscovery}} + Targets: {{len .Router.Targets}} + Connections: {{len .Router.Connections}}{{with printConnectionCounts .Router.Connections}} ({{.}}){{end}} + Peers: {{len .Router.Peers}}{{with printPeerConnectionCounts .Router.Peers}} (with {{.}} connections){{end}} + TrustedSubnets: {{printList .Router.TrustedSubnets}} {{if .IPAM}}\ - Service: ipam + Service: ipam {{if .IPAM.Entries}}\ {{if allIPAMOwnersUnreachable .IPAM}}\ - Status: all IP ranges owned by unreachable peers - use 'rmpeer' if they are dead + Status: all IP ranges owned by unreachable peers - use 'rmpeer' if they are dead {{else if len .IPAM.PendingAllocates}}\ - Status: waiting for IP range grant from peers + Status: waiting for IP range grant from peers {{else}}\ - Status: ready + Status: ready {{end}}\ {{else if .IPAM.Paxos}}\ - Status: awaiting consensus (quorum: {{.IPAM.Paxos.Quorum}}, known: {{.IPAM.Paxos.KnownNodes}}) + Status: awaiting consensus (quorum: {{.IPAM.Paxos.Quorum}}, known: {{.IPAM.Paxos.KnownNodes}}) {{else}}\ - Status: idle + Status: idle {{end}}\ - Range: {{.IPAM.Range}} - DefaultSubnet: {{.IPAM.DefaultSubnet}} + Range: {{.IPAM.Range}} + DefaultSubnet: {{.IPAM.DefaultSubnet}} {{end}}\ {{if .DNS}}\ - Service: dns - Domain: {{.DNS.Domain}} - Upstream: {{printList .DNS.Upstream}} - TTL: {{.DNS.TTL}} - Entries: {{countDNSEntries .DNS.Entries}} + Service: dns + Domain: {{.DNS.Domain}} + Upstream: {{printList .DNS.Upstream}} + TTL: {{.DNS.TTL}} + Entries: {{countDNSEntries .DNS.Entries}} {{end}}\ `) diff --git a/weave b/weave index feca703d..9d2cef47 100755 --- a/weave +++ b/weave @@ -1892,13 +1892,13 @@ EOF fi if [ -z "$SUB_STATUS" ] && check_running $PROXY_CONTAINER_NAME 2>/dev/null && PROXY_ADDRS=$(proxy_addrs) ; then echo - echo " Service: proxy" - echo " Address: $PROXY_ADDRS" + echo " Service: proxy" + echo " Address: $PROXY_ADDRS" fi if [ -z "$SUB_STATUS" ] && check_running $PLUGIN_CONTAINER_NAME 2>/dev/null ; then echo - echo " Service: plugin" - echo " DriverName: weave" + echo " Service: plugin" + echo " DriverName: weave" fi [ -n "$SUB_STATUS" ] || echo [ $res -eq 0 ] From b9792f8f96ba396f14a7e470459932bb8da2aa39 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Mon, 7 Dec 2015 16:04:49 +0000 Subject: [PATCH 5/7] Document trusted subnets Update features and troubleshooting markdown. --- site/features.md | 18 ++++++++++----- site/troubleshooting.md | 50 ++++++++++++++++++++++------------------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/site/features.md b/site/features.md index 4dbbb7ab..e7e949a1 100644 --- a/site/features.md +++ b/site/features.md @@ -63,7 +63,9 @@ Weave automatically chooses the fastest available method to transport data between peers. The most performant of these ('fastdp') offers near-native throughput and latency but does not support encryption; consequently supplying a password will cause the router to fall back -to a slower mode ('sleeve') that does. +to a slower mode ('sleeve') that does, for connections that traverse +untrusted networks (see the [security](#security) section for more +details). Even when encryption is not in use, certain adverse network conditions will cause this fallback to occur dynamically; in these circumstances, @@ -321,10 +323,16 @@ way to generate a random password which satsifies this requirement is < /dev/urandom tr -dc A-Za-z0-9 | head -c9 ; echo -The same password must be specified for all weave peers. Note that -supplying a password will [cause weave to fall back to a slower -method](#fast-data-path) for transporting data between -peers. +The same password must be specified for all weave peers; by default +both control and data plane traffic will then use authenticated +encryption. If some of your peers are colocated in a trusted network +(for example within the boundary of your own datacentre) you can use +the `--trusted-subnets` argument to `weave launch` to selectively +disable data plane encryption as an optimisation. Both peers must +consider the other to be in a trusted subnet for this to take place - +if they do not, weave will [fall back to a slower +method](#fast-data-path) for transporting data between peers as fast +datapath does not support encryption. Be aware that: diff --git a/site/troubleshooting.md b/site/troubleshooting.md index bc5bbb2b..22b81758 100644 --- a/site/troubleshooting.md +++ b/site/troubleshooting.md @@ -68,29 +68,30 @@ A status summary can be obtained with `weave status`: ```` $ weave status - Version: 1.1.0 + Version: 1.1.0 - Service: router - Protocol: weave 1..2 - Name: 4a:0f:f6:ec:1c:93(host1) - Encryption: disabled - PeerDiscovery: enabled - Targets: [192.168.48.14 192.168.48.15] - Connections: 5 (1 established, 1 pending, 1 retrying, 1 failed, 1 connecting) - Peers: 3 (with 5 established, 1 pending connections) + Service: router + Protocol: weave 1..2 + Name: 4a:0f:f6:ec:1c:93(host1) + Encryption: disabled + PeerDiscovery: enabled + Targets: [192.168.48.14 192.168.48.15] + Connections: 5 (1 established, 1 pending, 1 retrying, 1 failed, 1 connecting) + Peers: 3 (with 5 established, 1 pending connections) + TrustedSubnets: none - Service: ipam - Consensus: achieved - Range: 10.32.0.0-10.47.255.255 - DefaultSubnet: 10.32.0.0/12 + Service: ipam + Consensus: achieved + Range: 10.32.0.0-10.47.255.255 + DefaultSubnet: 10.32.0.0/12 - Service: dns - Domain: weave.local. - TTL: 1 - Entries: 9 + Service: dns + Domain: weave.local. + TTL: 1 + Entries: 9 - Service: proxy - Address: tcp://127.0.0.1:12375 + Service: proxy + Address: tcp://127.0.0.1:12375 ```` @@ -129,6 +130,9 @@ state. Further details are available with number of connections peers have to other peers. Further details are available with [`weave status peers`](#weave-status-peers). +'TrustedSubnets' shows subnets which the router trusts as specified by +the `--trusted-subnets` option to `weave launch`. + There are further sections for the [IP address allocator](ipam.html#troubleshooting), [weaveDNS](weavedns.html#troubleshooting), and [Weave Docker API @@ -141,8 +145,8 @@ obtained with `weave status connections`: ```` $ weave status connections -<- 192.168.48.12:33866 established fastdp 7e:21:4a:70:2f:45(host2) -<- 192.168.48.13:60773 pending fastdp 7e:ae:cd:d5:23:8d(host3) +<- 192.168.48.12:33866 established unencrypted fastdp 7e:21:4a:70:2f:45(host2) +<- 192.168.48.13:60773 pending encrypted fastdp 7e:ae:cd:d5:23:8d(host3) -> 192.168.48.14:6783 retrying dial tcp4 192.168.48.14:6783: no route to host -> 192.168.48.15:6783 failed dial tcp4 192.168.48.15:6783: no route to host, retry: 2015-08-06 18:55:38.246910357 +0000 UTC -> 192.168.48.16:6783 connecting @@ -162,8 +166,8 @@ The columns are as follows: heartbeat * `established` - TCP connection and corresponding UDP path are up * Info - the failure reason for failed and retrying connections, or - the data transport method, remote peer name and nickname for - pending and established connections + the encryption mode, data transport method, remote peer name and + nickname for pending and established connections ### List peers From 85d4b1f1379fe449d836ceb186f7eb0c4a2c5e82 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Mon, 7 Dec 2015 16:36:23 +0000 Subject: [PATCH 6/7] Smoke test trusted subnets --- test/110_encryption_2_test.sh | 3 +++ test/115_optional_encryption_2_test.sh | 30 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100755 test/115_optional_encryption_2_test.sh diff --git a/test/110_encryption_2_test.sh b/test/110_encryption_2_test.sh index 5f46a463..205a9928 100755 --- a/test/110_encryption_2_test.sh +++ b/test/110_encryption_2_test.sh @@ -14,4 +14,7 @@ start_container $HOST1 $C1/24 --name=c1 start_container $HOST2 $C2/24 --name=c2 assert_raises "exec_on $HOST1 c1 $PING $C2" +assert_raises "weave_on $HOST1 status connections | grep encrypted" +assert_raises "weave_on $HOST2 status connections | grep encrypted" + end_suite diff --git a/test/115_optional_encryption_2_test.sh b/test/115_optional_encryption_2_test.sh new file mode 100755 index 00000000..a84f2e65 --- /dev/null +++ b/test/115_optional_encryption_2_test.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +. ./config.sh + +start_suite "Optional encryption via trusted subnets" + +# Determine subnet for hosts given either an IP or name. We need to resolve +# these entries on the remote hosts to make sure we get the private +# IP addresses in the Circle/GCE context +HOST1_IP=$($SSH $HOST1 "getent hosts $HOST1" | grep $HOST1 | cut -d ' ' -f 1) +HOST2_IP=$($SSH $HOST2 "getent hosts $HOST2" | grep $HOST2 | cut -d ' ' -f 1) +HOST1_CIDR=$($SSH $HOST1 "ip addr show" | grep -oP $HOST1_IP/[0-9]+) +HOST2_CIDR=$($SSH $HOST2 "ip addr show" | grep -oP $HOST2_IP/[0-9]+) + +# Check asymmetric trust - connections should be encrypted +weave_on $HOST1 launch --password wfvAwt7sj --trusted-subnets $HOST2_CIDR +weave_on $HOST2 launch --password wfvAwt7sj $HOST1 +assert_raises "weave_on $HOST1 status connections | grep encrypted" +assert_raises "weave_on $HOST2 status connections | grep encrypted" + +weave_on $HOST1 stop +weave_on $HOST2 stop + +# Check symmetric trust - overlay in plaintext +weave_on $HOST1 launch --password wfvAwt7sj --trusted-subnets $HOST2_CIDR +weave_on $HOST2 launch --password wfvAwt7sj --trusted-subnets $HOST1_CIDR $HOST1 +assert_raises "weave_on $HOST1 status connections | grep unencrypted" +assert_raises "weave_on $HOST2 status connections | grep unencrypted" + +end_suite From e12dbb460536461443b937113512be58f7b4e3e6 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Tue, 15 Dec 2015 11:47:11 +0000 Subject: [PATCH 7/7] Disable pcap optimisation of encrypted sleeve Prior to optional encryption support, enabling encryption disabled the fast datapath overlay (because it doesn't support encryption) but left the OVS datapath netdev in place for bridging (so that users could switch encryption on and off without resetting the bridge). In this situation the ODP miss handler is guaranteed to be invoked for every packet, so as an optimisation the weave script configured the router to use pcap to capture packets from the bridge as that is slightly more efficient. The introduction of optional encryption means the guarantee no longer holds, and so the optimisation must be removed. --- weave | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/weave b/weave index 9d2cef47..7a412b49 100755 --- a/weave +++ b/weave @@ -298,8 +298,6 @@ DATAPATH=datapath BRIDGE_IFNAME=link-${BRIDGE} DATAPATH_IFNAME=${DATAPATH}-link CONTAINER_IFNAME=ethwe -# ROUTER_HOSTNETNS_IFNAME is only used for fastdp with encryption -ROUTER_HOSTNETNS_IFNAME=veth-weave PORT=${WEAVE_PORT:-6783} HTTP_PORT=6784 PROXY_PORT=12375 @@ -742,27 +740,7 @@ ask_version() { } router_opts_fastdp() { - if [ -z "$WEAVE_PASSWORD" ] ; then - echo "--datapath $DATAPATH" - else - # When using encryption, we still do bridging on the ODP - # datapath, because you can 'weave launch' without encryption - # and then later restart the router with encryption, or vice - # versa. Encryption disables the use of the fastdp Overlay, - # but the router could still use the fastdp Bridge to receive - # packets. However, pcap has better performance when sniffing - # every packet. So we pass --iface to use the pcap Bridge. - # - # Why don't we simply pass "--iface $BRIDGE". We could, - # except for the fact that NetworkManager likes to down the - # odp $BRIDGE netdev (at least under ubuntu), and you can only - # use pcap on an interface that is up. We avoid that by use - # pcap via a veth pair (NetworkManager leaves them alone). - # Having a netdev in the host netns called "ethwe" might - # surprise people, so it is called $ROUTER_HOSTNETNS_IFNAME - # instead. - echo "--datapath $DATAPATH --iface $ROUTER_HOSTNETNS_IFNAME" - fi + echo "--datapath $DATAPATH" } router_opts_bridge() { @@ -778,15 +756,7 @@ router_opts_bridged_fastdp() { ###################################################################### setup_router_iface_fastdp() { - if [ -n "$WEAVE_PASSWORD" ] ; then - # See router_opts_fastdp - # No-op if already attached - if ip link show $LOCAL_IFNAME >/dev/null 2>&1 ; then - return 0 - fi - connect_container_to_bridge $ROUTER_HOSTNETNS_IFNAME && - ip link set $ROUTER_HOSTNETNS_IFNAME up - fi + true } setup_router_iface_bridge() { @@ -1581,8 +1551,6 @@ launch_router() { if [ "$BRIDGE_TYPE" != bridge ] ; then NETHOST_OPT="--net=host" HTTP_IP=127.0.0.1 - # In case there is a lingering veth-weave netdev - ip link del $ROUTER_HOSTNETNS_IFNAME >/dev/null 2>&1 || true fi # Set WEAVE_DOCKER_ARGS in the environment in order to supply @@ -1635,10 +1603,6 @@ attach_router() { stop_router() { stop $CONTAINER_NAME "Weave" conntrack -D -p udp --dport $PORT >/dev/null 2>&1 || true - # Remove the veth-weave netdev in a fastdp context - if detect_bridge_type && [ "$BRIDGE_TYPE" != bridge ] ; then - ip link del $ROUTER_HOSTNETNS_IFNAME >/dev/null 2>&1 || true - fi } launch_proxy() {