summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip
diff options
context:
space:
mode:
authorNayana Bidari <nybidari@google.com>2020-02-25 15:03:51 -0800
committerNayana Bidari <nybidari@google.com>2020-02-25 15:03:51 -0800
commitacc405ba60834f5dce9ce04cd762d5cda02224cb (patch)
tree6571786bd38f1a5755a09dc717e9b0012d5c7d7a /pkg/tcpip
parentb30b7f3422202232ad1c385a7ac0d775151fee2f (diff)
Add nat table support for iptables.
- commit the changes for the comments.
Diffstat (limited to 'pkg/tcpip')
-rw-r--r--pkg/tcpip/iptables/iptables.go10
-rw-r--r--pkg/tcpip/iptables/targets.go66
-rw-r--r--pkg/tcpip/iptables/types.go4
-rw-r--r--pkg/tcpip/stack/nic.go13
4 files changed, 57 insertions, 36 deletions
diff --git a/pkg/tcpip/iptables/iptables.go b/pkg/tcpip/iptables/iptables.go
index c00d012c0..f7dc4f720 100644
--- a/pkg/tcpip/iptables/iptables.go
+++ b/pkg/tcpip/iptables/iptables.go
@@ -207,7 +207,7 @@ func (it *IPTables) checkTable(hook Hook, pkt tcpip.PacketBuffer, tablename stri
underflow := table.Rules[table.Underflows[hook]]
// Underflow is guaranteed to be an unconditional
// ACCEPT or DROP.
- switch v, _ := underflow.Target.Action(pkt); v {
+ switch v, _ := underflow.Target.Action(pkt, underflow.Filter); v {
case RuleAccept:
return TableAccept
case RuleDrop:
@@ -233,6 +233,12 @@ func (it *IPTables) checkTable(hook Hook, pkt tcpip.PacketBuffer, tablename stri
func (it *IPTables) checkRule(hook Hook, pkt tcpip.PacketBuffer, table Table, ruleIdx int) RuleVerdict {
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()
+ }
+
// First check whether the packet matches the IP header filter.
// TODO(gvisor.dev/issue/170): Support other fields of the filter.
if rule.Filter.Protocol != 0 && rule.Filter.Protocol != header.IPv4(pkt.NetworkHeader).TransportProtocol() {
@@ -252,6 +258,6 @@ func (it *IPTables) checkRule(hook Hook, pkt tcpip.PacketBuffer, table Table, ru
}
// All the matchers matched, so run the target.
- verdict, _ := rule.Target.Action(pkt)
+ verdict, _ := rule.Target.Action(pkt, rule.Filter)
return verdict
}
diff --git a/pkg/tcpip/iptables/targets.go b/pkg/tcpip/iptables/targets.go
index 06e65bece..a75938da3 100644
--- a/pkg/tcpip/iptables/targets.go
+++ b/pkg/tcpip/iptables/targets.go
@@ -26,7 +26,7 @@ import (
type AcceptTarget struct{}
// Action implements Target.Action.
-func (AcceptTarget) Action(packet tcpip.PacketBuffer) (RuleVerdict, string) {
+func (AcceptTarget) Action(packet tcpip.PacketBuffer, filter IPHeaderFilter) (RuleVerdict, string) {
return RuleAccept, ""
}
@@ -34,7 +34,7 @@ func (AcceptTarget) Action(packet tcpip.PacketBuffer) (RuleVerdict, string) {
type DropTarget struct{}
// Action implements Target.Action.
-func (DropTarget) Action(packet tcpip.PacketBuffer) (RuleVerdict, string) {
+func (DropTarget) Action(packet tcpip.PacketBuffer, filter IPHeaderFilter) (RuleVerdict, string) {
return RuleDrop, ""
}
@@ -43,7 +43,7 @@ func (DropTarget) Action(packet tcpip.PacketBuffer) (RuleVerdict, string) {
type ErrorTarget struct{}
// Action implements Target.Action.
-func (ErrorTarget) Action(packet tcpip.PacketBuffer) (RuleVerdict, string) {
+func (ErrorTarget) Action(packet tcpip.PacketBuffer, filter IPHeaderFilter) (RuleVerdict, string) {
log.Debugf("ErrorTarget triggered.")
return RuleDrop, ""
}
@@ -54,7 +54,7 @@ type UserChainTarget struct {
}
// Action implements Target.Action.
-func (UserChainTarget) Action(tcpip.PacketBuffer) (RuleVerdict, string) {
+func (UserChainTarget) Action(tcpip.PacketBuffer, IPHeaderFilter) (RuleVerdict, string) {
panic("UserChainTarget should never be called.")
}
@@ -63,29 +63,55 @@ func (UserChainTarget) Action(tcpip.PacketBuffer) (RuleVerdict, string) {
type ReturnTarget struct{}
// Action implements Target.Action.
-func (ReturnTarget) Action(tcpip.PacketBuffer) (RuleVerdict, string) {
+func (ReturnTarget) Action(tcpip.PacketBuffer, IPHeaderFilter) (RuleVerdict, string) {
return RuleReturn, ""
}
// 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 {
- RangeSize uint32
- Flags uint32
- MinIP tcpip.Address
- MaxIP tcpip.Address
- MinPort uint16
- MaxPort uint16
-}
+ // Flags to check if the redirect is for address or ports.
+ Flags uint32
-// Action implements Target.Action.
-func (rt RedirectTarget) Action(packet tcpip.PacketBuffer) (RuleVerdict, string) {
- log.Infof("RedirectTarget triggered.")
+ // Min address used to redirect.
+ MinIP tcpip.Address
+
+ // Max address used to redirect.
+ MaxIP tcpip.Address
- // TODO(gvisor.dev/issue/170): Checking only for UDP protocol.
- // We're yet to support for TCP protocol.
- headerView := packet.Data.First()
- h := header.UDP(headerView)
- h.SetDestinationPort(rt.MinPort)
+ // Min port used to redirect.
+ MinPort uint16
+ // Max port used to redirect.
+ MaxPort uint16
+}
+
+// Action implements Target.Action.
+func (rt RedirectTarget) Action(pkt tcpip.PacketBuffer, filter IPHeaderFilter) (RuleVerdict, string) {
+ headerView := pkt.Data.First()
+
+ // Network header should be set.
+ netHeader := header.IPv4(headerView)
+ if netHeader == nil {
+ return RuleDrop, ""
+ }
+
+ // 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())
+
+ switch protocol := filter.Protocol; protocol {
+ case header.UDPProtocolNumber:
+ udp := header.UDP(headerView[hlen:])
+ udp.SetDestinationPort(rt.MinPort)
+ case header.TCPProtocolNumber:
+ // 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)
+ default:
+ return RuleDrop, ""
+ }
return RuleAccept, ""
}
diff --git a/pkg/tcpip/iptables/types.go b/pkg/tcpip/iptables/types.go
index 5735d001b..0102831d0 100644
--- a/pkg/tcpip/iptables/types.go
+++ b/pkg/tcpip/iptables/types.go
@@ -63,7 +63,7 @@ const (
// TableAccept indicates the packet should continue through netstack.
TableAccept TableVerdict = iota
- // TableAccept indicates the packet should be dropped.
+ // TableDrop indicates the packet should be dropped.
TableDrop
)
@@ -175,5 +175,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 tcpip.PacketBuffer) (RuleVerdict, string)
+ Action(packet tcpip.PacketBuffer, filter IPHeaderFilter) (RuleVerdict, string)
}
diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go
index 2028f5201..a75dc0322 100644
--- a/pkg/tcpip/stack/nic.go
+++ b/pkg/tcpip/stack/nic.go
@@ -1087,19 +1087,8 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remote, local tcpip.Link
// TODO(gvisor.dev/issue/170): Not supporting iptables for IPv6 yet.
if protocol == header.IPv4ProtocolNumber {
- newPkt := pkt.Clone()
-
- headerView := newPkt.Data.First()
- h := header.IPv4(headerView)
- newPkt.NetworkHeader = headerView[:h.HeaderLength()]
-
- hlen := int(h.HeaderLength())
- tlen := int(h.TotalLength())
- newPkt.Data.TrimFront(hlen)
- newPkt.Data.CapLength(tlen - hlen)
-
ipt := n.stack.IPTables()
- if ok := ipt.Check(iptables.Prerouting, newPkt); !ok {
+ if ok := ipt.Check(iptables.Prerouting, pkt); !ok {
// iptables is telling us to drop the packet.
return
}