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  }