istio
227 строк · 8.8 Кб
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
15package config16
17import (18"encoding/json"19"fmt"20"net"21"net/netip"22"os/user"23"strconv"24"strings"25"time"26
27"github.com/miekg/dns"28
29"istio.io/istio/pkg/env"30"istio.io/istio/pkg/log"31netutil "istio.io/istio/pkg/util/net"32"istio.io/istio/tools/istio-iptables/pkg/constants"33)
34
35func DefaultConfig() *Config {36return &Config{37RestoreFormat: true,38ProxyPort: "15001",39InboundCapturePort: "15006",40InboundTunnelPort: "15008",41InboundTProxyMark: "1337",42InboundTProxyRouteTable: "133",43IptablesProbePort: constants.DefaultIptablesProbePortUint,44ProbeTimeout: constants.DefaultProbeTimeout,45OwnerGroupsInclude: constants.OwnerGroupsInclude.DefaultValue,46OwnerGroupsExclude: constants.OwnerGroupsExclude.DefaultValue,47HostIPv4LoopbackCidr: constants.HostIPv4LoopbackCidr.DefaultValue,48}49}
50
51// Command line options
52// nolint: maligned
53type Config struct {54ProxyPort string `json:"PROXY_PORT"`55InboundCapturePort string `json:"INBOUND_CAPTURE_PORT"`56InboundTunnelPort string `json:"INBOUND_TUNNEL_PORT"`57ProxyUID string `json:"PROXY_UID"`58ProxyGID string `json:"PROXY_GID"`59InboundInterceptionMode string `json:"INBOUND_INTERCEPTION_MODE"`60InboundTProxyMark string `json:"INBOUND_TPROXY_MARK"`61InboundTProxyRouteTable string `json:"INBOUND_TPROXY_ROUTE_TABLE"`62InboundPortsInclude string `json:"INBOUND_PORTS_INCLUDE"`63InboundPortsExclude string `json:"INBOUND_PORTS_EXCLUDE"`64OwnerGroupsInclude string `json:"OUTBOUND_OWNER_GROUPS_INCLUDE"`65OwnerGroupsExclude string `json:"OUTBOUND_OWNER_GROUPS_EXCLUDE"`66OutboundPortsInclude string `json:"OUTBOUND_PORTS_INCLUDE"`67OutboundPortsExclude string `json:"OUTBOUND_PORTS_EXCLUDE"`68OutboundIPRangesInclude string `json:"OUTBOUND_IPRANGES_INCLUDE"`69OutboundIPRangesExclude string `json:"OUTBOUND_IPRANGES_EXCLUDE"`70KubeVirtInterfaces string `json:"KUBE_VIRT_INTERFACES"`71ExcludeInterfaces string `json:"EXCLUDE_INTERFACES"`72IptablesProbePort uint16 `json:"IPTABLES_PROBE_PORT"`73ProbeTimeout time.Duration `json:"PROBE_TIMEOUT"`74DryRun bool `json:"DRY_RUN"`75RestoreFormat bool `json:"RESTORE_FORMAT"`76SkipRuleApply bool `json:"SKIP_RULE_APPLY"`77RunValidation bool `json:"RUN_VALIDATION"`78RedirectDNS bool `json:"REDIRECT_DNS"`79DropInvalid bool `json:"DROP_INVALID"`80CaptureAllDNS bool `json:"CAPTURE_ALL_DNS"`81EnableInboundIPv6 bool `json:"ENABLE_INBOUND_IPV6"`82DNSServersV4 []string `json:"DNS_SERVERS_V4"`83DNSServersV6 []string `json:"DNS_SERVERS_V6"`84NetworkNamespace string `json:"NETWORK_NAMESPACE"`85CNIMode bool `json:"CNI_MODE"`86TraceLogging bool `json:"IPTABLES_TRACE_LOGGING"`87DualStack bool `json:"DUAL_STACK"`88HostIP netip.Addr `json:"HOST_IP"`89HostIPv4LoopbackCidr string `json:"HOST_IPV4_LOOPBACK_CIDR"`90}
91
92func (c *Config) String() string {93output, err := json.MarshalIndent(c, "", "\t")94if err != nil {95log.Fatalf("Unable to marshal config object: %v", err)96}97return string(output)98}
99
100func (c *Config) Print() {101var b strings.Builder102b.WriteString(fmt.Sprintf("PROXY_PORT=%s\n", c.ProxyPort))103b.WriteString(fmt.Sprintf("PROXY_INBOUND_CAPTURE_PORT=%s\n", c.InboundCapturePort))104b.WriteString(fmt.Sprintf("PROXY_TUNNEL_PORT=%s\n", c.InboundTunnelPort))105b.WriteString(fmt.Sprintf("PROXY_UID=%s\n", c.ProxyUID))106b.WriteString(fmt.Sprintf("PROXY_GID=%s\n", c.ProxyGID))107b.WriteString(fmt.Sprintf("INBOUND_INTERCEPTION_MODE=%s\n", c.InboundInterceptionMode))108b.WriteString(fmt.Sprintf("INBOUND_TPROXY_MARK=%s\n", c.InboundTProxyMark))109b.WriteString(fmt.Sprintf("INBOUND_TPROXY_ROUTE_TABLE=%s\n", c.InboundTProxyRouteTable))110b.WriteString(fmt.Sprintf("INBOUND_PORTS_INCLUDE=%s\n", c.InboundPortsInclude))111b.WriteString(fmt.Sprintf("INBOUND_PORTS_EXCLUDE=%s\n", c.InboundPortsExclude))112b.WriteString(fmt.Sprintf("OUTBOUND_OWNER_GROUPS_INCLUDE=%s\n", c.OwnerGroupsInclude))113b.WriteString(fmt.Sprintf("OUTBOUND_OWNER_GROUPS_EXCLUDE=%s\n", c.OwnerGroupsExclude))114b.WriteString(fmt.Sprintf("OUTBOUND_IP_RANGES_INCLUDE=%s\n", c.OutboundIPRangesInclude))115b.WriteString(fmt.Sprintf("OUTBOUND_IP_RANGES_EXCLUDE=%s\n", c.OutboundIPRangesExclude))116b.WriteString(fmt.Sprintf("OUTBOUND_PORTS_INCLUDE=%s\n", c.OutboundPortsInclude))117b.WriteString(fmt.Sprintf("OUTBOUND_PORTS_EXCLUDE=%s\n", c.OutboundPortsExclude))118b.WriteString(fmt.Sprintf("KUBE_VIRT_INTERFACES=%s\n", c.KubeVirtInterfaces))119b.WriteString(fmt.Sprintf("ENABLE_INBOUND_IPV6=%t\n", c.EnableInboundIPv6))120b.WriteString(fmt.Sprintf("DUAL_STACK=%t\n", c.DualStack))121b.WriteString(fmt.Sprintf("DNS_CAPTURE=%t\n", c.RedirectDNS))122b.WriteString(fmt.Sprintf("DROP_INVALID=%t\n", c.DropInvalid))123b.WriteString(fmt.Sprintf("CAPTURE_ALL_DNS=%t\n", c.CaptureAllDNS))124b.WriteString(fmt.Sprintf("DNS_SERVERS=%s,%s\n", c.DNSServersV4, c.DNSServersV6))125b.WriteString(fmt.Sprintf("NETWORK_NAMESPACE=%s\n", c.NetworkNamespace))126b.WriteString(fmt.Sprintf("CNI_MODE=%s\n", strconv.FormatBool(c.CNIMode)))127b.WriteString(fmt.Sprintf("EXCLUDE_INTERFACES=%s\n", c.ExcludeInterfaces))128log.Infof("Istio iptables variables:\n%s", b.String())129}
130
131func (c *Config) Validate() error {132if err := ValidateOwnerGroups(c.OwnerGroupsInclude, c.OwnerGroupsExclude); err != nil {133return err134}135return ValidateIPv4LoopbackCidr(c.HostIPv4LoopbackCidr)136}
137
138var envoyUserVar = env.Register(constants.EnvoyUser, "istio-proxy", "Envoy proxy username")139
140func (c *Config) FillConfigFromEnvironment() {141// Fill in env-var only options142c.OwnerGroupsInclude = constants.OwnerGroupsInclude.Get()143c.OwnerGroupsExclude = constants.OwnerGroupsExclude.Get()144
145c.HostIPv4LoopbackCidr = constants.HostIPv4LoopbackCidr.Get()146
147// TODO: Make this more configurable, maybe with an allowlist of users to be captured for output instead of a denylist.148if c.ProxyUID == "" {149usr, err := user.Lookup(envoyUserVar.Get())150var userID string151// Default to the UID of ENVOY_USER152if err != nil {153userID = constants.DefaultProxyUID154} else {155userID = usr.Uid156}157c.ProxyUID = userID158}159
160// For TPROXY as its uid and gid are same.161if c.ProxyGID == "" {162c.ProxyGID = c.ProxyUID163}164// Detect whether IPv6 is enabled by checking if the pod's IP address is IPv4 or IPv6.165hostIP, isIPv6, err := getLocalIP(c.DualStack)166if err != nil {167log.Fatal(err)168}169
170c.HostIP = hostIP171c.EnableInboundIPv6 = isIPv6172
173// Lookup DNS nameservers. We only do this if DNS is enabled in case of some obscure theoretical174// case where reading /etc/resolv.conf could fail.175// If capture all DNS option is enabled, we don't need to read from the dns resolve conf. All176// traffic to port 53 will be captured.177if c.RedirectDNS && !c.CaptureAllDNS {178dnsConfig, err := dns.ClientConfigFromFile("/etc/resolv.conf")179if err != nil {180log.Fatalf("failed to load /etc/resolv.conf: %v", err)181}182c.DNSServersV4, c.DNSServersV6 = netutil.IPsSplitV4V6(dnsConfig.Servers)183}184}
185
186// mock net.InterfaceAddrs to make its unit test become available
187var (188LocalIPAddrs = net.InterfaceAddrs189)
190
191// getLocalIP returns one of the local IP address and it should support IPv6 or not
192func getLocalIP(dualStack bool) (netip.Addr, bool, error) {193var isIPv6 bool194var ipAddrs []netip.Addr195addrs, err := LocalIPAddrs()196if err != nil {197return netip.Addr{}, isIPv6, err198}199
200for _, a := range addrs {201if ipnet, ok := a.(*net.IPNet); ok {202ip := ipnet.IP203ipAddr, ok := netip.AddrFromSlice(ip)204if !ok {205continue206}207// unwrap the IPv4-mapped IPv6 address208unwrapAddr := ipAddr.Unmap()209if !unwrapAddr.IsLoopback() && !unwrapAddr.IsLinkLocalUnicast() && !unwrapAddr.IsLinkLocalMulticast() {210isIPv6 = unwrapAddr.Is6()211ipAddrs = append(ipAddrs, unwrapAddr)212if !dualStack {213return unwrapAddr, isIPv6, nil214}215if isIPv6 {216break217}218}219}220}221
222if len(ipAddrs) > 0 {223return ipAddrs[0], isIPv6, nil224}225
226return netip.Addr{}, isIPv6, fmt.Errorf("no valid local IP address found")227}
228