Add test for iptables TCP rule
Added tests for tcp protocol with input and output rules including options sport and dport Increased timeout in iptables_test as TCP tests were timing out with existing value.
This commit is contained in:
parent
9aeb053bba
commit
98327a94cc
|
@ -6,6 +6,7 @@ go_library(
|
|||
name = "iptables",
|
||||
srcs = [
|
||||
"filter_input.go",
|
||||
"filter_output.go",
|
||||
"iptables.go",
|
||||
"iptables_util.go",
|
||||
"nat.go",
|
||||
|
|
|
@ -31,6 +31,8 @@ func init() {
|
|||
RegisterTestCase(FilterInputDropUDP{})
|
||||
RegisterTestCase(FilterInputDropUDPPort{})
|
||||
RegisterTestCase(FilterInputDropDifferentUDPPort{})
|
||||
RegisterTestCase(FilterInputDropTCPDestPort{})
|
||||
RegisterTestCase(FilterInputDropTCPSrcPort{})
|
||||
}
|
||||
|
||||
// FilterInputDropUDP tests that we can drop UDP traffic.
|
||||
|
@ -122,3 +124,67 @@ func (FilterInputDropDifferentUDPPort) ContainerAction(ip net.IP) error {
|
|||
func (FilterInputDropDifferentUDPPort) LocalAction(ip net.IP) error {
|
||||
return sendUDPLoop(ip, acceptPort, sendloopDuration)
|
||||
}
|
||||
|
||||
// FilterInputDropTCP 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("Connections 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("connections 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 sent from port %d should not be accepted", dropPort)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// 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("connections 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 sent from 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("connections 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
|
||||
}
|
|
@ -28,7 +28,7 @@ import (
|
|||
"gvisor.dev/gvisor/runsc/testutil"
|
||||
)
|
||||
|
||||
const timeout time.Duration = 10 * time.Second
|
||||
const timeout time.Duration = 18 * time.Second
|
||||
|
||||
var image = flag.String("image", "bazel/test/iptables/runner:runner", "image to run tests in")
|
||||
|
||||
|
@ -189,3 +189,27 @@ func TestNATDropUDP(t *testing.T) {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,3 +80,58 @@ 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: 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 {
|
||||
conn.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// connectTCP connects the TCP server over specified local port, server IP
|
||||
// and remote/server port
|
||||
func connectTCP(ip net.IP, remotePort int, localPort int, duration time.Duration) error {
|
||||
remote := net.TCPAddr{
|
||||
IP: ip,
|
||||
Port: remotePort,
|
||||
}
|
||||
|
||||
local := net.TCPAddr{
|
||||
Port: localPort,
|
||||
}
|
||||
|
||||
// Container may not be up. Retry DialTCP
|
||||
// over a given duration
|
||||
to := time.After(duration)
|
||||
var res error
|
||||
for timedOut := false; !timedOut; {
|
||||
conn, err := net.DialTCP("tcp4", &local, &remote)
|
||||
res = err
|
||||
if res == nil {
|
||||
conn.Close()
|
||||
return nil
|
||||
}
|
||||
select{
|
||||
case <-to:
|
||||
timedOut = true
|
||||
default:
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue