mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 02:00:43 +00:00
Merge pull request #1410 from weaveworks/1408-dnat-shortlived-connections
Correctly attribute DNAT-ed short-lived connections
This commit is contained in:
@@ -298,7 +298,7 @@ func (c *container) NetworkMode() (string, bool) {
|
||||
func addScopeToIPs(hostID string, ips []string) []string {
|
||||
ipsWithScopes := []string{}
|
||||
for _, ip := range ips {
|
||||
ipsWithScopes = append(ipsWithScopes, report.MakeScopedAddressNodeID(hostID, ip))
|
||||
ipsWithScopes = append(ipsWithScopes, report.MakeAddressNodeID(hostID, ip))
|
||||
}
|
||||
return ipsWithScopes
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ func TestContainer(t *testing.T) {
|
||||
want := report.EmptySets.
|
||||
Add("docker_container_ports", report.MakeStringSet("1.2.3.4:80->80/tcp", "81/tcp")).
|
||||
Add("docker_container_ips", report.MakeStringSet("1.2.3.4")).
|
||||
Add("docker_container_ips_with_scopes", report.MakeStringSet("scope;1.2.3.4"))
|
||||
Add("docker_container_ips_with_scopes", report.MakeStringSet(";1.2.3.4"))
|
||||
|
||||
test.Poll(t, 100*time.Millisecond, want, func() interface{} {
|
||||
return c.NetworkInfo([]net.IP{})
|
||||
|
||||
@@ -30,7 +30,7 @@ func TestNat(t *testing.T) {
|
||||
// the setup is this:
|
||||
//
|
||||
// container2 (10.0.47.2:222222), host2 (2.3.4.5:22223) ->
|
||||
// host1 (1.2.3.4:80), container1 (10.0.47.2:80)
|
||||
// host1 (1.2.3.4:80), container1 (10.0.47.1:80)
|
||||
|
||||
// from the PoV of host1
|
||||
{
|
||||
|
||||
@@ -106,7 +106,7 @@ func (r *Reporter) Report() (report.Report, error) {
|
||||
rpt := report.MakeReport()
|
||||
seenTuples := map[string]fourTuple{}
|
||||
|
||||
// Consult the flowWalker for short-live connections
|
||||
// Consult the flowWalker for short-lived connections
|
||||
{
|
||||
extraNodeInfo := map[string]string{
|
||||
Conntracked: "true",
|
||||
@@ -118,6 +118,18 @@ func (r *Reporter) Report() (report.Report, error) {
|
||||
uint16(f.Original.Layer4.SrcPort),
|
||||
uint16(f.Original.Layer4.DstPort),
|
||||
}
|
||||
// Handle DNAT-ed short-lived connections.
|
||||
// The NAT mapper won't help since it only runs periodically,
|
||||
// missing the short-lived connections.
|
||||
if f.Original.Layer3.DstIP != f.Reply.Layer3.SrcIP {
|
||||
tuple = fourTuple{
|
||||
f.Reply.Layer3.DstIP,
|
||||
f.Reply.Layer3.SrcIP,
|
||||
uint16(f.Reply.Layer4.DstPort),
|
||||
uint16(f.Reply.Layer4.SrcPort),
|
||||
}
|
||||
}
|
||||
|
||||
seenTuples[tuple.key()] = tuple
|
||||
r.addConnection(&rpt, tuple, extraNodeInfo, extraNodeInfo)
|
||||
})
|
||||
|
||||
@@ -94,7 +94,7 @@ func (r *Reporter) podEvent(e Event, pod Pod) {
|
||||
}
|
||||
|
||||
func isPauseContainer(n report.Node, rpt report.Report) bool {
|
||||
containerImageIDs, ok := n.Sets.Lookup(report.ContainerImage)
|
||||
containerImageIDs, ok := n.Parents.Lookup(report.ContainerImage)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -138,8 +138,12 @@ func probeMain(flags probeFlags) {
|
||||
p.AddTagger(probe.NewTopologyTagger(), host.NewTagger(hostID))
|
||||
|
||||
if flags.dockerEnabled {
|
||||
if err := report.AddLocalBridge(flags.dockerBridge); err != nil {
|
||||
log.Errorf("Docker: problem with bridge %s: %v", flags.dockerBridge, err)
|
||||
// Don't add the bridge in Kubernetes since container IPs are global and
|
||||
// shouldn't be scoped
|
||||
if !flags.kubernetesEnabled {
|
||||
if err := report.AddLocalBridge(flags.dockerBridge); err != nil {
|
||||
log.Errorf("Docker: problem with bridge %s: %v", flags.dockerBridge, err)
|
||||
}
|
||||
}
|
||||
if registry, err := docker.NewRegistry(flags.dockerInterval, clients, true, hostID); err == nil {
|
||||
defer registry.Stop()
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/weaveworks/scope/common/mtime"
|
||||
|
||||
"github.com/weaveworks/scope/probe/docker"
|
||||
"github.com/weaveworks/scope/probe/endpoint"
|
||||
"github.com/weaveworks/scope/probe/host"
|
||||
@@ -23,10 +25,27 @@ var (
|
||||
serverPort = "80"
|
||||
serverEndpointNodeID = report.MakeEndpointNodeID(serverHostID, serverIP, serverPort)
|
||||
|
||||
containerID = "a1b2c3d4e5"
|
||||
containerIP = "192.168.0.1"
|
||||
containerName = "foo"
|
||||
containerNodeID = report.MakeContainerNodeID(containerID)
|
||||
container1ID = "11b2c3d4e5"
|
||||
container1IP = "192.168.0.1"
|
||||
container1Name = "foo"
|
||||
container1NodeID = report.MakeContainerNodeID(container1ID)
|
||||
|
||||
container1Port = "16782"
|
||||
container1EndpointNodeID = report.MakeEndpointNodeID(serverHostID, container1IP, container1Port)
|
||||
|
||||
duplicatedIP = "192.168.0.2"
|
||||
duplicatedPort = "80"
|
||||
duplicatedEndpointNodeID = report.MakeEndpointNodeID(serverHostID, duplicatedIP, duplicatedPort)
|
||||
|
||||
container2ID = "21b2c3d4e5"
|
||||
container2IP = duplicatedIP
|
||||
container2Name = "bar"
|
||||
container2NodeID = report.MakeContainerNodeID(container2ID)
|
||||
|
||||
pauseContainerID = "31b2c3d4e5"
|
||||
pauseContainerIP = duplicatedIP
|
||||
pauseContainerName = "POD"
|
||||
pauseContainerNodeID = report.MakeContainerNodeID(pauseContainerID)
|
||||
|
||||
rpt = report.Report{
|
||||
Endpoint: report.Topology{
|
||||
@@ -44,19 +63,52 @@ var (
|
||||
endpoint.Conntracked: "true",
|
||||
}).
|
||||
WithTopology(report.Endpoint),
|
||||
|
||||
container1EndpointNodeID: report.MakeNodeWith(container1EndpointNodeID, map[string]string{
|
||||
endpoint.Addr: container1IP,
|
||||
endpoint.Port: container1Port,
|
||||
endpoint.Conntracked: "true",
|
||||
}).
|
||||
WithAdjacent(duplicatedEndpointNodeID).WithTopology(report.Endpoint),
|
||||
|
||||
duplicatedEndpointNodeID: report.MakeNodeWith(duplicatedEndpointNodeID, map[string]string{
|
||||
endpoint.Addr: duplicatedIP,
|
||||
endpoint.Port: duplicatedPort,
|
||||
endpoint.Conntracked: "true",
|
||||
}).
|
||||
WithTopology(report.Endpoint),
|
||||
},
|
||||
},
|
||||
Container: report.Topology{
|
||||
Nodes: report.Nodes{
|
||||
containerNodeID: report.MakeNodeWith(containerNodeID, map[string]string{
|
||||
docker.ContainerID: containerID,
|
||||
docker.ContainerName: containerName,
|
||||
container1NodeID: report.MakeNodeWith(container1NodeID, map[string]string{
|
||||
docker.ContainerID: container1ID,
|
||||
docker.ContainerName: container1Name,
|
||||
report.HostNodeID: serverHostNodeID,
|
||||
}).
|
||||
WithSets(report.EmptySets.
|
||||
Add(docker.ContainerIPs, report.MakeStringSet(containerIP)).
|
||||
Add(docker.ContainerIPs, report.MakeStringSet(container1IP)).
|
||||
Add(docker.ContainerIPsWithScopes, report.MakeStringSet(report.MakeAddressNodeID("", container1IP))).
|
||||
Add(docker.ContainerPorts, report.MakeStringSet(fmt.Sprintf("%s:%s->%s/tcp", serverIP, serverPort, serverPort))),
|
||||
).WithTopology(report.Container),
|
||||
container2NodeID: report.MakeNodeWith(container2NodeID, map[string]string{
|
||||
docker.ContainerID: container2ID,
|
||||
docker.ContainerName: container2Name,
|
||||
report.HostNodeID: serverHostNodeID,
|
||||
}).
|
||||
WithSets(report.EmptySets.
|
||||
Add(docker.ContainerIPs, report.MakeStringSet(container2IP)).
|
||||
Add(docker.ContainerIPsWithScopes, report.MakeStringSet(report.MakeAddressNodeID("", container2IP))),
|
||||
).WithTopology(report.Container),
|
||||
pauseContainerNodeID: report.MakeNodeWith(pauseContainerNodeID, map[string]string{
|
||||
docker.ContainerID: pauseContainerID,
|
||||
docker.ContainerName: pauseContainerName,
|
||||
report.HostNodeID: serverHostNodeID,
|
||||
}).
|
||||
WithSets(report.EmptySets.
|
||||
Add(docker.ContainerIPs, report.MakeStringSet(pauseContainerIP)).
|
||||
Add(docker.ContainerIPsWithScopes, report.MakeStringSet(report.MakeAddressNodeID("", pauseContainerIP))),
|
||||
).WithTopology(report.Container).WithLatest(report.DoesNotMakeConnections, mtime.Now(), ""),
|
||||
},
|
||||
},
|
||||
Host: report.Topology{
|
||||
@@ -81,7 +133,21 @@ func TestShortLivedInternetNodeConnections(t *testing.T) {
|
||||
t.Fatal("Expected output to have an incoming internet node")
|
||||
}
|
||||
|
||||
if !internet.Adjacency.Contains(report.MakeContainerNodeID(containerID)) {
|
||||
t.Errorf("Expected internet node to have adjacency to %s, but only had %v", report.MakeContainerNodeID(containerID), internet.Adjacency)
|
||||
if !internet.Adjacency.Contains(container1NodeID) {
|
||||
t.Errorf("Expected internet node to have adjacency to %s, but only had %v", container1NodeID, internet.Adjacency)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPauseContainerDiscarded(t *testing.T) {
|
||||
have := Prune(render.ContainerWithImageNameRenderer.Render(rpt, render.FilterNoop))
|
||||
// There should be a single connection between from container1 and the destination should be container2
|
||||
container1, ok := have[container1NodeID]
|
||||
if !ok {
|
||||
t.Fatal("Expected output to have container1")
|
||||
}
|
||||
|
||||
if !container1.Adjacency.Contains(container2NodeID) {
|
||||
t.Errorf("Expected container1 to have adjacency to %s, but only had %v", container2NodeID, container1.Adjacency)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user