summaryrefslogtreecommitdiffhomepage
path: root/test/iptables
diff options
context:
space:
mode:
authorKevin Krakauer <krakauer@google.com>2020-01-21 13:16:25 -0800
committerKevin Krakauer <krakauer@google.com>2020-01-21 13:16:25 -0800
commit62357a0afb5f4128a11dc9a1dfadd2957ec39e2d (patch)
tree2f93dc1bb5680434f3bcd69df60d45af89777a94 /test/iptables
parentbd292894097ffdf316bc78d81aebd0a2988124f3 (diff)
parent2ba6198851dc1e293295d7cadf8c0ae456b68beb (diff)
Merge branch 'master' into iptables-write-filter-proto
Diffstat (limited to 'test/iptables')
-rw-r--r--test/iptables/BUILD2
-rw-r--r--test/iptables/filter_input.go72
-rw-r--r--test/iptables/filter_output.go87
-rw-r--r--test/iptables/iptables_test.go38
-rw-r--r--test/iptables/iptables_util.go32
-rw-r--r--test/iptables/nat.go80
6 files changed, 295 insertions, 16 deletions
diff --git a/test/iptables/BUILD b/test/iptables/BUILD
index 6a9d05828..22f470092 100644
--- a/test/iptables/BUILD
+++ b/test/iptables/BUILD
@@ -7,8 +7,10 @@ go_library(
testonly = 1,
srcs = [
"filter_input.go",
+ "filter_output.go",
"iptables.go",
"iptables_util.go",
+ "nat.go",
],
importpath = "gvisor.dev/gvisor/test/iptables",
visibility = ["//test/iptables:__subpackages__"],
diff --git a/test/iptables/filter_input.go b/test/iptables/filter_input.go
index a3f0052b5..fd02ff2ff 100644
--- a/test/iptables/filter_input.go
+++ b/test/iptables/filter_input.go
@@ -28,11 +28,13 @@ const (
)
func init() {
+ RegisterTestCase(FilterInputDropAll{})
+ RegisterTestCase(FilterInputDropDifferentUDPPort{})
RegisterTestCase(FilterInputDropOnlyUDP{})
- RegisterTestCase(FilterInputDropUDP{})
+ RegisterTestCase(FilterInputDropTCPDestPort{})
+ RegisterTestCase(FilterInputDropTCPSrcPort{})
RegisterTestCase(FilterInputDropUDPPort{})
- RegisterTestCase(FilterInputDropDifferentUDPPort{})
- RegisterTestCase(FilterInputDropAll{})
+ RegisterTestCase(FilterInputDropUDP{})
}
// FilterInputDropUDP tests that we can drop UDP traffic.
@@ -92,7 +94,7 @@ func (FilterInputDropOnlyUDP) ContainerAction(ip net.IP) error {
func (FilterInputDropOnlyUDP) LocalAction(ip net.IP) error {
// Try to establish a TCP connection with the container, which should
// succeed.
- return connectLoopTCP(ip, acceptPort, sendloopDuration)
+ return connectTCP(ip, acceptPort, dropPort, sendloopDuration)
}
// FilterInputDropUDPPort tests that we can drop UDP traffic by port.
@@ -154,6 +156,68 @@ func (FilterInputDropDifferentUDPPort) LocalAction(ip net.IP) error {
return sendUDPLoop(ip, acceptPort, sendloopDuration)
}
+// FilterInputDropTCPDestPort tests that connections are not accepted on specified source ports.
+type FilterInputDropTCPDestPort struct{}
+
+// Name implements TestCase.Name.
+func (FilterInputDropTCPDestPort) Name() string {
+ return "FilterInputDropTCPDestPort"
+}
+
+// ContainerAction implements TestCase.ContainerAction.
+func (FilterInputDropTCPDestPort) ContainerAction(ip net.IP) error {
+ if err := filterTable("-A", "INPUT", "-p", "tcp", "-m", "tcp", "--dport", fmt.Sprintf("%d", dropPort), "-j", "DROP"); err != nil {
+ return err
+ }
+
+ // Listen for TCP packets on drop port.
+ if err := listenTCP(dropPort, sendloopDuration); err == nil {
+ return fmt.Errorf("connection on port %d should not be accepted, but got accepted", dropPort)
+ }
+
+ return nil
+}
+
+// LocalAction implements TestCase.LocalAction.
+func (FilterInputDropTCPDestPort) LocalAction(ip net.IP) error {
+ if err := connectTCP(ip, dropPort, acceptPort, sendloopDuration); err == nil {
+ return fmt.Errorf("connection destined to port %d should not be accepted, but got accepted", dropPort)
+ }
+
+ return nil
+}
+
+// FilterInputDropTCPSrcPort tests that connections are not accepted on specified source ports.
+type FilterInputDropTCPSrcPort struct{}
+
+// Name implements TestCase.Name.
+func (FilterInputDropTCPSrcPort) Name() string {
+ return "FilterInputDropTCPSrcPort"
+}
+
+// ContainerAction implements TestCase.ContainerAction.
+func (FilterInputDropTCPSrcPort) ContainerAction(ip net.IP) error {
+ if err := filterTable("-A", "INPUT", "-p", "tcp", "-m", "tcp", "--sport", fmt.Sprintf("%d", dropPort), "-j", "DROP"); err != nil {
+ return err
+ }
+
+ // Listen for TCP packets on accept port.
+ if err := listenTCP(acceptPort, sendloopDuration); err == nil {
+ return fmt.Errorf("connection destined to port %d should not be accepted, but got accepted", dropPort)
+ }
+
+ return nil
+}
+
+// LocalAction implements TestCase.LocalAction.
+func (FilterInputDropTCPSrcPort) LocalAction(ip net.IP) error {
+ if err := connectTCP(ip, acceptPort, dropPort, sendloopDuration); err == nil {
+ return fmt.Errorf("connection on port %d should not be acceptedi, but got accepted", dropPort)
+ }
+
+ return nil
+}
+
// FilterInputDropAll tests that we can drop all traffic to the INPUT chain.
type FilterInputDropAll struct{}
diff --git a/test/iptables/filter_output.go b/test/iptables/filter_output.go
new file mode 100644
index 000000000..ee2c49f9a
--- /dev/null
+++ b/test/iptables/filter_output.go
@@ -0,0 +1,87 @@
+// Copyright 2020 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package iptables
+
+import (
+ "fmt"
+ "net"
+)
+
+func init() {
+ RegisterTestCase(FilterOutputDropTCPDestPort{})
+ RegisterTestCase(FilterOutputDropTCPSrcPort{})
+}
+
+// FilterOutputDropTCPDestPort tests that connections are not accepted on specified source ports.
+type FilterOutputDropTCPDestPort struct{}
+
+// Name implements TestCase.Name.
+func (FilterOutputDropTCPDestPort) Name() string {
+ return "FilterOutputDropTCPDestPort"
+}
+
+// ContainerAction implements TestCase.ContainerAction.
+func (FilterOutputDropTCPDestPort) ContainerAction(ip net.IP) error {
+ if err := filterTable("-A", "OUTPUT", "-p", "tcp", "-m", "tcp", "--dport", fmt.Sprintf("%d", dropPort), "-j", "DROP"); err != nil {
+ return err
+ }
+
+ // Listen for TCP packets on accept port.
+ if err := listenTCP(acceptPort, sendloopDuration); err == nil {
+ return fmt.Errorf("connection destined to port %d should not be accepted, but got accepted", dropPort)
+ }
+
+ return nil
+}
+
+// LocalAction implements TestCase.LocalAction.
+func (FilterOutputDropTCPDestPort) LocalAction(ip net.IP) error {
+ if err := connectTCP(ip, acceptPort, dropPort, sendloopDuration); err == nil {
+ return fmt.Errorf("connection on port %d should not be accepted, but got accepted", dropPort)
+ }
+
+ return nil
+}
+
+// FilterOutputDropTCPSrcPort tests that connections are not accepted on specified source ports.
+type FilterOutputDropTCPSrcPort struct{}
+
+// Name implements TestCase.Name.
+func (FilterOutputDropTCPSrcPort) Name() string {
+ return "FilterOutputDropTCPSrcPort"
+}
+
+// ContainerAction implements TestCase.ContainerAction.
+func (FilterOutputDropTCPSrcPort) ContainerAction(ip net.IP) error {
+ if err := filterTable("-A", "OUTPUT", "-p", "tcp", "-m", "tcp", "--sport", fmt.Sprintf("%d", dropPort), "-j", "DROP"); err != nil {
+ return err
+ }
+
+ // Listen for TCP packets on drop port.
+ if err := listenTCP(dropPort, sendloopDuration); err == nil {
+ return fmt.Errorf("connection on port %d should not be accepted, but got accepted", dropPort)
+ }
+
+ return nil
+}
+
+// LocalAction implements TestCase.LocalAction.
+func (FilterOutputDropTCPSrcPort) LocalAction(ip net.IP) error {
+ if err := connectTCP(ip, dropPort, acceptPort, sendloopDuration); err == nil {
+ return fmt.Errorf("connection destined to port %d should not be accepted, but got accepted", dropPort)
+ }
+
+ return nil
+}
diff --git a/test/iptables/iptables_test.go b/test/iptables/iptables_test.go
index 635beea36..63e691af6 100644
--- a/test/iptables/iptables_test.go
+++ b/test/iptables/iptables_test.go
@@ -28,7 +28,7 @@ import (
"gvisor.dev/gvisor/runsc/testutil"
)
-const timeout time.Duration = 10 * time.Second
+const timeout = 18 * time.Second
var image = flag.String("image", "bazel/test/iptables/runner:runner", "image to run tests in")
@@ -189,3 +189,39 @@ func TestFilterInputDropOnlyUDP(t *testing.T) {
t.Fatal(err)
}
}
+
+func TestNATRedirectUDPPort(t *testing.T) {
+ if err := singleTest(NATRedirectUDPPort{}); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestNATDropUDP(t *testing.T) {
+ if err := singleTest(NATDropUDP{}); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestFilterInputDropTCPDestPort(t *testing.T) {
+ if err := singleTest(FilterInputDropTCPDestPort{}); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestFilterInputDropTCPSrcPort(t *testing.T) {
+ if err := singleTest(FilterInputDropTCPSrcPort{}); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestFilterOutputDropTCPDestPort(t *testing.T) {
+ if err := singleTest(FilterOutputDropTCPDestPort{}); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestFilterOutputDropTCPSrcPort(t *testing.T) {
+ if err := singleTest(FilterOutputDropTCPSrcPort{}); err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/test/iptables/iptables_util.go b/test/iptables/iptables_util.go
index 3dcaafb79..b40d0dc4f 100644
--- a/test/iptables/iptables_util.go
+++ b/test/iptables/iptables_util.go
@@ -83,32 +83,42 @@ func sendUDPLoop(ip net.IP, port int, duration time.Duration) error {
return nil
}
+// listenTCP listens for connections on a TCP port.
func listenTCP(port int, timeout time.Duration) error {
- localAddr := net.TCPAddr{Port: acceptPort}
- listener, err := net.ListenTCP("tcp4", &localAddr)
+ localAddr := net.TCPAddr{
+ Port: port,
+ }
+
+ // Starts listening on port.
+ lConn, err := net.ListenTCP("tcp4", &localAddr)
if err != nil {
return err
}
- defer listener.Close()
- listener.SetDeadline(time.Now().Add(timeout))
- conn, err := listener.AcceptTCP()
+ defer lConn.Close()
+
+ // Accept connections on port.
+ lConn.SetDeadline(time.Now().Add(timeout))
+ conn, err := lConn.AcceptTCP()
if err != nil {
- return fmt.Errorf("failed to establish a connection %v", err)
+ return err
}
- defer conn.Close()
-
+ conn.Close()
return nil
}
-func connectLoopTCP(ip net.IP, port int, timeout time.Duration) error {
+// connectTCP connects the TCP server over specified local port, server IP and remote/server port.
+func connectTCP(ip net.IP, remotePort, localPort int, timeout time.Duration) error {
contAddr := net.TCPAddr{
IP: ip,
- Port: port,
+ Port: remotePort,
}
// The container may not be listening when we first connect, so retry
// upon error.
cb := func() error {
- conn, err := net.DialTCP("tcp4", nil, &contAddr)
+ localAddr := net.TCPAddr{
+ Port: localPort,
+ }
+ conn, err := net.DialTCP("tcp4", &localAddr, &contAddr)
if conn != nil {
conn.Close()
}
diff --git a/test/iptables/nat.go b/test/iptables/nat.go
new file mode 100644
index 000000000..b5c6f927e
--- /dev/null
+++ b/test/iptables/nat.go
@@ -0,0 +1,80 @@
+// Copyright 2020 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package iptables
+
+import (
+ "fmt"
+ "net"
+)
+
+const (
+ redirectPort = 42
+)
+
+func init() {
+ RegisterTestCase(NATRedirectUDPPort{})
+ RegisterTestCase(NATDropUDP{})
+}
+
+// NATRedirectUDPPort tests that packets are redirected to different port.
+type NATRedirectUDPPort struct{}
+
+// Name implements TestCase.Name.
+func (NATRedirectUDPPort) Name() string {
+ return "NATRedirectUDPPort"
+}
+
+// ContainerAction implements TestCase.ContainerAction.
+func (NATRedirectUDPPort) ContainerAction(ip net.IP) error {
+ if err := filterTable("-t", "nat", "-A", "PREROUTING", "-p", "udp", "-j", "REDIRECT", "--to-ports", fmt.Sprintf("%d", redirectPort)); err != nil {
+ return err
+ }
+
+ if err := listenUDP(redirectPort, sendloopDuration); err != nil {
+ return fmt.Errorf("packets on port %d should be allowed, but encountered an error: %v", redirectPort, err)
+ }
+ return nil
+}
+
+// LocalAction implements TestCase.LocalAction.
+func (NATRedirectUDPPort) LocalAction(ip net.IP) error {
+ return sendUDPLoop(ip, acceptPort, sendloopDuration)
+}
+
+// NATDropUDP tests that packets are not received in ports other than redirect port.
+type NATDropUDP struct{}
+
+// Name implements TestCase.Name.
+func (NATDropUDP) Name() string {
+ return "NATDropUDP"
+}
+
+// ContainerAction implements TestCase.ContainerAction.
+func (NATDropUDP) ContainerAction(ip net.IP) error {
+ if err := filterTable("-t", "nat", "-A", "PREROUTING", "-p", "udp", "-j", "REDIRECT", "--to-ports", fmt.Sprintf("%d", redirectPort)); err != nil {
+ return err
+ }
+
+ if err := listenUDP(acceptPort, sendloopDuration); err == nil {
+ return fmt.Errorf("packets on port %d should have been redirected to port %d", acceptPort, redirectPort)
+ }
+
+ return nil
+}
+
+// LocalAction implements TestCase.LocalAction.
+func (NATDropUDP) LocalAction(ip net.IP) error {
+ return sendUDPLoop(ip, acceptPort, sendloopDuration)
+}