Added a test that we don't pass yet
This commit is contained in:
parent
aeb3a4017b
commit
89d11b4d96
|
@ -323,10 +323,9 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
|
|||
|
||||
// TODO(gvisor.dev/issue/170): We should support IPTIP
|
||||
// filtering. We reject any nonzero IPTIP values for now.
|
||||
emptyIPTIP := linux.IPTIP{}
|
||||
if entry.IP != emptyIPTIP {
|
||||
log.Warningf("netfilter: non-empty struct iptip found")
|
||||
return syserr.ErrInvalidArgument
|
||||
filter, err := filterFromIPTIP(entry.IP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the target of the rule.
|
||||
|
@ -336,7 +335,10 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
|
|||
}
|
||||
optVal = optVal[consumed:]
|
||||
|
||||
table.Rules = append(table.Rules, iptables.Rule{Target: target})
|
||||
table.Rules = append(table.Rules, iptables.Rule{
|
||||
Filter: filter,
|
||||
Target: target,
|
||||
})
|
||||
offsets = append(offsets, offset)
|
||||
offset += linux.SizeOfIPTEntry + consumed
|
||||
}
|
||||
|
@ -447,6 +449,31 @@ func parseTarget(optVal []byte) (iptables.Target, uint32, *syserr.Error) {
|
|||
return nil, 0, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
func filterFromIPTIP(iptip linux.IPTIP) (iptables.IPHeaderFilter, *syserr.Error) {
|
||||
if containsUnsupportedFields(iptip) {
|
||||
log.Warningf("netfilter: unsupported fields in struct iptip: %+v")
|
||||
return iptables.IPHeaderFilter{}, syserr.ErrInvalidArgument
|
||||
}
|
||||
return iptables.IPHeaderFilter{
|
||||
Protocol: iptip.Protocol,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func containsUnsupportedFields(iptip linux.IPTIP) bool {
|
||||
// Currently we check that everything except protocol is zeroed.
|
||||
var emptyInetAddr = linux.InetAddr{}
|
||||
var emptyInterface = [linux.IFNAMSIZ]byte{}
|
||||
return iptip.Dst != emptyInetAddr ||
|
||||
iptip.SrcMask != emptyInetAddr ||
|
||||
iptip.DstMask != emptyInetAddr ||
|
||||
iptip.InputInterface != emptyInterface ||
|
||||
iptip.OutputInterface != emptyInterface ||
|
||||
iptip.InputInterfaceMask != emptyInterface ||
|
||||
iptip.OutputInterfaceMask != emptyInterface ||
|
||||
iptip.Flags != 0 ||
|
||||
iptip.InverseFlags != 0
|
||||
}
|
||||
|
||||
func hookFromLinux(hook int) iptables.Hook {
|
||||
switch hook {
|
||||
case linux.NF_INET_PRE_ROUTING:
|
||||
|
|
|
@ -185,6 +185,13 @@ func (it *IPTables) checkTable(hook Hook, pkt tcpip.PacketBuffer, tablename stri
|
|||
|
||||
func (it *IPTables) checkRule(hook Hook, pkt tcpip.PacketBuffer, table Table, ruleIdx int) Verdict {
|
||||
rule := table.Rules[ruleIdx]
|
||||
|
||||
// First check whether the packet matches the IP header filter.
|
||||
// TODO(gvisor.dev/issue/170): Support other fields of the filter.
|
||||
// if rule.Filter.Protocol != pkt.Protocol {
|
||||
// return Continue
|
||||
// }
|
||||
|
||||
// Go through each rule matcher. If they all match, run
|
||||
// the rule target.
|
||||
for _, matcher := range rule.Matchers {
|
||||
|
|
|
@ -151,8 +151,8 @@ func (table *Table) SetMetadata(metadata interface{}) {
|
|||
// packets this rule applies to. If there are no matchers in the rule, it
|
||||
// applies to any packet.
|
||||
type Rule struct {
|
||||
// IPHeaderFilters holds basic IP filtering fields common to every rule.
|
||||
IPHeaderFilter IPHeaderFilter
|
||||
// IPHeaderFilter holds basic IP filtering fields common to every rule.
|
||||
Filter IPHeaderFilter
|
||||
|
||||
// Matchers is the list of matchers for this rule.
|
||||
Matchers []Matcher
|
||||
|
|
|
@ -4,6 +4,7 @@ package(licenses = ["notice"])
|
|||
|
||||
go_library(
|
||||
name = "iptables",
|
||||
testonly = 1,
|
||||
srcs = [
|
||||
"filter_input.go",
|
||||
"iptables.go",
|
||||
|
@ -11,6 +12,9 @@ go_library(
|
|||
],
|
||||
importpath = "gvisor.dev/gvisor/test/iptables",
|
||||
visibility = ["//test/iptables:__subpackages__"],
|
||||
deps = [
|
||||
"//runsc/testutil",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
|
|
|
@ -28,6 +28,7 @@ const (
|
|||
)
|
||||
|
||||
func init() {
|
||||
RegisterTestCase(FilterInputDropOnlyUDP{})
|
||||
RegisterTestCase(FilterInputDropUDP{})
|
||||
RegisterTestCase(FilterInputDropUDPPort{})
|
||||
RegisterTestCase(FilterInputDropDifferentUDPPort{})
|
||||
|
@ -65,6 +66,35 @@ 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 connectLoopTCP(ip, acceptPort, sendloopDuration)
|
||||
}
|
||||
|
||||
// FilterInputDropUDPPort tests that we can drop UDP traffic by port.
|
||||
type FilterInputDropUDPPort struct{}
|
||||
|
||||
|
|
|
@ -160,11 +160,11 @@ func logContainer(output string, err error) {
|
|||
log.Infof(msg)
|
||||
}
|
||||
|
||||
func TestFilterInputDropUDP(t *testing.T) {
|
||||
if err := singleTest(FilterInputDropUDP{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
// 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 {
|
||||
|
@ -183,3 +183,9 @@ func TestFilterInputDropUDP(t *testing.T) {
|
|||
// t.Fatal(err)
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestFilterInputDropOnlyUDP(t *testing.T) {
|
||||
if err := singleTest(FilterInputDropOnlyUDP{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ import (
|
|||
"net"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"gvisor.dev/gvisor/runsc/testutil"
|
||||
)
|
||||
|
||||
const iptablesBinary = "iptables"
|
||||
|
@ -80,3 +82,41 @@ func sendUDPLoop(ip net.IP, port int, duration time.Duration) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func listenTCP(port int, timeout time.Duration) error {
|
||||
localAddr := net.TCPAddr{Port: acceptPort}
|
||||
listener, err := net.ListenTCP("tcp4", &localAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer listener.Close()
|
||||
listener.SetDeadline(time.Now().Add(timeout))
|
||||
conn, err := listener.AcceptTCP()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to establish a connection %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func connectLoopTCP(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.
|
||||
cb := func() error {
|
||||
conn, err := net.DialTCP("tcp4", nil, &contAddr)
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
if err := testutil.Poll(cb, timeout); err != nil {
|
||||
return fmt.Errorf("timed out waiting to send IP, most recent error: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ container_image(
|
|||
|
||||
go_image(
|
||||
name = "runner",
|
||||
testonly = 1,
|
||||
srcs = ["main.go"],
|
||||
base = ":iptables-base",
|
||||
deps = ["//test/iptables"],
|
||||
|
|
Loading…
Reference in New Issue