summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/socket/netfilter/netfilter.go14
-rw-r--r--pkg/tcpip/iptables/targets.go55
-rw-r--r--pkg/tcpip/iptables/types.go2
3 files changed, 53 insertions, 18 deletions
diff --git a/pkg/sentry/socket/netfilter/netfilter.go b/pkg/sentry/socket/netfilter/netfilter.go
index f68a2260d..c8a9e67b8 100644
--- a/pkg/sentry/socket/netfilter/netfilter.go
+++ b/pkg/sentry/socket/netfilter/netfilter.go
@@ -292,9 +292,9 @@ func marshalRedirectTarget() []byte {
},
}
copy(target.Target.Name[:], redirectTargetName)
-
+
ret := make([]byte, 0, linux.SizeOfXTRedirectTarget)
- return binary.Marshal(ret, usermem.ByteOrder, target)
+ return binary.Marshal(ret, usermem.ByteOrder, target)
}
func marshalJumpTarget(jt JumpTarget) []byte {
@@ -670,15 +670,21 @@ func parseTarget(filter iptables.IPHeaderFilter, optVal []byte) (iptables.Target
// TODO(gvisor.dev/issue/170): Check if the flags are valid.
// Also check if we need to map ports or IP.
- // For now, redirect target only supports dest port change.
+ // For now, redirect target only supports destination port change.
+ // Port range and IP range are not supported yet.
if nfRange.RangeIPV4.Flags&linux.NF_NAT_RANGE_PROTO_SPECIFIED == 0 {
return nil, fmt.Errorf("netfilter.SetEntries: invalid argument.")
}
- target.Flags = nfRange.RangeIPV4.Flags
+ target.RangeProtoSpecified = true
target.MinIP = tcpip.Address(nfRange.RangeIPV4.MinIP[:])
target.MaxIP = tcpip.Address(nfRange.RangeIPV4.MaxIP[:])
+ // TODO(gvisor.dev/issue/170): Port range is not supported yet.
+ if nfRange.RangeIPV4.MinPort != nfRange.RangeIPV4.MaxPort {
+ return nil, fmt.Errorf("netfilter.SetEntries: invalid argument.")
+ }
+
// Convert port from big endian to little endian.
port := make([]byte, 2)
binary.BigEndian.PutUint16(port, nfRange.RangeIPV4.MinPort)
diff --git a/pkg/tcpip/iptables/targets.go b/pkg/tcpip/iptables/targets.go
index 96318118c..ae5af7c53 100644
--- a/pkg/tcpip/iptables/targets.go
+++ b/pkg/tcpip/iptables/targets.go
@@ -69,8 +69,11 @@ func (ReturnTarget) Action(tcpip.PacketBuffer) (RuleVerdict, int) {
// 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 {
- // Flags to check if the redirect is for address or ports.
- Flags uint32
+ // TODO(gvisor.dev/issue/170): Other flags need to be aded after
+ // we support them.
+ // RangeProtoSpecified flag indicates single port is specified to
+ // redirect.
+ RangeProtoSpecified bool
// Min address used to redirect.
MinIP tcpip.Address
@@ -86,30 +89,56 @@ type RedirectTarget struct {
}
// 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) {
- headerView := pkt.Data.First()
+ newPkt := pkt.Clone()
- // Network header should be set.
+ // Set network header.
+ headerView := newPkt.Data.First()
netHeader := header.IPv4(headerView)
- if netHeader == nil {
- return RuleDrop, 0
- }
+ newPkt.NetworkHeader = headerView[:netHeader.HeaderLength()]
- // TODO(gvisor.dev/issue/170): Check Flags in RedirectTarget if
- // we need to change dest address (for OUTPUT chain) or ports.
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:
- udp := header.UDP(headerView[hlen:])
- udp.SetDestinationPort(rt.MinPort)
+ 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.
- tcp := header.TCP(headerView[hlen:])
- tcp.SetDestinationPort(rt.MinPort)
+ 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
index 9c2ad2d46..7d032fd23 100644
--- a/pkg/tcpip/iptables/types.go
+++ b/pkg/tcpip/iptables/types.go
@@ -163,6 +163,6 @@ type Matcher interface {
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.
+ // Jump, it also returns the index of the rule to jump to.
Action(packet tcpip.PacketBuffer) (RuleVerdict, int)
}