summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKevin Krakauer <krakauer@google.com>2020-01-08 14:48:47 -0800
committerKevin Krakauer <krakauer@google.com>2020-01-08 14:48:47 -0800
commitb2a881784c8e525c1fea71c6f23663413d107f05 (patch)
tree6529dc74dcf1fc21d0b3199f149356cb877f5ddc
parent447f64c561e6b5893c1bbae7d641187b7aca64ac (diff)
Built dead-simple traversal, but now getting depedency cycle error :'(
-rw-r--r--pkg/sentry/socket/netfilter/netfilter.go4
-rw-r--r--pkg/tcpip/iptables/BUILD4
-rw-r--r--pkg/tcpip/iptables/iptables.go59
-rw-r--r--pkg/tcpip/network/ipv4/ipv4.go6
-rw-r--r--test/iptables/filter_input.go2
5 files changed, 73 insertions, 2 deletions
diff --git a/pkg/sentry/socket/netfilter/netfilter.go b/pkg/sentry/socket/netfilter/netfilter.go
index e4c493141..57785220e 100644
--- a/pkg/sentry/socket/netfilter/netfilter.go
+++ b/pkg/sentry/socket/netfilter/netfilter.go
@@ -368,6 +368,10 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
}
}
+ // TODO(gvisor.dev/issue/170): Check the following conditions:
+ // - There are no loops.
+ // - There are no chains without an unconditional final rule.
+
ipt := stack.IPTables()
table.SetMetadata(metadata{
HookEntry: replace.HookEntry,
diff --git a/pkg/tcpip/iptables/BUILD b/pkg/tcpip/iptables/BUILD
index cc5f531e2..6ed7c6da0 100644
--- a/pkg/tcpip/iptables/BUILD
+++ b/pkg/tcpip/iptables/BUILD
@@ -11,5 +11,7 @@ go_library(
],
importpath = "gvisor.dev/gvisor/pkg/tcpip/iptables",
visibility = ["//visibility:public"],
- deps = ["//pkg/tcpip/buffer"],
+ deps = [
+ "//pkg/tcpip",
+ ],
)
diff --git a/pkg/tcpip/iptables/iptables.go b/pkg/tcpip/iptables/iptables.go
index 9e7005374..025a4679d 100644
--- a/pkg/tcpip/iptables/iptables.go
+++ b/pkg/tcpip/iptables/iptables.go
@@ -16,6 +16,8 @@
// tool.
package iptables
+import "github.com/google/netstack/tcpip"
+
const (
TablenameNat = "nat"
TablenameMangle = "mangle"
@@ -121,3 +123,60 @@ 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.
+ log.Infof("kevin: iptables.IPTables: checking hook %v", hook)
+
+ // Go through each table containing the hook.
+ for _, tablename := range it.Priorities[hook] {
+ verdict := it.checkTable(tablename)
+ switch verdict {
+ // TODO: We either got a final verdict or simply continue on.
+ }
+ }
+}
+
+func (it *IPTables) checkTable(hook Hook, pkt tcpip.PacketBuffer, tablename string) bool {
+ log.Infof("kevin: iptables.IPTables: checking table %q", tablename)
+ table := it.Tables[tablename]
+ ruleIdx := table.BuiltinChains[hook]
+
+ // Start from ruleIdx and go down until a rule gives us a verdict.
+ for ruleIdx := table.BuiltinChains[hook]; ruleIdx < len(table.Rules); ruleIdx++ {
+ verdict := checkRule(hook, pkt, table, ruleIdx)
+ switch verdict {
+ case Accept, Drop:
+ return verdict
+ case Continue:
+ continue
+ case Stolen, Queue, Repeat, None, Jump, Return:
+ }
+ }
+
+ panic("Traversed past the entire list of iptables rules.")
+}
+
+func (it *IPTables) checkRule(hook Hook, pkt tcpip.PacketBuffer, table Table, ruleIdx int) Verdict {
+ rule := table.Rules[ruleIdx]
+ // 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/network/ipv4/ipv4.go b/pkg/tcpip/network/ipv4/ipv4.go
index e645cf62c..bbb5aafee 100644
--- a/pkg/tcpip/network/ipv4/ipv4.go
+++ b/pkg/tcpip/network/ipv4/ipv4.go
@@ -350,6 +350,12 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt tcpip.PacketBuffer) {
}
pkt.NetworkHeader = headerView[:h.HeaderLength()]
+ // iptables filtering.
+ if ok := iptables.Check(iptables.Input, pkt); !ok {
+ // iptables is telling us to drop the packet.
+ return
+ }
+
hlen := int(h.HeaderLength())
tlen := int(h.TotalLength())
pkt.Data.TrimFront(hlen)
diff --git a/test/iptables/filter_input.go b/test/iptables/filter_input.go
index 1723a4d3e..7c4d469fa 100644
--- a/test/iptables/filter_input.go
+++ b/test/iptables/filter_input.go
@@ -138,7 +138,7 @@ func (FilterInputDropAll) ContainerAction(ip net.IP) error {
return err
}
- // Listen for All packets on dropPort.
+ // 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() {