k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/util/iptables/testing/fake_test.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 Copyright 2022 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package testing 21 22 import ( 23 "bytes" 24 "strings" 25 "testing" 26 27 "github.com/lithammer/dedent" 28 29 "k8s.io/kubernetes/pkg/util/iptables" 30 ) 31 32 func TestFakeIPTables(t *testing.T) { 33 fake := NewFake() 34 buf := bytes.NewBuffer(nil) 35 36 err := fake.SaveInto("", buf) 37 if err != nil { 38 t.Fatalf("unexpected error from SaveInto: %v", err) 39 } 40 expected := dedent.Dedent(strings.Trim(` 41 *nat 42 :PREROUTING - [0:0] 43 :INPUT - [0:0] 44 :OUTPUT - [0:0] 45 :POSTROUTING - [0:0] 46 COMMIT 47 *filter 48 :INPUT - [0:0] 49 :FORWARD - [0:0] 50 :OUTPUT - [0:0] 51 COMMIT 52 *mangle 53 COMMIT 54 `, "\n")) 55 if buf.String() != expected { 56 t.Fatalf("bad initial dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 57 } 58 59 // EnsureChain 60 existed, err := fake.EnsureChain(iptables.Table("blah"), iptables.Chain("KUBE-TEST")) 61 if err == nil { 62 t.Errorf("did not get expected error creating chain in non-existent table") 63 } else if existed { 64 t.Errorf("wrong return value from EnsureChain with non-existent table") 65 } 66 existed, err = fake.EnsureChain(iptables.TableNAT, iptables.Chain("KUBE-TEST")) 67 if err != nil { 68 t.Errorf("unexpected error creating chain: %v", err) 69 } else if existed { 70 t.Errorf("wrong return value from EnsureChain with non-existent chain") 71 } 72 existed, err = fake.EnsureChain(iptables.TableNAT, iptables.Chain("KUBE-TEST")) 73 if err != nil { 74 t.Errorf("unexpected error creating chain: %v", err) 75 } else if !existed { 76 t.Errorf("wrong return value from EnsureChain with existing chain") 77 } 78 79 // ChainExists 80 exists, err := fake.ChainExists(iptables.TableNAT, iptables.Chain("KUBE-TEST")) 81 if err != nil { 82 t.Errorf("unexpected error checking chain: %v", err) 83 } else if !exists { 84 t.Errorf("wrong return value from ChainExists with existing chain") 85 } 86 exists, err = fake.ChainExists(iptables.TableNAT, iptables.Chain("KUBE-TEST-NOT")) 87 if err != nil { 88 t.Errorf("unexpected error checking chain: %v", err) 89 } else if exists { 90 t.Errorf("wrong return value from ChainExists with non-existent chain") 91 } 92 93 // EnsureRule 94 existed, err = fake.EnsureRule(iptables.Append, iptables.Table("blah"), iptables.Chain("KUBE-TEST"), "-j", "ACCEPT") 95 if err == nil { 96 t.Errorf("did not get expected error creating rule in non-existent table") 97 } else if existed { 98 t.Errorf("wrong return value from EnsureRule with non-existent table") 99 } 100 existed, err = fake.EnsureRule(iptables.Append, iptables.TableNAT, iptables.Chain("KUBE-TEST-NOT"), "-j", "ACCEPT") 101 if err == nil { 102 t.Errorf("did not get expected error creating rule in non-existent chain") 103 } else if existed { 104 t.Errorf("wrong return value from EnsureRule with non-existent chain") 105 } 106 existed, err = fake.EnsureRule(iptables.Append, iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "ACCEPT") 107 if err != nil { 108 t.Errorf("unexpected error creating rule: %v", err) 109 } else if existed { 110 t.Errorf("wrong return value from EnsureRule with non-existent rule") 111 } 112 existed, err = fake.EnsureRule(iptables.Prepend, iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "DROP") 113 if err != nil { 114 t.Errorf("unexpected error creating rule: %v", err) 115 } else if existed { 116 t.Errorf("wrong return value from EnsureRule with non-existent rule") 117 } 118 existed, err = fake.EnsureRule(iptables.Append, iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "DROP") 119 if err != nil { 120 t.Errorf("unexpected error creating rule: %v", err) 121 } else if !existed { 122 t.Errorf("wrong return value from EnsureRule with already-existing rule") 123 } 124 125 // Sanity-check... 126 buf.Reset() 127 err = fake.SaveInto("", buf) 128 if err != nil { 129 t.Fatalf("unexpected error from SaveInto: %v", err) 130 } 131 expected = dedent.Dedent(strings.Trim(` 132 *nat 133 :PREROUTING - [0:0] 134 :INPUT - [0:0] 135 :OUTPUT - [0:0] 136 :POSTROUTING - [0:0] 137 :KUBE-TEST - [0:0] 138 -A KUBE-TEST -j DROP 139 -A KUBE-TEST -j ACCEPT 140 COMMIT 141 *filter 142 :INPUT - [0:0] 143 :FORWARD - [0:0] 144 :OUTPUT - [0:0] 145 COMMIT 146 *mangle 147 COMMIT 148 `, "\n")) 149 if buf.String() != expected { 150 t.Fatalf("bad sanity-check dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 151 } 152 153 // DeleteRule 154 err = fake.DeleteRule(iptables.Table("blah"), iptables.Chain("KUBE-TEST"), "-j", "DROP") 155 if err == nil { 156 t.Errorf("did not get expected error deleting rule in non-existent table") 157 } 158 err = fake.DeleteRule(iptables.TableNAT, iptables.Chain("KUBE-TEST-NOT"), "-j", "DROP") 159 if err == nil { 160 t.Errorf("did not get expected error deleting rule in non-existent chain") 161 } 162 err = fake.DeleteRule(iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "DROPLET") 163 if err != nil { 164 t.Errorf("unexpected error deleting non-existent rule: %v", err) 165 } 166 err = fake.DeleteRule(iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "DROP") 167 if err != nil { 168 t.Errorf("unexpected error deleting rule: %v", err) 169 } 170 171 // Restore 172 rules := dedent.Dedent(strings.Trim(` 173 *nat 174 :KUBE-RESTORED - [0:0] 175 :KUBE-MISC-CHAIN - [0:0] 176 :KUBE-MISC-TWO - [0:0] 177 :KUBE-EMPTY - [0:0] 178 -A KUBE-RESTORED -m comment --comment "restored chain" -j ACCEPT 179 -A KUBE-MISC-CHAIN -s 1.2.3.4 -j KUBE-MISC-TWO 180 -A KUBE-MISC-CHAIN -d 5.6.7.8 -j MASQUERADE 181 -A KUBE-MISC-TWO -j ACCEPT 182 COMMIT 183 `, "\n")) 184 err = fake.Restore(iptables.TableNAT, []byte(rules), iptables.NoFlushTables, iptables.NoRestoreCounters) 185 if err != nil { 186 t.Fatalf("unexpected error from Restore: %v", err) 187 } 188 189 // We used NoFlushTables, so this should leave KUBE-TEST unchanged 190 buf.Reset() 191 err = fake.SaveInto("", buf) 192 if err != nil { 193 t.Fatalf("unexpected error from SaveInto: %v", err) 194 } 195 expected = dedent.Dedent(strings.Trim(` 196 *nat 197 :PREROUTING - [0:0] 198 :INPUT - [0:0] 199 :OUTPUT - [0:0] 200 :POSTROUTING - [0:0] 201 :KUBE-TEST - [0:0] 202 :KUBE-RESTORED - [0:0] 203 :KUBE-MISC-CHAIN - [0:0] 204 :KUBE-MISC-TWO - [0:0] 205 :KUBE-EMPTY - [0:0] 206 -A KUBE-TEST -j ACCEPT 207 -A KUBE-RESTORED -m comment --comment "restored chain" -j ACCEPT 208 -A KUBE-MISC-CHAIN -s 1.2.3.4 -j KUBE-MISC-TWO 209 -A KUBE-MISC-CHAIN -d 5.6.7.8 -j MASQUERADE 210 -A KUBE-MISC-TWO -j ACCEPT 211 COMMIT 212 *filter 213 :INPUT - [0:0] 214 :FORWARD - [0:0] 215 :OUTPUT - [0:0] 216 COMMIT 217 *mangle 218 COMMIT 219 `, "\n")) 220 if buf.String() != expected { 221 t.Fatalf("bad post-restore dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 222 } 223 224 // Trying to use Restore to delete a chain that another chain jumps to will fail 225 rules = dedent.Dedent(strings.Trim(` 226 *nat 227 :KUBE-MISC-TWO - [0:0] 228 -X KUBE-MISC-TWO 229 COMMIT 230 `, "\n")) 231 err = fake.Restore(iptables.TableNAT, []byte(rules), iptables.NoFlushTables, iptables.RestoreCounters) 232 if err == nil || !strings.Contains(err.Error(), "referenced by existing rules") { 233 t.Fatalf("Expected 'referenced by existing rules' error from Restore, got %v", err) 234 } 235 236 // Trying to use Restore to add a jump to a non-existent chain will fail 237 rules = dedent.Dedent(strings.Trim(` 238 *nat 239 :KUBE-MISC-TWO - [0:0] 240 -A KUBE-MISC-TWO -j KUBE-MISC-THREE 241 COMMIT 242 `, "\n")) 243 err = fake.Restore(iptables.TableNAT, []byte(rules), iptables.NoFlushTables, iptables.RestoreCounters) 244 if err == nil || !strings.Contains(err.Error(), "non-existent chain") { 245 t.Fatalf("Expected 'non-existent chain' error from Restore, got %v", err) 246 } 247 248 // more Restore; empty out one chain and delete another, but also update its counters 249 rules = dedent.Dedent(strings.Trim(` 250 *nat 251 :KUBE-RESTORED - [0:0] 252 :KUBE-TEST - [99:9999] 253 -X KUBE-RESTORED 254 COMMIT 255 `, "\n")) 256 err = fake.Restore(iptables.TableNAT, []byte(rules), iptables.NoFlushTables, iptables.RestoreCounters) 257 if err != nil { 258 t.Fatalf("unexpected error from Restore: %v", err) 259 } 260 261 buf.Reset() 262 err = fake.SaveInto("", buf) 263 if err != nil { 264 t.Fatalf("unexpected error from SaveInto: %v", err) 265 } 266 expected = dedent.Dedent(strings.Trim(` 267 *nat 268 :PREROUTING - [0:0] 269 :INPUT - [0:0] 270 :OUTPUT - [0:0] 271 :POSTROUTING - [0:0] 272 :KUBE-TEST - [99:9999] 273 :KUBE-MISC-CHAIN - [0:0] 274 :KUBE-MISC-TWO - [0:0] 275 :KUBE-EMPTY - [0:0] 276 -A KUBE-MISC-CHAIN -s 1.2.3.4 -j KUBE-MISC-TWO 277 -A KUBE-MISC-CHAIN -d 5.6.7.8 -j MASQUERADE 278 -A KUBE-MISC-TWO -j ACCEPT 279 COMMIT 280 *filter 281 :INPUT - [0:0] 282 :FORWARD - [0:0] 283 :OUTPUT - [0:0] 284 COMMIT 285 *mangle 286 COMMIT 287 `, "\n")) 288 if buf.String() != expected { 289 t.Fatalf("bad post-second-restore dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 290 } 291 292 // RestoreAll, FlushTables 293 rules = dedent.Dedent(strings.Trim(` 294 *filter 295 :INPUT - [0:0] 296 :FORWARD - [0:0] 297 :OUTPUT - [0:0] 298 :KUBE-TEST - [0:0] 299 -A KUBE-TEST -m comment --comment "filter table KUBE-TEST" -j ACCEPT 300 COMMIT 301 *nat 302 :PREROUTING - [0:0] 303 :INPUT - [0:0] 304 :OUTPUT - [0:0] 305 :POSTROUTING - [0:0] 306 :KUBE-TEST - [88:8888] 307 :KUBE-NEW-CHAIN - [0:0] 308 -A KUBE-NEW-CHAIN -d 172.30.0.1 -j DNAT --to-destination 10.0.0.1 309 -A KUBE-NEW-CHAIN -d 172.30.0.2 -j DNAT --to-destination 10.0.0.2 310 -A KUBE-NEW-CHAIN -d 172.30.0.3 -j DNAT --to-destination 10.0.0.3 311 COMMIT 312 `, "\n")) 313 err = fake.RestoreAll([]byte(rules), iptables.FlushTables, iptables.NoRestoreCounters) 314 if err != nil { 315 t.Fatalf("unexpected error from RestoreAll: %v", err) 316 } 317 318 buf.Reset() 319 err = fake.SaveInto("", buf) 320 if err != nil { 321 t.Fatalf("unexpected error from SaveInto: %v", err) 322 } 323 expected = dedent.Dedent(strings.Trim(` 324 *nat 325 :PREROUTING - [0:0] 326 :INPUT - [0:0] 327 :OUTPUT - [0:0] 328 :POSTROUTING - [0:0] 329 :KUBE-TEST - [88:8888] 330 :KUBE-NEW-CHAIN - [0:0] 331 -A KUBE-NEW-CHAIN -d 172.30.0.1 -j DNAT --to-destination 10.0.0.1 332 -A KUBE-NEW-CHAIN -d 172.30.0.2 -j DNAT --to-destination 10.0.0.2 333 -A KUBE-NEW-CHAIN -d 172.30.0.3 -j DNAT --to-destination 10.0.0.3 334 COMMIT 335 *filter 336 :INPUT - [0:0] 337 :FORWARD - [0:0] 338 :OUTPUT - [0:0] 339 :KUBE-TEST - [0:0] 340 -A KUBE-TEST -m comment --comment "filter table KUBE-TEST" -j ACCEPT 341 COMMIT 342 *mangle 343 COMMIT 344 `, "\n")) 345 if buf.String() != expected { 346 t.Fatalf("bad post-restore-all dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 347 } 348 }