github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/supervisor/iptablesctrl/instance.go (about) 1 package iptablesctrl 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "strings" 8 9 "go.aporeto.io/enforcerd/trireme-lib/controller/constants" 10 provider "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/aclprovider" 11 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/ebpf" 12 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/fqconfig" 13 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/ipsetmanager" 14 "go.aporeto.io/enforcerd/trireme-lib/controller/runtime" 15 "go.aporeto.io/enforcerd/trireme-lib/policy" 16 "go.uber.org/zap" 17 ) 18 19 const ( 20 //IPV4 version for ipv4 21 IPV4 = iota 22 //IPV6 version for ipv6 23 IPV6 24 ) 25 26 //Instance is the structure holding the ipv4 and ipv6 handles 27 type Instance struct { 28 iptv4 *iptables 29 iptv6 *iptables 30 } 31 32 // SetTargetNetworks updates ths target networks. There are three different 33 // types of target networks: 34 // - TCPTargetNetworks for TCP traffic (by default 0.0.0.0/0) 35 // - UDPTargetNetworks for UDP traffic (by default empty) 36 // - ExcludedNetworks that are always ignored (by default empty) 37 func (i *Instance) SetTargetNetworks(c *runtime.Configuration) error { 38 39 if err := i.iptv4.SetTargetNetworks(c); err != nil { 40 return err 41 } 42 43 if err := i.iptv6.SetTargetNetworks(c); err != nil { 44 return err 45 } 46 47 return nil 48 } 49 50 // Run starts the iptables controller 51 func (i *Instance) Run(ctx context.Context) error { 52 53 if err := i.iptv4.Run(ctx); err != nil { 54 return err 55 } 56 57 if err := i.iptv6.Run(ctx); err != nil { 58 return err 59 } 60 61 return nil 62 } 63 64 // ConfigureRules implments the ConfigureRules interface. It will create the 65 // port sets and then it will call install rules to create all the ACLs for 66 // the given chains. PortSets are only created here. Updates will use the 67 // exact same logic. 68 func (i *Instance) ConfigureRules(version int, contextID string, pu *policy.PUInfo) error { 69 if err := i.iptv4.ConfigureRules(version, contextID, pu); err != nil { 70 return err 71 } 72 73 if err := i.iptv6.ConfigureRules(version, contextID, pu); err != nil { 74 return err 75 } 76 77 return nil 78 } 79 80 // DeleteRules implements the DeleteRules interface. This is responsible 81 // for cleaning all ACLs and associated chains, as well as ll the sets 82 // that we have created. Note, that this only clears up the state 83 // for a given processing unit. 84 func (i *Instance) DeleteRules(version int, contextID string, tcpPorts, udpPorts string, mark string, username string, containerInfo *policy.PUInfo) error { 85 86 if err := i.iptv4.DeleteRules(version, contextID, tcpPorts, udpPorts, mark, username, containerInfo); err != nil { 87 zap.L().Warn("Delete rules for iptables v4 returned error") 88 } 89 90 if err := i.iptv6.DeleteRules(version, contextID, tcpPorts, udpPorts, mark, username, containerInfo); err != nil { 91 zap.L().Warn("Delete rules for iptables v6 returned error") 92 } 93 94 return nil 95 } 96 97 // UpdateRules implements the update part of the interface. Update will call 98 // installrules to install the new rules and then it will delete the old rules. 99 // For installations that do not have latests iptables-restore we time 100 // the operations so that the switch is almost atomic, by creating the new rules 101 // first. For latest kernel versions iptables-restorce will update all the rules 102 // in one shot. 103 func (i *Instance) UpdateRules(version int, contextID string, containerInfo *policy.PUInfo, oldContainerInfo *policy.PUInfo) error { 104 105 if err := i.iptv4.UpdateRules(version, contextID, containerInfo, oldContainerInfo); err != nil { 106 return err 107 } 108 109 if err := i.iptv6.UpdateRules(version, contextID, containerInfo, oldContainerInfo); err != nil { 110 return err 111 } 112 113 return nil 114 } 115 116 // CleanUp requires the implementor to clean up all ACLs and destroy all 117 // the IP sets. 118 func (i *Instance) CleanUp() error { 119 120 if err := i.iptv4.CleanUp(); err != nil { 121 zap.L().Error("Failed to cleanup ipv4 rules") 122 } 123 124 if err := i.iptv6.CleanUp(); err != nil { 125 zap.L().Error("Failed to cleanup ipv6 rules") 126 } 127 128 return nil 129 } 130 131 // CreateCustomRulesChain creates a custom rules chain if it doesnt exist 132 func (i *Instance) CreateCustomRulesChain() error { 133 nonbatchedv4tableprovider, _ := provider.NewGoIPTablesProviderV4([]string{}, CustomQOSChain) 134 nonbatchedv6tableprovider, _ := provider.NewGoIPTablesProviderV6([]string{}, CustomQOSChain) 135 err := nonbatchedv4tableprovider.NewChain(customQOSChainTable, CustomQOSChain) 136 if err != nil { 137 zap.L().Debug("Chain already exists", zap.Error(err)) 138 139 } 140 postroutingchainrulesv4, err := nonbatchedv4tableprovider.ListRules(customQOSChainTable, customQOSChainNFHook) 141 if err != nil { 142 zap.L().Error("ListRules returned error", zap.Error(err)) 143 return err 144 } 145 checkCustomRulesv4 := func() bool { 146 for _, rule := range postroutingchainrulesv4 { 147 if strings.Contains(rule, CustomQOSChain) { 148 return true 149 } 150 } 151 return false 152 } 153 if !checkCustomRulesv4() { 154 if err := nonbatchedv4tableprovider.Insert(customQOSChainTable, customQOSChainNFHook, 1, 155 "-m", "addrtype", 156 "--src-type", "LOCAL", 157 "-j", CustomQOSChain, 158 ); err != nil { 159 zap.L().Debug("Unable to create ipv4 custom rule", zap.Error(err)) 160 } 161 } 162 163 err = nonbatchedv6tableprovider.NewChain(customQOSChainTable, CustomQOSChain) 164 if err != nil { 165 zap.L().Debug("Chain already exists", zap.Error(err)) 166 } 167 postroutingchainrulesv6, err := nonbatchedv6tableprovider.ListRules(customQOSChainTable, customQOSChainNFHook) 168 if err != nil { 169 return err 170 } 171 checkCustomRulesv6 := func() bool { 172 for _, rule := range postroutingchainrulesv6 { 173 if strings.Contains(rule, CustomQOSChain) { 174 return true 175 } 176 } 177 return false 178 } 179 if !checkCustomRulesv6() { 180 if err := nonbatchedv6tableprovider.Append(customQOSChainTable, customQOSChainNFHook, 181 "-m", "addrtype", 182 "--src-type", "LOCAL", 183 "-j", CustomQOSChain, 184 ); err != nil { 185 zap.L().Debug("Unable to create ipv6 custom rule", zap.Error(err)) 186 } 187 } 188 189 return nil 190 } 191 192 // NewInstance creates a new iptables controller instance 193 func NewInstance(fqc fqconfig.FilterQueue, mode constants.ModeType, ipv6Enabled bool, ebpf ebpf.BPFModule, iptablesLockfile string, serviceMeshType policy.ServiceMesh) (*Instance, error) { 194 195 // our iptables binary `aporeto-iptables` uses the environment variable XT_LOCK_NAME 196 // to set the iptables lockfile. Standard iptables does not look at this environment variable 197 if iptablesLockfile != "" { 198 if err := os.Setenv("XT_LOCK_NAME", iptablesLockfile); err != nil { 199 return nil, fmt.Errorf("unable to set XT_LOCK_NAME: %s", err) 200 } 201 } 202 203 ipv4Impl, err := GetIPv4Impl() 204 if err != nil { 205 return nil, fmt.Errorf("unable to create ipv4 instance: %s", err) 206 } 207 208 ipsetV4 := ipsetmanager.V4() 209 iptInstanceV4 := createIPInstance(ipv4Impl, ipsetV4, fqc, mode, ebpf, serviceMeshType) 210 211 ipv6Impl, err := GetIPv6Impl(ipv6Enabled) 212 if err != nil { 213 return nil, fmt.Errorf("unable to create ipv6 instance: %s", err) 214 } 215 216 ipsetV6 := ipsetmanager.V6() 217 iptInstanceV6 := createIPInstance(ipv6Impl, ipsetV6, fqc, mode, ebpf, serviceMeshType) 218 219 return newInstanceWithProviders(iptInstanceV4, iptInstanceV6) 220 } 221 222 // newInstanceWithProviders is called after ipt and ips have been created. This helps 223 // with all the unit testing to be able to mock the providers. 224 func newInstanceWithProviders(iptv4 *iptables, iptv6 *iptables) (*Instance, error) { 225 226 i := &Instance{ 227 iptv4: iptv4, 228 iptv6: iptv6, 229 } 230 231 return i, nil 232 } 233 234 // ACLProvider returns the current ACL provider that can be re-used by other entities. 235 func (i *Instance) ACLProvider() []provider.IptablesProvider { 236 return []provider.IptablesProvider{i.iptv4.impl, i.iptv6.impl} 237 }