proxier.go 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package iptables
  14. //
  15. // NOTE: this needs to be tested in e2e since it uses iptables for everything.
  16. //
  17. import (
  18. "bytes"
  19. "crypto/sha256"
  20. "encoding/base32"
  21. "fmt"
  22. "net"
  23. "reflect"
  24. "strconv"
  25. "strings"
  26. "sync"
  27. "sync/atomic"
  28. "time"
  29. v1 "k8s.io/api/core/v1"
  30. discovery "k8s.io/api/discovery/v1beta1"
  31. "k8s.io/apimachinery/pkg/types"
  32. "k8s.io/apimachinery/pkg/util/wait"
  33. utilfeature "k8s.io/apiserver/pkg/util/feature"
  34. "k8s.io/client-go/tools/record"
  35. "k8s.io/klog"
  36. "k8s.io/kubernetes/pkg/features"
  37. "k8s.io/kubernetes/pkg/proxy"
  38. "k8s.io/kubernetes/pkg/proxy/healthcheck"
  39. "k8s.io/kubernetes/pkg/proxy/metaproxier"
  40. "k8s.io/kubernetes/pkg/proxy/metrics"
  41. utilproxy "k8s.io/kubernetes/pkg/proxy/util"
  42. proxyutiliptables "k8s.io/kubernetes/pkg/proxy/util/iptables"
  43. "k8s.io/kubernetes/pkg/util/async"
  44. "k8s.io/kubernetes/pkg/util/conntrack"
  45. utiliptables "k8s.io/kubernetes/pkg/util/iptables"
  46. utilsysctl "k8s.io/kubernetes/pkg/util/sysctl"
  47. utilexec "k8s.io/utils/exec"
  48. utilnet "k8s.io/utils/net"
  49. )
  50. const (
  51. // the services chain
  52. kubeServicesChain utiliptables.Chain = "KUBE-SERVICES"
  53. // the external services chain
  54. kubeExternalServicesChain utiliptables.Chain = "KUBE-EXTERNAL-SERVICES"
  55. // the nodeports chain
  56. kubeNodePortsChain utiliptables.Chain = "KUBE-NODEPORTS"
  57. // the kubernetes postrouting chain
  58. kubePostroutingChain utiliptables.Chain = "KUBE-POSTROUTING"
  59. // KubeMarkMasqChain is the mark-for-masquerade chain
  60. KubeMarkMasqChain utiliptables.Chain = "KUBE-MARK-MASQ"
  61. // KubeMarkDropChain is the mark-for-drop chain
  62. KubeMarkDropChain utiliptables.Chain = "KUBE-MARK-DROP"
  63. // the kubernetes forward chain
  64. kubeForwardChain utiliptables.Chain = "KUBE-FORWARD"
  65. )
  66. // KernelCompatTester tests whether the required kernel capabilities are
  67. // present to run the iptables proxier.
  68. type KernelCompatTester interface {
  69. IsCompatible() error
  70. }
  71. // CanUseIPTablesProxier returns true if we should use the iptables Proxier
  72. // instead of the "classic" userspace Proxier.
  73. func CanUseIPTablesProxier(kcompat KernelCompatTester) (bool, error) {
  74. if err := kcompat.IsCompatible(); err != nil {
  75. return false, err
  76. }
  77. return true, nil
  78. }
  79. var _ KernelCompatTester = LinuxKernelCompatTester{}
  80. // LinuxKernelCompatTester is the Linux implementation of KernelCompatTester
  81. type LinuxKernelCompatTester struct{}
  82. // IsCompatible checks for the required sysctls. We don't care about the value, just
  83. // that it exists. If this Proxier is chosen, we'll initialize it as we
  84. // need.
  85. func (lkct LinuxKernelCompatTester) IsCompatible() error {
  86. _, err := utilsysctl.New().GetSysctl(sysctlRouteLocalnet)
  87. return err
  88. }
  89. const sysctlRouteLocalnet = "net/ipv4/conf/all/route_localnet"
  90. const sysctlBridgeCallIPTables = "net/bridge/bridge-nf-call-iptables"
  91. // internal struct for string service information
  92. type serviceInfo struct {
  93. *proxy.BaseServiceInfo
  94. // The following fields are computed and stored for performance reasons.
  95. serviceNameString string
  96. servicePortChainName utiliptables.Chain
  97. serviceFirewallChainName utiliptables.Chain
  98. serviceLBChainName utiliptables.Chain
  99. }
  100. // returns a new proxy.ServicePort which abstracts a serviceInfo
  101. func newServiceInfo(port *v1.ServicePort, service *v1.Service, baseInfo *proxy.BaseServiceInfo) proxy.ServicePort {
  102. info := &serviceInfo{BaseServiceInfo: baseInfo}
  103. // Store the following for performance reasons.
  104. svcName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
  105. svcPortName := proxy.ServicePortName{NamespacedName: svcName, Port: port.Name}
  106. protocol := strings.ToLower(string(info.Protocol()))
  107. info.serviceNameString = svcPortName.String()
  108. info.servicePortChainName = servicePortChainName(info.serviceNameString, protocol)
  109. info.serviceFirewallChainName = serviceFirewallChainName(info.serviceNameString, protocol)
  110. info.serviceLBChainName = serviceLBChainName(info.serviceNameString, protocol)
  111. return info
  112. }
  113. // internal struct for endpoints information
  114. type endpointsInfo struct {
  115. *proxy.BaseEndpointInfo
  116. // The following fields we lazily compute and store here for performance
  117. // reasons. If the protocol is the same as you expect it to be, then the
  118. // chainName can be reused, otherwise it should be recomputed.
  119. protocol string
  120. chainName utiliptables.Chain
  121. }
  122. // returns a new proxy.Endpoint which abstracts a endpointsInfo
  123. func newEndpointInfo(baseInfo *proxy.BaseEndpointInfo) proxy.Endpoint {
  124. return &endpointsInfo{BaseEndpointInfo: baseInfo}
  125. }
  126. // Equal overrides the Equal() function implemented by proxy.BaseEndpointInfo.
  127. func (e *endpointsInfo) Equal(other proxy.Endpoint) bool {
  128. o, ok := other.(*endpointsInfo)
  129. if !ok {
  130. klog.Error("Failed to cast endpointsInfo")
  131. return false
  132. }
  133. return e.Endpoint == o.Endpoint &&
  134. e.IsLocal == o.IsLocal &&
  135. e.protocol == o.protocol &&
  136. e.chainName == o.chainName
  137. }
  138. // Returns the endpoint chain name for a given endpointsInfo.
  139. func (e *endpointsInfo) endpointChain(svcNameString, protocol string) utiliptables.Chain {
  140. if e.protocol != protocol {
  141. e.protocol = protocol
  142. e.chainName = servicePortEndpointChainName(svcNameString, protocol, e.Endpoint)
  143. }
  144. return e.chainName
  145. }
  146. // Proxier is an iptables based proxy for connections between a localhost:lport
  147. // and services that provide the actual backends.
  148. type Proxier struct {
  149. // endpointsChanges and serviceChanges contains all changes to endpoints and
  150. // services that happened since iptables was synced. For a single object,
  151. // changes are accumulated, i.e. previous is state from before all of them,
  152. // current is state after applying all of those.
  153. endpointsChanges *proxy.EndpointChangeTracker
  154. serviceChanges *proxy.ServiceChangeTracker
  155. mu sync.Mutex // protects the following fields
  156. serviceMap proxy.ServiceMap
  157. endpointsMap proxy.EndpointsMap
  158. portsMap map[utilproxy.LocalPort]utilproxy.Closeable
  159. nodeLabels map[string]string
  160. // endpointsSynced, endpointSlicesSynced, and servicesSynced are set to true
  161. // when corresponding objects are synced after startup. This is used to avoid
  162. // updating iptables with some partial data after kube-proxy restart.
  163. endpointsSynced bool
  164. endpointSlicesSynced bool
  165. servicesSynced bool
  166. initialized int32
  167. syncRunner *async.BoundedFrequencyRunner // governs calls to syncProxyRules
  168. syncPeriod time.Duration
  169. // These are effectively const and do not need the mutex to be held.
  170. iptables utiliptables.Interface
  171. masqueradeAll bool
  172. masqueradeMark string
  173. exec utilexec.Interface
  174. localDetector proxyutiliptables.LocalTrafficDetector
  175. hostname string
  176. nodeIP net.IP
  177. portMapper utilproxy.PortOpener
  178. recorder record.EventRecorder
  179. serviceHealthServer healthcheck.ServiceHealthServer
  180. healthzServer healthcheck.ProxierHealthUpdater
  181. // Since converting probabilities (floats) to strings is expensive
  182. // and we are using only probabilities in the format of 1/n, we are
  183. // precomputing some number of those and cache for future reuse.
  184. precomputedProbabilities []string
  185. // The following buffers are used to reuse memory and avoid allocations
  186. // that are significantly impacting performance.
  187. iptablesData *bytes.Buffer
  188. existingFilterChainsData *bytes.Buffer
  189. filterChains *bytes.Buffer
  190. filterRules *bytes.Buffer
  191. natChains *bytes.Buffer
  192. natRules *bytes.Buffer
  193. // endpointChainsNumber is the total amount of endpointChains across all
  194. // services that we will generate (it is computed at the beginning of
  195. // syncProxyRules method). If that is large enough, comments in some
  196. // iptable rules are dropped to improve performance.
  197. endpointChainsNumber int
  198. // Values are as a parameter to select the interfaces where nodeport works.
  199. nodePortAddresses []string
  200. // networkInterfacer defines an interface for several net library functions.
  201. // Inject for test purpose.
  202. networkInterfacer utilproxy.NetworkInterfacer
  203. }
  204. // listenPortOpener opens ports by calling bind() and listen().
  205. type listenPortOpener struct{}
  206. // OpenLocalPort holds the given local port open.
  207. func (l *listenPortOpener) OpenLocalPort(lp *utilproxy.LocalPort, isIPv6 bool) (utilproxy.Closeable, error) {
  208. return openLocalPort(lp, isIPv6)
  209. }
  210. // Proxier implements proxy.Provider
  211. var _ proxy.Provider = &Proxier{}
  212. // NewProxier returns a new Proxier given an iptables Interface instance.
  213. // Because of the iptables logic, it is assumed that there is only a single Proxier active on a machine.
  214. // An error will be returned if iptables fails to update or acquire the initial lock.
  215. // Once a proxier is created, it will keep iptables up to date in the background and
  216. // will not terminate if a particular iptables call fails.
  217. func NewProxier(ipt utiliptables.Interface,
  218. sysctl utilsysctl.Interface,
  219. exec utilexec.Interface,
  220. syncPeriod time.Duration,
  221. minSyncPeriod time.Duration,
  222. masqueradeAll bool,
  223. masqueradeBit int,
  224. localDetector proxyutiliptables.LocalTrafficDetector,
  225. hostname string,
  226. nodeIP net.IP,
  227. recorder record.EventRecorder,
  228. healthzServer healthcheck.ProxierHealthUpdater,
  229. nodePortAddresses []string,
  230. ) (*Proxier, error) {
  231. // Set the route_localnet sysctl we need for
  232. if val, _ := sysctl.GetSysctl(sysctlRouteLocalnet); val != 1 {
  233. if err := sysctl.SetSysctl(sysctlRouteLocalnet, 1); err != nil {
  234. return nil, fmt.Errorf("can't set sysctl %s: %v", sysctlRouteLocalnet, err)
  235. }
  236. }
  237. // Proxy needs br_netfilter and bridge-nf-call-iptables=1 when containers
  238. // are connected to a Linux bridge (but not SDN bridges). Until most
  239. // plugins handle this, log when config is missing
  240. if val, err := sysctl.GetSysctl(sysctlBridgeCallIPTables); err == nil && val != 1 {
  241. klog.Warning("missing br-netfilter module or unset sysctl br-nf-call-iptables; proxy may not work as intended")
  242. }
  243. // Generate the masquerade mark to use for SNAT rules.
  244. masqueradeValue := 1 << uint(masqueradeBit)
  245. masqueradeMark := fmt.Sprintf("%#08x/%#08x", masqueradeValue, masqueradeValue)
  246. endpointSlicesEnabled := utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceProxying)
  247. serviceHealthServer := healthcheck.NewServiceHealthServer(hostname, recorder)
  248. isIPv6 := ipt.IsIpv6()
  249. proxier := &Proxier{
  250. portsMap: make(map[utilproxy.LocalPort]utilproxy.Closeable),
  251. serviceMap: make(proxy.ServiceMap),
  252. serviceChanges: proxy.NewServiceChangeTracker(newServiceInfo, &isIPv6, recorder),
  253. endpointsMap: make(proxy.EndpointsMap),
  254. endpointsChanges: proxy.NewEndpointChangeTracker(hostname, newEndpointInfo, &isIPv6, recorder, endpointSlicesEnabled),
  255. syncPeriod: syncPeriod,
  256. iptables: ipt,
  257. masqueradeAll: masqueradeAll,
  258. masqueradeMark: masqueradeMark,
  259. exec: exec,
  260. localDetector: localDetector,
  261. hostname: hostname,
  262. nodeIP: nodeIP,
  263. portMapper: &listenPortOpener{},
  264. recorder: recorder,
  265. serviceHealthServer: serviceHealthServer,
  266. healthzServer: healthzServer,
  267. precomputedProbabilities: make([]string, 0, 1001),
  268. iptablesData: bytes.NewBuffer(nil),
  269. existingFilterChainsData: bytes.NewBuffer(nil),
  270. filterChains: bytes.NewBuffer(nil),
  271. filterRules: bytes.NewBuffer(nil),
  272. natChains: bytes.NewBuffer(nil),
  273. natRules: bytes.NewBuffer(nil),
  274. nodePortAddresses: nodePortAddresses,
  275. networkInterfacer: utilproxy.RealNetwork{},
  276. }
  277. burstSyncs := 2
  278. klog.V(3).Infof("minSyncPeriod: %v, syncPeriod: %v, burstSyncs: %d", minSyncPeriod, syncPeriod, burstSyncs)
  279. // We pass syncPeriod to ipt.Monitor, which will call us only if it needs to.
  280. // We need to pass *some* maxInterval to NewBoundedFrequencyRunner anyway though.
  281. // time.Hour is arbitrary.
  282. proxier.syncRunner = async.NewBoundedFrequencyRunner("sync-runner", proxier.syncProxyRules, minSyncPeriod, time.Hour, burstSyncs)
  283. go ipt.Monitor(utiliptables.Chain("KUBE-PROXY-CANARY"),
  284. []utiliptables.Table{utiliptables.TableMangle, utiliptables.TableNAT, utiliptables.TableFilter},
  285. proxier.syncProxyRules, syncPeriod, wait.NeverStop)
  286. return proxier, nil
  287. }
  288. // NewDualStackProxier creates a MetaProxier instance, with IPv4 and IPv6 proxies.
  289. func NewDualStackProxier(
  290. ipt [2]utiliptables.Interface,
  291. sysctl utilsysctl.Interface,
  292. exec utilexec.Interface,
  293. syncPeriod time.Duration,
  294. minSyncPeriod time.Duration,
  295. masqueradeAll bool,
  296. masqueradeBit int,
  297. localDetectors [2]proxyutiliptables.LocalTrafficDetector,
  298. hostname string,
  299. nodeIP [2]net.IP,
  300. recorder record.EventRecorder,
  301. healthzServer healthcheck.ProxierHealthUpdater,
  302. nodePortAddresses []string,
  303. ) (proxy.Provider, error) {
  304. // Create an ipv4 instance of the single-stack proxier
  305. ipv4Proxier, err := NewProxier(ipt[0], sysctl,
  306. exec, syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[0], hostname,
  307. nodeIP[0], recorder, healthzServer, nodePortAddresses)
  308. if err != nil {
  309. return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err)
  310. }
  311. ipv6Proxier, err := NewProxier(ipt[1], sysctl,
  312. exec, syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[1], hostname,
  313. nodeIP[1], recorder, healthzServer, nodePortAddresses)
  314. if err != nil {
  315. return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err)
  316. }
  317. return metaproxier.NewMetaProxier(ipv4Proxier, ipv6Proxier), nil // TODO move meta-proxier to mode-neutral package
  318. }
  319. type iptablesJumpChain struct {
  320. table utiliptables.Table
  321. dstChain utiliptables.Chain
  322. srcChain utiliptables.Chain
  323. comment string
  324. extraArgs []string
  325. }
  326. var iptablesJumpChains = []iptablesJumpChain{
  327. {utiliptables.TableFilter, kubeExternalServicesChain, utiliptables.ChainInput, "kubernetes externally-visible service portals", []string{"-m", "conntrack", "--ctstate", "NEW"}},
  328. {utiliptables.TableFilter, kubeServicesChain, utiliptables.ChainForward, "kubernetes service portals", []string{"-m", "conntrack", "--ctstate", "NEW"}},
  329. {utiliptables.TableFilter, kubeServicesChain, utiliptables.ChainOutput, "kubernetes service portals", []string{"-m", "conntrack", "--ctstate", "NEW"}},
  330. {utiliptables.TableFilter, kubeServicesChain, utiliptables.ChainInput, "kubernetes service portals", []string{"-m", "conntrack", "--ctstate", "NEW"}},
  331. {utiliptables.TableFilter, kubeForwardChain, utiliptables.ChainForward, "kubernetes forwarding rules", nil},
  332. {utiliptables.TableNAT, kubeServicesChain, utiliptables.ChainOutput, "kubernetes service portals", nil},
  333. {utiliptables.TableNAT, kubeServicesChain, utiliptables.ChainPrerouting, "kubernetes service portals", nil},
  334. {utiliptables.TableNAT, kubePostroutingChain, utiliptables.ChainPostrouting, "kubernetes postrouting rules", nil},
  335. }
  336. var iptablesCleanupOnlyChains = []iptablesJumpChain{}
  337. // CleanupLeftovers removes all iptables rules and chains created by the Proxier
  338. // It returns true if an error was encountered. Errors are logged.
  339. func CleanupLeftovers(ipt utiliptables.Interface) (encounteredError bool) {
  340. // Unlink our chains
  341. for _, jump := range append(iptablesJumpChains, iptablesCleanupOnlyChains...) {
  342. args := append(jump.extraArgs,
  343. "-m", "comment", "--comment", jump.comment,
  344. "-j", string(jump.dstChain),
  345. )
  346. if err := ipt.DeleteRule(jump.table, jump.srcChain, args...); err != nil {
  347. if !utiliptables.IsNotFoundError(err) {
  348. klog.Errorf("Error removing pure-iptables proxy rule: %v", err)
  349. encounteredError = true
  350. }
  351. }
  352. }
  353. // Flush and remove all of our "-t nat" chains.
  354. iptablesData := bytes.NewBuffer(nil)
  355. if err := ipt.SaveInto(utiliptables.TableNAT, iptablesData); err != nil {
  356. klog.Errorf("Failed to execute iptables-save for %s: %v", utiliptables.TableNAT, err)
  357. encounteredError = true
  358. } else {
  359. existingNATChains := utiliptables.GetChainLines(utiliptables.TableNAT, iptablesData.Bytes())
  360. natChains := bytes.NewBuffer(nil)
  361. natRules := bytes.NewBuffer(nil)
  362. writeLine(natChains, "*nat")
  363. // Start with chains we know we need to remove.
  364. for _, chain := range []utiliptables.Chain{kubeServicesChain, kubeNodePortsChain, kubePostroutingChain} {
  365. if _, found := existingNATChains[chain]; found {
  366. chainString := string(chain)
  367. writeBytesLine(natChains, existingNATChains[chain]) // flush
  368. writeLine(natRules, "-X", chainString) // delete
  369. }
  370. }
  371. // Hunt for service and endpoint chains.
  372. for chain := range existingNATChains {
  373. chainString := string(chain)
  374. if strings.HasPrefix(chainString, "KUBE-SVC-") || strings.HasPrefix(chainString, "KUBE-SEP-") || strings.HasPrefix(chainString, "KUBE-FW-") || strings.HasPrefix(chainString, "KUBE-XLB-") {
  375. writeBytesLine(natChains, existingNATChains[chain]) // flush
  376. writeLine(natRules, "-X", chainString) // delete
  377. }
  378. }
  379. writeLine(natRules, "COMMIT")
  380. natLines := append(natChains.Bytes(), natRules.Bytes()...)
  381. // Write it.
  382. err = ipt.Restore(utiliptables.TableNAT, natLines, utiliptables.NoFlushTables, utiliptables.RestoreCounters)
  383. if err != nil {
  384. klog.Errorf("Failed to execute iptables-restore for %s: %v", utiliptables.TableNAT, err)
  385. metrics.IptablesRestoreFailuresTotal.Inc()
  386. encounteredError = true
  387. }
  388. }
  389. // Flush and remove all of our "-t filter" chains.
  390. iptablesData.Reset()
  391. if err := ipt.SaveInto(utiliptables.TableFilter, iptablesData); err != nil {
  392. klog.Errorf("Failed to execute iptables-save for %s: %v", utiliptables.TableFilter, err)
  393. encounteredError = true
  394. } else {
  395. existingFilterChains := utiliptables.GetChainLines(utiliptables.TableFilter, iptablesData.Bytes())
  396. filterChains := bytes.NewBuffer(nil)
  397. filterRules := bytes.NewBuffer(nil)
  398. writeLine(filterChains, "*filter")
  399. for _, chain := range []utiliptables.Chain{kubeServicesChain, kubeExternalServicesChain, kubeForwardChain} {
  400. if _, found := existingFilterChains[chain]; found {
  401. chainString := string(chain)
  402. writeBytesLine(filterChains, existingFilterChains[chain])
  403. writeLine(filterRules, "-X", chainString)
  404. }
  405. }
  406. writeLine(filterRules, "COMMIT")
  407. filterLines := append(filterChains.Bytes(), filterRules.Bytes()...)
  408. // Write it.
  409. if err := ipt.Restore(utiliptables.TableFilter, filterLines, utiliptables.NoFlushTables, utiliptables.RestoreCounters); err != nil {
  410. klog.Errorf("Failed to execute iptables-restore for %s: %v", utiliptables.TableFilter, err)
  411. metrics.IptablesRestoreFailuresTotal.Inc()
  412. encounteredError = true
  413. }
  414. }
  415. return encounteredError
  416. }
  417. func computeProbability(n int) string {
  418. return fmt.Sprintf("%0.10f", 1.0/float64(n))
  419. }
  420. // This assumes proxier.mu is held
  421. func (proxier *Proxier) precomputeProbabilities(numberOfPrecomputed int) {
  422. if len(proxier.precomputedProbabilities) == 0 {
  423. proxier.precomputedProbabilities = append(proxier.precomputedProbabilities, "<bad value>")
  424. }
  425. for i := len(proxier.precomputedProbabilities); i <= numberOfPrecomputed; i++ {
  426. proxier.precomputedProbabilities = append(proxier.precomputedProbabilities, computeProbability(i))
  427. }
  428. }
  429. // This assumes proxier.mu is held
  430. func (proxier *Proxier) probability(n int) string {
  431. if n >= len(proxier.precomputedProbabilities) {
  432. proxier.precomputeProbabilities(n)
  433. }
  434. return proxier.precomputedProbabilities[n]
  435. }
  436. // Sync is called to synchronize the proxier state to iptables as soon as possible.
  437. func (proxier *Proxier) Sync() {
  438. if proxier.healthzServer != nil {
  439. proxier.healthzServer.QueuedUpdate()
  440. }
  441. proxier.syncRunner.Run()
  442. }
  443. // SyncLoop runs periodic work. This is expected to run as a goroutine or as the main loop of the app. It does not return.
  444. func (proxier *Proxier) SyncLoop() {
  445. // Update healthz timestamp at beginning in case Sync() never succeeds.
  446. if proxier.healthzServer != nil {
  447. proxier.healthzServer.Updated()
  448. }
  449. proxier.syncRunner.Loop(wait.NeverStop)
  450. }
  451. func (proxier *Proxier) setInitialized(value bool) {
  452. var initialized int32
  453. if value {
  454. initialized = 1
  455. }
  456. atomic.StoreInt32(&proxier.initialized, initialized)
  457. }
  458. func (proxier *Proxier) isInitialized() bool {
  459. return atomic.LoadInt32(&proxier.initialized) > 0
  460. }
  461. // OnServiceAdd is called whenever creation of new service object
  462. // is observed.
  463. func (proxier *Proxier) OnServiceAdd(service *v1.Service) {
  464. proxier.OnServiceUpdate(nil, service)
  465. }
  466. // OnServiceUpdate is called whenever modification of an existing
  467. // service object is observed.
  468. func (proxier *Proxier) OnServiceUpdate(oldService, service *v1.Service) {
  469. if proxier.serviceChanges.Update(oldService, service) && proxier.isInitialized() {
  470. proxier.Sync()
  471. }
  472. }
  473. // OnServiceDelete is called whenever deletion of an existing service
  474. // object is observed.
  475. func (proxier *Proxier) OnServiceDelete(service *v1.Service) {
  476. proxier.OnServiceUpdate(service, nil)
  477. }
  478. // OnServiceSynced is called once all the initial even handlers were
  479. // called and the state is fully propagated to local cache.
  480. func (proxier *Proxier) OnServiceSynced() {
  481. proxier.mu.Lock()
  482. proxier.servicesSynced = true
  483. if utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceProxying) {
  484. proxier.setInitialized(proxier.endpointSlicesSynced)
  485. } else {
  486. proxier.setInitialized(proxier.endpointsSynced)
  487. }
  488. proxier.mu.Unlock()
  489. // Sync unconditionally - this is called once per lifetime.
  490. proxier.syncProxyRules()
  491. }
  492. // OnEndpointsAdd is called whenever creation of new endpoints object
  493. // is observed.
  494. func (proxier *Proxier) OnEndpointsAdd(endpoints *v1.Endpoints) {
  495. proxier.OnEndpointsUpdate(nil, endpoints)
  496. }
  497. // OnEndpointsUpdate is called whenever modification of an existing
  498. // endpoints object is observed.
  499. func (proxier *Proxier) OnEndpointsUpdate(oldEndpoints, endpoints *v1.Endpoints) {
  500. if proxier.endpointsChanges.Update(oldEndpoints, endpoints) && proxier.isInitialized() {
  501. proxier.Sync()
  502. }
  503. }
  504. // OnEndpointsDelete is called whenever deletion of an existing endpoints
  505. // object is observed.
  506. func (proxier *Proxier) OnEndpointsDelete(endpoints *v1.Endpoints) {
  507. proxier.OnEndpointsUpdate(endpoints, nil)
  508. }
  509. // OnEndpointsSynced is called once all the initial event handlers were
  510. // called and the state is fully propagated to local cache.
  511. func (proxier *Proxier) OnEndpointsSynced() {
  512. proxier.mu.Lock()
  513. proxier.endpointsSynced = true
  514. proxier.setInitialized(proxier.servicesSynced)
  515. proxier.mu.Unlock()
  516. // Sync unconditionally - this is called once per lifetime.
  517. proxier.syncProxyRules()
  518. }
  519. // OnEndpointSliceAdd is called whenever creation of a new endpoint slice object
  520. // is observed.
  521. func (proxier *Proxier) OnEndpointSliceAdd(endpointSlice *discovery.EndpointSlice) {
  522. if proxier.endpointsChanges.EndpointSliceUpdate(endpointSlice, false) && proxier.isInitialized() {
  523. proxier.Sync()
  524. }
  525. }
  526. // OnEndpointSliceUpdate is called whenever modification of an existing endpoint
  527. // slice object is observed.
  528. func (proxier *Proxier) OnEndpointSliceUpdate(_, endpointSlice *discovery.EndpointSlice) {
  529. if proxier.endpointsChanges.EndpointSliceUpdate(endpointSlice, false) && proxier.isInitialized() {
  530. proxier.Sync()
  531. }
  532. }
  533. // OnEndpointSliceDelete is called whenever deletion of an existing endpoint slice
  534. // object is observed.
  535. func (proxier *Proxier) OnEndpointSliceDelete(endpointSlice *discovery.EndpointSlice) {
  536. if proxier.endpointsChanges.EndpointSliceUpdate(endpointSlice, true) && proxier.isInitialized() {
  537. proxier.Sync()
  538. }
  539. }
  540. // OnEndpointSlicesSynced is called once all the initial event handlers were
  541. // called and the state is fully propagated to local cache.
  542. func (proxier *Proxier) OnEndpointSlicesSynced() {
  543. proxier.mu.Lock()
  544. proxier.endpointSlicesSynced = true
  545. proxier.setInitialized(proxier.servicesSynced)
  546. proxier.mu.Unlock()
  547. // Sync unconditionally - this is called once per lifetime.
  548. proxier.syncProxyRules()
  549. }
  550. // OnNodeAdd is called whenever creation of new node object
  551. // is observed.
  552. func (proxier *Proxier) OnNodeAdd(node *v1.Node) {
  553. if node.Name != proxier.hostname {
  554. klog.Errorf("Received a watch event for a node %s that doesn't match the current node %v", node.Name, proxier.hostname)
  555. return
  556. }
  557. if reflect.DeepEqual(proxier.nodeLabels, node.Labels) {
  558. return
  559. }
  560. proxier.mu.Lock()
  561. proxier.nodeLabels = node.Labels
  562. proxier.mu.Unlock()
  563. proxier.syncProxyRules()
  564. }
  565. // OnNodeUpdate is called whenever modification of an existing
  566. // node object is observed.
  567. func (proxier *Proxier) OnNodeUpdate(oldNode, node *v1.Node) {
  568. if node.Name != proxier.hostname {
  569. klog.Errorf("Received a watch event for a node %s that doesn't match the current node %v", node.Name, proxier.hostname)
  570. return
  571. }
  572. if reflect.DeepEqual(proxier.nodeLabels, node.Labels) {
  573. return
  574. }
  575. proxier.mu.Lock()
  576. proxier.nodeLabels = node.Labels
  577. proxier.mu.Unlock()
  578. proxier.syncProxyRules()
  579. }
  580. // OnNodeDelete is called whever deletion of an existing node
  581. // object is observed.
  582. func (proxier *Proxier) OnNodeDelete(node *v1.Node) {
  583. if node.Name != proxier.hostname {
  584. klog.Errorf("Received a watch event for a node %s that doesn't match the current node %v", node.Name, proxier.hostname)
  585. return
  586. }
  587. proxier.mu.Lock()
  588. proxier.nodeLabels = nil
  589. proxier.mu.Unlock()
  590. proxier.syncProxyRules()
  591. }
  592. // OnNodeSynced is called once all the initial event handlers were
  593. // called and the state is fully propagated to local cache.
  594. func (proxier *Proxier) OnNodeSynced() {
  595. }
  596. // portProtoHash takes the ServicePortName and protocol for a service
  597. // returns the associated 16 character hash. This is computed by hashing (sha256)
  598. // then encoding to base32 and truncating to 16 chars. We do this because IPTables
  599. // Chain Names must be <= 28 chars long, and the longer they are the harder they are to read.
  600. func portProtoHash(servicePortName string, protocol string) string {
  601. hash := sha256.Sum256([]byte(servicePortName + protocol))
  602. encoded := base32.StdEncoding.EncodeToString(hash[:])
  603. return encoded[:16]
  604. }
  605. // servicePortChainName takes the ServicePortName for a service and
  606. // returns the associated iptables chain. This is computed by hashing (sha256)
  607. // then encoding to base32 and truncating with the prefix "KUBE-SVC-".
  608. func servicePortChainName(servicePortName string, protocol string) utiliptables.Chain {
  609. return utiliptables.Chain("KUBE-SVC-" + portProtoHash(servicePortName, protocol))
  610. }
  611. // serviceFirewallChainName takes the ServicePortName for a service and
  612. // returns the associated iptables chain. This is computed by hashing (sha256)
  613. // then encoding to base32 and truncating with the prefix "KUBE-FW-".
  614. func serviceFirewallChainName(servicePortName string, protocol string) utiliptables.Chain {
  615. return utiliptables.Chain("KUBE-FW-" + portProtoHash(servicePortName, protocol))
  616. }
  617. // serviceLBPortChainName takes the ServicePortName for a service and
  618. // returns the associated iptables chain. This is computed by hashing (sha256)
  619. // then encoding to base32 and truncating with the prefix "KUBE-XLB-". We do
  620. // this because IPTables Chain Names must be <= 28 chars long, and the longer
  621. // they are the harder they are to read.
  622. func serviceLBChainName(servicePortName string, protocol string) utiliptables.Chain {
  623. return utiliptables.Chain("KUBE-XLB-" + portProtoHash(servicePortName, protocol))
  624. }
  625. // This is the same as servicePortChainName but with the endpoint included.
  626. func servicePortEndpointChainName(servicePortName string, protocol string, endpoint string) utiliptables.Chain {
  627. hash := sha256.Sum256([]byte(servicePortName + protocol + endpoint))
  628. encoded := base32.StdEncoding.EncodeToString(hash[:])
  629. return utiliptables.Chain("KUBE-SEP-" + encoded[:16])
  630. }
  631. // After a UDP endpoint has been removed, we must flush any pending conntrack entries to it, or else we
  632. // risk sending more traffic to it, all of which will be lost (because UDP).
  633. // This assumes the proxier mutex is held
  634. // TODO: move it to util
  635. func (proxier *Proxier) deleteEndpointConnections(connectionMap []proxy.ServiceEndpoint) {
  636. for _, epSvcPair := range connectionMap {
  637. if svcInfo, ok := proxier.serviceMap[epSvcPair.ServicePortName]; ok && svcInfo.Protocol() == v1.ProtocolUDP {
  638. endpointIP := utilproxy.IPPart(epSvcPair.Endpoint)
  639. nodePort := svcInfo.NodePort()
  640. var err error
  641. if nodePort != 0 {
  642. err = conntrack.ClearEntriesForPortNAT(proxier.exec, endpointIP, nodePort, v1.ProtocolUDP)
  643. } else {
  644. err = conntrack.ClearEntriesForNAT(proxier.exec, svcInfo.ClusterIP().String(), endpointIP, v1.ProtocolUDP)
  645. }
  646. if err != nil {
  647. klog.Errorf("Failed to delete %s endpoint connections, error: %v", epSvcPair.ServicePortName.String(), err)
  648. }
  649. for _, extIP := range svcInfo.ExternalIPStrings() {
  650. err := conntrack.ClearEntriesForNAT(proxier.exec, extIP, endpointIP, v1.ProtocolUDP)
  651. if err != nil {
  652. klog.Errorf("Failed to delete %s endpoint connections for externalIP %s, error: %v", epSvcPair.ServicePortName.String(), extIP, err)
  653. }
  654. }
  655. for _, lbIP := range svcInfo.LoadBalancerIPStrings() {
  656. err := conntrack.ClearEntriesForNAT(proxier.exec, lbIP, endpointIP, v1.ProtocolUDP)
  657. if err != nil {
  658. klog.Errorf("Failed to delete %s endpoint connections for LoabBalancerIP %s, error: %v", epSvcPair.ServicePortName.String(), lbIP, err)
  659. }
  660. }
  661. }
  662. }
  663. }
  664. const endpointChainsNumberThreshold = 1000
  665. // Assumes proxier.mu is held.
  666. func (proxier *Proxier) appendServiceCommentLocked(args []string, svcName string) []string {
  667. // Not printing these comments, can reduce size of iptables (in case of large
  668. // number of endpoints) even by 40%+. So if total number of endpoint chains
  669. // is large enough, we simply drop those comments.
  670. if proxier.endpointChainsNumber > endpointChainsNumberThreshold {
  671. return args
  672. }
  673. return append(args, "-m", "comment", "--comment", svcName)
  674. }
  675. // This is where all of the iptables-save/restore calls happen.
  676. // The only other iptables rules are those that are setup in iptablesInit()
  677. // This assumes proxier.mu is NOT held
  678. func (proxier *Proxier) syncProxyRules() {
  679. proxier.mu.Lock()
  680. defer proxier.mu.Unlock()
  681. // don't sync rules till we've received services and endpoints
  682. if !proxier.isInitialized() {
  683. klog.V(2).Info("Not syncing iptables until Services and Endpoints have been received from master")
  684. return
  685. }
  686. // Keep track of how long syncs take.
  687. start := time.Now()
  688. defer func() {
  689. metrics.SyncProxyRulesLatency.Observe(metrics.SinceInSeconds(start))
  690. klog.V(4).Infof("syncProxyRules took %v", time.Since(start))
  691. }()
  692. localAddrs, err := utilproxy.GetLocalAddrs()
  693. if err != nil {
  694. klog.Errorf("Failed to get local addresses during proxy sync: %v, assuming external IPs are not local", err)
  695. } else if len(localAddrs) == 0 {
  696. klog.Warning("No local addresses found, assuming all external IPs are not local")
  697. }
  698. localAddrSet := utilnet.IPSet{}
  699. localAddrSet.Insert(localAddrs...)
  700. // We assume that if this was called, we really want to sync them,
  701. // even if nothing changed in the meantime. In other words, callers are
  702. // responsible for detecting no-op changes and not calling this function.
  703. serviceUpdateResult := proxy.UpdateServiceMap(proxier.serviceMap, proxier.serviceChanges)
  704. endpointUpdateResult := proxier.endpointsMap.Update(proxier.endpointsChanges)
  705. staleServices := serviceUpdateResult.UDPStaleClusterIP
  706. // merge stale services gathered from updateEndpointsMap
  707. for _, svcPortName := range endpointUpdateResult.StaleServiceNames {
  708. if svcInfo, ok := proxier.serviceMap[svcPortName]; ok && svcInfo != nil && svcInfo.Protocol() == v1.ProtocolUDP {
  709. klog.V(2).Infof("Stale udp service %v -> %s", svcPortName, svcInfo.ClusterIP().String())
  710. staleServices.Insert(svcInfo.ClusterIP().String())
  711. for _, extIP := range svcInfo.ExternalIPStrings() {
  712. staleServices.Insert(extIP)
  713. }
  714. }
  715. }
  716. klog.V(3).Info("Syncing iptables rules")
  717. success := false
  718. defer func() {
  719. if !success {
  720. klog.Infof("Sync failed; retrying in %s", proxier.syncPeriod)
  721. proxier.syncRunner.RetryAfter(proxier.syncPeriod)
  722. }
  723. }()
  724. // Create and link the kube chains.
  725. for _, jump := range iptablesJumpChains {
  726. if _, err := proxier.iptables.EnsureChain(jump.table, jump.dstChain); err != nil {
  727. klog.Errorf("Failed to ensure that %s chain %s exists: %v", jump.table, jump.dstChain, err)
  728. return
  729. }
  730. args := append(jump.extraArgs,
  731. "-m", "comment", "--comment", jump.comment,
  732. "-j", string(jump.dstChain),
  733. )
  734. if _, err := proxier.iptables.EnsureRule(utiliptables.Prepend, jump.table, jump.srcChain, args...); err != nil {
  735. klog.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", jump.table, jump.srcChain, jump.dstChain, err)
  736. return
  737. }
  738. }
  739. //
  740. // Below this point we will not return until we try to write the iptables rules.
  741. //
  742. // Get iptables-save output so we can check for existing chains and rules.
  743. // This will be a map of chain name to chain with rules as stored in iptables-save/iptables-restore
  744. existingFilterChains := make(map[utiliptables.Chain][]byte)
  745. proxier.existingFilterChainsData.Reset()
  746. err = proxier.iptables.SaveInto(utiliptables.TableFilter, proxier.existingFilterChainsData)
  747. if err != nil { // if we failed to get any rules
  748. klog.Errorf("Failed to execute iptables-save, syncing all rules: %v", err)
  749. } else { // otherwise parse the output
  750. existingFilterChains = utiliptables.GetChainLines(utiliptables.TableFilter, proxier.existingFilterChainsData.Bytes())
  751. }
  752. // IMPORTANT: existingNATChains may share memory with proxier.iptablesData.
  753. existingNATChains := make(map[utiliptables.Chain][]byte)
  754. proxier.iptablesData.Reset()
  755. err = proxier.iptables.SaveInto(utiliptables.TableNAT, proxier.iptablesData)
  756. if err != nil { // if we failed to get any rules
  757. klog.Errorf("Failed to execute iptables-save, syncing all rules: %v", err)
  758. } else { // otherwise parse the output
  759. existingNATChains = utiliptables.GetChainLines(utiliptables.TableNAT, proxier.iptablesData.Bytes())
  760. }
  761. // Reset all buffers used later.
  762. // This is to avoid memory reallocations and thus improve performance.
  763. proxier.filterChains.Reset()
  764. proxier.filterRules.Reset()
  765. proxier.natChains.Reset()
  766. proxier.natRules.Reset()
  767. // Write table headers.
  768. writeLine(proxier.filterChains, "*filter")
  769. writeLine(proxier.natChains, "*nat")
  770. // Make sure we keep stats for the top-level chains, if they existed
  771. // (which most should have because we created them above).
  772. for _, chainName := range []utiliptables.Chain{kubeServicesChain, kubeExternalServicesChain, kubeForwardChain} {
  773. if chain, ok := existingFilterChains[chainName]; ok {
  774. writeBytesLine(proxier.filterChains, chain)
  775. } else {
  776. writeLine(proxier.filterChains, utiliptables.MakeChainLine(chainName))
  777. }
  778. }
  779. for _, chainName := range []utiliptables.Chain{kubeServicesChain, kubeNodePortsChain, kubePostroutingChain, KubeMarkMasqChain} {
  780. if chain, ok := existingNATChains[chainName]; ok {
  781. writeBytesLine(proxier.natChains, chain)
  782. } else {
  783. writeLine(proxier.natChains, utiliptables.MakeChainLine(chainName))
  784. }
  785. }
  786. // Install the kubernetes-specific postrouting rules. We use a whole chain for
  787. // this so that it is easier to flush and change, for example if the mark
  788. // value should ever change.
  789. // NB: THIS MUST MATCH the corresponding code in the kubelet
  790. masqRule := []string{
  791. "-A", string(kubePostroutingChain),
  792. "-m", "comment", "--comment", `"kubernetes service traffic requiring SNAT"`,
  793. "-m", "mark", "--mark", proxier.masqueradeMark,
  794. "-j", "MASQUERADE",
  795. }
  796. if proxier.iptables.HasRandomFully() {
  797. masqRule = append(masqRule, "--random-fully")
  798. klog.V(3).Info("Using `--random-fully` in the MASQUERADE rule for iptables")
  799. } else {
  800. klog.V(3).Info("Not using `--random-fully` in the MASQUERADE rule for iptables because the local version of iptables does not support it")
  801. }
  802. writeLine(proxier.natRules, masqRule...)
  803. // Install the kubernetes-specific masquerade mark rule. We use a whole chain for
  804. // this so that it is easier to flush and change, for example if the mark
  805. // value should ever change.
  806. writeLine(proxier.natRules, []string{
  807. "-A", string(KubeMarkMasqChain),
  808. "-j", "MARK", "--set-xmark", proxier.masqueradeMark,
  809. }...)
  810. // Accumulate NAT chains to keep.
  811. activeNATChains := map[utiliptables.Chain]bool{} // use a map as a set
  812. // Accumulate the set of local ports that we will be holding open once this update is complete
  813. replacementPortsMap := map[utilproxy.LocalPort]utilproxy.Closeable{}
  814. // We are creating those slices ones here to avoid memory reallocations
  815. // in every loop. Note that reuse the memory, instead of doing:
  816. // slice = <some new slice>
  817. // you should always do one of the below:
  818. // slice = slice[:0] // and then append to it
  819. // slice = append(slice[:0], ...)
  820. endpoints := make([]*endpointsInfo, 0)
  821. endpointChains := make([]utiliptables.Chain, 0)
  822. // To avoid growing this slice, we arbitrarily set its size to 64,
  823. // there is never more than that many arguments for a single line.
  824. // Note that even if we go over 64, it will still be correct - it
  825. // is just for efficiency, not correctness.
  826. args := make([]string, 64)
  827. // Compute total number of endpoint chains across all services.
  828. proxier.endpointChainsNumber = 0
  829. for svcName := range proxier.serviceMap {
  830. proxier.endpointChainsNumber += len(proxier.endpointsMap[svcName])
  831. }
  832. // Build rules for each service.
  833. for svcName, svc := range proxier.serviceMap {
  834. svcInfo, ok := svc.(*serviceInfo)
  835. if !ok {
  836. klog.Errorf("Failed to cast serviceInfo %q", svcName.String())
  837. continue
  838. }
  839. isIPv6 := utilnet.IsIPv6(svcInfo.ClusterIP())
  840. protocol := strings.ToLower(string(svcInfo.Protocol()))
  841. svcNameString := svcInfo.serviceNameString
  842. allEndpoints := proxier.endpointsMap[svcName]
  843. hasEndpoints := len(allEndpoints) > 0
  844. // Service Topology will not be enabled in the following cases:
  845. // 1. externalTrafficPolicy=Local (mutually exclusive with service topology).
  846. // 2. ServiceTopology is not enabled.
  847. // 3. EndpointSlice is not enabled (service topology depends on endpoint slice
  848. // to get topology information).
  849. if !svcInfo.OnlyNodeLocalEndpoints() && utilfeature.DefaultFeatureGate.Enabled(features.ServiceTopology) && utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceProxying) {
  850. allEndpoints = proxy.FilterTopologyEndpoint(proxier.nodeLabels, svcInfo.TopologyKeys(), allEndpoints)
  851. hasEndpoints = len(allEndpoints) > 0
  852. }
  853. svcChain := svcInfo.servicePortChainName
  854. if hasEndpoints {
  855. // Create the per-service chain, retaining counters if possible.
  856. if chain, ok := existingNATChains[svcChain]; ok {
  857. writeBytesLine(proxier.natChains, chain)
  858. } else {
  859. writeLine(proxier.natChains, utiliptables.MakeChainLine(svcChain))
  860. }
  861. activeNATChains[svcChain] = true
  862. }
  863. svcXlbChain := svcInfo.serviceLBChainName
  864. if svcInfo.OnlyNodeLocalEndpoints() {
  865. // Only for services request OnlyLocal traffic
  866. // create the per-service LB chain, retaining counters if possible.
  867. if lbChain, ok := existingNATChains[svcXlbChain]; ok {
  868. writeBytesLine(proxier.natChains, lbChain)
  869. } else {
  870. writeLine(proxier.natChains, utiliptables.MakeChainLine(svcXlbChain))
  871. }
  872. activeNATChains[svcXlbChain] = true
  873. }
  874. // Capture the clusterIP.
  875. if hasEndpoints {
  876. args = append(args[:0],
  877. "-A", string(kubeServicesChain),
  878. "-m", "comment", "--comment", fmt.Sprintf(`"%s cluster IP"`, svcNameString),
  879. "-m", protocol, "-p", protocol,
  880. "-d", utilproxy.ToCIDR(svcInfo.ClusterIP()),
  881. "--dport", strconv.Itoa(svcInfo.Port()),
  882. )
  883. if proxier.masqueradeAll {
  884. writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
  885. } else if proxier.localDetector.IsImplemented() {
  886. // This masquerades off-cluster traffic to a service VIP. The idea
  887. // is that you can establish a static route for your Service range,
  888. // routing to any node, and that node will bridge into the Service
  889. // for you. Since that might bounce off-node, we masquerade here.
  890. // If/when we support "Local" policy for VIPs, we should update this.
  891. writeLine(proxier.natRules, proxier.localDetector.JumpIfNotLocal(args, string(KubeMarkMasqChain))...)
  892. }
  893. writeLine(proxier.natRules, append(args, "-j", string(svcChain))...)
  894. } else {
  895. // No endpoints.
  896. writeLine(proxier.filterRules,
  897. "-A", string(kubeServicesChain),
  898. "-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString),
  899. "-m", protocol, "-p", protocol,
  900. "-d", utilproxy.ToCIDR(svcInfo.ClusterIP()),
  901. "--dport", strconv.Itoa(svcInfo.Port()),
  902. "-j", "REJECT",
  903. )
  904. }
  905. // Capture externalIPs.
  906. for _, externalIP := range svcInfo.ExternalIPStrings() {
  907. // If the "external" IP happens to be an IP that is local to this
  908. // machine, hold the local port open so no other process can open it
  909. // (because the socket might open but it would never work).
  910. if localAddrSet.Len() > 0 && (svcInfo.Protocol() != v1.ProtocolSCTP) && localAddrSet.Has(net.ParseIP(externalIP)) {
  911. lp := utilproxy.LocalPort{
  912. Description: "externalIP for " + svcNameString,
  913. IP: externalIP,
  914. Port: svcInfo.Port(),
  915. Protocol: protocol,
  916. }
  917. if proxier.portsMap[lp] != nil {
  918. klog.V(4).Infof("Port %s was open before and is still needed", lp.String())
  919. replacementPortsMap[lp] = proxier.portsMap[lp]
  920. } else {
  921. socket, err := proxier.portMapper.OpenLocalPort(&lp, isIPv6)
  922. if err != nil {
  923. msg := fmt.Sprintf("can't open %s, skipping this externalIP: %v", lp.String(), err)
  924. proxier.recorder.Eventf(
  925. &v1.ObjectReference{
  926. Kind: "Node",
  927. Name: proxier.hostname,
  928. UID: types.UID(proxier.hostname),
  929. Namespace: "",
  930. }, v1.EventTypeWarning, err.Error(), msg)
  931. klog.Error(msg)
  932. continue
  933. }
  934. replacementPortsMap[lp] = socket
  935. }
  936. }
  937. if hasEndpoints {
  938. args = append(args[:0],
  939. "-A", string(kubeServicesChain),
  940. "-m", "comment", "--comment", fmt.Sprintf(`"%s external IP"`, svcNameString),
  941. "-m", protocol, "-p", protocol,
  942. "-d", utilproxy.ToCIDR(net.ParseIP(externalIP)),
  943. "--dport", strconv.Itoa(svcInfo.Port()),
  944. )
  945. // We have to SNAT packets to external IPs.
  946. writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
  947. // Allow traffic for external IPs that does not come from a bridge (i.e. not from a container)
  948. // nor from a local process to be forwarded to the service.
  949. // This rule roughly translates to "all traffic from off-machine".
  950. // This is imperfect in the face of network plugins that might not use a bridge, but we can revisit that later.
  951. externalTrafficOnlyArgs := append(args,
  952. "-m", "physdev", "!", "--physdev-is-in",
  953. "-m", "addrtype", "!", "--src-type", "LOCAL")
  954. writeLine(proxier.natRules, append(externalTrafficOnlyArgs, "-j", string(svcChain))...)
  955. dstLocalOnlyArgs := append(args, "-m", "addrtype", "--dst-type", "LOCAL")
  956. // Allow traffic bound for external IPs that happen to be recognized as local IPs to stay local.
  957. // This covers cases like GCE load-balancers which get added to the local routing table.
  958. writeLine(proxier.natRules, append(dstLocalOnlyArgs, "-j", string(svcChain))...)
  959. } else {
  960. // No endpoints.
  961. writeLine(proxier.filterRules,
  962. "-A", string(kubeExternalServicesChain),
  963. "-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString),
  964. "-m", protocol, "-p", protocol,
  965. "-d", utilproxy.ToCIDR(net.ParseIP(externalIP)),
  966. "--dport", strconv.Itoa(svcInfo.Port()),
  967. "-j", "REJECT",
  968. )
  969. }
  970. }
  971. // Capture load-balancer ingress.
  972. fwChain := svcInfo.serviceFirewallChainName
  973. for _, ingress := range svcInfo.LoadBalancerIPStrings() {
  974. if ingress != "" {
  975. if hasEndpoints {
  976. // create service firewall chain
  977. if chain, ok := existingNATChains[fwChain]; ok {
  978. writeBytesLine(proxier.natChains, chain)
  979. } else {
  980. writeLine(proxier.natChains, utiliptables.MakeChainLine(fwChain))
  981. }
  982. activeNATChains[fwChain] = true
  983. // The service firewall rules are created based on ServiceSpec.loadBalancerSourceRanges field.
  984. // This currently works for loadbalancers that preserves source ips.
  985. // For loadbalancers which direct traffic to service NodePort, the firewall rules will not apply.
  986. args = append(args[:0],
  987. "-A", string(kubeServicesChain),
  988. "-m", "comment", "--comment", fmt.Sprintf(`"%s loadbalancer IP"`, svcNameString),
  989. "-m", protocol, "-p", protocol,
  990. "-d", utilproxy.ToCIDR(net.ParseIP(ingress)),
  991. "--dport", strconv.Itoa(svcInfo.Port()),
  992. )
  993. // jump to service firewall chain
  994. writeLine(proxier.natRules, append(args, "-j", string(fwChain))...)
  995. args = append(args[:0],
  996. "-A", string(fwChain),
  997. "-m", "comment", "--comment", fmt.Sprintf(`"%s loadbalancer IP"`, svcNameString),
  998. )
  999. // Each source match rule in the FW chain may jump to either the SVC or the XLB chain
  1000. chosenChain := svcXlbChain
  1001. // If we are proxying globally, we need to masquerade in case we cross nodes.
  1002. // If we are proxying only locally, we can retain the source IP.
  1003. if !svcInfo.OnlyNodeLocalEndpoints() {
  1004. writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
  1005. chosenChain = svcChain
  1006. }
  1007. if len(svcInfo.LoadBalancerSourceRanges()) == 0 {
  1008. // allow all sources, so jump directly to the KUBE-SVC or KUBE-XLB chain
  1009. writeLine(proxier.natRules, append(args, "-j", string(chosenChain))...)
  1010. } else {
  1011. // firewall filter based on each source range
  1012. allowFromNode := false
  1013. for _, src := range svcInfo.LoadBalancerSourceRanges() {
  1014. writeLine(proxier.natRules, append(args, "-s", src, "-j", string(chosenChain))...)
  1015. // ignore error because it has been validated
  1016. _, cidr, _ := net.ParseCIDR(src)
  1017. if cidr.Contains(proxier.nodeIP) {
  1018. allowFromNode = true
  1019. }
  1020. }
  1021. // generally, ip route rule was added to intercept request to loadbalancer vip from the
  1022. // loadbalancer's backend hosts. In this case, request will not hit the loadbalancer but loop back directly.
  1023. // Need to add the following rule to allow request on host.
  1024. if allowFromNode {
  1025. writeLine(proxier.natRules, append(args, "-s", utilproxy.ToCIDR(net.ParseIP(ingress)), "-j", string(chosenChain))...)
  1026. }
  1027. }
  1028. // If the packet was able to reach the end of firewall chain, then it did not get DNATed.
  1029. // It means the packet cannot go thru the firewall, then mark it for DROP
  1030. writeLine(proxier.natRules, append(args, "-j", string(KubeMarkDropChain))...)
  1031. } else {
  1032. // No endpoints.
  1033. writeLine(proxier.filterRules,
  1034. "-A", string(kubeServicesChain),
  1035. "-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString),
  1036. "-m", protocol, "-p", protocol,
  1037. "-d", utilproxy.ToCIDR(net.ParseIP(ingress)),
  1038. "--dport", strconv.Itoa(svcInfo.Port()),
  1039. "-j", "REJECT",
  1040. )
  1041. }
  1042. }
  1043. }
  1044. // Capture nodeports. If we had more than 2 rules it might be
  1045. // worthwhile to make a new per-service chain for nodeport rules, but
  1046. // with just 2 rules it ends up being a waste and a cognitive burden.
  1047. if svcInfo.NodePort() != 0 {
  1048. // Hold the local port open so no other process can open it
  1049. // (because the socket might open but it would never work).
  1050. addresses, err := utilproxy.GetNodeAddresses(proxier.nodePortAddresses, proxier.networkInterfacer)
  1051. if err != nil {
  1052. klog.Errorf("Failed to get node ip address matching nodeport cidr: %v", err)
  1053. continue
  1054. }
  1055. lps := make([]utilproxy.LocalPort, 0)
  1056. for address := range addresses {
  1057. lp := utilproxy.LocalPort{
  1058. Description: "nodePort for " + svcNameString,
  1059. IP: address,
  1060. Port: svcInfo.NodePort(),
  1061. Protocol: protocol,
  1062. }
  1063. if utilproxy.IsZeroCIDR(address) {
  1064. // Empty IP address means all
  1065. lp.IP = ""
  1066. lps = append(lps, lp)
  1067. // If we encounter a zero CIDR, then there is no point in processing the rest of the addresses.
  1068. break
  1069. }
  1070. lps = append(lps, lp)
  1071. }
  1072. // For ports on node IPs, open the actual port and hold it.
  1073. for _, lp := range lps {
  1074. if proxier.portsMap[lp] != nil {
  1075. klog.V(4).Infof("Port %s was open before and is still needed", lp.String())
  1076. replacementPortsMap[lp] = proxier.portsMap[lp]
  1077. } else if svcInfo.Protocol() != v1.ProtocolSCTP {
  1078. socket, err := proxier.portMapper.OpenLocalPort(&lp, isIPv6)
  1079. if err != nil {
  1080. klog.Errorf("can't open %s, skipping this nodePort: %v", lp.String(), err)
  1081. continue
  1082. }
  1083. if lp.Protocol == "udp" {
  1084. // TODO: We might have multiple services using the same port, and this will clear conntrack for all of them.
  1085. // This is very low impact. The NodePort range is intentionally obscure, and unlikely to actually collide with real Services.
  1086. // This only affects UDP connections, which are not common.
  1087. // See issue: https://github.com/kubernetes/kubernetes/issues/49881
  1088. err := conntrack.ClearEntriesForPort(proxier.exec, lp.Port, isIPv6, v1.ProtocolUDP)
  1089. if err != nil {
  1090. klog.Errorf("Failed to clear udp conntrack for port %d, error: %v", lp.Port, err)
  1091. }
  1092. }
  1093. replacementPortsMap[lp] = socket
  1094. }
  1095. }
  1096. if hasEndpoints {
  1097. args = append(args[:0],
  1098. "-A", string(kubeNodePortsChain),
  1099. "-m", "comment", "--comment", svcNameString,
  1100. "-m", protocol, "-p", protocol,
  1101. "--dport", strconv.Itoa(svcInfo.NodePort()),
  1102. )
  1103. if !svcInfo.OnlyNodeLocalEndpoints() {
  1104. // Nodeports need SNAT, unless they're local.
  1105. writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
  1106. // Jump to the service chain.
  1107. writeLine(proxier.natRules, append(args, "-j", string(svcChain))...)
  1108. } else {
  1109. // TODO: Make all nodePorts jump to the firewall chain.
  1110. // Currently we only create it for loadbalancers (#33586).
  1111. // Fix localhost martian source error
  1112. loopback := "127.0.0.0/8"
  1113. if isIPv6 {
  1114. loopback = "::1/128"
  1115. }
  1116. writeLine(proxier.natRules, append(args, "-s", loopback, "-j", string(KubeMarkMasqChain))...)
  1117. writeLine(proxier.natRules, append(args, "-j", string(svcXlbChain))...)
  1118. }
  1119. } else {
  1120. // No endpoints.
  1121. writeLine(proxier.filterRules,
  1122. "-A", string(kubeExternalServicesChain),
  1123. "-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString),
  1124. "-m", "addrtype", "--dst-type", "LOCAL",
  1125. "-m", protocol, "-p", protocol,
  1126. "--dport", strconv.Itoa(svcInfo.NodePort()),
  1127. "-j", "REJECT",
  1128. )
  1129. }
  1130. }
  1131. if !hasEndpoints {
  1132. continue
  1133. }
  1134. // Generate the per-endpoint chains. We do this in multiple passes so we
  1135. // can group rules together.
  1136. // These two slices parallel each other - keep in sync
  1137. endpoints = endpoints[:0]
  1138. endpointChains = endpointChains[:0]
  1139. var endpointChain utiliptables.Chain
  1140. for _, ep := range allEndpoints {
  1141. epInfo, ok := ep.(*endpointsInfo)
  1142. if !ok {
  1143. klog.Errorf("Failed to cast endpointsInfo %q", ep.String())
  1144. continue
  1145. }
  1146. endpoints = append(endpoints, epInfo)
  1147. endpointChain = epInfo.endpointChain(svcNameString, protocol)
  1148. endpointChains = append(endpointChains, endpointChain)
  1149. // Create the endpoint chain, retaining counters if possible.
  1150. if chain, ok := existingNATChains[utiliptables.Chain(endpointChain)]; ok {
  1151. writeBytesLine(proxier.natChains, chain)
  1152. } else {
  1153. writeLine(proxier.natChains, utiliptables.MakeChainLine(endpointChain))
  1154. }
  1155. activeNATChains[endpointChain] = true
  1156. }
  1157. // First write session affinity rules, if applicable.
  1158. if svcInfo.SessionAffinityType() == v1.ServiceAffinityClientIP {
  1159. for _, endpointChain := range endpointChains {
  1160. args = append(args[:0],
  1161. "-A", string(svcChain),
  1162. )
  1163. args = proxier.appendServiceCommentLocked(args, svcNameString)
  1164. args = append(args,
  1165. "-m", "recent", "--name", string(endpointChain),
  1166. "--rcheck", "--seconds", strconv.Itoa(svcInfo.StickyMaxAgeSeconds()), "--reap",
  1167. "-j", string(endpointChain),
  1168. )
  1169. writeLine(proxier.natRules, args...)
  1170. }
  1171. }
  1172. // Now write loadbalancing & DNAT rules.
  1173. n := len(endpointChains)
  1174. localEndpointChains := make([]utiliptables.Chain, 0)
  1175. for i, endpointChain := range endpointChains {
  1176. // Write ingress loadbalancing & DNAT rules only for services that request OnlyLocal traffic.
  1177. if svcInfo.OnlyNodeLocalEndpoints() && endpoints[i].IsLocal {
  1178. localEndpointChains = append(localEndpointChains, endpointChains[i])
  1179. }
  1180. epIP := endpoints[i].IP()
  1181. if epIP == "" {
  1182. // Error parsing this endpoint has been logged. Skip to next endpoint.
  1183. continue
  1184. }
  1185. // Balancing rules in the per-service chain.
  1186. args = append(args[:0], "-A", string(svcChain))
  1187. args = proxier.appendServiceCommentLocked(args, svcNameString)
  1188. if i < (n - 1) {
  1189. // Each rule is a probabilistic match.
  1190. args = append(args,
  1191. "-m", "statistic",
  1192. "--mode", "random",
  1193. "--probability", proxier.probability(n-i))
  1194. }
  1195. // The final (or only if n == 1) rule is a guaranteed match.
  1196. args = append(args, "-j", string(endpointChain))
  1197. writeLine(proxier.natRules, args...)
  1198. // Rules in the per-endpoint chain.
  1199. args = append(args[:0], "-A", string(endpointChain))
  1200. args = proxier.appendServiceCommentLocked(args, svcNameString)
  1201. // Handle traffic that loops back to the originator with SNAT.
  1202. writeLine(proxier.natRules, append(args,
  1203. "-s", utilproxy.ToCIDR(net.ParseIP(epIP)),
  1204. "-j", string(KubeMarkMasqChain))...)
  1205. // Update client-affinity lists.
  1206. if svcInfo.SessionAffinityType() == v1.ServiceAffinityClientIP {
  1207. args = append(args, "-m", "recent", "--name", string(endpointChain), "--set")
  1208. }
  1209. // DNAT to final destination.
  1210. args = append(args, "-m", protocol, "-p", protocol, "-j", "DNAT", "--to-destination", endpoints[i].Endpoint)
  1211. writeLine(proxier.natRules, args...)
  1212. }
  1213. // The logic below this applies only if this service is marked as OnlyLocal
  1214. if !svcInfo.OnlyNodeLocalEndpoints() {
  1215. continue
  1216. }
  1217. // First rule in the chain redirects all pod -> external VIP traffic to the
  1218. // Service's ClusterIP instead. This happens whether or not we have local
  1219. // endpoints; only if localDetector is implemented
  1220. if proxier.localDetector.IsImplemented() {
  1221. args = append(args[:0],
  1222. "-A", string(svcXlbChain),
  1223. "-m", "comment", "--comment",
  1224. `"Redirect pods trying to reach external loadbalancer VIP to clusterIP"`,
  1225. )
  1226. writeLine(proxier.natRules, proxier.localDetector.JumpIfLocal(args, string(svcChain))...)
  1227. }
  1228. // Next, redirect all src-type=LOCAL -> LB IP to the service chain for externalTrafficPolicy=Local
  1229. // This allows traffic originating from the host to be redirected to the service correctly,
  1230. // otherwise traffic to LB IPs are dropped if there are no local endpoints.
  1231. args = append(args[:0], "-A", string(svcXlbChain))
  1232. writeLine(proxier.natRules, append(args,
  1233. "-m", "comment", "--comment", fmt.Sprintf(`"masquerade LOCAL traffic for %s LB IP"`, svcNameString),
  1234. "-m", "addrtype", "--src-type", "LOCAL", "-j", string(KubeMarkMasqChain))...)
  1235. writeLine(proxier.natRules, append(args,
  1236. "-m", "comment", "--comment", fmt.Sprintf(`"route LOCAL traffic for %s LB IP to service chain"`, svcNameString),
  1237. "-m", "addrtype", "--src-type", "LOCAL", "-j", string(svcChain))...)
  1238. numLocalEndpoints := len(localEndpointChains)
  1239. if numLocalEndpoints == 0 {
  1240. // Blackhole all traffic since there are no local endpoints
  1241. args = append(args[:0],
  1242. "-A", string(svcXlbChain),
  1243. "-m", "comment", "--comment",
  1244. fmt.Sprintf(`"%s has no local endpoints"`, svcNameString),
  1245. "-j",
  1246. string(KubeMarkDropChain),
  1247. )
  1248. writeLine(proxier.natRules, args...)
  1249. } else {
  1250. // First write session affinity rules only over local endpoints, if applicable.
  1251. if svcInfo.SessionAffinityType() == v1.ServiceAffinityClientIP {
  1252. for _, endpointChain := range localEndpointChains {
  1253. writeLine(proxier.natRules,
  1254. "-A", string(svcXlbChain),
  1255. "-m", "comment", "--comment", svcNameString,
  1256. "-m", "recent", "--name", string(endpointChain),
  1257. "--rcheck", "--seconds", strconv.Itoa(svcInfo.StickyMaxAgeSeconds()), "--reap",
  1258. "-j", string(endpointChain))
  1259. }
  1260. }
  1261. // Setup probability filter rules only over local endpoints
  1262. for i, endpointChain := range localEndpointChains {
  1263. // Balancing rules in the per-service chain.
  1264. args = append(args[:0],
  1265. "-A", string(svcXlbChain),
  1266. "-m", "comment", "--comment",
  1267. fmt.Sprintf(`"Balancing rule %d for %s"`, i, svcNameString),
  1268. )
  1269. if i < (numLocalEndpoints - 1) {
  1270. // Each rule is a probabilistic match.
  1271. args = append(args,
  1272. "-m", "statistic",
  1273. "--mode", "random",
  1274. "--probability", proxier.probability(numLocalEndpoints-i))
  1275. }
  1276. // The final (or only if n == 1) rule is a guaranteed match.
  1277. args = append(args, "-j", string(endpointChain))
  1278. writeLine(proxier.natRules, args...)
  1279. }
  1280. }
  1281. }
  1282. // Delete chains no longer in use.
  1283. for chain := range existingNATChains {
  1284. if !activeNATChains[chain] {
  1285. chainString := string(chain)
  1286. if !strings.HasPrefix(chainString, "KUBE-SVC-") && !strings.HasPrefix(chainString, "KUBE-SEP-") && !strings.HasPrefix(chainString, "KUBE-FW-") && !strings.HasPrefix(chainString, "KUBE-XLB-") {
  1287. // Ignore chains that aren't ours.
  1288. continue
  1289. }
  1290. // We must (as per iptables) write a chain-line for it, which has
  1291. // the nice effect of flushing the chain. Then we can remove the
  1292. // chain.
  1293. writeBytesLine(proxier.natChains, existingNATChains[chain])
  1294. writeLine(proxier.natRules, "-X", chainString)
  1295. }
  1296. }
  1297. // Finally, tail-call to the nodeports chain. This needs to be after all
  1298. // other service portal rules.
  1299. addresses, err := utilproxy.GetNodeAddresses(proxier.nodePortAddresses, proxier.networkInterfacer)
  1300. if err != nil {
  1301. klog.Errorf("Failed to get node ip address matching nodeport cidr")
  1302. } else {
  1303. isIPv6 := proxier.iptables.IsIpv6()
  1304. for address := range addresses {
  1305. // TODO(thockin, m1093782566): If/when we have dual-stack support we will want to distinguish v4 from v6 zero-CIDRs.
  1306. if utilproxy.IsZeroCIDR(address) {
  1307. args = append(args[:0],
  1308. "-A", string(kubeServicesChain),
  1309. "-m", "comment", "--comment", `"kubernetes service nodeports; NOTE: this must be the last rule in this chain"`,
  1310. "-m", "addrtype", "--dst-type", "LOCAL",
  1311. "-j", string(kubeNodePortsChain))
  1312. writeLine(proxier.natRules, args...)
  1313. // Nothing else matters after the zero CIDR.
  1314. break
  1315. }
  1316. // Ignore IP addresses with incorrect version
  1317. if isIPv6 && !utilnet.IsIPv6String(address) || !isIPv6 && utilnet.IsIPv6String(address) {
  1318. klog.Errorf("IP address %s has incorrect IP version", address)
  1319. continue
  1320. }
  1321. // create nodeport rules for each IP one by one
  1322. args = append(args[:0],
  1323. "-A", string(kubeServicesChain),
  1324. "-m", "comment", "--comment", `"kubernetes service nodeports; NOTE: this must be the last rule in this chain"`,
  1325. "-d", address,
  1326. "-j", string(kubeNodePortsChain))
  1327. writeLine(proxier.natRules, args...)
  1328. }
  1329. }
  1330. // Drop the packets in INVALID state, which would potentially cause
  1331. // unexpected connection reset.
  1332. // https://github.com/kubernetes/kubernetes/issues/74839
  1333. writeLine(proxier.filterRules,
  1334. "-A", string(kubeForwardChain),
  1335. "-m", "conntrack",
  1336. "--ctstate", "INVALID",
  1337. "-j", "DROP",
  1338. )
  1339. // If the masqueradeMark has been added then we want to forward that same
  1340. // traffic, this allows NodePort traffic to be forwarded even if the default
  1341. // FORWARD policy is not accept.
  1342. writeLine(proxier.filterRules,
  1343. "-A", string(kubeForwardChain),
  1344. "-m", "comment", "--comment", `"kubernetes forwarding rules"`,
  1345. "-m", "mark", "--mark", proxier.masqueradeMark,
  1346. "-j", "ACCEPT",
  1347. )
  1348. // The following two rules ensure the traffic after the initial packet
  1349. // accepted by the "kubernetes forwarding rules" rule above will be
  1350. // accepted.
  1351. writeLine(proxier.filterRules,
  1352. "-A", string(kubeForwardChain),
  1353. "-m", "comment", "--comment", `"kubernetes forwarding conntrack pod source rule"`,
  1354. "-m", "conntrack",
  1355. "--ctstate", "RELATED,ESTABLISHED",
  1356. "-j", "ACCEPT",
  1357. )
  1358. writeLine(proxier.filterRules,
  1359. "-A", string(kubeForwardChain),
  1360. "-m", "comment", "--comment", `"kubernetes forwarding conntrack pod destination rule"`,
  1361. "-m", "conntrack",
  1362. "--ctstate", "RELATED,ESTABLISHED",
  1363. "-j", "ACCEPT",
  1364. )
  1365. // Write the end-of-table markers.
  1366. writeLine(proxier.filterRules, "COMMIT")
  1367. writeLine(proxier.natRules, "COMMIT")
  1368. // Sync rules.
  1369. // NOTE: NoFlushTables is used so we don't flush non-kubernetes chains in the table
  1370. proxier.iptablesData.Reset()
  1371. proxier.iptablesData.Write(proxier.filterChains.Bytes())
  1372. proxier.iptablesData.Write(proxier.filterRules.Bytes())
  1373. proxier.iptablesData.Write(proxier.natChains.Bytes())
  1374. proxier.iptablesData.Write(proxier.natRules.Bytes())
  1375. klog.V(5).Infof("Restoring iptables rules: %s", proxier.iptablesData.Bytes())
  1376. err = proxier.iptables.RestoreAll(proxier.iptablesData.Bytes(), utiliptables.NoFlushTables, utiliptables.RestoreCounters)
  1377. if err != nil {
  1378. klog.Errorf("Failed to execute iptables-restore: %v", err)
  1379. metrics.IptablesRestoreFailuresTotal.Inc()
  1380. // Revert new local ports.
  1381. klog.V(2).Infof("Closing local ports after iptables-restore failure")
  1382. utilproxy.RevertPorts(replacementPortsMap, proxier.portsMap)
  1383. return
  1384. }
  1385. success = true
  1386. for name, lastChangeTriggerTimes := range endpointUpdateResult.LastChangeTriggerTimes {
  1387. for _, lastChangeTriggerTime := range lastChangeTriggerTimes {
  1388. latency := metrics.SinceInSeconds(lastChangeTriggerTime)
  1389. metrics.NetworkProgrammingLatency.Observe(latency)
  1390. klog.V(4).Infof("Network programming of %s took %f seconds", name, latency)
  1391. }
  1392. }
  1393. // Close old local ports and save new ones.
  1394. for k, v := range proxier.portsMap {
  1395. if replacementPortsMap[k] == nil {
  1396. v.Close()
  1397. }
  1398. }
  1399. proxier.portsMap = replacementPortsMap
  1400. if proxier.healthzServer != nil {
  1401. proxier.healthzServer.Updated()
  1402. }
  1403. metrics.SyncProxyRulesLastTimestamp.SetToCurrentTime()
  1404. // Update service healthchecks. The endpoints list might include services that are
  1405. // not "OnlyLocal", but the services list will not, and the serviceHealthServer
  1406. // will just drop those endpoints.
  1407. if err := proxier.serviceHealthServer.SyncServices(serviceUpdateResult.HCServiceNodePorts); err != nil {
  1408. klog.Errorf("Error syncing healthcheck services: %v", err)
  1409. }
  1410. if err := proxier.serviceHealthServer.SyncEndpoints(endpointUpdateResult.HCEndpointsLocalIPSize); err != nil {
  1411. klog.Errorf("Error syncing healthcheck endpoints: %v", err)
  1412. }
  1413. // Finish housekeeping.
  1414. // TODO: these could be made more consistent.
  1415. for _, svcIP := range staleServices.UnsortedList() {
  1416. if err := conntrack.ClearEntriesForIP(proxier.exec, svcIP, v1.ProtocolUDP); err != nil {
  1417. klog.Errorf("Failed to delete stale service IP %s connections, error: %v", svcIP, err)
  1418. }
  1419. }
  1420. proxier.deleteEndpointConnections(endpointUpdateResult.StaleEndpoints)
  1421. }
  1422. // Join all words with spaces, terminate with newline and write to buf.
  1423. func writeLine(buf *bytes.Buffer, words ...string) {
  1424. // We avoid strings.Join for performance reasons.
  1425. for i := range words {
  1426. buf.WriteString(words[i])
  1427. if i < len(words)-1 {
  1428. buf.WriteByte(' ')
  1429. } else {
  1430. buf.WriteByte('\n')
  1431. }
  1432. }
  1433. }
  1434. func writeBytesLine(buf *bytes.Buffer, bytes []byte) {
  1435. buf.Write(bytes)
  1436. buf.WriteByte('\n')
  1437. }
  1438. func openLocalPort(lp *utilproxy.LocalPort, isIPv6 bool) (utilproxy.Closeable, error) {
  1439. // For ports on node IPs, open the actual port and hold it, even though we
  1440. // use iptables to redirect traffic.
  1441. // This ensures a) that it's safe to use that port and b) that (a) stays
  1442. // true. The risk is that some process on the node (e.g. sshd or kubelet)
  1443. // is using a port and we give that same port out to a Service. That would
  1444. // be bad because iptables would silently claim the traffic but the process
  1445. // would never know.
  1446. // NOTE: We should not need to have a real listen()ing socket - bind()
  1447. // should be enough, but I can't figure out a way to e2e test without
  1448. // it. Tools like 'ss' and 'netstat' do not show sockets that are
  1449. // bind()ed but not listen()ed, and at least the default debian netcat
  1450. // has no way to avoid about 10 seconds of retries.
  1451. var socket utilproxy.Closeable
  1452. switch lp.Protocol {
  1453. case "tcp":
  1454. network := "tcp4"
  1455. if isIPv6 {
  1456. network = "tcp6"
  1457. }
  1458. listener, err := net.Listen(network, net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port)))
  1459. if err != nil {
  1460. return nil, err
  1461. }
  1462. socket = listener
  1463. case "udp":
  1464. network := "udp4"
  1465. if isIPv6 {
  1466. network = "udp6"
  1467. }
  1468. addr, err := net.ResolveUDPAddr(network, net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port)))
  1469. if err != nil {
  1470. return nil, err
  1471. }
  1472. conn, err := net.ListenUDP(network, addr)
  1473. if err != nil {
  1474. return nil, err
  1475. }
  1476. socket = conn
  1477. default:
  1478. return nil, fmt.Errorf("unknown protocol %q", lp.Protocol)
  1479. }
  1480. klog.V(2).Infof("Opened local port %s", lp.String())
  1481. return socket, nil
  1482. }