istio.io/istio@v0.0.0-20240520182934-d79c90f27776/cni/pkg/iptables/iptables_linux.go (about) 1 // Copyright Istio 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 iptables 16 17 import ( 18 "errors" 19 "fmt" 20 "net" 21 22 "github.com/vishvananda/netlink" 23 "golang.org/x/sys/unix" 24 ) 25 26 func AddInpodMarkIPRule(cfg *Config) error { 27 err := forEachInpodMarkIPRule(cfg, netlink.RuleAdd) 28 if errors.Is(err, unix.EEXIST) { 29 log.Debugf("Ignoring exists error adding inpod mark ip rule: %v", err) 30 return nil 31 } 32 return err 33 } 34 35 func DelInpodMarkIPRule(cfg *Config) error { 36 return forEachInpodMarkIPRule(cfg, netlink.RuleDel) 37 } 38 39 func forEachInpodMarkIPRule(cfg *Config, f func(*netlink.Rule) error) error { 40 var rules []*netlink.Rule 41 families := []int{unix.AF_INET} 42 if cfg.EnableIPv6 { 43 families = append(families, unix.AF_INET6) 44 } 45 for _, family := range families { 46 // Equiv: 47 // ip rule add fwmark 0x111/0xfff pref 32764 lookup 100 48 // 49 // Adds in-pod rules for marking packets with the istio-specific TPROXY mark. 50 // A very similar mechanism is used for sidecar TPROXY. 51 // 52 // TODO largely identical/copied from tools/istio-iptables/pkg/capture/run_linux.go 53 inpodMarkRule := netlink.NewRule() 54 inpodMarkRule.Family = family 55 inpodMarkRule.Table = RouteTableInbound 56 inpodMarkRule.Mark = InpodTProxyMark 57 inpodMarkRule.Mask = InpodTProxyMask 58 inpodMarkRule.Priority = 32764 59 rules = append(rules, inpodMarkRule) 60 } 61 62 for _, rule := range rules { 63 log.Debugf("Iterating netlink rule : %+v", rule) 64 if err := f(rule); err != nil { 65 return fmt.Errorf("failed to configure netlink rule: %w", err) 66 } 67 } 68 69 return nil 70 } 71 72 func AddLoopbackRoutes(cfg *Config) error { 73 return forEachLoopbackRoute(cfg, netlink.RouteReplace) 74 } 75 76 func DelLoopbackRoutes(cfg *Config) error { 77 return forEachLoopbackRoute(cfg, netlink.RouteDel) 78 } 79 80 func forEachLoopbackRoute(cfg *Config, f func(*netlink.Route) error) error { 81 loopbackLink, err := netlink.LinkByName("lo") 82 if err != nil { 83 return fmt.Errorf("failed to find 'lo' link: %v", err) 84 } 85 86 // Set up netlink routes for localhost 87 cidrs := []string{"0.0.0.0/0"} 88 if cfg.EnableIPv6 { 89 cidrs = append(cidrs, "0::0/0") 90 } 91 for _, fullCIDR := range cidrs { 92 _, localhostDst, err := net.ParseCIDR(fullCIDR) 93 if err != nil { 94 return fmt.Errorf("parse CIDR: %v", err) 95 } 96 97 netlinkRoutes := []*netlink.Route{ 98 // In routing table ${INBOUND_TPROXY_ROUTE_TABLE}, create a single default rule to route all traffic to 99 // the loopback interface. 100 // Equiv: "ip route add local 0.0.0.0/0 dev lo table 100" 101 { 102 Dst: localhostDst, 103 Scope: netlink.SCOPE_HOST, 104 Type: unix.RTN_LOCAL, 105 Table: RouteTableInbound, 106 LinkIndex: loopbackLink.Attrs().Index, 107 }, 108 } 109 110 for _, route := range netlinkRoutes { 111 log.Debugf("Iterating netlink route : %+v", route) 112 if err := f(route); err != nil { 113 log.Errorf("Failed to add netlink route : %+v", route) 114 return fmt.Errorf("failed to add route: %v", err) 115 } 116 } 117 } 118 return nil 119 }