summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip
diff options
context:
space:
mode:
authorKevin Krakauer <krakauer@google.com>2020-01-31 13:46:13 -0800
committerKevin Krakauer <krakauer@google.com>2020-01-31 13:46:13 -0800
commiteba7bdc24d31388ca81eeab251ed2db108f785dc (patch)
tree465da8d7f4a14d35b92cd67b3913084306b4fcb4 /pkg/tcpip
parent2142c70118a6f5ac3ca438a240525af4fa114f7f (diff)
iptables: enable TCP matching with "-m tcp".
A couple other things that changed: - There's a proper extension registration system for matchers. Anyone adding another matcher can use tcp_matcher.go or udp_matcher.go as a template. - All logging and use of syserr.Error in the netfilter package happens at the highest possible level (public functions). Lower-level functions just return normal, descriptive golang errors.
Diffstat (limited to 'pkg/tcpip')
-rw-r--r--pkg/tcpip/iptables/BUILD1
-rw-r--r--pkg/tcpip/iptables/types.go3
-rw-r--r--pkg/tcpip/iptables/udp_matcher.go113
3 files changed, 3 insertions, 114 deletions
diff --git a/pkg/tcpip/iptables/BUILD b/pkg/tcpip/iptables/BUILD
index bab26580b..d1b73cfdf 100644
--- a/pkg/tcpip/iptables/BUILD
+++ b/pkg/tcpip/iptables/BUILD
@@ -8,7 +8,6 @@ go_library(
"iptables.go",
"targets.go",
"types.go",
- "udp_matcher.go",
],
visibility = ["//visibility:public"],
deps = [
diff --git a/pkg/tcpip/iptables/types.go b/pkg/tcpip/iptables/types.go
index 7f77802a0..d660aab04 100644
--- a/pkg/tcpip/iptables/types.go
+++ b/pkg/tcpip/iptables/types.go
@@ -171,6 +171,9 @@ type IPHeaderFilter struct {
// 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.
diff --git a/pkg/tcpip/iptables/udp_matcher.go b/pkg/tcpip/iptables/udp_matcher.go
deleted file mode 100644
index 3bb076f9c..000000000
--- a/pkg/tcpip/iptables/udp_matcher.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2020 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 (
- "fmt"
-
- "gvisor.dev/gvisor/pkg/log"
- "gvisor.dev/gvisor/pkg/tcpip"
- "gvisor.dev/gvisor/pkg/tcpip/header"
-)
-
-// TODO(gvisor.dev/issue/170): The following per-matcher params should be
-// supported:
-// - Table name
-// - Match size
-// - User size
-// - Hooks
-// - Proto
-// - Family
-
-// UDPMatcher matches UDP packets and their headers. It implements Matcher.
-type UDPMatcher struct {
- Data UDPMatcherParams
-}
-
-// UDPMatcherParams are the parameters used to create a UDPMatcher.
-type UDPMatcherParams struct {
- SourcePortStart uint16
- SourcePortEnd uint16
- DestinationPortStart uint16
- DestinationPortEnd uint16
- InverseFlags uint8
-}
-
-// NewUDPMatcher returns a new instance of UDPMatcher.
-func NewUDPMatcher(filter IPHeaderFilter, data UDPMatcherParams) (Matcher, error) {
- log.Infof("Adding rule with UDPMatcherParams: %+v", data)
-
- if data.InverseFlags != 0 {
- return nil, fmt.Errorf("unsupported UDP matcher inverse flags set")
- }
-
- if filter.Protocol != header.UDPProtocolNumber {
- return nil, fmt.Errorf("UDP matching is only valid for protocol %d.", header.UDPProtocolNumber)
- }
-
- return &UDPMatcher{Data: data}, nil
-}
-
-// Match implements Matcher.Match.
-func (um *UDPMatcher) Match(hook Hook, pkt tcpip.PacketBuffer, interfaceName string) (bool, bool) {
- netHeader := header.IPv4(pkt.NetworkHeader)
-
- // TODO(gvisor.dev/issue/170): Proto checks should ultimately be moved
- // into the iptables.Check codepath as matchers are added.
- if netHeader.TransportProtocol() != header.UDPProtocolNumber {
- return false, false
- }
-
- // We dont't match fragments.
- if frag := netHeader.FragmentOffset(); frag != 0 {
- if frag == 1 {
- log.Warningf("Dropping UDP packet: malicious fragmented packet.")
- return false, true
- }
- return false, false
- }
-
- // Now we need the transport header. However, this may not have been set
- // yet.
- // TODO(gvisor.dev/issue/170): Parsing the transport header should
- // ultimately be moved into the iptables.Check codepath as matchers are
- // added.
- var udpHeader header.UDP
- if pkt.TransportHeader != nil {
- udpHeader = header.UDP(pkt.TransportHeader)
- } else {
- // The UDP header hasn't been parsed yet. We have to do it here.
- if len(pkt.Data.First()) < header.UDPMinimumSize {
- // There's no valid UDP header here, so we hotdrop the
- // packet.
- log.Warningf("Dropping UDP packet: size too small.")
- return false, true
- }
- udpHeader = header.UDP(pkt.Data.First())
- }
-
- // Check whether the source and destination ports are within the
- // matching range.
- sourcePort := udpHeader.SourcePort()
- destinationPort := udpHeader.DestinationPort()
- if sourcePort < um.Data.SourcePortStart || um.Data.SourcePortEnd < sourcePort {
- return false, false
- }
- if destinationPort < um.Data.DestinationPortStart || um.Data.DestinationPortEnd < destinationPort {
- return false, false
- }
-
- return true, false
-}