summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry
diff options
context:
space:
mode:
authorNayana Bidari <nybidari@google.com>2020-03-27 12:18:45 -0700
committerNayana Bidari <nybidari@google.com>2020-05-01 16:59:40 -0700
commitb660f16d18827f0310594c80d9387de11430f15f (patch)
treee645837d657b8e5feefa655840a969f4f3d87314 /pkg/sentry
parent40d6aae1220292985a85ee03248ad5781edb4c80 (diff)
Support for connection tracking of TCP packets.
Connection tracking is used to track packets in prerouting and output hooks of iptables. The NAT rules modify the tuples in connections. The connection tracking code modifies the packets by looking at the modified tuples.
Diffstat (limited to 'pkg/sentry')
-rw-r--r--pkg/sentry/socket/netfilter/netfilter.go14
-rw-r--r--pkg/sentry/socket/netfilter/targets.go3
-rw-r--r--pkg/sentry/socket/netfilter/tcp_matcher.go17
-rw-r--r--pkg/sentry/socket/netfilter/udp_matcher.go17
4 files changed, 44 insertions, 7 deletions
diff --git a/pkg/sentry/socket/netfilter/netfilter.go b/pkg/sentry/socket/netfilter/netfilter.go
index 72d093aa8..40736fb38 100644
--- a/pkg/sentry/socket/netfilter/netfilter.go
+++ b/pkg/sentry/socket/netfilter/netfilter.go
@@ -251,7 +251,7 @@ func marshalTarget(target stack.Target) []byte {
case stack.ReturnTarget:
return marshalStandardTarget(stack.RuleReturn)
case stack.RedirectTarget:
- return marshalRedirectTarget()
+ return marshalRedirectTarget(tg)
case JumpTarget:
return marshalJumpTarget(tg)
default:
@@ -288,7 +288,7 @@ func marshalErrorTarget(errorName string) []byte {
return binary.Marshal(ret, usermem.ByteOrder, target)
}
-func marshalRedirectTarget() []byte {
+func marshalRedirectTarget(rt stack.RedirectTarget) []byte {
// This is a redirect target named redirect
target := linux.XTRedirectTarget{
Target: linux.XTEntryTarget{
@@ -298,6 +298,16 @@ func marshalRedirectTarget() []byte {
copy(target.Target.Name[:], redirectTargetName)
ret := make([]byte, 0, linux.SizeOfXTRedirectTarget)
+ target.NfRange.RangeSize = 1
+ if rt.RangeProtoSpecified {
+ target.NfRange.RangeIPV4.Flags |= linux.NF_NAT_RANGE_PROTO_SPECIFIED
+ }
+ // Convert port from little endian to big endian.
+ port := make([]byte, 2)
+ binary.LittleEndian.PutUint16(port, rt.MinPort)
+ target.NfRange.RangeIPV4.MinPort = binary.BigEndian.Uint16(port)
+ binary.LittleEndian.PutUint16(port, rt.MaxPort)
+ target.NfRange.RangeIPV4.MaxPort = binary.BigEndian.Uint16(port)
return binary.Marshal(ret, usermem.ByteOrder, target)
}
diff --git a/pkg/sentry/socket/netfilter/targets.go b/pkg/sentry/socket/netfilter/targets.go
index c948de876..84abe8d29 100644
--- a/pkg/sentry/socket/netfilter/targets.go
+++ b/pkg/sentry/socket/netfilter/targets.go
@@ -15,6 +15,7 @@
package netfilter
import (
+ "gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -29,6 +30,6 @@ type JumpTarget struct {
}
// Action implements stack.Target.Action.
-func (jt JumpTarget) Action(stack.PacketBuffer) (stack.RuleVerdict, int) {
+func (jt JumpTarget) Action(*stack.PacketBuffer, *stack.ConnTrackTable, stack.Hook, *stack.GSO, *stack.Route, tcpip.Address) (stack.RuleVerdict, int) {
return stack.RuleJump, jt.RuleNum
}
diff --git a/pkg/sentry/socket/netfilter/tcp_matcher.go b/pkg/sentry/socket/netfilter/tcp_matcher.go
index 55c0f04f3..57a1e1c12 100644
--- a/pkg/sentry/socket/netfilter/tcp_matcher.go
+++ b/pkg/sentry/socket/netfilter/tcp_matcher.go
@@ -120,14 +120,27 @@ func (tm *TCPMatcher) Match(hook stack.Hook, pkt stack.PacketBuffer, interfaceNa
if pkt.TransportHeader != nil {
tcpHeader = header.TCP(pkt.TransportHeader)
} else {
+ var length int
+ if hook == stack.Prerouting {
+ // The network header hasn't been parsed yet. We have to do it here.
+ hdr, ok := pkt.Data.PullUp(header.IPv4MinimumSize)
+ if !ok {
+ // There's no valid TCP header here, so we hotdrop the
+ // packet.
+ return false, true
+ }
+ h := header.IPv4(hdr)
+ pkt.NetworkHeader = hdr
+ length = int(h.HeaderLength())
+ }
// The TCP header hasn't been parsed yet. We have to do it here.
- hdr, ok := pkt.Data.PullUp(header.TCPMinimumSize)
+ hdr, ok := pkt.Data.PullUp(length + header.TCPMinimumSize)
if !ok {
// There's no valid TCP header here, so we hotdrop the
// packet.
return false, true
}
- tcpHeader = header.TCP(hdr)
+ tcpHeader = header.TCP(hdr[length:])
}
// Check whether the source and destination ports are within the
diff --git a/pkg/sentry/socket/netfilter/udp_matcher.go b/pkg/sentry/socket/netfilter/udp_matcher.go
index 04d03d494..cfa9e621d 100644
--- a/pkg/sentry/socket/netfilter/udp_matcher.go
+++ b/pkg/sentry/socket/netfilter/udp_matcher.go
@@ -119,14 +119,27 @@ func (um *UDPMatcher) Match(hook stack.Hook, pkt stack.PacketBuffer, interfaceNa
if pkt.TransportHeader != nil {
udpHeader = header.UDP(pkt.TransportHeader)
} else {
+ var length int
+ if hook == stack.Prerouting {
+ // The network header hasn't been parsed yet. We have to do it here.
+ hdr, ok := pkt.Data.PullUp(header.IPv4MinimumSize)
+ if !ok {
+ // There's no valid UDP header here, so we hotdrop the
+ // packet.
+ return false, true
+ }
+ h := header.IPv4(hdr)
+ pkt.NetworkHeader = hdr
+ length = int(h.HeaderLength())
+ }
// The UDP header hasn't been parsed yet. We have to do it here.
- hdr, ok := pkt.Data.PullUp(header.UDPMinimumSize)
+ hdr, ok := pkt.Data.PullUp(length + header.UDPMinimumSize)
if !ok {
// There's no valid UDP header here, so we hotdrop the
// packet.
return false, true
}
- udpHeader = header.UDP(hdr)
+ udpHeader = header.UDP(hdr[length:])
}
// Check whether the source and destination ports are within the