istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tools/istio-iptables/pkg/cmd/root.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 cmd 16 17 import ( 18 "fmt" 19 "os" 20 21 "github.com/spf13/cobra" 22 23 "istio.io/istio/pkg/flag" 24 "istio.io/istio/pkg/log" 25 "istio.io/istio/tools/istio-iptables/pkg/capture" 26 "istio.io/istio/tools/istio-iptables/pkg/config" 27 "istio.io/istio/tools/istio-iptables/pkg/constants" 28 dep "istio.io/istio/tools/istio-iptables/pkg/dependencies" 29 "istio.io/istio/tools/istio-iptables/pkg/validation" 30 ) 31 32 const InvalidDropByIptables = "INVALID_DROP" 33 34 func handleErrorWithCode(err error, code int) { 35 log.Error(err) 36 os.Exit(code) 37 } 38 39 func bindCmdlineFlags(cfg *config.Config, cmd *cobra.Command) { 40 fs := cmd.Flags() 41 flag.Bind(fs, constants.EnvoyPort, "p", "Specify the envoy port to which redirect all TCP traffic.", &cfg.ProxyPort) 42 43 flag.BindEnv(fs, constants.InboundCapturePort, "z", 44 "Port to which all inbound TCP traffic to the pod/VM should be redirected to.", 45 &cfg.InboundCapturePort) 46 47 flag.BindEnv(fs, constants.InboundTunnelPort, "e", 48 "Specify the istio tunnel port for inbound tcp traffic.", 49 &cfg.InboundTunnelPort) 50 51 flag.BindEnv(fs, constants.ProxyUID, "u", 52 "Specify the UID of the user for which the redirection is not applied. Typically, this is the UID of the proxy container.", 53 &cfg.ProxyUID) 54 55 flag.BindEnv(fs, constants.ProxyGID, "g", 56 "Specify the GID of the user for which the redirection is not applied (same default value as -u param).", 57 &cfg.ProxyGID) 58 59 flag.BindEnv(fs, constants.InboundInterceptionMode, "m", 60 "The mode used to redirect inbound connections to Envoy, either \"REDIRECT\" or \"TPROXY\".", 61 &cfg.InboundInterceptionMode) 62 63 flag.BindEnv(fs, constants.InboundPorts, "b", 64 "Comma separated list of inbound ports for which traffic is to be redirected to Envoy (optional). "+ 65 "The wildcard character \"*\" can be used to configure redirection for all ports. An empty list will disable.", 66 &cfg.InboundPortsInclude) 67 68 flag.BindEnv(fs, constants.LocalExcludePorts, "d", 69 "Comma separated list of inbound ports to be excluded from redirection to Envoy (optional). "+ 70 "Only applies when all inbound traffic (i.e. \"*\") is being redirected.", 71 &cfg.InboundPortsExclude) 72 73 flag.BindEnv(fs, constants.ExcludeInterfaces, "c", 74 "Comma separated list of NIC (optional). Neither inbound nor outbound traffic will be captured.", 75 &cfg.ExcludeInterfaces) 76 77 flag.BindEnv(fs, constants.ServiceCidr, "i", 78 "Comma separated list of IP ranges in CIDR form to redirect to envoy (optional). "+ 79 "The wildcard character \"*\" can be used to redirect all outbound traffic. An empty list will disable all outbound.", 80 &cfg.OutboundIPRangesInclude) 81 82 flag.BindEnv(fs, constants.ServiceExcludeCidr, "x", 83 "Comma separated list of IP ranges in CIDR form to be excluded from redirection. "+ 84 "Only applies when all outbound traffic (i.e. \"*\") is being redirected.", 85 &cfg.OutboundIPRangesExclude) 86 87 flag.BindEnv(fs, constants.OutboundPorts, "q", 88 "Comma separated list of outbound ports to be explicitly included for redirection to Envoy.", 89 &cfg.OutboundPortsInclude) 90 91 flag.BindEnv(fs, constants.LocalOutboundPortsExclude, "o", 92 "Comma separated list of outbound ports to be excluded from redirection to Envoy.", 93 &cfg.OutboundPortsExclude) 94 95 flag.BindEnv(fs, constants.KubeVirtInterfaces, "k", 96 "Comma separated list of virtual interfaces whose inbound traffic (from VM) will be treated as outbound.", 97 &cfg.KubeVirtInterfaces) 98 99 flag.BindEnv(fs, constants.InboundTProxyMark, "t", "", &cfg.InboundTProxyMark) 100 101 flag.BindEnv(fs, constants.InboundTProxyRouteTable, "r", "", &cfg.InboundTProxyRouteTable) 102 103 flag.BindEnv(fs, constants.DryRun, "n", "Do not call any external dependencies like iptables.", 104 &cfg.DryRun) 105 106 flag.BindEnv(fs, constants.TraceLogging, "", "Insert tracing logs for each iptables rules, using the LOG chain.", &cfg.TraceLogging) 107 108 flag.BindEnv(fs, constants.RestoreFormat, "f", "Print iptables rules in iptables-restore interpretable format.", 109 &cfg.RestoreFormat) 110 111 flag.BindEnv(fs, constants.IptablesProbePort, "", "Set listen port for failure detection.", &cfg.IptablesProbePort) 112 113 flag.BindEnv(fs, constants.ProbeTimeout, "", "Failure detection timeout.", &cfg.ProbeTimeout) 114 115 flag.BindEnv(fs, constants.SkipRuleApply, "", "Skip iptables apply.", &cfg.SkipRuleApply) 116 117 flag.BindEnv(fs, constants.RunValidation, "", "Validate iptables.", &cfg.RunValidation) 118 119 flag.BindEnv(fs, constants.RedirectDNS, "", "Enable capture of dns traffic by istio-agent.", &cfg.RedirectDNS) 120 // Allow binding to a different var, for consistency with other components 121 flag.AdditionalEnv(fs, constants.RedirectDNS, "ISTIO_META_DNS_CAPTURE") 122 123 flag.BindEnv(fs, constants.DropInvalid, "", "Enable invalid drop in the iptables rules.", &cfg.DropInvalid) 124 // This could have just used the default but for backwards compat we support the old env. 125 flag.AdditionalEnv(fs, constants.DropInvalid, InvalidDropByIptables) 126 127 flag.BindEnv(fs, constants.DualStack, "", "Enable ipv4/ipv6 redirects for dual-stack.", &cfg.DualStack) 128 // Allow binding to a different var, for consistency with other components 129 flag.AdditionalEnv(fs, constants.DualStack, "ISTIO_DUAL_STACK") 130 131 flag.BindEnv(fs, constants.CaptureAllDNS, "", 132 "Instead of only capturing DNS traffic to DNS server IP, capture all DNS traffic at port 53. This setting is only effective when redirect dns is enabled.", 133 &cfg.CaptureAllDNS) 134 135 flag.BindEnv(fs, constants.NetworkNamespace, "", "The network namespace that iptables rules should be applied to.", 136 &cfg.NetworkNamespace) 137 138 flag.BindEnv(fs, constants.CNIMode, "", "Whether to run as CNI plugin.", &cfg.CNIMode) 139 } 140 141 func GetCommand(logOpts *log.Options) *cobra.Command { 142 cfg := config.DefaultConfig() 143 cmd := &cobra.Command{ 144 Use: "istio-iptables", 145 Short: "Set up iptables rules for Istio Sidecar", 146 Long: "istio-iptables is responsible for setting up port forwarding for Istio Sidecar.", 147 PreRunE: func(cmd *cobra.Command, args []string) error { 148 if err := log.Configure(logOpts); err != nil { 149 return err 150 } 151 return nil 152 }, 153 Run: func(cmd *cobra.Command, args []string) { 154 if err := cfg.FillConfigFromEnvironment(); err != nil { 155 handleErrorWithCode(err, 1) 156 } 157 if err := cfg.Validate(); err != nil { 158 handleErrorWithCode(err, 1) 159 } 160 if err := ProgramIptables(cfg); err != nil { 161 handleErrorWithCode(err, 1) 162 } 163 164 if cfg.RunValidation { 165 validator := validation.NewValidator(cfg) 166 167 if err := validator.Run(); err != nil { 168 // nolint: revive, stylecheck 169 msg := fmt.Errorf(`iptables validation failed; workload is not ready for Istio. 170 When using Istio CNI, this can occur if a pod is scheduled before the node is ready. 171 172 If installed with 'cni.repair.deletePods=true', this pod should automatically be deleted and retry. 173 Otherwise, this pod will need to be manually removed so that it is scheduled on a node with istio-cni running, allowing iptables rules to be established. 174 `) 175 handleErrorWithCode(msg, constants.ValidationErrorCode) 176 } 177 } 178 }, 179 } 180 bindCmdlineFlags(cfg, cmd) 181 return cmd 182 } 183 184 type IptablesError struct { 185 Error error 186 ExitCode int 187 } 188 189 func ProgramIptables(cfg *config.Config) error { 190 var ext dep.Dependencies 191 if cfg.DryRun { 192 log.Info("running iptables in dry-run mode, no rule changes will be made") 193 ext = &dep.DependenciesStub{} 194 } else { 195 ext = &dep.RealDependencies{ 196 CNIMode: cfg.CNIMode, 197 NetworkNamespace: cfg.NetworkNamespace, 198 } 199 } 200 201 iptConfigurator := capture.NewIptablesConfigurator(cfg, ext) 202 203 if !cfg.SkipRuleApply { 204 if err := iptConfigurator.Run(); err != nil { 205 return err 206 } 207 if err := capture.ConfigureRoutes(cfg); err != nil { 208 return fmt.Errorf("failed to configure routes: %v", err) 209 } 210 } 211 return nil 212 }