istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tools/istio-iptables/pkg/capture/run_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  package capture
    15  
    16  import (
    17  	"fmt"
    18  	"net"
    19  	"strconv"
    20  
    21  	"github.com/vishvananda/netlink"
    22  	"golang.org/x/sys/unix"
    23  
    24  	"istio.io/istio/pkg/log"
    25  	"istio.io/istio/tools/istio-iptables/pkg/config"
    26  	"istio.io/istio/tools/istio-iptables/pkg/constants"
    27  )
    28  
    29  // configureTProxyRoutes configures ip firewall rules to enable TPROXY support.
    30  // See https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/original_src_filter
    31  func configureTProxyRoutes(cfg *config.Config) error {
    32  	if cfg.InboundPortsInclude != "" {
    33  		if cfg.InboundInterceptionMode == constants.TPROXY {
    34  			link, err := netlink.LinkByName("lo")
    35  			if err != nil {
    36  				return fmt.Errorf("failed to find 'lo' link: %v", err)
    37  			}
    38  			tproxyTable, err := strconv.Atoi(cfg.InboundTProxyRouteTable)
    39  			if err != nil {
    40  				return fmt.Errorf("failed to parse InboundTProxyRouteTable: %v", err)
    41  			}
    42  			tproxyMark, err := strconv.Atoi(cfg.InboundTProxyMark)
    43  			if err != nil {
    44  				return fmt.Errorf("failed to parse InboundTProxyMark: %v", err)
    45  			}
    46  			// Route all packets marked in chain ISTIODIVERT using routing table ${INBOUND_TPROXY_ROUTE_TABLE}.
    47  			// Equivalent to `ip rule add fwmark <tproxyMark> lookup <tproxyTable>`
    48  			families := []int{unix.AF_INET}
    49  			if cfg.EnableIPv6 {
    50  				families = append(families, unix.AF_INET6)
    51  			}
    52  			for _, family := range families {
    53  				r := netlink.NewRule()
    54  				r.Family = family
    55  				r.Table = tproxyTable
    56  				r.Mark = tproxyMark
    57  				if err := netlink.RuleAdd(r); err != nil {
    58  					return fmt.Errorf("failed to configure netlink rule: %v", err)
    59  				}
    60  			}
    61  			// In routing table ${INBOUND_TPROXY_ROUTE_TABLE}, create a single default rule to route all traffic to
    62  			// the loopback interface.
    63  			// Equivalent to `ip route add local default dev lo table <table>`
    64  			cidrs := []string{"0.0.0.0/0"}
    65  			if cfg.EnableIPv6 {
    66  				cidrs = append(cidrs, "0::0/0")
    67  			}
    68  			for _, fullCIDR := range cidrs {
    69  				_, dst, err := net.ParseCIDR(fullCIDR)
    70  				if err != nil {
    71  					return fmt.Errorf("parse CIDR: %v", err)
    72  				}
    73  
    74  				if err := netlink.RouteAdd(&netlink.Route{
    75  					Dst:       dst,
    76  					Scope:     netlink.SCOPE_HOST,
    77  					Type:      unix.RTN_LOCAL,
    78  					Table:     tproxyTable,
    79  					LinkIndex: link.Attrs().Index,
    80  				}); ignoreExists(err) != nil {
    81  					return fmt.Errorf("failed to add route: %v", err)
    82  				}
    83  			}
    84  		}
    85  	}
    86  	return nil
    87  }
    88  
    89  func ConfigureRoutes(cfg *config.Config) error {
    90  	if cfg.DryRun {
    91  		log.Infof("skipping configuring routes due to dry run mode")
    92  		return nil
    93  	}
    94  	if err := configureIPv6Addresses(cfg); err != nil {
    95  		return err
    96  	}
    97  	if err := configureTProxyRoutes(cfg); err != nil {
    98  		return err
    99  	}
   100  	return nil
   101  }