summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/iptables
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/iptables')
-rw-r--r--pkg/tcpip/iptables/BUILD18
-rw-r--r--pkg/tcpip/iptables/iptables.go314
-rw-r--r--pkg/tcpip/iptables/targets.go144
-rw-r--r--pkg/tcpip/iptables/types.go180
4 files changed, 0 insertions, 656 deletions
diff --git a/pkg/tcpip/iptables/BUILD b/pkg/tcpip/iptables/BUILD
deleted file mode 100644
index d1b73cfdf..000000000
--- a/pkg/tcpip/iptables/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-load("//tools:defs.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "iptables",
- srcs = [
- "iptables.go",
- "targets.go",
- "types.go",
- ],
- visibility = ["//visibility:public"],
- deps = [
- "//pkg/log",
- "//pkg/tcpip",
- "//pkg/tcpip/header",
- ],
-)
diff --git a/pkg/tcpip/iptables/iptables.go b/pkg/tcpip/iptables/iptables.go
deleted file mode 100644
index d30571c74..000000000
--- a/pkg/tcpip/iptables/iptables.go
+++ /dev/null
@@ -1,314 +0,0 @@
-// 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.
-// 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 supports packet filtering and manipulation via the iptables
-// tool.
-package iptables
-
-import (
- "fmt"
-
- "gvisor.dev/gvisor/pkg/tcpip"
- "gvisor.dev/gvisor/pkg/tcpip/header"
-)
-
-// Table names.
-const (
- TablenameNat = "nat"
- TablenameMangle = "mangle"
- TablenameFilter = "filter"
-)
-
-// Chain names as defined by net/ipv4/netfilter/ip_tables.c.
-const (
- ChainNamePrerouting = "PREROUTING"
- ChainNameInput = "INPUT"
- ChainNameForward = "FORWARD"
- ChainNameOutput = "OUTPUT"
- ChainNamePostrouting = "POSTROUTING"
-)
-
-// HookUnset indicates that there is no hook set for an entrypoint or
-// underflow.
-const HookUnset = -1
-
-// DefaultTables returns a default set of tables. Each chain is set to accept
-// all packets.
-func DefaultTables() IPTables {
- // TODO(gvisor.dev/issue/170): We may be able to swap out some strings for
- // iotas.
- return IPTables{
- Tables: map[string]Table{
- TablenameNat: Table{
- Rules: []Rule{
- Rule{Target: AcceptTarget{}},
- Rule{Target: AcceptTarget{}},
- Rule{Target: AcceptTarget{}},
- Rule{Target: AcceptTarget{}},
- Rule{Target: ErrorTarget{}},
- },
- BuiltinChains: map[Hook]int{
- Prerouting: 0,
- Input: 1,
- Output: 2,
- Postrouting: 3,
- },
- Underflows: map[Hook]int{
- Prerouting: 0,
- Input: 1,
- Output: 2,
- Postrouting: 3,
- },
- UserChains: map[string]int{},
- },
- TablenameMangle: Table{
- Rules: []Rule{
- Rule{Target: AcceptTarget{}},
- Rule{Target: AcceptTarget{}},
- Rule{Target: ErrorTarget{}},
- },
- BuiltinChains: map[Hook]int{
- Prerouting: 0,
- Output: 1,
- },
- Underflows: map[Hook]int{
- Prerouting: 0,
- Output: 1,
- },
- UserChains: map[string]int{},
- },
- TablenameFilter: Table{
- Rules: []Rule{
- Rule{Target: AcceptTarget{}},
- Rule{Target: AcceptTarget{}},
- Rule{Target: AcceptTarget{}},
- Rule{Target: ErrorTarget{}},
- },
- BuiltinChains: map[Hook]int{
- Input: 0,
- Forward: 1,
- Output: 2,
- },
- Underflows: map[Hook]int{
- Input: 0,
- Forward: 1,
- Output: 2,
- },
- UserChains: map[string]int{},
- },
- },
- Priorities: map[Hook][]string{
- Input: []string{TablenameNat, TablenameFilter},
- Prerouting: []string{TablenameMangle, TablenameNat},
- Output: []string{TablenameMangle, TablenameNat, TablenameFilter},
- },
- }
-}
-
-// EmptyFilterTable returns a Table with no rules and the filter table chains
-// mapped to HookUnset.
-func EmptyFilterTable() Table {
- return Table{
- Rules: []Rule{},
- BuiltinChains: map[Hook]int{
- Input: HookUnset,
- Forward: HookUnset,
- Output: HookUnset,
- },
- Underflows: map[Hook]int{
- Input: HookUnset,
- Forward: HookUnset,
- Output: HookUnset,
- },
- UserChains: map[string]int{},
- }
-}
-
-// EmptyNatTable returns a Table with no rules and the filter table chains
-// mapped to HookUnset.
-func EmptyNatTable() Table {
- return Table{
- Rules: []Rule{},
- BuiltinChains: map[Hook]int{
- Prerouting: HookUnset,
- Input: HookUnset,
- Output: HookUnset,
- Postrouting: HookUnset,
- },
- Underflows: map[Hook]int{
- Prerouting: HookUnset,
- Input: HookUnset,
- Output: HookUnset,
- Postrouting: HookUnset,
- },
- UserChains: map[string]int{},
- }
-}
-
-// A chainVerdict is what a table decides should be done with a packet.
-type chainVerdict int
-
-const (
- // chainAccept indicates the packet should continue through netstack.
- chainAccept chainVerdict = iota
-
- // chainAccept indicates the packet should be dropped.
- chainDrop
-
- // chainReturn indicates the packet should return to the calling chain
- // or the underflow rule of a builtin chain.
- chainReturn
-)
-
-// 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.
-//
-// Precondition: pkt.NetworkHeader is set.
-func (it *IPTables) Check(hook Hook, pkt tcpip.PacketBuffer) bool {
- // Go through each table containing the hook.
- for _, tablename := range it.Priorities[hook] {
- table := it.Tables[tablename]
- ruleIdx := table.BuiltinChains[hook]
- switch verdict := it.checkChain(hook, pkt, table, ruleIdx); verdict {
- // If the table returns Accept, move on to the next table.
- case chainAccept:
- continue
- // The Drop verdict is final.
- case chainDrop:
- return false
- case chainReturn:
- // Any Return from a built-in chain means we have to
- // call the underflow.
- underflow := table.Rules[table.Underflows[hook]]
- switch v, _ := underflow.Target.Action(pkt); v {
- case RuleAccept:
- continue
- case RuleDrop:
- return false
- case RuleJump, RuleReturn:
- panic("Underflows should only return RuleAccept or RuleDrop.")
- default:
- panic(fmt.Sprintf("Unknown verdict: %d", v))
- }
-
- default:
- panic(fmt.Sprintf("Unknown verdict %v.", verdict))
- }
- }
-
- // Every table returned Accept.
- return true
-}
-
-// Precondition: pkt.NetworkHeader is set.
-func (it *IPTables) checkChain(hook Hook, pkt tcpip.PacketBuffer, table Table, ruleIdx int) chainVerdict {
- // Start from ruleIdx and walk the list of rules until a rule gives us
- // a verdict.
- for ruleIdx < len(table.Rules) {
- switch verdict, jumpTo := it.checkRule(hook, pkt, table, ruleIdx); verdict {
- case RuleAccept:
- return chainAccept
-
- case RuleDrop:
- return chainDrop
-
- case RuleReturn:
- return chainReturn
-
- case RuleJump:
- // "Jumping" to the next rule just means we're
- // continuing on down the list.
- if jumpTo == ruleIdx+1 {
- ruleIdx++
- continue
- }
- switch verdict := it.checkChain(hook, pkt, table, jumpTo); verdict {
- case chainAccept:
- return chainAccept
- case chainDrop:
- return chainDrop
- case chainReturn:
- ruleIdx++
- continue
- default:
- panic(fmt.Sprintf("Unknown verdict: %d", verdict))
- }
-
- default:
- panic(fmt.Sprintf("Unknown verdict: %d", verdict))
- }
-
- }
-
- // We got through the entire table without a decision. Default to DROP
- // for safety.
- return chainDrop
-}
-
-// Precondition: pk.NetworkHeader is set.
-func (it *IPTables) checkRule(hook Hook, pkt tcpip.PacketBuffer, table Table, ruleIdx int) (RuleVerdict, int) {
- rule := table.Rules[ruleIdx]
-
- // If pkt.NetworkHeader hasn't been set yet, it will be contained in
- // pkt.Data.First().
- if pkt.NetworkHeader == nil {
- pkt.NetworkHeader = pkt.Data.First()
- }
-
- // Check whether the packet matches the IP header filter.
- if !filterMatch(rule.Filter, header.IPv4(pkt.NetworkHeader)) {
- // Continue on to the next rule.
- return RuleJump, ruleIdx + 1
- }
-
- // 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 RuleDrop, 0
- }
- if !matches {
- // Continue on to the next rule.
- return RuleJump, ruleIdx + 1
- }
- }
-
- // All the matchers matched, so run the target.
- return rule.Target.Action(pkt)
-}
-
-func filterMatch(filter IPHeaderFilter, hdr header.IPv4) bool {
- // TODO(gvisor.dev/issue/170): Support other fields of the filter.
- // Check the transport protocol.
- if filter.Protocol != 0 && filter.Protocol != hdr.TransportProtocol() {
- return false
- }
-
- // Check the destination IP.
- dest := hdr.DestinationAddress()
- matches := true
- for i := range filter.Dst {
- if dest[i]&filter.DstMask[i] != filter.Dst[i] {
- matches = false
- break
- }
- }
- if matches == filter.DstInvert {
- return false
- }
-
- return true
-}
diff --git a/pkg/tcpip/iptables/targets.go b/pkg/tcpip/iptables/targets.go
deleted file mode 100644
index e457f2349..000000000
--- a/pkg/tcpip/iptables/targets.go
+++ /dev/null
@@ -1,144 +0,0 @@
-// 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.
-// 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 (
- "gvisor.dev/gvisor/pkg/log"
- "gvisor.dev/gvisor/pkg/tcpip"
- "gvisor.dev/gvisor/pkg/tcpip/header"
-)
-
-// AcceptTarget accepts packets.
-type AcceptTarget struct{}
-
-// Action implements Target.Action.
-func (AcceptTarget) Action(packet tcpip.PacketBuffer) (RuleVerdict, int) {
- return RuleAccept, 0
-}
-
-// DropTarget drops packets.
-type DropTarget struct{}
-
-// Action implements Target.Action.
-func (DropTarget) Action(packet tcpip.PacketBuffer) (RuleVerdict, int) {
- return RuleDrop, 0
-}
-
-// ErrorTarget logs an error and drops the packet. It represents a target that
-// should be unreachable.
-type ErrorTarget struct{}
-
-// Action implements Target.Action.
-func (ErrorTarget) Action(packet tcpip.PacketBuffer) (RuleVerdict, int) {
- log.Debugf("ErrorTarget triggered.")
- return RuleDrop, 0
-}
-
-// UserChainTarget marks a rule as the beginning of a user chain.
-type UserChainTarget struct {
- Name string
-}
-
-// Action implements Target.Action.
-func (UserChainTarget) Action(tcpip.PacketBuffer) (RuleVerdict, int) {
- panic("UserChainTarget should never be called.")
-}
-
-// ReturnTarget returns from the current chain. If the chain is a built-in, the
-// hook's underflow should be called.
-type ReturnTarget struct{}
-
-// Action implements Target.Action.
-func (ReturnTarget) Action(tcpip.PacketBuffer) (RuleVerdict, int) {
- return RuleReturn, 0
-}
-
-// RedirectTarget redirects the packet by modifying the destination port/IP.
-// Min and Max values for IP and Ports in the struct indicate the range of
-// values which can be used to redirect.
-type RedirectTarget struct {
- // TODO(gvisor.dev/issue/170): Other flags need to be added after
- // we support them.
- // RangeProtoSpecified flag indicates single port is specified to
- // redirect.
- RangeProtoSpecified bool
-
- // Min address used to redirect.
- MinIP tcpip.Address
-
- // Max address used to redirect.
- MaxIP tcpip.Address
-
- // Min port used to redirect.
- MinPort uint16
-
- // Max port used to redirect.
- MaxPort uint16
-}
-
-// Action implements Target.Action.
-// TODO(gvisor.dev/issue/170): Parse headers without copying. The current
-// implementation only works for PREROUTING and calls pkt.Clone(), neither
-// of which should be the case.
-func (rt RedirectTarget) Action(pkt tcpip.PacketBuffer) (RuleVerdict, int) {
- newPkt := pkt.Clone()
-
- // Set network header.
- headerView := newPkt.Data.First()
- netHeader := header.IPv4(headerView)
- newPkt.NetworkHeader = headerView[:header.IPv4MinimumSize]
-
- hlen := int(netHeader.HeaderLength())
- tlen := int(netHeader.TotalLength())
- newPkt.Data.TrimFront(hlen)
- newPkt.Data.CapLength(tlen - hlen)
-
- // TODO(gvisor.dev/issue/170): Change destination address to
- // loopback or interface address on which the packet was
- // received.
-
- // TODO(gvisor.dev/issue/170): Check Flags in RedirectTarget if
- // we need to change dest address (for OUTPUT chain) or ports.
- switch protocol := netHeader.TransportProtocol(); protocol {
- case header.UDPProtocolNumber:
- var udpHeader header.UDP
- if newPkt.TransportHeader != nil {
- udpHeader = header.UDP(newPkt.TransportHeader)
- } else {
- if len(pkt.Data.First()) < header.UDPMinimumSize {
- return RuleDrop, 0
- }
- udpHeader = header.UDP(newPkt.Data.First())
- }
- udpHeader.SetDestinationPort(rt.MinPort)
- case header.TCPProtocolNumber:
- var tcpHeader header.TCP
- if newPkt.TransportHeader != nil {
- tcpHeader = header.TCP(newPkt.TransportHeader)
- } else {
- if len(pkt.Data.First()) < header.TCPMinimumSize {
- return RuleDrop, 0
- }
- tcpHeader = header.TCP(newPkt.TransportHeader)
- }
- // TODO(gvisor.dev/issue/170): Need to recompute checksum
- // and implement nat connection tracking to support TCP.
- tcpHeader.SetDestinationPort(rt.MinPort)
- default:
- return RuleDrop, 0
- }
-
- return RuleAccept, 0
-}
diff --git a/pkg/tcpip/iptables/types.go b/pkg/tcpip/iptables/types.go
deleted file mode 100644
index e7fcf6bff..000000000
--- a/pkg/tcpip/iptables/types.go
+++ /dev/null
@@ -1,180 +0,0 @@
-// 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.
-// 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 (
- "gvisor.dev/gvisor/pkg/tcpip"
-)
-
-// A Hook specifies one of the hooks built into the network stack.
-//
-// Userspace app Userspace app
-// ^ |
-// | v
-// [Input] [Output]
-// ^ |
-// | v
-// | routing
-// | |
-// | v
-// ----->[Prerouting]----->routing----->[Forward]---------[Postrouting]----->
-type Hook uint
-
-// These values correspond to values in include/uapi/linux/netfilter.h.
-const (
- // Prerouting happens before a packet is routed to applications or to
- // be forwarded.
- Prerouting Hook = iota
-
- // Input happens before a packet reaches an application.
- Input
-
- // Forward happens once it's decided that a packet should be forwarded
- // to another host.
- Forward
-
- // Output happens after a packet is written by an application to be
- // sent out.
- Output
-
- // Postrouting happens just before a packet goes out on the wire.
- Postrouting
-
- // The total number of hooks.
- NumHooks
-)
-
-// A RuleVerdict is what a rule decides should be done with a packet.
-type RuleVerdict int
-
-const (
- // RuleAccept indicates the packet should continue through netstack.
- RuleAccept RuleVerdict = iota
-
- // RuleDrop indicates the packet should be dropped.
- RuleDrop
-
- // RuleJump indicates the packet should jump to another chain.
- RuleJump
-
- // RuleReturn indicates the packet should return to the previous chain.
- RuleReturn
-)
-
-// IPTables holds all the tables for a netstack.
-type IPTables struct {
- // Tables maps table names to tables. User tables have arbitrary names.
- Tables map[string]Table
-
- // Priorities maps each hook to a list of table names. The order of the
- // list is the order in which each table should be visited for that
- // hook.
- Priorities map[Hook][]string
-}
-
-// A Table defines a set of chains and hooks into the network stack. It is
-// really just a list of rules with some metadata for entrypoints and such.
-type Table struct {
- // Rules holds the rules that make up the table.
- Rules []Rule
-
- // BuiltinChains maps builtin chains to their entrypoint rule in Rules.
- BuiltinChains map[Hook]int
-
- // Underflows maps builtin chains to their underflow rule in Rules
- // (i.e. the rule to execute if the chain returns without a verdict).
- Underflows map[Hook]int
-
- // UserChains holds user-defined chains for the keyed by name. Users
- // can give their chains arbitrary names.
- UserChains map[string]int
-
- // Metadata holds information about the Table that is useful to users
- // of IPTables, but not to the netstack IPTables code itself.
- metadata interface{}
-}
-
-// ValidHooks returns a bitmap of the builtin hooks for the given table.
-func (table *Table) ValidHooks() uint32 {
- hooks := uint32(0)
- for hook := range table.BuiltinChains {
- hooks |= 1 << hook
- }
- return hooks
-}
-
-// Metadata returns the metadata object stored in table.
-func (table *Table) Metadata() interface{} {
- return table.metadata
-}
-
-// SetMetadata sets the metadata object stored in table.
-func (table *Table) SetMetadata(metadata interface{}) {
- table.metadata = metadata
-}
-
-// A Rule is a packet processing rule. It consists of two pieces. First it
-// contains zero or more matchers, each of which is a specification of which
-// 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
-
- // Target is the action to invoke if all the matchers match the packet.
- Target Target
-}
-
-// IPHeaderFilter holds basic IP filtering data common to every rule.
-type IPHeaderFilter struct {
- // Protocol matches the transport protocol.
- Protocol tcpip.TransportProtocolNumber
-
- // Dst matches the destination IP address.
- Dst tcpip.Address
-
- // DstMask masks bits of the destination IP address when comparing with
- // Dst.
- DstMask tcpip.Address
-
- // DstInvert inverts the meaning of the destination IP check, i.e. when
- // true the filter will match packets that fail the destination
- // comparison.
- DstInvert bool
-}
-
-// A Matcher is the interface for matching packets.
-type Matcher interface {
- // Name returns the name of the Matcher.
- Name() string
-
- // Match returns whether the packet matches and whether the packet
- // should be "hotdropped", i.e. dropped immediately. This is usually
- // used for suspicious packets.
- //
- // Precondition: packet.NetworkHeader is set.
- Match(hook Hook, packet tcpip.PacketBuffer, interfaceName string) (matches bool, hotdrop bool)
-}
-
-// A Target is the interface for taking an action for a packet.
-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 index of the rule to jump to.
- Action(packet tcpip.PacketBuffer) (RuleVerdict, int)
-}