summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/iptables
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/iptables')
-rw-r--r--pkg/tcpip/iptables/BUILD6
-rw-r--r--pkg/tcpip/iptables/iptables.go86
-rw-r--r--pkg/tcpip/iptables/targets.go9
-rw-r--r--pkg/tcpip/iptables/types.go17
4 files changed, 105 insertions, 13 deletions
diff --git a/pkg/tcpip/iptables/BUILD b/pkg/tcpip/iptables/BUILD
index 64769c333..d1b73cfdf 100644
--- a/pkg/tcpip/iptables/BUILD
+++ b/pkg/tcpip/iptables/BUILD
@@ -1,4 +1,4 @@
-load("//tools/go_stateify:defs.bzl", "go_library")
+load("//tools:defs.bzl", "go_library")
package(licenses = ["notice"])
@@ -9,10 +9,10 @@ go_library(
"targets.go",
"types.go",
],
- importpath = "gvisor.dev/gvisor/pkg/tcpip/iptables",
visibility = ["//visibility:public"],
deps = [
"//pkg/log",
- "//pkg/tcpip/buffer",
+ "//pkg/tcpip",
+ "//pkg/tcpip/header",
],
)
diff --git a/pkg/tcpip/iptables/iptables.go b/pkg/tcpip/iptables/iptables.go
index 647970133..4bfb3149e 100644
--- a/pkg/tcpip/iptables/iptables.go
+++ b/pkg/tcpip/iptables/iptables.go
@@ -1,4 +1,4 @@
-// Copyright 2019 The gVisor authors.
+// 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.
@@ -16,6 +16,13 @@
// tool.
package iptables
+import (
+ "fmt"
+
+ "gvisor.dev/gvisor/pkg/tcpip"
+ "gvisor.dev/gvisor/pkg/tcpip/header"
+)
+
// Table names.
const (
TablenameNat = "nat"
@@ -127,3 +134,80 @@ func EmptyFilterTable() Table {
UserChains: map[string]int{},
}
}
+
+// Check runs pkt through the rules for hook. It returns true when the packet
+// should continue traversing the network stack and false when it should be
+// dropped.
+func (it *IPTables) Check(hook Hook, pkt tcpip.PacketBuffer) bool {
+ // TODO(gvisor.dev/issue/170): A lot of this is uncomplicated because
+ // we're missing features. Jumps, the call stack, etc. aren't checked
+ // for yet because we're yet to support them.
+
+ // Go through each table containing the hook.
+ for _, tablename := range it.Priorities[hook] {
+ switch verdict := it.checkTable(hook, pkt, tablename); verdict {
+ // If the table returns Accept, move on to the next table.
+ case Accept:
+ continue
+ // The Drop verdict is final.
+ case Drop:
+ return false
+ case Stolen, Queue, Repeat, None, Jump, Return, Continue:
+ panic(fmt.Sprintf("Unimplemented verdict %v.", verdict))
+ default:
+ panic(fmt.Sprintf("Unknown verdict %v.", verdict))
+ }
+ }
+
+ // Every table returned Accept.
+ return true
+}
+
+func (it *IPTables) checkTable(hook Hook, pkt tcpip.PacketBuffer, tablename string) Verdict {
+ // Start from ruleIdx and walk the list of rules until a rule gives us
+ // a verdict.
+ table := it.Tables[tablename]
+ for ruleIdx := table.BuiltinChains[hook]; ruleIdx < len(table.Rules); ruleIdx++ {
+ switch verdict := it.checkRule(hook, pkt, table, ruleIdx); verdict {
+ // In either of these cases, this table is done with the packet.
+ case Accept, Drop:
+ return verdict
+ // Continue traversing the rules of the table.
+ case Continue:
+ continue
+ case Stolen, Queue, Repeat, None, Jump, Return:
+ panic(fmt.Sprintf("Unimplemented verdict %v.", verdict))
+ default:
+ panic(fmt.Sprintf("Unknown verdict %v.", verdict))
+ }
+ }
+
+ panic(fmt.Sprintf("Traversed past the entire list of iptables rules in table %q.", tablename))
+}
+
+// Precondition: pk.NetworkHeader is set.
+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 != 0 && rule.Filter.Protocol != header.IPv4(pkt.NetworkHeader).TransportProtocol() {
+ return Continue
+ }
+
+ // Go through each rule matcher. If they all match, run
+ // the rule target.
+ for _, matcher := range rule.Matchers {
+ matches, hotdrop := matcher.Match(hook, pkt, "")
+ if hotdrop {
+ return Drop
+ }
+ if !matches {
+ return Continue
+ }
+ }
+
+ // All the matchers matched, so run the target.
+ verdict, _ := rule.Target.Action(pkt)
+ return verdict
+}
diff --git a/pkg/tcpip/iptables/targets.go b/pkg/tcpip/iptables/targets.go
index b94a4c941..4dd281371 100644
--- a/pkg/tcpip/iptables/targets.go
+++ b/pkg/tcpip/iptables/targets.go
@@ -18,14 +18,14 @@ package iptables
import (
"gvisor.dev/gvisor/pkg/log"
- "gvisor.dev/gvisor/pkg/tcpip/buffer"
+ "gvisor.dev/gvisor/pkg/tcpip"
)
// UnconditionalAcceptTarget accepts all packets.
type UnconditionalAcceptTarget struct{}
// Action implements Target.Action.
-func (UnconditionalAcceptTarget) Action(packet buffer.VectorisedView) (Verdict, string) {
+func (UnconditionalAcceptTarget) Action(packet tcpip.PacketBuffer) (Verdict, string) {
return Accept, ""
}
@@ -33,7 +33,7 @@ func (UnconditionalAcceptTarget) Action(packet buffer.VectorisedView) (Verdict,
type UnconditionalDropTarget struct{}
// Action implements Target.Action.
-func (UnconditionalDropTarget) Action(packet buffer.VectorisedView) (Verdict, string) {
+func (UnconditionalDropTarget) Action(packet tcpip.PacketBuffer) (Verdict, string) {
return Drop, ""
}
@@ -42,8 +42,7 @@ func (UnconditionalDropTarget) Action(packet buffer.VectorisedView) (Verdict, st
type ErrorTarget struct{}
// Action implements Target.Action.
-func (ErrorTarget) Action(packet buffer.VectorisedView) (Verdict, string) {
+func (ErrorTarget) Action(packet tcpip.PacketBuffer) (Verdict, string) {
log.Warningf("ErrorTarget triggered.")
return Drop, ""
-
}
diff --git a/pkg/tcpip/iptables/types.go b/pkg/tcpip/iptables/types.go
index 540f8c0b4..50893cc55 100644
--- a/pkg/tcpip/iptables/types.go
+++ b/pkg/tcpip/iptables/types.go
@@ -1,4 +1,4 @@
-// Copyright 2019 The gVisor authors.
+// 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.
@@ -15,7 +15,7 @@
package iptables
import (
- "gvisor.dev/gvisor/pkg/tcpip/buffer"
+ "gvisor.dev/gvisor/pkg/tcpip"
)
// A Hook specifies one of the hooks built into the network stack.
@@ -153,6 +153,9 @@ 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 {
+ // Filter holds basic IP filtering fields common to every rule.
+ Filter IPHeaderFilter
+
// Matchers is the list of matchers for this rule.
Matchers []Matcher
@@ -160,12 +163,18 @@ type Rule struct {
Target Target
}
+// IPHeaderFilter holds basic IP filtering data common to every rule.
+type IPHeaderFilter struct {
+ // Protocol matches the transport protocol.
+ Protocol tcpip.TransportProtocolNumber
+}
+
// A Matcher is the interface for matching packets.
type Matcher interface {
// Match returns whether the packet matches and whether the packet
// should be "hotdropped", i.e. dropped immediately. This is usually
// used for suspicious packets.
- Match(hook Hook, packet buffer.VectorisedView, interfaceName string) (matches bool, hotdrop bool)
+ Match(hook Hook, packet tcpip.PacketBuffer, interfaceName string) (matches bool, hotdrop bool)
}
// A Target is the interface for taking an action for a packet.
@@ -173,5 +182,5 @@ type Target interface {
// Action takes an action on the packet and returns a verdict on how
// traversal should (or should not) continue. If the return value is
// Jump, it also returns the name of the chain to jump to.
- Action(packet buffer.VectorisedView) (Verdict, string)
+ Action(packet tcpip.PacketBuffer) (Verdict, string)
}