summaryrefslogtreecommitdiffhomepage
path: root/test/iptables
diff options
context:
space:
mode:
Diffstat (limited to 'test/iptables')
-rw-r--r--test/iptables/BUILD31
-rw-r--r--test/iptables/README.md44
-rw-r--r--test/iptables/filter_input.go124
-rw-r--r--test/iptables/iptables.go53
-rw-r--r--test/iptables/iptables_test.go179
-rw-r--r--test/iptables/iptables_util.go82
-rw-r--r--test/iptables/runner/BUILD16
-rw-r--r--test/iptables/runner/Dockerfile4
-rw-r--r--test/iptables/runner/main.go70
9 files changed, 0 insertions, 603 deletions
diff --git a/test/iptables/BUILD b/test/iptables/BUILD
deleted file mode 100644
index fa833c3b2..000000000
--- a/test/iptables/BUILD
+++ /dev/null
@@ -1,31 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "iptables",
- srcs = [
- "filter_input.go",
- "iptables.go",
- "iptables_util.go",
- ],
- importpath = "gvisor.dev/gvisor/test/iptables",
- visibility = ["//test/iptables:__subpackages__"],
-)
-
-go_test(
- name = "iptables_test",
- srcs = [
- "iptables_test.go",
- ],
- embed = [":iptables"],
- tags = [
- "local",
- "manual",
- ],
- deps = [
- "//pkg/log",
- "//runsc/dockerutil",
- "//runsc/testutil",
- ],
-)
diff --git a/test/iptables/README.md b/test/iptables/README.md
deleted file mode 100644
index 9f8e34420..000000000
--- a/test/iptables/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# iptables Tests
-
-iptables tests are run via `scripts/iptables_test.sh`.
-
-## 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 the testing Docker container:
-
-```bash
-$ bazel run //test/iptables/runner -- --norun
-```
-
-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 923f44e68..000000000
--- a/test/iptables/filter_input.go
+++ /dev/null
@@ -1,124 +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"
- "time"
-)
-
-const (
- dropPort = 2401
- acceptPort = 2402
- sendloopDuration = 2 * time.Second
- network = "udp4"
-)
-
-func init() {
- RegisterTestCase(FilterInputDropUDP{})
- RegisterTestCase(FilterInputDropUDPPort{})
- RegisterTestCase(FilterInputDropDifferentUDPPort{})
-}
-
-// 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)
-}
-
-// 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)
-}
diff --git a/test/iptables/iptables.go b/test/iptables/iptables.go
deleted file mode 100644
index 2e565d988..000000000
--- a/test/iptables/iptables.go
+++ /dev/null
@@ -1,53 +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"
-)
-
-// IPExchangePort is the port the container listens on to receive the IP
-// address of the local process.
-const IPExchangePort = 2349
-
-// 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 bfbf1bb87..000000000
--- a/test/iptables/iptables_test.go
+++ /dev/null
@@ -1,179 +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"
- "path"
- "testing"
- "time"
-
- "flag"
- "gvisor.dev/gvisor/pkg/log"
- "gvisor.dev/gvisor/runsc/dockerutil"
- "gvisor.dev/gvisor/runsc/testutil"
-)
-
-const timeout time.Duration = 10 * time.Second
-
-var image = flag.String("image", "bazel/test/iptables/runner:runner", "image to run tests in")
-
-type result struct {
- output string
- err error
-}
-
-// 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(test TestCase) error {
- if _, ok := Tests[test.Name()]; !ok {
- return fmt.Errorf("no test found with name %q. Has it been registered?", test.Name())
- }
-
- // Create and start the container.
- cont := dockerutil.MakeDocker("gvisor-iptables")
- defer cont.CleanUp()
- resultChan := make(chan *result)
- go func() {
- output, err := cont.RunFg("--cap-add=NET_ADMIN", *image, "-name", test.Name())
- logContainer(output, err)
- resultChan <- &result{output, err}
- }()
-
- // Get the container IP.
- ip, err := getIP(cont)
- if err != nil {
- return fmt.Errorf("failed to get container IP: %v", err)
- }
-
- // Give the container our IP.
- if err := sendIP(ip); err != nil {
- return fmt.Errorf("failed to send IP to container: %v", err)
- }
-
- // Run our side of the test.
- errChan := make(chan error)
- go func() {
- errChan <- test.LocalAction(ip)
- }()
-
- // Wait for both the container and local tests to finish.
- var res *result
- to := time.After(timeout)
- for localDone := false; res == nil || !localDone; {
- select {
- case res = <-resultChan:
- log.Infof("Container finished.")
- case err, localDone = <-errChan:
- log.Infof("Local finished.")
- if err != nil {
- return fmt.Errorf("local test failed: %v", err)
- }
- case <-to:
- return fmt.Errorf("timed out after %f seconds", timeout.Seconds())
- }
- }
-
- return res.err
-}
-
-func getIP(cont dockerutil.Docker) (net.IP, error) {
- // The container might not have started yet, so retry a few times.
- var ipStr string
- to := time.After(timeout)
- for ipStr == "" {
- ipStr, _ = cont.FindIP()
- select {
- case <-to:
- return net.IP{}, fmt.Errorf("timed out getting IP after %f seconds", timeout.Seconds())
- default:
- time.Sleep(250 * time.Millisecond)
- }
- }
- ip := net.ParseIP(ipStr)
- if ip == nil {
- return net.IP{}, fmt.Errorf("invalid IP: %q", ipStr)
- }
- log.Infof("Container has IP of %s", ipStr)
- return ip, nil
-}
-
-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, timeout); 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 logContainer(output string, err error) {
- msg := fmt.Sprintf("Container error: %v\nContainer output:\n%v", err, output)
- if artifactsDir := os.Getenv("TEST_UNDECLARED_OUTPUTS_DIR"); artifactsDir != "" {
- fpath := path.Join(artifactsDir, "container.log")
- if file, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE, 0644); err != nil {
- log.Warningf("Failed to open log file %q: %v", fpath, err)
- } else {
- defer file.Close()
- if _, err := file.Write([]byte(msg)); err == nil {
- return
- }
- log.Warningf("Failed to write to log file %s: %v", fpath, err)
- }
- }
-
- // We couldn't write to the output directory -- just log to stderr.
- log.Infof(msg)
-}
-
-func TestFilterInputDropUDP(t *testing.T) {
- if err := singleTest(FilterInputDropUDP{}); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestFilterInputDropUDPPort(t *testing.T) {
- if err := singleTest(FilterInputDropUDPPort{}); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestFilterInputDropDifferentUDPPort(t *testing.T) {
- if err := singleTest(FilterInputDropDifferentUDPPort{}); err != nil {
- t.Fatal(err)
- }
-}
diff --git a/test/iptables/iptables_util.go b/test/iptables/iptables_util.go
deleted file mode 100644
index 3a4d11f1a..000000000
--- a/test/iptables/iptables_util.go
+++ /dev/null
@@ -1,82 +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"
-)
-
-const iptablesBinary = "iptables"
-
-// filterTable calls `iptables -t filter` with the given args.
-func filterTable(args ...string) error {
- args = append([]string{"-t", "filter"}, 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
-}
-
-// 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
-}
diff --git a/test/iptables/runner/BUILD b/test/iptables/runner/BUILD
deleted file mode 100644
index c6c42d870..000000000
--- a/test/iptables/runner/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-load("@io_bazel_rules_docker//go:image.bzl", "go_image")
-load("@io_bazel_rules_docker//container:container.bzl", "container_image")
-
-package(licenses = ["notice"])
-
-container_image(
- name = "iptables-base",
- base = "@iptables-test//image",
-)
-
-go_image(
- name = "runner",
- srcs = ["main.go"],
- base = ":iptables-base",
- deps = ["//test/iptables"],
-)
diff --git a/test/iptables/runner/Dockerfile b/test/iptables/runner/Dockerfile
deleted file mode 100644
index b77db44a1..000000000
--- a/test/iptables/runner/Dockerfile
+++ /dev/null
@@ -1,4 +0,0 @@
-# This Dockerfile builds the image hosted at
-# gcr.io/gvisor-presubmit/iptables-test.
-FROM ubuntu
-RUN apt update && apt install -y iptables
diff --git a/test/iptables/runner/main.go b/test/iptables/runner/main.go
deleted file mode 100644
index 3c794114e..000000000
--- a/test/iptables/runner/main.go
+++ /dev/null
@@ -1,70 +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)
- }
-}
-
-// 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
-}