summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/stack/iptables_targets.go
diff options
context:
space:
mode:
authorGhanan Gowripalan <ghanan@google.com>2021-10-11 21:34:07 -0700
committergVisor bot <gvisor-bot@google.com>2021-10-11 21:36:35 -0700
commitab1ef0baba1d15c4d4e7717d23cf8b32fd6b5feb (patch)
treed5e57be6e49190e8c2e3ca8812055fc25844271a /pkg/tcpip/stack/iptables_targets.go
parentb9176535cea01e35f819edf312d0f5e7da3e8ffd (diff)
Support DNAT target
PiperOrigin-RevId: 402468096
Diffstat (limited to 'pkg/tcpip/stack/iptables_targets.go')
-rw-r--r--pkg/tcpip/stack/iptables_targets.go74
1 files changed, 51 insertions, 23 deletions
diff --git a/pkg/tcpip/stack/iptables_targets.go b/pkg/tcpip/stack/iptables_targets.go
index 7e5a1672a..85490e2d4 100644
--- a/pkg/tcpip/stack/iptables_targets.go
+++ b/pkg/tcpip/stack/iptables_targets.go
@@ -83,6 +83,45 @@ func (*ReturnTarget) Action(*PacketBuffer, Hook, *Route, AddressableEndpoint) (R
return RuleReturn, 0
}
+// DNATTarget modifies the destination port/IP of packets.
+type DNATTarget struct {
+ // The new destination address for packets.
+ //
+ // Immutable.
+ Addr tcpip.Address
+
+ // The new destination port for packets.
+ //
+ // Immutable.
+ Port uint16
+
+ // NetworkProtocol is the network protocol the target is used with.
+ //
+ // Immutable.
+ NetworkProtocol tcpip.NetworkProtocolNumber
+}
+
+// Action implements Target.Action.
+func (rt *DNATTarget) Action(pkt *PacketBuffer, hook Hook, r *Route, addressEP AddressableEndpoint) (RuleVerdict, int) {
+ // Sanity check.
+ if rt.NetworkProtocol != pkt.NetworkProtocolNumber {
+ panic(fmt.Sprintf(
+ "DNATTarget.Action with NetworkProtocol %d called on packet with NetworkProtocolNumber %d",
+ rt.NetworkProtocol, pkt.NetworkProtocolNumber))
+ }
+
+ switch hook {
+ case Prerouting, Output:
+ case Input, Forward, Postrouting:
+ panic(fmt.Sprintf("%s not supported for DNAT", hook))
+ default:
+ panic(fmt.Sprintf("%s unrecognized", hook))
+ }
+
+ return natAction(pkt, hook, r, rt.Port, rt.Addr, true /* dnat */)
+
+}
+
// RedirectTarget redirects the packet to this machine by modifying the
// destination port/IP. Outgoing packets are redirected to the loopback device,
// and incoming packets are redirected to the incoming interface (rather than
@@ -105,16 +144,6 @@ func (rt *RedirectTarget) Action(pkt *PacketBuffer, hook Hook, r *Route, address
rt.NetworkProtocol, pkt.NetworkProtocolNumber))
}
- // Packet is already manipulated.
- if pkt.NatDone {
- return RuleAccept, 0
- }
-
- // Drop the packet if network and transport header are not set.
- if pkt.NetworkHeader().View().IsEmpty() || pkt.TransportHeader().View().IsEmpty() {
- return RuleDrop, 0
- }
-
// Change the address to loopback (127.0.0.1 or ::1) in Output and to
// the primary address of the incoming interface in Prerouting.
var address tcpip.Address
@@ -132,12 +161,7 @@ func (rt *RedirectTarget) Action(pkt *PacketBuffer, hook Hook, r *Route, address
panic("redirect target is supported only on output and prerouting hooks")
}
- if t := pkt.tuple; t != nil {
- t.conn.performNAT(pkt, hook, r, rt.Port, address, true /* dnat */)
- return RuleAccept, 0
- }
-
- return RuleDrop, 0
+ return natAction(pkt, hook, r, rt.Port, address, true /* dnat */)
}
// SNATTarget modifies the source port/IP in the outgoing packets.
@@ -150,7 +174,7 @@ type SNATTarget struct {
NetworkProtocol tcpip.NetworkProtocolNumber
}
-func snatAction(pkt *PacketBuffer, hook Hook, r *Route, port uint16, address tcpip.Address) (RuleVerdict, int) {
+func natAction(pkt *PacketBuffer, hook Hook, r *Route, port uint16, address tcpip.Address, dnat bool) (RuleVerdict, int) {
// Packet is already manipulated.
if pkt.NatDone {
return RuleAccept, 0
@@ -161,6 +185,11 @@ func snatAction(pkt *PacketBuffer, hook Hook, r *Route, port uint16, address tcp
return RuleDrop, 0
}
+ t := pkt.tuple
+ if t == nil {
+ return RuleDrop, 0
+ }
+
// TODO(https://gvisor.dev/issue/5773): If the port is in use, pick a
// different port.
if port == 0 {
@@ -169,13 +198,12 @@ func snatAction(pkt *PacketBuffer, hook Hook, r *Route, port uint16, address tcp
port = header.UDP(pkt.TransportHeader().View()).SourcePort()
case header.TCPProtocolNumber:
port = header.TCP(pkt.TransportHeader().View()).SourcePort()
+ default:
+ panic(fmt.Sprintf("unsupported transport protocol = %d", pkt.TransportProtocolNumber))
}
}
- if t := pkt.tuple; t != nil {
- t.conn.performNAT(pkt, hook, r, port, address, false /* dnat */)
- }
-
+ t.conn.performNAT(pkt, hook, r, port, address, dnat)
return RuleAccept, 0
}
@@ -196,7 +224,7 @@ func (st *SNATTarget) Action(pkt *PacketBuffer, hook Hook, r *Route, _ Addressab
panic(fmt.Sprintf("%s unrecognized", hook))
}
- return snatAction(pkt, hook, r, st.Port, st.Addr)
+ return natAction(pkt, hook, r, st.Port, st.Addr, false /* dnat */)
}
// MasqueradeTarget modifies the source port/IP in the outgoing packets.
@@ -232,7 +260,7 @@ func (mt *MasqueradeTarget) Action(pkt *PacketBuffer, hook Hook, r *Route, addre
address := ep.AddressWithPrefix().Address
ep.DecRef()
- return snatAction(pkt, hook, r, 0 /* port */, address)
+ return natAction(pkt, hook, r, 0 /* port */, address, false /* dnat */)
}
func rewritePacket(n header.Network, t header.ChecksummableTransport, updateSRCFields, fullChecksum, updatePseudoHeader bool, newPort uint16, newAddr tcpip.Address) {