k8s.io/kubernetes@v1.29.3/pkg/proxy/util/iptables/traffic.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package iptables 18 19 import ( 20 "fmt" 21 22 netutils "k8s.io/utils/net" 23 ) 24 25 // LocalTrafficDetector in a interface to take action (jump) based on whether traffic originated locally 26 // at the node or not 27 type LocalTrafficDetector interface { 28 // IsImplemented returns true if the implementation does something, false otherwise 29 IsImplemented() bool 30 31 // IfLocal returns iptables arguments that will match traffic from a pod 32 IfLocal() []string 33 34 // IfNotLocal returns iptables arguments that will match traffic that is not from a pod 35 IfNotLocal() []string 36 37 // IfLocalNFT returns nftables arguments that will match traffic from a pod 38 IfLocalNFT() []string 39 40 // IfNotLocalNFT returns nftables arguments that will match traffic that is not from a pod 41 IfNotLocalNFT() []string 42 } 43 44 type noOpLocalDetector struct{} 45 46 // NewNoOpLocalDetector is a no-op implementation of LocalTrafficDetector 47 func NewNoOpLocalDetector() LocalTrafficDetector { 48 return &noOpLocalDetector{} 49 } 50 51 func (n *noOpLocalDetector) IsImplemented() bool { 52 return false 53 } 54 55 func (n *noOpLocalDetector) IfLocal() []string { 56 return nil // no-op; matches all traffic 57 } 58 59 func (n *noOpLocalDetector) IfNotLocal() []string { 60 return nil // no-op; matches all traffic 61 } 62 63 func (n *noOpLocalDetector) IfLocalNFT() []string { 64 return nil // no-op; matches all traffic 65 } 66 67 func (n *noOpLocalDetector) IfNotLocalNFT() []string { 68 return nil // no-op; matches all traffic 69 } 70 71 type detectLocalByCIDR struct { 72 ifLocal []string 73 ifNotLocal []string 74 ifLocalNFT []string 75 ifNotLocalNFT []string 76 } 77 78 // NewDetectLocalByCIDR implements the LocalTrafficDetector interface using a CIDR. This can be used when a single CIDR 79 // range can be used to capture the notion of local traffic. 80 func NewDetectLocalByCIDR(cidr string) (LocalTrafficDetector, error) { 81 _, parsed, err := netutils.ParseCIDRSloppy(cidr) 82 if err != nil { 83 return nil, err 84 } 85 86 nftFamily := "ip" 87 if netutils.IsIPv6CIDR(parsed) { 88 nftFamily = "ip6" 89 } 90 91 return &detectLocalByCIDR{ 92 ifLocal: []string{"-s", cidr}, 93 ifNotLocal: []string{"!", "-s", cidr}, 94 ifLocalNFT: []string{nftFamily, "saddr", cidr}, 95 ifNotLocalNFT: []string{nftFamily, "saddr", "!=", cidr}, 96 }, nil 97 } 98 99 func (d *detectLocalByCIDR) IsImplemented() bool { 100 return true 101 } 102 103 func (d *detectLocalByCIDR) IfLocal() []string { 104 return d.ifLocal 105 } 106 107 func (d *detectLocalByCIDR) IfNotLocal() []string { 108 return d.ifNotLocal 109 } 110 111 func (d *detectLocalByCIDR) IfLocalNFT() []string { 112 return d.ifLocalNFT 113 } 114 115 func (d *detectLocalByCIDR) IfNotLocalNFT() []string { 116 return d.ifNotLocalNFT 117 } 118 119 type detectLocalByBridgeInterface struct { 120 ifLocal []string 121 ifNotLocal []string 122 ifLocalNFT []string 123 ifNotLocalNFT []string 124 } 125 126 // NewDetectLocalByBridgeInterface implements the LocalTrafficDetector interface using a bridge interface name. 127 // This can be used when a bridge can be used to capture the notion of local traffic from pods. 128 func NewDetectLocalByBridgeInterface(interfaceName string) (LocalTrafficDetector, error) { 129 if len(interfaceName) == 0 { 130 return nil, fmt.Errorf("no bridge interface name set") 131 } 132 return &detectLocalByBridgeInterface{ 133 ifLocal: []string{"-i", interfaceName}, 134 ifNotLocal: []string{"!", "-i", interfaceName}, 135 ifLocalNFT: []string{"iif", interfaceName}, 136 ifNotLocalNFT: []string{"iif", "!=", interfaceName}, 137 }, nil 138 } 139 140 func (d *detectLocalByBridgeInterface) IsImplemented() bool { 141 return true 142 } 143 144 func (d *detectLocalByBridgeInterface) IfLocal() []string { 145 return d.ifLocal 146 } 147 148 func (d *detectLocalByBridgeInterface) IfNotLocal() []string { 149 return d.ifNotLocal 150 } 151 152 func (d *detectLocalByBridgeInterface) IfLocalNFT() []string { 153 return d.ifLocalNFT 154 } 155 156 func (d *detectLocalByBridgeInterface) IfNotLocalNFT() []string { 157 return d.ifNotLocalNFT 158 } 159 160 type detectLocalByInterfaceNamePrefix struct { 161 ifLocal []string 162 ifNotLocal []string 163 ifLocalNFT []string 164 ifNotLocalNFT []string 165 } 166 167 // NewDetectLocalByInterfaceNamePrefix implements the LocalTrafficDetector interface using an interface name prefix. 168 // This can be used when a pod interface name prefix can be used to capture the notion of local traffic. Note 169 // that this will match on all interfaces that start with the given prefix. 170 func NewDetectLocalByInterfaceNamePrefix(interfacePrefix string) (LocalTrafficDetector, error) { 171 if len(interfacePrefix) == 0 { 172 return nil, fmt.Errorf("no interface prefix set") 173 } 174 return &detectLocalByInterfaceNamePrefix{ 175 ifLocal: []string{"-i", interfacePrefix + "+"}, 176 ifNotLocal: []string{"!", "-i", interfacePrefix + "+"}, 177 ifLocalNFT: []string{"iif", interfacePrefix + "*"}, 178 ifNotLocalNFT: []string{"iif", "!=", interfacePrefix + "*"}, 179 }, nil 180 } 181 182 func (d *detectLocalByInterfaceNamePrefix) IsImplemented() bool { 183 return true 184 } 185 186 func (d *detectLocalByInterfaceNamePrefix) IfLocal() []string { 187 return d.ifLocal 188 } 189 190 func (d *detectLocalByInterfaceNamePrefix) IfNotLocal() []string { 191 return d.ifNotLocal 192 } 193 194 func (d *detectLocalByInterfaceNamePrefix) IfLocalNFT() []string { 195 return d.ifLocalNFT 196 } 197 198 func (d *detectLocalByInterfaceNamePrefix) IfNotLocalNFT() []string { 199 return d.ifNotLocalNFT 200 }