summaryrefslogtreecommitdiffhomepage
path: root/test/iptables
diff options
context:
space:
mode:
Diffstat (limited to 'test/iptables')
-rw-r--r--test/iptables/BUILD36
-rw-r--r--test/iptables/README.md54
-rw-r--r--test/iptables/filter_input.go669
-rw-r--r--test/iptables/filter_output.go288
-rw-r--r--test/iptables/iptables.go60
-rw-r--r--test/iptables/iptables_test.go260
-rw-r--r--test/iptables/iptables_util.go171
-rw-r--r--test/iptables/nat.go402
-rw-r--r--test/iptables/runner/BUILD12
-rw-r--r--test/iptables/runner/main.go73
10 files changed, 0 insertions, 2025 deletions
diff --git a/test/iptables/BUILD b/test/iptables/BUILD
deleted file mode 100644
index 3e29ca90d..000000000
--- a/test/iptables/BUILD
+++ /dev/null
@@ -1,36 +0,0 @@
-load("//tools:defs.bzl", "go_library", "go_test")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "iptables",
- testonly = 1,
- srcs = [
- "filter_input.go",
- "filter_output.go",
- "iptables.go",
- "iptables_util.go",
- "nat.go",
- ],
- visibility = ["//test/iptables:__subpackages__"],
- deps = [
- "//pkg/test/testutil",
- ],
-)
-
-go_test(
- name = "iptables_test",
- srcs = [
- "iptables_test.go",
- ],
- data = ["//test/iptables/runner"],
- library = ":iptables",
- tags = [
- "local",
- "manual",
- ],
- deps = [
- "//pkg/test/dockerutil",
- "//pkg/test/testutil",
- ],
-)
diff --git a/test/iptables/README.md b/test/iptables/README.md
deleted file mode 100644
index b9f44bd40..000000000
--- a/test/iptables/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# iptables Tests
-
-iptables tests are run via `scripts/iptables_test.sh`.
-
-iptables requires raw socket support, so you must add the `--net-raw=true` flag
-to `/etc/docker/daemon.json` in order to use it.
-
-## Test Structure
-
-Each test implements `TestCase`, providing (1) a function to run inside the
-container and (2) a function to run locally. Those processes are given each
-others' IP addresses. The test succeeds when both functions succeed.
-
-The function inside the container (`ContainerAction`) typically sets some
-iptables rules and then tries to send or receive packets. The local function
-(`LocalAction`) will typically just send or receive packets.
-
-### Adding Tests
-
-1) Add your test to the `iptables` package.
-
-2) Register the test in an `init` function via `RegisterTestCase` (see
-`filter_input.go` as an example).
-
-3) Add it to `iptables_test.go` (see the other tests in that file).
-
-Your test is now runnable with bazel!
-
-## Run individual tests
-
-Build and install `runsc`. Re-run this when you modify gVisor:
-
-```bash
-$ bazel build //runsc && sudo cp bazel-bin/runsc/linux_amd64_pure_stripped/runsc $(which runsc)
-```
-
-Build the testing Docker container. Re-run this when you modify the test code in
-this directory:
-
-```bash
-$ make load-iptables
-```
-
-Run an individual test via:
-
-```bash
-$ bazel test //test/iptables:iptables_test --test_filter=<TESTNAME>
-```
-
-To run an individual test with `runc`:
-
-```bash
-$ bazel test //test/iptables:iptables_test --test_filter=<TESTNAME> --test_arg=--runtime=runc
-```
diff --git a/test/iptables/filter_input.go b/test/iptables/filter_input.go
deleted file mode 100644
index 41e0cfa8d..000000000
--- a/test/iptables/filter_input.go
+++ /dev/null
@@ -1,669 +0,0 @@
-// Copyright 2019 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 (
- "errors"
- "fmt"
- "net"
- "time"
-)
-
-const (
- dropPort = 2401
- acceptPort = 2402
- sendloopDuration = 2 * time.Second
- network = "udp4"
- chainName = "foochain"
-)
-
-func init() {
- RegisterTestCase(FilterInputDropAll{})
- RegisterTestCase(FilterInputDropDifferentUDPPort{})
- RegisterTestCase(FilterInputDropOnlyUDP{})
- RegisterTestCase(FilterInputDropTCPDestPort{})
- RegisterTestCase(FilterInputDropTCPSrcPort{})
- RegisterTestCase(FilterInputDropUDPPort{})
- RegisterTestCase(FilterInputDropUDP{})
- RegisterTestCase(FilterInputCreateUserChain{})
- RegisterTestCase(FilterInputDefaultPolicyAccept{})
- RegisterTestCase(FilterInputDefaultPolicyDrop{})
- RegisterTestCase(FilterInputReturnUnderflow{})
- RegisterTestCase(FilterInputSerializeJump{})
- RegisterTestCase(FilterInputJumpBasic{})
- RegisterTestCase(FilterInputJumpReturn{})
- RegisterTestCase(FilterInputJumpReturnDrop{})
- RegisterTestCase(FilterInputJumpBuiltin{})
- RegisterTestCase(FilterInputJumpTwice{})
- RegisterTestCase(FilterInputDestination{})
- RegisterTestCase(FilterInputInvertDestination{})
-}
-
-// FilterInputDropUDP tests that we can drop UDP traffic.
-type FilterInputDropUDP struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputDropUDP) Name() string {
- return "FilterInputDropUDP"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputDropUDP) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "INPUT", "-p", "udp", "-j", "DROP"); err != nil {
- return err
- }
-
- // Listen for UDP packets on dropPort.
- if err := listenUDP(dropPort, sendloopDuration); err == nil {
- return fmt.Errorf("packets on port %d should have been dropped, but got a packet", dropPort)
- } else if netErr, ok := err.(net.Error); !ok || !netErr.Timeout() {
- return fmt.Errorf("error reading: %v", err)
- }
-
- // At this point we know that reading timed out and never received a
- // packet.
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputDropUDP) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, dropPort, sendloopDuration)
-}
-
-// FilterInputDropOnlyUDP tests that "-p udp -j DROP" only affects UDP traffic.
-type FilterInputDropOnlyUDP struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputDropOnlyUDP) Name() string {
- return "FilterInputDropOnlyUDP"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputDropOnlyUDP) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "INPUT", "-p", "udp", "-j", "DROP"); err != nil {
- return err
- }
-
- // Listen for a TCP connection, which should be allowed.
- if err := listenTCP(acceptPort, sendloopDuration); err != nil {
- return fmt.Errorf("failed to establish a connection %v", err)
- }
-
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputDropOnlyUDP) LocalAction(ip net.IP) error {
- // Try to establish a TCP connection with the container, which should
- // succeed.
- return connectTCP(ip, acceptPort, sendloopDuration)
-}
-
-// FilterInputDropUDPPort tests that we can drop UDP traffic by port.
-type FilterInputDropUDPPort struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputDropUDPPort) Name() string {
- return "FilterInputDropUDPPort"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputDropUDPPort) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "INPUT", "-p", "udp", "-m", "udp", "--destination-port", fmt.Sprintf("%d", dropPort), "-j", "DROP"); err != nil {
- return err
- }
-
- // Listen for UDP packets on dropPort.
- if err := listenUDP(dropPort, sendloopDuration); err == nil {
- return fmt.Errorf("packets on port %d should have been dropped, but got a packet", dropPort)
- } else if netErr, ok := err.(net.Error); !ok || !netErr.Timeout() {
- return fmt.Errorf("error reading: %v", err)
- }
-
- // At this point we know that reading timed out and never received a
- // packet.
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputDropUDPPort) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, dropPort, sendloopDuration)
-}
-
-// FilterInputDropDifferentUDPPort tests that dropping traffic for a single UDP port
-// doesn't drop packets on other ports.
-type FilterInputDropDifferentUDPPort struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputDropDifferentUDPPort) Name() string {
- return "FilterInputDropDifferentUDPPort"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputDropDifferentUDPPort) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "INPUT", "-p", "udp", "-m", "udp", "--destination-port", fmt.Sprintf("%d", dropPort), "-j", "DROP"); err != nil {
- return err
- }
-
- // Listen for UDP packets on another port.
- if err := listenUDP(acceptPort, sendloopDuration); err != nil {
- return fmt.Errorf("packets on port %d should be allowed, but encountered an error: %v", acceptPort, err)
- }
-
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-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 {
- // Ensure we cannot connect to the container.
- for start := time.Now(); time.Since(start) < sendloopDuration; {
- if err := connectTCP(ip, dropPort, sendloopDuration-time.Since(start)); err == nil {
- return fmt.Errorf("expected not to connect, but was able to connect on port %d", 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 {
- // Drop anything from an ephemeral port.
- if err := filterTable("-A", "INPUT", "-p", "tcp", "-m", "tcp", "--sport", "1024:65535", "-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 was", dropPort)
- }
-
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputDropTCPSrcPort) LocalAction(ip net.IP) error {
- // Ensure we cannot connect to the container.
- for start := time.Now(); time.Since(start) < sendloopDuration; {
- if err := connectTCP(ip, acceptPort, sendloopDuration-time.Since(start)); err == nil {
- return fmt.Errorf("expected not to connect, but was able to connect on port %d", acceptPort)
- }
- }
-
- return nil
-}
-
-// FilterInputDropAll tests that we can drop all traffic to the INPUT chain.
-type FilterInputDropAll struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputDropAll) Name() string {
- return "FilterInputDropAll"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputDropAll) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "INPUT", "-j", "DROP"); err != nil {
- return err
- }
-
- // Listen for all packets on dropPort.
- if err := listenUDP(dropPort, sendloopDuration); err == nil {
- return fmt.Errorf("packets should have been dropped, but got a packet")
- } else if netErr, ok := err.(net.Error); !ok || !netErr.Timeout() {
- return fmt.Errorf("error reading: %v", err)
- }
-
- // At this point we know that reading timed out and never received a
- // packet.
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputDropAll) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, dropPort, sendloopDuration)
-}
-
-// FilterInputMultiUDPRules verifies that multiple UDP rules are applied
-// correctly. This has the added benefit of testing whether we're serializing
-// rules correctly -- if we do it incorrectly, the iptables tool will
-// misunderstand and save the wrong tables.
-type FilterInputMultiUDPRules struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputMultiUDPRules) Name() string {
- return "FilterInputMultiUDPRules"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputMultiUDPRules) ContainerAction(ip net.IP) error {
- rules := [][]string{
- {"-A", "INPUT", "-p", "udp", "-m", "udp", "--destination-port", fmt.Sprintf("%d", dropPort), "-j", "DROP"},
- {"-A", "INPUT", "-p", "udp", "-m", "udp", "--destination-port", fmt.Sprintf("%d", acceptPort), "-j", "ACCEPT"},
- {"-L"},
- }
- return filterTableRules(rules)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputMultiUDPRules) LocalAction(ip net.IP) error {
- // No-op.
- return nil
-}
-
-// FilterInputRequireProtocolUDP checks that "-m udp" requires "-p udp" to be
-// specified.
-type FilterInputRequireProtocolUDP struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputRequireProtocolUDP) Name() string {
- return "FilterInputRequireProtocolUDP"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputRequireProtocolUDP) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "INPUT", "-m", "udp", "--destination-port", fmt.Sprintf("%d", dropPort), "-j", "DROP"); err == nil {
- return errors.New("expected iptables to fail with out \"-p udp\", but succeeded")
- }
- return nil
-}
-
-func (FilterInputRequireProtocolUDP) LocalAction(ip net.IP) error {
- // No-op.
- return nil
-}
-
-// FilterInputCreateUserChain tests chain creation.
-type FilterInputCreateUserChain struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputCreateUserChain) Name() string {
- return "FilterInputCreateUserChain"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputCreateUserChain) ContainerAction(ip net.IP) error {
- rules := [][]string{
- // Create a chain.
- {"-N", chainName},
- // Add a simple rule to the chain.
- {"-A", chainName, "-j", "DROP"},
- }
- return filterTableRules(rules)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputCreateUserChain) LocalAction(ip net.IP) error {
- // No-op.
- return nil
-}
-
-// FilterInputDefaultPolicyAccept tests the default ACCEPT policy.
-type FilterInputDefaultPolicyAccept struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputDefaultPolicyAccept) Name() string {
- return "FilterInputDefaultPolicyAccept"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputDefaultPolicyAccept) ContainerAction(ip net.IP) error {
- // Set the default policy to accept, then receive a packet.
- if err := filterTable("-P", "INPUT", "ACCEPT"); err != nil {
- return err
- }
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputDefaultPolicyAccept) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// FilterInputDefaultPolicyDrop tests the default DROP policy.
-type FilterInputDefaultPolicyDrop struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputDefaultPolicyDrop) Name() string {
- return "FilterInputDefaultPolicyDrop"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputDefaultPolicyDrop) ContainerAction(ip net.IP) error {
- if err := filterTable("-P", "INPUT", "DROP"); err != nil {
- return err
- }
-
- // Listen for UDP packets on dropPort.
- if err := listenUDP(dropPort, sendloopDuration); err == nil {
- return fmt.Errorf("packets on port %d should have been dropped, but got a packet", dropPort)
- } else if netErr, ok := err.(net.Error); !ok || !netErr.Timeout() {
- return fmt.Errorf("error reading: %v", err)
- }
-
- // At this point we know that reading timed out and never received a
- // packet.
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputDefaultPolicyDrop) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// FilterInputReturnUnderflow tests that -j RETURN in a built-in chain causes
-// the underflow rule (i.e. default policy) to be executed.
-type FilterInputReturnUnderflow struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputReturnUnderflow) Name() string {
- return "FilterInputReturnUnderflow"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputReturnUnderflow) ContainerAction(ip net.IP) error {
- // Add a RETURN rule followed by an unconditional accept, and set the
- // default policy to DROP.
- rules := [][]string{
- {"-A", "INPUT", "-j", "RETURN"},
- {"-A", "INPUT", "-j", "DROP"},
- {"-P", "INPUT", "ACCEPT"},
- }
- if err := filterTableRules(rules); err != nil {
- return err
- }
-
- // We should receive packets, as the RETURN rule will trigger the default
- // ACCEPT policy.
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputReturnUnderflow) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// FilterInputSerializeJump verifies that we can serialize jumps.
-type FilterInputSerializeJump struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputSerializeJump) Name() string {
- return "FilterInputSerializeJump"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputSerializeJump) ContainerAction(ip net.IP) error {
- // Write a JUMP rule, the serialize it with `-L`.
- rules := [][]string{
- {"-N", chainName},
- {"-A", "INPUT", "-j", chainName},
- {"-L"},
- }
- return filterTableRules(rules)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputSerializeJump) LocalAction(ip net.IP) error {
- // No-op.
- return nil
-}
-
-// FilterInputJumpBasic jumps to a chain and executes a rule there.
-type FilterInputJumpBasic struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputJumpBasic) Name() string {
- return "FilterInputJumpBasic"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputJumpBasic) ContainerAction(ip net.IP) error {
- rules := [][]string{
- {"-P", "INPUT", "DROP"},
- {"-N", chainName},
- {"-A", "INPUT", "-j", chainName},
- {"-A", chainName, "-j", "ACCEPT"},
- }
- if err := filterTableRules(rules); err != nil {
- return err
- }
-
- // Listen for UDP packets on acceptPort.
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputJumpBasic) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// FilterInputJumpReturn jumps, returns, and executes a rule.
-type FilterInputJumpReturn struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputJumpReturn) Name() string {
- return "FilterInputJumpReturn"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputJumpReturn) ContainerAction(ip net.IP) error {
- rules := [][]string{
- {"-N", chainName},
- {"-P", "INPUT", "ACCEPT"},
- {"-A", "INPUT", "-j", chainName},
- {"-A", chainName, "-j", "RETURN"},
- {"-A", chainName, "-j", "DROP"},
- }
- if err := filterTableRules(rules); err != nil {
- return err
- }
-
- // Listen for UDP packets on acceptPort.
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputJumpReturn) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// FilterInputJumpReturnDrop jumps to a chain, returns, and DROPs packets.
-type FilterInputJumpReturnDrop struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputJumpReturnDrop) Name() string {
- return "FilterInputJumpReturnDrop"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputJumpReturnDrop) ContainerAction(ip net.IP) error {
- rules := [][]string{
- {"-N", chainName},
- {"-A", "INPUT", "-j", chainName},
- {"-A", "INPUT", "-j", "DROP"},
- {"-A", chainName, "-j", "RETURN"},
- }
- if err := filterTableRules(rules); err != nil {
- return err
- }
-
- // Listen for UDP packets on dropPort.
- if err := listenUDP(dropPort, sendloopDuration); err == nil {
- return fmt.Errorf("packets on port %d should have been dropped, but got a packet", dropPort)
- } else if netErr, ok := err.(net.Error); !ok || !netErr.Timeout() {
- return fmt.Errorf("error reading: %v", err)
- }
-
- // At this point we know that reading timed out and never received a
- // packet.
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputJumpReturnDrop) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, dropPort, sendloopDuration)
-}
-
-// FilterInputJumpBuiltin verifies that jumping to a top-levl chain is illegal.
-type FilterInputJumpBuiltin struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputJumpBuiltin) Name() string {
- return "FilterInputJumpBuiltin"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputJumpBuiltin) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "INPUT", "-j", "OUTPUT"); err == nil {
- return fmt.Errorf("iptables should be unable to jump to a built-in chain")
- }
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputJumpBuiltin) LocalAction(ip net.IP) error {
- // No-op.
- return nil
-}
-
-// FilterInputJumpTwice jumps twice, then returns twice and executes a rule.
-type FilterInputJumpTwice struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputJumpTwice) Name() string {
- return "FilterInputJumpTwice"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputJumpTwice) ContainerAction(ip net.IP) error {
- const chainName2 = chainName + "2"
- rules := [][]string{
- {"-P", "INPUT", "DROP"},
- {"-N", chainName},
- {"-N", chainName2},
- {"-A", "INPUT", "-j", chainName},
- {"-A", chainName, "-j", chainName2},
- {"-A", "INPUT", "-j", "ACCEPT"},
- }
- if err := filterTableRules(rules); err != nil {
- return err
- }
-
- // UDP packets should jump and return twice, eventually hitting the
- // ACCEPT rule.
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputJumpTwice) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// FilterInputDestination verifies that we can filter packets via `-d
-// <ipaddr>`.
-type FilterInputDestination struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputDestination) Name() string {
- return "FilterInputDestination"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputDestination) ContainerAction(ip net.IP) error {
- addrs, err := localAddrs()
- if err != nil {
- return err
- }
-
- // Make INPUT's default action DROP, then ACCEPT all packets bound for
- // this machine.
- rules := [][]string{{"-P", "INPUT", "DROP"}}
- for _, addr := range addrs {
- rules = append(rules, []string{"-A", "INPUT", "-d", addr, "-j", "ACCEPT"})
- }
- if err := filterTableRules(rules); err != nil {
- return err
- }
-
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputDestination) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// FilterInputInvertDestination verifies that we can filter packets via `! -d
-// <ipaddr>`.
-type FilterInputInvertDestination struct{}
-
-// Name implements TestCase.Name.
-func (FilterInputInvertDestination) Name() string {
- return "FilterInputInvertDestination"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterInputInvertDestination) ContainerAction(ip net.IP) error {
- // Make INPUT's default action DROP, then ACCEPT all packets not bound
- // for 127.0.0.1.
- rules := [][]string{
- {"-P", "INPUT", "DROP"},
- {"-A", "INPUT", "!", "-d", localIP, "-j", "ACCEPT"},
- }
- if err := filterTableRules(rules); err != nil {
- return err
- }
-
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterInputInvertDestination) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
diff --git a/test/iptables/filter_output.go b/test/iptables/filter_output.go
deleted file mode 100644
index b1382d353..000000000
--- a/test/iptables/filter_output.go
+++ /dev/null
@@ -1,288 +0,0 @@
-// 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{})
- RegisterTestCase(FilterOutputDestination{})
- RegisterTestCase(FilterOutputInvertDestination{})
- RegisterTestCase(FilterOutputAcceptTCPOwner{})
- RegisterTestCase(FilterOutputDropTCPOwner{})
- RegisterTestCase(FilterOutputAcceptUDPOwner{})
- RegisterTestCase(FilterOutputDropUDPOwner{})
- RegisterTestCase(FilterOutputOwnerFail{})
-}
-
-// 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", "1024:65535", "-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, 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, sendloopDuration); err == nil {
- return fmt.Errorf("connection destined to port %d should not be accepted, but got accepted", dropPort)
- }
-
- return nil
-}
-
-// FilterOutputAcceptTCPOwner tests that TCP connections from uid owner are accepted.
-type FilterOutputAcceptTCPOwner struct{}
-
-// Name implements TestCase.Name.
-func (FilterOutputAcceptTCPOwner) Name() string {
- return "FilterOutputAcceptTCPOwner"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterOutputAcceptTCPOwner) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "OUTPUT", "-p", "tcp", "-m", "owner", "--uid-owner", "root", "-j", "ACCEPT"); err != nil {
- return err
- }
-
- // Listen for TCP packets on accept port.
- if err := listenTCP(acceptPort, sendloopDuration); err != nil {
- return fmt.Errorf("connection on port %d should be accepted, but got dropped", acceptPort)
- }
-
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterOutputAcceptTCPOwner) LocalAction(ip net.IP) error {
- if err := connectTCP(ip, acceptPort, sendloopDuration); err != nil {
- return fmt.Errorf("connection destined to port %d should be accepted, but got dropped", acceptPort)
- }
-
- return nil
-}
-
-// FilterOutputDropTCPOwner tests that TCP connections from uid owner are dropped.
-type FilterOutputDropTCPOwner struct{}
-
-// Name implements TestCase.Name.
-func (FilterOutputDropTCPOwner) Name() string {
- return "FilterOutputDropTCPOwner"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterOutputDropTCPOwner) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "OUTPUT", "-p", "tcp", "-m", "owner", "--uid-owner", "root", "-j", "DROP"); err != nil {
- return err
- }
-
- // Listen for TCP packets on accept port.
- if err := listenTCP(acceptPort, sendloopDuration); err == nil {
- return fmt.Errorf("connection on port %d should be dropped, but got accepted", acceptPort)
- }
-
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterOutputDropTCPOwner) LocalAction(ip net.IP) error {
- if err := connectTCP(ip, acceptPort, sendloopDuration); err == nil {
- return fmt.Errorf("connection destined to port %d should be dropped, but got accepted", acceptPort)
- }
-
- return nil
-}
-
-// FilterOutputAcceptUDPOwner tests that UDP packets from uid owner are accepted.
-type FilterOutputAcceptUDPOwner struct{}
-
-// Name implements TestCase.Name.
-func (FilterOutputAcceptUDPOwner) Name() string {
- return "FilterOutputAcceptUDPOwner"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterOutputAcceptUDPOwner) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "OUTPUT", "-p", "udp", "-m", "owner", "--uid-owner", "root", "-j", "ACCEPT"); err != nil {
- return err
- }
-
- // Send UDP packets on acceptPort.
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterOutputAcceptUDPOwner) LocalAction(ip net.IP) error {
- // Listen for UDP packets on acceptPort.
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// FilterOutputDropUDPOwner tests that UDP packets from uid owner are dropped.
-type FilterOutputDropUDPOwner struct{}
-
-// Name implements TestCase.Name.
-func (FilterOutputDropUDPOwner) Name() string {
- return "FilterOutputDropUDPOwner"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterOutputDropUDPOwner) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "OUTPUT", "-p", "udp", "-m", "owner", "--uid-owner", "root", "-j", "DROP"); err != nil {
- return err
- }
-
- // Send UDP packets on dropPort.
- return sendUDPLoop(ip, dropPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterOutputDropUDPOwner) LocalAction(ip net.IP) error {
- // Listen for UDP packets on dropPort.
- if err := listenUDP(dropPort, sendloopDuration); err == nil {
- return fmt.Errorf("packets should not be received")
- }
-
- return nil
-}
-
-// FilterOutputOwnerFail tests that without uid/gid option, owner rule
-// will fail.
-type FilterOutputOwnerFail struct{}
-
-// Name implements TestCase.Name.
-func (FilterOutputOwnerFail) Name() string {
- return "FilterOutputOwnerFail"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterOutputOwnerFail) ContainerAction(ip net.IP) error {
- if err := filterTable("-A", "OUTPUT", "-p", "udp", "-m", "owner", "-j", "ACCEPT"); err == nil {
- return fmt.Errorf("Invalid argument")
- }
-
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterOutputOwnerFail) LocalAction(ip net.IP) error {
- // no-op.
- return nil
-}
-
-// FilterOutputDestination tests that we can selectively allow packets to
-// certain destinations.
-type FilterOutputDestination struct{}
-
-// Name implements TestCase.Name.
-func (FilterOutputDestination) Name() string {
- return "FilterOutputDestination"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterOutputDestination) ContainerAction(ip net.IP) error {
- rules := [][]string{
- {"-A", "OUTPUT", "-d", ip.String(), "-j", "ACCEPT"},
- {"-P", "OUTPUT", "DROP"},
- }
- if err := filterTableRules(rules); err != nil {
- return err
- }
-
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterOutputDestination) LocalAction(ip net.IP) error {
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// FilterOutputInvertDestination tests that we can selectively allow packets
-// not headed for a particular destination.
-type FilterOutputInvertDestination struct{}
-
-// Name implements TestCase.Name.
-func (FilterOutputInvertDestination) Name() string {
- return "FilterOutputInvertDestination"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (FilterOutputInvertDestination) ContainerAction(ip net.IP) error {
- rules := [][]string{
- {"-A", "OUTPUT", "!", "-d", localIP, "-j", "ACCEPT"},
- {"-P", "OUTPUT", "DROP"},
- }
- if err := filterTableRules(rules); err != nil {
- return err
- }
-
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (FilterOutputInvertDestination) LocalAction(ip net.IP) error {
- return listenUDP(acceptPort, sendloopDuration)
-}
diff --git a/test/iptables/iptables.go b/test/iptables/iptables.go
deleted file mode 100644
index 16cb4f4da..000000000
--- a/test/iptables/iptables.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2019 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 contains a set of iptables tests implemented as TestCases
-package iptables
-
-import (
- "fmt"
- "net"
- "time"
-)
-
-// IPExchangePort is the port the container listens on to receive the IP
-// address of the local process.
-const IPExchangePort = 2349
-
-// TerminalStatement is the last statement in the test runner.
-const TerminalStatement = "Finished!"
-
-// TestTimeout is the timeout used for all tests.
-const TestTimeout = 10 * time.Minute
-
-// A TestCase contains one action to run in the container and one to run
-// locally. The actions run concurrently and each must succeed for the test
-// pass.
-type TestCase interface {
- // Name returns the name of the test.
- Name() string
-
- // ContainerAction runs inside the container. It receives the IP of the
- // local process.
- ContainerAction(ip net.IP) error
-
- // LocalAction runs locally. It receives the IP of the container.
- LocalAction(ip net.IP) error
-}
-
-// Tests maps test names to TestCase.
-//
-// New TestCases are added by calling RegisterTestCase in an init function.
-var Tests = map[string]TestCase{}
-
-// RegisterTestCase registers tc so it can be run.
-func RegisterTestCase(tc TestCase) {
- if _, ok := Tests[tc.Name()]; ok {
- panic(fmt.Sprintf("TestCase %s already registered.", tc.Name()))
- }
- Tests[tc.Name()] = tc
-}
diff --git a/test/iptables/iptables_test.go b/test/iptables/iptables_test.go
deleted file mode 100644
index 63a862d35..000000000
--- a/test/iptables/iptables_test.go
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2019 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"
- "testing"
-
- "gvisor.dev/gvisor/pkg/test/dockerutil"
- "gvisor.dev/gvisor/pkg/test/testutil"
-)
-
-// singleTest runs a TestCase. Each test follows a pattern:
-// - Create a container.
-// - Get the container's IP.
-// - Send the container our IP.
-// - Start a new goroutine running the local action of the test.
-// - Wait for both the container and local actions to finish.
-//
-// Container output is logged to $TEST_UNDECLARED_OUTPUTS_DIR if it exists, or
-// to stderr.
-func singleTest(t *testing.T, test TestCase) {
- if _, ok := Tests[test.Name()]; !ok {
- t.Fatalf("no test found with name %q. Has it been registered?", test.Name())
- }
-
- d := dockerutil.MakeDocker(t)
- defer d.CleanUp()
-
- // Create and start the container.
- d.CopyFiles("/runner", "test/iptables/runner/runner")
- if err := d.Spawn(dockerutil.RunOpts{
- Image: "iptables",
- CapAdd: []string{"NET_ADMIN"},
- }, "/runner/runner", "-name", test.Name()); err != nil {
- t.Fatalf("docker run failed: %v", err)
- }
-
- // Get the container IP.
- ip, err := d.FindIP()
- if err != nil {
- t.Fatalf("failed to get container IP: %v", err)
- }
-
- // Give the container our IP.
- if err := sendIP(ip); err != nil {
- t.Fatalf("failed to send IP to container: %v", err)
- }
-
- // Run our side of the test.
- if err := test.LocalAction(ip); err != nil {
- t.Fatalf("LocalAction failed: %v", err)
- }
-
- // Wait for the final statement. This structure has the side effect
- // that all container logs will appear within the individual test
- // context.
- if _, err := d.WaitForOutput(TerminalStatement, TestTimeout); err != nil {
- t.Fatalf("test failed: %v", err)
- }
-}
-
-func sendIP(ip net.IP) error {
- contAddr := net.TCPAddr{
- IP: ip,
- Port: IPExchangePort,
- }
- var conn *net.TCPConn
- // The container may not be listening when we first connect, so retry
- // upon error.
- cb := func() error {
- c, err := net.DialTCP("tcp4", nil, &contAddr)
- conn = c
- return err
- }
- if err := testutil.Poll(cb, TestTimeout); err != nil {
- return fmt.Errorf("timed out waiting to send IP, most recent error: %v", err)
- }
- if _, err := conn.Write([]byte{0}); err != nil {
- return fmt.Errorf("error writing to container: %v", err)
- }
- return nil
-}
-
-func TestFilterInputDropUDP(t *testing.T) {
- singleTest(t, FilterInputDropUDP{})
-}
-
-func TestFilterInputDropUDPPort(t *testing.T) {
- singleTest(t, FilterInputDropUDPPort{})
-}
-
-func TestFilterInputDropDifferentUDPPort(t *testing.T) {
- singleTest(t, FilterInputDropDifferentUDPPort{})
-}
-
-func TestFilterInputDropAll(t *testing.T) {
- singleTest(t, FilterInputDropAll{})
-}
-
-func TestFilterInputDropOnlyUDP(t *testing.T) {
- singleTest(t, FilterInputDropOnlyUDP{})
-}
-
-func TestFilterInputDropTCPDestPort(t *testing.T) {
- singleTest(t, FilterInputDropTCPDestPort{})
-}
-
-func TestFilterInputDropTCPSrcPort(t *testing.T) {
- singleTest(t, FilterInputDropTCPSrcPort{})
-}
-
-func TestFilterInputCreateUserChain(t *testing.T) {
- singleTest(t, FilterInputCreateUserChain{})
-}
-
-func TestFilterInputDefaultPolicyAccept(t *testing.T) {
- singleTest(t, FilterInputDefaultPolicyAccept{})
-}
-
-func TestFilterInputDefaultPolicyDrop(t *testing.T) {
- singleTest(t, FilterInputDefaultPolicyDrop{})
-}
-
-func TestFilterInputReturnUnderflow(t *testing.T) {
- singleTest(t, FilterInputReturnUnderflow{})
-}
-
-func TestFilterOutputDropTCPDestPort(t *testing.T) {
- singleTest(t, FilterOutputDropTCPDestPort{})
-}
-
-func TestFilterOutputDropTCPSrcPort(t *testing.T) {
- singleTest(t, FilterOutputDropTCPSrcPort{})
-}
-
-func TestFilterOutputAcceptTCPOwner(t *testing.T) {
- singleTest(t, FilterOutputAcceptTCPOwner{})
-}
-
-func TestFilterOutputDropTCPOwner(t *testing.T) {
- singleTest(t, FilterOutputDropTCPOwner{})
-}
-
-func TestFilterOutputAcceptUDPOwner(t *testing.T) {
- singleTest(t, FilterOutputAcceptUDPOwner{})
-}
-
-func TestFilterOutputDropUDPOwner(t *testing.T) {
- singleTest(t, FilterOutputDropUDPOwner{})
-}
-
-func TestFilterOutputOwnerFail(t *testing.T) {
- singleTest(t, FilterOutputOwnerFail{})
-}
-
-func TestJumpSerialize(t *testing.T) {
- singleTest(t, FilterInputSerializeJump{})
-}
-
-func TestJumpBasic(t *testing.T) {
- singleTest(t, FilterInputJumpBasic{})
-}
-
-func TestJumpReturn(t *testing.T) {
- singleTest(t, FilterInputJumpReturn{})
-}
-
-func TestJumpReturnDrop(t *testing.T) {
- singleTest(t, FilterInputJumpReturnDrop{})
-}
-
-func TestJumpBuiltin(t *testing.T) {
- singleTest(t, FilterInputJumpBuiltin{})
-}
-
-func TestJumpTwice(t *testing.T) {
- singleTest(t, FilterInputJumpTwice{})
-}
-
-func TestInputDestination(t *testing.T) {
- singleTest(t, FilterInputDestination{})
-}
-
-func TestInputInvertDestination(t *testing.T) {
- singleTest(t, FilterInputInvertDestination{})
-}
-
-func TestOutputDestination(t *testing.T) {
- singleTest(t, FilterOutputDestination{})
-}
-
-func TestOutputInvertDestination(t *testing.T) {
- singleTest(t, FilterOutputInvertDestination{})
-}
-
-func TestNATPreRedirectUDPPort(t *testing.T) {
- singleTest(t, NATPreRedirectUDPPort{})
-}
-
-func TestNATPreRedirectTCPPort(t *testing.T) {
- singleTest(t, NATPreRedirectTCPPort{})
-}
-
-func TestNATOutRedirectUDPPort(t *testing.T) {
- singleTest(t, NATOutRedirectUDPPort{})
-}
-
-func TestNATOutRedirectTCPPort(t *testing.T) {
- singleTest(t, NATOutRedirectTCPPort{})
-}
-
-func TestNATDropUDP(t *testing.T) {
- singleTest(t, NATDropUDP{})
-}
-
-func TestNATAcceptAll(t *testing.T) {
- singleTest(t, NATAcceptAll{})
-}
-
-func TestNATOutRedirectIP(t *testing.T) {
- singleTest(t, NATOutRedirectIP{})
-}
-
-func TestNATOutDontRedirectIP(t *testing.T) {
- singleTest(t, NATOutDontRedirectIP{})
-}
-
-func TestNATOutRedirectInvert(t *testing.T) {
- singleTest(t, NATOutRedirectInvert{})
-}
-
-func TestNATPreRedirectIP(t *testing.T) {
- singleTest(t, NATPreRedirectIP{})
-}
-
-func TestNATPreDontRedirectIP(t *testing.T) {
- singleTest(t, NATPreDontRedirectIP{})
-}
-
-func TestNATPreRedirectInvert(t *testing.T) {
- singleTest(t, NATPreRedirectInvert{})
-}
-
-func TestNATRedirectRequiresProtocol(t *testing.T) {
- singleTest(t, NATRedirectRequiresProtocol{})
-}
diff --git a/test/iptables/iptables_util.go b/test/iptables/iptables_util.go
deleted file mode 100644
index 2f988cd18..000000000
--- a/test/iptables/iptables_util.go
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2019 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"
- "os/exec"
- "time"
-
- "gvisor.dev/gvisor/pkg/test/testutil"
-)
-
-const iptablesBinary = "iptables"
-const localIP = "127.0.0.1"
-
-// filterTable calls `iptables -t filter` with the given args.
-func filterTable(args ...string) error {
- return tableCmd("filter", args)
-}
-
-// natTable calls `iptables -t nat` with the given args.
-func natTable(args ...string) error {
- return tableCmd("nat", args)
-}
-
-func tableCmd(table string, args []string) error {
- args = append([]string{"-t", table}, args...)
- cmd := exec.Command(iptablesBinary, args...)
- if out, err := cmd.CombinedOutput(); err != nil {
- return fmt.Errorf("error running iptables with args %v\nerror: %v\noutput: %s", args, err, string(out))
- }
- return nil
-}
-
-// filterTableRules is like filterTable, but runs multiple iptables commands.
-func filterTableRules(argsList [][]string) error {
- return tableRules("filter", argsList)
-}
-
-// natTableRules is like natTable, but runs multiple iptables commands.
-func natTableRules(argsList [][]string) error {
- return tableRules("nat", argsList)
-}
-
-func tableRules(table string, argsList [][]string) error {
- for _, args := range argsList {
- if err := tableCmd(table, args); err != nil {
- return err
- }
- }
- return nil
-}
-
-// listenUDP listens on a UDP port and returns the value of net.Conn.Read() for
-// the first read on that port.
-func listenUDP(port int, timeout time.Duration) error {
- localAddr := net.UDPAddr{
- Port: port,
- }
- conn, err := net.ListenUDP(network, &localAddr)
- if err != nil {
- return err
- }
- defer conn.Close()
- conn.SetDeadline(time.Now().Add(timeout))
- _, err = conn.Read([]byte{0})
- return err
-}
-
-// sendUDPLoop sends 1 byte UDP packets repeatedly to the IP and port specified
-// over a duration.
-func sendUDPLoop(ip net.IP, port int, duration time.Duration) error {
- // Send packets for a few seconds.
- remote := net.UDPAddr{
- IP: ip,
- Port: port,
- }
- conn, err := net.DialUDP(network, nil, &remote)
- if err != nil {
- return err
- }
- defer conn.Close()
-
- to := time.After(duration)
- for timedOut := false; !timedOut; {
- // This may return an error (connection refused) if the remote
- // hasn't started listening yet or they're dropping our
- // packets. So we ignore Write errors and depend on the remote
- // to report a failure if it doesn't get a packet it needs.
- conn.Write([]byte{0})
- select {
- case <-to:
- timedOut = true
- default:
- time.Sleep(200 * time.Millisecond)
- }
- }
-
- return nil
-}
-
-// listenTCP listens for connections on a TCP port.
-func listenTCP(port int, timeout time.Duration) error {
- localAddr := net.TCPAddr{
- Port: port,
- }
-
- // Starts listening on port.
- lConn, err := net.ListenTCP("tcp4", &localAddr)
- if err != nil {
- return err
- }
- defer lConn.Close()
-
- // Accept connections on port.
- lConn.SetDeadline(time.Now().Add(timeout))
- conn, err := lConn.AcceptTCP()
- if err != nil {
- return err
- }
- conn.Close()
- return nil
-}
-
-// connectTCP connects to the given IP and port from an ephemeral local address.
-func connectTCP(ip net.IP, port int, timeout time.Duration) error {
- contAddr := net.TCPAddr{
- IP: ip,
- Port: port,
- }
- // The container may not be listening when we first connect, so retry
- // upon error.
- callback := func() error {
- conn, err := net.DialTimeout("tcp", contAddr.String(), timeout)
- if conn != nil {
- conn.Close()
- }
- return err
- }
- if err := testutil.Poll(callback, timeout); err != nil {
- return fmt.Errorf("timed out waiting to connect IP on port %v, most recent error: %v", port, err)
- }
-
- return nil
-}
-
-// localAddrs returns a list of local network interface addresses.
-func localAddrs() ([]string, error) {
- addrs, err := net.InterfaceAddrs()
- if err != nil {
- return nil, err
- }
- addrStrs := make([]string, 0, len(addrs))
- for _, addr := range addrs {
- addrStrs = append(addrStrs, addr.String())
- }
- return addrStrs, nil
-}
diff --git a/test/iptables/nat.go b/test/iptables/nat.go
deleted file mode 100644
index 0a10ce7fe..000000000
--- a/test/iptables/nat.go
+++ /dev/null
@@ -1,402 +0,0 @@
-// 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 (
- "errors"
- "fmt"
- "net"
- "time"
-)
-
-const (
- redirectPort = 42
-)
-
-func init() {
- RegisterTestCase(NATPreRedirectUDPPort{})
- RegisterTestCase(NATPreRedirectTCPPort{})
- RegisterTestCase(NATOutRedirectUDPPort{})
- RegisterTestCase(NATOutRedirectTCPPort{})
- RegisterTestCase(NATDropUDP{})
- RegisterTestCase(NATAcceptAll{})
- RegisterTestCase(NATPreRedirectIP{})
- RegisterTestCase(NATPreDontRedirectIP{})
- RegisterTestCase(NATPreRedirectInvert{})
- RegisterTestCase(NATOutRedirectIP{})
- RegisterTestCase(NATOutDontRedirectIP{})
- RegisterTestCase(NATOutRedirectInvert{})
- RegisterTestCase(NATRedirectRequiresProtocol{})
-}
-
-// NATPreRedirectUDPPort tests that packets are redirected to different port.
-type NATPreRedirectUDPPort struct{}
-
-// Name implements TestCase.Name.
-func (NATPreRedirectUDPPort) Name() string {
- return "NATPreRedirectUDPPort"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATPreRedirectUDPPort) ContainerAction(ip net.IP) error {
- if err := natTable("-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 (NATPreRedirectUDPPort) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// NATPreRedirectTCPPort tests that connections are redirected on specified ports.
-type NATPreRedirectTCPPort struct{}
-
-// Name implements TestCase.Name.
-func (NATPreRedirectTCPPort) Name() string {
- return "NATPreRedirectTCPPort"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATPreRedirectTCPPort) ContainerAction(ip net.IP) error {
- if err := natTable("-A", "PREROUTING", "-p", "tcp", "-m", "tcp", "--dport", fmt.Sprintf("%d", dropPort), "-j", "REDIRECT", "--to-ports", fmt.Sprintf("%d", acceptPort)); err != nil {
- return err
- }
-
- // Listen for TCP packets on redirect port.
- return listenTCP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATPreRedirectTCPPort) LocalAction(ip net.IP) error {
- return connectTCP(ip, dropPort, sendloopDuration)
-}
-
-// NATOutRedirectUDPPort tests that packets are redirected to different port.
-type NATOutRedirectUDPPort struct{}
-
-// Name implements TestCase.Name.
-func (NATOutRedirectUDPPort) Name() string {
- return "NATOutRedirectUDPPort"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATOutRedirectUDPPort) ContainerAction(ip net.IP) error {
- dest := []byte{200, 0, 0, 1}
- return loopbackTest(dest, "-A", "OUTPUT", "-p", "udp", "-j", "REDIRECT", "--to-ports", fmt.Sprintf("%d", acceptPort))
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATOutRedirectUDPPort) LocalAction(ip net.IP) error {
- // No-op.
- return nil
-}
-
-// 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 := natTable("-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)
-}
-
-// NATAcceptAll tests that all UDP packets are accepted.
-type NATAcceptAll struct{}
-
-// Name implements TestCase.Name.
-func (NATAcceptAll) Name() string {
- return "NATAcceptAll"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATAcceptAll) ContainerAction(ip net.IP) error {
- if err := natTable("-A", "PREROUTING", "-p", "udp", "-j", "ACCEPT"); err != nil {
- return err
- }
-
- if err := listenUDP(acceptPort, sendloopDuration); err != nil {
- return fmt.Errorf("packets on port %d should be allowed, but encountered an error: %v", acceptPort, err)
- }
-
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATAcceptAll) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// NATOutRedirectIP uses iptables to select packets based on destination IP and
-// redirects them.
-type NATOutRedirectIP struct{}
-
-// Name implements TestCase.Name.
-func (NATOutRedirectIP) Name() string {
- return "NATOutRedirectIP"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATOutRedirectIP) ContainerAction(ip net.IP) error {
- // Redirect OUTPUT packets to a listening localhost port.
- dest := net.IP([]byte{200, 0, 0, 2})
- return loopbackTest(dest, "-A", "OUTPUT", "-d", dest.String(), "-p", "udp", "-j", "REDIRECT", "--to-port", fmt.Sprintf("%d", acceptPort))
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATOutRedirectIP) LocalAction(ip net.IP) error {
- // No-op.
- return nil
-}
-
-// NATOutDontRedirectIP tests that iptables matching with "-d" does not match
-// packets it shouldn't.
-type NATOutDontRedirectIP struct{}
-
-// Name implements TestCase.Name.
-func (NATOutDontRedirectIP) Name() string {
- return "NATOutDontRedirectIP"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATOutDontRedirectIP) ContainerAction(ip net.IP) error {
- if err := natTable("-A", "OUTPUT", "-d", localIP, "-p", "udp", "-j", "REDIRECT", "--to-port", fmt.Sprintf("%d", dropPort)); err != nil {
- return err
- }
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATOutDontRedirectIP) LocalAction(ip net.IP) error {
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// NATOutRedirectInvert tests that iptables can match with "! -d".
-type NATOutRedirectInvert struct{}
-
-// Name implements TestCase.Name.
-func (NATOutRedirectInvert) Name() string {
- return "NATOutRedirectInvert"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATOutRedirectInvert) ContainerAction(ip net.IP) error {
- // Redirect OUTPUT packets to a listening localhost port.
- dest := []byte{200, 0, 0, 3}
- destStr := "200.0.0.2"
- return loopbackTest(dest, "-A", "OUTPUT", "!", "-d", destStr, "-p", "udp", "-j", "REDIRECT", "--to-port", fmt.Sprintf("%d", acceptPort))
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATOutRedirectInvert) LocalAction(ip net.IP) error {
- // No-op.
- return nil
-}
-
-// NATPreRedirectIP tests that we can use iptables to select packets based on
-// destination IP and redirect them.
-type NATPreRedirectIP struct{}
-
-// Name implements TestCase.Name.
-func (NATPreRedirectIP) Name() string {
- return "NATPreRedirectIP"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATPreRedirectIP) ContainerAction(ip net.IP) error {
- addrs, err := localAddrs()
- if err != nil {
- return err
- }
-
- var rules [][]string
- for _, addr := range addrs {
- rules = append(rules, []string{"-A", "PREROUTING", "-p", "udp", "-d", addr, "-j", "REDIRECT", "--to-ports", fmt.Sprintf("%d", acceptPort)})
- }
- if err := natTableRules(rules); err != nil {
- return err
- }
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATPreRedirectIP) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, dropPort, sendloopDuration)
-}
-
-// NATPreDontRedirectIP tests that iptables matching with "-d" does not match
-// packets it shouldn't.
-type NATPreDontRedirectIP struct{}
-
-// Name implements TestCase.Name.
-func (NATPreDontRedirectIP) Name() string {
- return "NATPreDontRedirectIP"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATPreDontRedirectIP) ContainerAction(ip net.IP) error {
- if err := natTable("-A", "PREROUTING", "-p", "udp", "-d", localIP, "-j", "REDIRECT", "--to-ports", fmt.Sprintf("%d", dropPort)); err != nil {
- return err
- }
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATPreDontRedirectIP) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, acceptPort, sendloopDuration)
-}
-
-// NATPreRedirectInvert tests that iptables can match with "! -d".
-type NATPreRedirectInvert struct{}
-
-// Name implements TestCase.Name.
-func (NATPreRedirectInvert) Name() string {
- return "NATPreRedirectInvert"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATPreRedirectInvert) ContainerAction(ip net.IP) error {
- if err := natTable("-A", "PREROUTING", "-p", "udp", "!", "-d", localIP, "-j", "REDIRECT", "--to-ports", fmt.Sprintf("%d", acceptPort)); err != nil {
- return err
- }
- return listenUDP(acceptPort, sendloopDuration)
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATPreRedirectInvert) LocalAction(ip net.IP) error {
- return sendUDPLoop(ip, dropPort, sendloopDuration)
-}
-
-// NATRedirectRequiresProtocol tests that use of the --to-ports flag requires a
-// protocol to be specified with -p.
-type NATRedirectRequiresProtocol struct{}
-
-// Name implements TestCase.Name.
-func (NATRedirectRequiresProtocol) Name() string {
- return "NATRedirectRequiresProtocol"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATRedirectRequiresProtocol) ContainerAction(ip net.IP) error {
- if err := natTable("-A", "PREROUTING", "-d", localIP, "-j", "REDIRECT", "--to-ports", fmt.Sprintf("%d", acceptPort)); err == nil {
- return errors.New("expected an error using REDIRECT --to-ports without a protocol")
- }
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATRedirectRequiresProtocol) LocalAction(ip net.IP) error {
- // No-op.
- return nil
-}
-
-// loopbackTests runs an iptables rule and ensures that packets sent to
-// dest:dropPort are received by localhost:acceptPort.
-func loopbackTest(dest net.IP, args ...string) error {
- if err := natTable(args...); err != nil {
- return err
- }
- sendCh := make(chan error)
- listenCh := make(chan error)
- go func() {
- sendCh <- sendUDPLoop(dest, dropPort, sendloopDuration)
- }()
- go func() {
- listenCh <- listenUDP(acceptPort, sendloopDuration)
- }()
- select {
- case err := <-listenCh:
- if err != nil {
- return err
- }
- case <-time.After(sendloopDuration):
- return errors.New("timed out")
- }
- // sendCh will always take the full sendloop time.
- return <-sendCh
-}
-
-// NATOutRedirectTCPPort tests that connections are redirected on specified ports.
-type NATOutRedirectTCPPort struct{}
-
-// Name implements TestCase.Name.
-func (NATOutRedirectTCPPort) Name() string {
- return "NATOutRedirectTCPPort"
-}
-
-// ContainerAction implements TestCase.ContainerAction.
-func (NATOutRedirectTCPPort) ContainerAction(ip net.IP) error {
- if err := natTable("-A", "OUTPUT", "-p", "tcp", "-m", "tcp", "--dport", fmt.Sprintf("%d", dropPort), "-j", "REDIRECT", "--to-ports", fmt.Sprintf("%d", acceptPort)); err != nil {
- return err
- }
-
- timeout := 20 * time.Second
- dest := []byte{127, 0, 0, 1}
- localAddr := net.TCPAddr{
- IP: dest,
- Port: acceptPort,
- }
-
- // Starts listening on port.
- lConn, err := net.ListenTCP("tcp", &localAddr)
- if err != nil {
- return err
- }
- defer lConn.Close()
-
- // Accept connections on port.
- lConn.SetDeadline(time.Now().Add(timeout))
- err = connectTCP(ip, dropPort, timeout)
- if err != nil {
- return err
- }
-
- conn, err := lConn.AcceptTCP()
- if err != nil {
- return err
- }
- conn.Close()
-
- return nil
-}
-
-// LocalAction implements TestCase.LocalAction.
-func (NATOutRedirectTCPPort) LocalAction(ip net.IP) error {
- return nil
-}
diff --git a/test/iptables/runner/BUILD b/test/iptables/runner/BUILD
deleted file mode 100644
index 24504a1b9..000000000
--- a/test/iptables/runner/BUILD
+++ /dev/null
@@ -1,12 +0,0 @@
-load("//tools:defs.bzl", "go_binary")
-
-package(licenses = ["notice"])
-
-go_binary(
- name = "runner",
- testonly = 1,
- srcs = ["main.go"],
- pure = True,
- visibility = ["//test/iptables:__subpackages__"],
- deps = ["//test/iptables"],
-)
diff --git a/test/iptables/runner/main.go b/test/iptables/runner/main.go
deleted file mode 100644
index 6f77c0684..000000000
--- a/test/iptables/runner/main.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2019 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 main runs iptables tests from within a docker container.
-package main
-
-import (
- "flag"
- "fmt"
- "log"
- "net"
-
- "gvisor.dev/gvisor/test/iptables"
-)
-
-var name = flag.String("name", "", "name of the test to run")
-
-func main() {
- flag.Parse()
-
- // Find out which test we're running.
- test, ok := iptables.Tests[*name]
- if !ok {
- log.Fatalf("No test found named %q", *name)
- }
- log.Printf("Running test %q", *name)
-
- // Get the IP of the local process.
- ip, err := getIP()
- if err != nil {
- log.Fatal(err)
- }
-
- // Run the test.
- if err := test.ContainerAction(ip); err != nil {
- log.Fatalf("Failed running test %q: %v", *name, err)
- }
-
- // Emit the final line.
- log.Printf("%s", iptables.TerminalStatement)
-}
-
-// getIP listens for a connection from the local process and returns the source
-// IP of that connection.
-func getIP() (net.IP, error) {
- localAddr := net.TCPAddr{
- Port: iptables.IPExchangePort,
- }
- listener, err := net.ListenTCP("tcp4", &localAddr)
- if err != nil {
- return net.IP{}, fmt.Errorf("failed listening for IP: %v", err)
- }
- defer listener.Close()
- conn, err := listener.AcceptTCP()
- if err != nil {
- return net.IP{}, fmt.Errorf("failed accepting IP: %v", err)
- }
- defer conn.Close()
- log.Printf("Connected to %v", conn.RemoteAddr())
-
- return conn.RemoteAddr().(*net.TCPAddr).IP, nil
-}