inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/tcpip/stack/iptables_targets.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package stack 16 17 import ( 18 "fmt" 19 "math" 20 21 "inet.af/netstack/log" 22 "inet.af/netstack/tcpip" 23 "inet.af/netstack/tcpip/header" 24 ) 25 26 // AcceptTarget accepts packets. 27 type AcceptTarget struct { 28 // NetworkProtocol is the network protocol the target is used with. 29 NetworkProtocol tcpip.NetworkProtocolNumber 30 } 31 32 // Action implements Target.Action. 33 func (*AcceptTarget) Action(*PacketBuffer, Hook, *Route, AddressableEndpoint) (RuleVerdict, int) { 34 return RuleAccept, 0 35 } 36 37 // DropTarget drops packets. 38 type DropTarget struct { 39 // NetworkProtocol is the network protocol the target is used with. 40 NetworkProtocol tcpip.NetworkProtocolNumber 41 } 42 43 // Action implements Target.Action. 44 func (*DropTarget) Action(*PacketBuffer, Hook, *Route, AddressableEndpoint) (RuleVerdict, int) { 45 return RuleDrop, 0 46 } 47 48 // ErrorTarget logs an error and drops the packet. It represents a target that 49 // should be unreachable. 50 type ErrorTarget struct { 51 // NetworkProtocol is the network protocol the target is used with. 52 NetworkProtocol tcpip.NetworkProtocolNumber 53 } 54 55 // Action implements Target.Action. 56 func (*ErrorTarget) Action(*PacketBuffer, Hook, *Route, AddressableEndpoint) (RuleVerdict, int) { 57 log.Debugf("ErrorTarget triggered.") 58 return RuleDrop, 0 59 } 60 61 // UserChainTarget marks a rule as the beginning of a user chain. 62 type UserChainTarget struct { 63 // Name is the chain name. 64 Name string 65 66 // NetworkProtocol is the network protocol the target is used with. 67 NetworkProtocol tcpip.NetworkProtocolNumber 68 } 69 70 // Action implements Target.Action. 71 func (*UserChainTarget) Action(*PacketBuffer, Hook, *Route, AddressableEndpoint) (RuleVerdict, int) { 72 panic("UserChainTarget should never be called.") 73 } 74 75 // ReturnTarget returns from the current chain. If the chain is a built-in, the 76 // hook's underflow should be called. 77 type ReturnTarget struct { 78 // NetworkProtocol is the network protocol the target is used with. 79 NetworkProtocol tcpip.NetworkProtocolNumber 80 } 81 82 // Action implements Target.Action. 83 func (*ReturnTarget) Action(*PacketBuffer, Hook, *Route, AddressableEndpoint) (RuleVerdict, int) { 84 return RuleReturn, 0 85 } 86 87 // DNATTarget modifies the destination port/IP of packets. 88 type DNATTarget struct { 89 // The new destination address for packets. 90 // 91 // Immutable. 92 Addr tcpip.Address 93 94 // The new destination port for packets. 95 // 96 // Immutable. 97 Port uint16 98 99 // NetworkProtocol is the network protocol the target is used with. 100 // 101 // Immutable. 102 NetworkProtocol tcpip.NetworkProtocolNumber 103 } 104 105 // Action implements Target.Action. 106 func (rt *DNATTarget) Action(pkt *PacketBuffer, hook Hook, r *Route, addressEP AddressableEndpoint) (RuleVerdict, int) { 107 // Sanity check. 108 if rt.NetworkProtocol != pkt.NetworkProtocolNumber { 109 panic(fmt.Sprintf( 110 "DNATTarget.Action with NetworkProtocol %d called on packet with NetworkProtocolNumber %d", 111 rt.NetworkProtocol, pkt.NetworkProtocolNumber)) 112 } 113 114 switch hook { 115 case Prerouting, Output: 116 case Input, Forward, Postrouting: 117 panic(fmt.Sprintf("%s not supported for DNAT", hook)) 118 default: 119 panic(fmt.Sprintf("%s unrecognized", hook)) 120 } 121 122 return dnatAction(pkt, hook, r, rt.Port, rt.Addr) 123 124 } 125 126 // RedirectTarget redirects the packet to this machine by modifying the 127 // destination port/IP. Outgoing packets are redirected to the loopback device, 128 // and incoming packets are redirected to the incoming interface (rather than 129 // forwarded). 130 type RedirectTarget struct { 131 // Port indicates port used to redirect. It is immutable. 132 Port uint16 133 134 // NetworkProtocol is the network protocol the target is used with. It 135 // is immutable. 136 NetworkProtocol tcpip.NetworkProtocolNumber 137 } 138 139 // Action implements Target.Action. 140 func (rt *RedirectTarget) Action(pkt *PacketBuffer, hook Hook, r *Route, addressEP AddressableEndpoint) (RuleVerdict, int) { 141 // Sanity check. 142 if rt.NetworkProtocol != pkt.NetworkProtocolNumber { 143 panic(fmt.Sprintf( 144 "RedirectTarget.Action with NetworkProtocol %d called on packet with NetworkProtocolNumber %d", 145 rt.NetworkProtocol, pkt.NetworkProtocolNumber)) 146 } 147 148 // Change the address to loopback (127.0.0.1 or ::1) in Output and to 149 // the primary address of the incoming interface in Prerouting. 150 var address tcpip.Address 151 switch hook { 152 case Output: 153 if pkt.NetworkProtocolNumber == header.IPv4ProtocolNumber { 154 address = tcpip.Address([]byte{127, 0, 0, 1}) 155 } else { 156 address = header.IPv6Loopback 157 } 158 case Prerouting: 159 // addressEP is expected to be set for the prerouting hook. 160 address = addressEP.MainAddress().Address 161 default: 162 panic("redirect target is supported only on output and prerouting hooks") 163 } 164 165 return dnatAction(pkt, hook, r, rt.Port, address) 166 } 167 168 // SNATTarget modifies the source port/IP in the outgoing packets. 169 type SNATTarget struct { 170 Addr tcpip.Address 171 Port uint16 172 173 // NetworkProtocol is the network protocol the target is used with. It 174 // is immutable. 175 NetworkProtocol tcpip.NetworkProtocolNumber 176 } 177 178 func dnatAction(pkt *PacketBuffer, hook Hook, r *Route, port uint16, address tcpip.Address) (RuleVerdict, int) { 179 return natAction(pkt, hook, r, portRange{start: port, size: 1}, address, true /* dnat */) 180 } 181 182 func snatAction(pkt *PacketBuffer, hook Hook, r *Route, port uint16, address tcpip.Address) (RuleVerdict, int) { 183 ports := portRange{start: port, size: 1} 184 if port == 0 { 185 // As per iptables(8), 186 // 187 // If no port range is specified, then source ports below 512 will be 188 // mapped to other ports below 512: those between 512 and 1023 inclusive 189 // will be mapped to ports below 1024, and other ports will be mapped to 190 // 1024 or above. 191 switch protocol := pkt.TransportProtocolNumber; protocol { 192 case header.UDPProtocolNumber: 193 port = header.UDP(pkt.TransportHeader().View()).SourcePort() 194 case header.TCPProtocolNumber: 195 port = header.TCP(pkt.TransportHeader().View()).SourcePort() 196 default: 197 panic(fmt.Sprintf("unsupported transport protocol = %d", pkt.TransportProtocolNumber)) 198 } 199 200 switch { 201 case port < 512: 202 ports = portRange{start: 1, size: 511} 203 case port < 1024: 204 ports = portRange{start: 1, size: 1023} 205 default: 206 ports = portRange{start: 1024, size: math.MaxUint16 - 1023} 207 } 208 } 209 210 return natAction(pkt, hook, r, ports, address, false /* dnat */) 211 } 212 213 func natAction(pkt *PacketBuffer, hook Hook, r *Route, ports portRange, address tcpip.Address, dnat bool) (RuleVerdict, int) { 214 // Drop the packet if network and transport header are not set. 215 if pkt.NetworkHeader().View().IsEmpty() || pkt.TransportHeader().View().IsEmpty() { 216 return RuleDrop, 0 217 } 218 219 if t := pkt.tuple; t != nil { 220 t.conn.performNAT(pkt, hook, r, ports, address, dnat) 221 return RuleAccept, 0 222 } 223 224 return RuleDrop, 0 225 } 226 227 // Action implements Target.Action. 228 func (st *SNATTarget) Action(pkt *PacketBuffer, hook Hook, r *Route, _ AddressableEndpoint) (RuleVerdict, int) { 229 // Sanity check. 230 if st.NetworkProtocol != pkt.NetworkProtocolNumber { 231 panic(fmt.Sprintf( 232 "SNATTarget.Action with NetworkProtocol %d called on packet with NetworkProtocolNumber %d", 233 st.NetworkProtocol, pkt.NetworkProtocolNumber)) 234 } 235 236 switch hook { 237 case Postrouting, Input: 238 case Prerouting, Output, Forward: 239 panic(fmt.Sprintf("%s not supported", hook)) 240 default: 241 panic(fmt.Sprintf("%s unrecognized", hook)) 242 } 243 244 return snatAction(pkt, hook, r, st.Port, st.Addr) 245 } 246 247 // MasqueradeTarget modifies the source port/IP in the outgoing packets. 248 type MasqueradeTarget struct { 249 // NetworkProtocol is the network protocol the target is used with. It 250 // is immutable. 251 NetworkProtocol tcpip.NetworkProtocolNumber 252 } 253 254 // Action implements Target.Action. 255 func (mt *MasqueradeTarget) Action(pkt *PacketBuffer, hook Hook, r *Route, addressEP AddressableEndpoint) (RuleVerdict, int) { 256 // Sanity check. 257 if mt.NetworkProtocol != pkt.NetworkProtocolNumber { 258 panic(fmt.Sprintf( 259 "MasqueradeTarget.Action with NetworkProtocol %d called on packet with NetworkProtocolNumber %d", 260 mt.NetworkProtocol, pkt.NetworkProtocolNumber)) 261 } 262 263 switch hook { 264 case Postrouting: 265 case Prerouting, Input, Forward, Output: 266 panic(fmt.Sprintf("masquerade target is supported only on postrouting hook; hook = %d", hook)) 267 default: 268 panic(fmt.Sprintf("%s unrecognized", hook)) 269 } 270 271 // addressEP is expected to be set for the postrouting hook. 272 ep := addressEP.AcquireOutgoingPrimaryAddress(pkt.Network().DestinationAddress(), false /* allowExpired */) 273 if ep == nil { 274 // No address exists that we can use as a source address. 275 return RuleDrop, 0 276 } 277 278 address := ep.AddressWithPrefix().Address 279 ep.DecRef() 280 return snatAction(pkt, hook, r, 0 /* port */, address) 281 } 282 283 func rewritePacket(n header.Network, t header.ChecksummableTransport, updateSRCFields, fullChecksum, updatePseudoHeader bool, newPort uint16, newAddr tcpip.Address) { 284 if updateSRCFields { 285 if fullChecksum { 286 t.SetSourcePortWithChecksumUpdate(newPort) 287 } else { 288 t.SetSourcePort(newPort) 289 } 290 } else { 291 if fullChecksum { 292 t.SetDestinationPortWithChecksumUpdate(newPort) 293 } else { 294 t.SetDestinationPort(newPort) 295 } 296 } 297 298 if updatePseudoHeader { 299 var oldAddr tcpip.Address 300 if updateSRCFields { 301 oldAddr = n.SourceAddress() 302 } else { 303 oldAddr = n.DestinationAddress() 304 } 305 306 t.UpdateChecksumPseudoHeaderAddress(oldAddr, newAddr, fullChecksum) 307 } 308 309 if checksummableNetHeader, ok := n.(header.ChecksummableNetwork); ok { 310 if updateSRCFields { 311 checksummableNetHeader.SetSourceAddressWithChecksumUpdate(newAddr) 312 } else { 313 checksummableNetHeader.SetDestinationAddressWithChecksumUpdate(newAddr) 314 } 315 } else if updateSRCFields { 316 n.SetSourceAddress(newAddr) 317 } else { 318 n.SetDestinationAddress(newAddr) 319 } 320 }