diff options
Diffstat (limited to 'pkg/tcpip/iptables')
-rw-r--r-- | pkg/tcpip/iptables/BUILD | 2 | ||||
-rw-r--r-- | pkg/tcpip/iptables/iptables.go | 80 | ||||
-rw-r--r-- | pkg/tcpip/iptables/targets.go | 9 | ||||
-rw-r--r-- | pkg/tcpip/iptables/types.go | 8 |
4 files changed, 88 insertions, 11 deletions
diff --git a/pkg/tcpip/iptables/BUILD b/pkg/tcpip/iptables/BUILD index 64769c333..2893c80cd 100644 --- a/pkg/tcpip/iptables/BUILD +++ b/pkg/tcpip/iptables/BUILD @@ -13,6 +13,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/log", - "//pkg/tcpip/buffer", + "//pkg/tcpip", ], ) diff --git a/pkg/tcpip/iptables/iptables.go b/pkg/tcpip/iptables/iptables.go index db0450a21..91abbbea8 100644 --- a/pkg/tcpip/iptables/iptables.go +++ b/pkg/tcpip/iptables/iptables.go @@ -16,6 +16,13 @@ // tool. package iptables +import ( + "fmt" + + "gvisor.dev/gvisor/pkg/log" + "gvisor.dev/gvisor/pkg/tcpip" +) + const ( TablenameNat = "nat" TablenameMangle = "mangle" @@ -121,3 +128,76 @@ 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(hook, pkt, tablename) + switch verdict { + // If the table returns Accept, move on to the next table. + case Accept: + continue + // The Drop verdict is final. + case Drop: + log.Infof("kevin: Packet dropped") + return false + case Stolen, Queue, Repeat, None, Jump, Return, Continue: + panic(fmt.Sprintf("Unimplemented verdict %v.", verdict)) + } + } + + // Every table returned Accept. + log.Infof("kevin: Packet accepted") + return true +} + +func (it *IPTables) checkTable(hook Hook, pkt tcpip.PacketBuffer, tablename string) Verdict { + log.Infof("kevin: iptables.IPTables: checking table %q", tablename) + table := it.Tables[tablename] + log.Infof("kevin: iptables.IPTables: table %+v", table) + + // Start from ruleIdx and go down until a rule gives us a verdict. + for ruleIdx := table.BuiltinChains[hook]; ruleIdx < len(table.Rules); ruleIdx++ { + verdict := it.checkRule(hook, pkt, table, ruleIdx) + switch verdict { + // For 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)) + } + } + + panic(fmt.Sprintf("Traversed past the entire list of iptables rules in table %q.", tablename)) +} + +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/iptables/targets.go b/pkg/tcpip/iptables/targets.go index d65ed8df5..8180dcefd 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{} // Actions 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..9f6906100 100644 --- a/pkg/tcpip/iptables/types.go +++ b/pkg/tcpip/iptables/types.go @@ -14,9 +14,7 @@ package iptables -import ( - "gvisor.dev/gvisor/pkg/tcpip/buffer" -) +import "gvisor.dev/gvisor/pkg/tcpip" // A Hook specifies one of the hooks built into the network stack. // @@ -165,7 +163,7 @@ 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 +171,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) } |