gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/iptables/iptables_test.go (about) 1 // Copyright 2019 The gVisor 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 iptables 16 17 import ( 18 "context" 19 "errors" 20 "fmt" 21 "net" 22 "slices" 23 "sync" 24 "testing" 25 26 "gvisor.dev/gvisor/pkg/log" 27 "gvisor.dev/gvisor/pkg/test/dockerutil" 28 "gvisor.dev/gvisor/pkg/test/testutil" 29 ) 30 31 // singleTest runs a TestCase. Each test follows a pattern: 32 // - Create a container. 33 // - Get the container's IP. 34 // - Send the container our IP. 35 // - Start a new goroutine running the local action of the test. 36 // - Wait for both the container and local actions to finish. 37 // 38 // Container output is logged to $TEST_UNDECLARED_OUTPUTS_DIR if it exists, or 39 // to stderr. 40 func singleTest(t *testing.T, test TestCase) { 41 for _, tc := range []bool{false, true} { 42 subtest := "IPv4" 43 if tc { 44 subtest = "IPv6" 45 } 46 t.Run(subtest, func(t *testing.T) { 47 iptablesTest(t, test, tc) 48 }) 49 } 50 } 51 52 func iptablesTest(t *testing.T, test TestCase, ipv6 bool) { 53 if _, ok := Tests[test.Name()]; !ok { 54 log.Infof("no test found with name %q. Has it been registered?", test.Name()) 55 t.FailNow() 56 } 57 58 // Wait for the local and container goroutines to finish. 59 var wg sync.WaitGroup 60 defer wg.Wait() 61 62 ctx, cancel := context.WithTimeout(context.Background(), TestTimeout) 63 defer cancel() 64 65 d := dockerutil.MakeContainer(ctx, t) 66 defer func() { 67 if logs, err := d.Logs(context.Background()); err != nil { 68 log.Infof("Failed to retrieve container logs.") 69 } else { 70 log.Infof("=== Container logs: ===\n%s", logs) 71 } 72 // Use a new context, as cleanup should run even when we 73 // timeout. 74 d.CleanUp(context.Background()) 75 }() 76 77 // Create and start the container. 78 opts := dockerutil.RunOpts{ 79 Image: "iptables", 80 CapAdd: []string{"NET_ADMIN"}, 81 } 82 d.CopyFiles(&opts, "/runner", "test/iptables/runner/runner") 83 args := []string{"/runner/runner", "-name", test.Name()} 84 if ipv6 { 85 args = append(args, "-ipv6") 86 } 87 if err := d.Spawn(ctx, opts, args...); err != nil { 88 log.Infof("docker run failed: %v", err) 89 t.FailNow() 90 } 91 92 // Get the container IP. 93 ip, err := d.FindIP(ctx, ipv6) 94 if err != nil { 95 // If ipv6 is not configured, don't fail. 96 if ipv6 && err == dockerutil.ErrNoIP { 97 log.Infof("No ipv6 address is available.") 98 t.Skip() 99 } 100 log.Infof("failed to get container IP: %v", err) 101 t.FailNow() 102 } 103 104 // Give the container our IP. 105 if err := sendIP(ip); err != nil { 106 log.Infof("failed to send IP to container: %v", err) 107 t.FailNow() 108 } 109 110 // Run our side of the test. 111 errCh := make(chan error, 2) 112 wg.Add(1) 113 go func() { 114 defer wg.Done() 115 if err := test.LocalAction(ctx, ip, ipv6); err != nil && !errors.Is(err, context.Canceled) { 116 errCh <- fmt.Errorf("LocalAction failed: %v", err) 117 } else { 118 errCh <- nil 119 } 120 if test.LocalSufficient() { 121 errCh <- nil 122 } 123 }() 124 125 // Run the container side. 126 wg.Add(1) 127 go func() { 128 defer wg.Done() 129 // Wait for the final statement. This structure has the side 130 // effect that all container logs will appear within the 131 // individual test context. 132 if _, err := d.WaitForOutput(ctx, TerminalStatement, TestTimeout); err != nil && !errors.Is(err, context.Canceled) { 133 errCh <- fmt.Errorf("ContainerAction failed: %v", err) 134 } else { 135 errCh <- nil 136 } 137 if test.ContainerSufficient() { 138 errCh <- nil 139 } 140 }() 141 142 for i := 0; i < 2; i++ { 143 select { 144 case err := <-errCh: 145 if err != nil { 146 t.Fatal(err) 147 } 148 } 149 } 150 } 151 152 func sendIP(ip net.IP) error { 153 contAddr := net.TCPAddr{ 154 IP: ip, 155 Port: IPExchangePort, 156 } 157 var conn *net.TCPConn 158 // The container may not be listening when we first connect, so retry 159 // upon error. 160 cb := func() error { 161 c, err := net.DialTCP("tcp", nil, &contAddr) 162 conn = c 163 return err 164 } 165 if err := testutil.Poll(cb, TestTimeout); err != nil { 166 return fmt.Errorf("timed out waiting to send IP, most recent error: %v", err) 167 } 168 if _, err := conn.Write([]byte{0}); err != nil { 169 return fmt.Errorf("error writing to container: %v", err) 170 } 171 return nil 172 } 173 174 func TestFilterInputDropUDP(t *testing.T) { 175 singleTest(t, &FilterInputDropUDP{}) 176 } 177 178 func TestFilterInputDropUDPPort(t *testing.T) { 179 singleTest(t, &FilterInputDropUDPPort{}) 180 } 181 182 func TestFilterInputDropDifferentUDPPort(t *testing.T) { 183 singleTest(t, &FilterInputDropDifferentUDPPort{}) 184 } 185 186 func TestFilterInputDropAll(t *testing.T) { 187 singleTest(t, &FilterInputDropAll{}) 188 } 189 190 func TestFilterInputDropOnlyUDP(t *testing.T) { 191 singleTest(t, &FilterInputDropOnlyUDP{}) 192 } 193 194 func TestFilterInputDropTCPDestPort(t *testing.T) { 195 singleTest(t, &FilterInputDropTCPDestPort{}) 196 } 197 198 func TestFilterInputDropTCPSrcPort(t *testing.T) { 199 singleTest(t, &FilterInputDropTCPSrcPort{}) 200 } 201 202 func TestFilterInputCreateUserChain(t *testing.T) { 203 singleTest(t, &FilterInputCreateUserChain{}) 204 } 205 206 func TestFilterInputDefaultPolicyAccept(t *testing.T) { 207 singleTest(t, &FilterInputDefaultPolicyAccept{}) 208 } 209 210 func TestFilterInputDefaultPolicyDrop(t *testing.T) { 211 singleTest(t, &FilterInputDefaultPolicyDrop{}) 212 } 213 214 func TestFilterInputReturnUnderflow(t *testing.T) { 215 singleTest(t, &FilterInputReturnUnderflow{}) 216 } 217 218 func TestFilterOutputDropTCPDestPort(t *testing.T) { 219 singleTest(t, &FilterOutputDropTCPDestPort{}) 220 } 221 222 func TestFilterOutputDropTCPSrcPort(t *testing.T) { 223 singleTest(t, &FilterOutputDropTCPSrcPort{}) 224 } 225 226 func TestFilterOutputAcceptTCPOwner(t *testing.T) { 227 singleTest(t, &FilterOutputAcceptTCPOwner{}) 228 } 229 230 func TestFilterOutputDropTCPOwner(t *testing.T) { 231 singleTest(t, &FilterOutputDropTCPOwner{}) 232 } 233 234 func TestFilterOutputAcceptUDPOwner(t *testing.T) { 235 singleTest(t, &FilterOutputAcceptUDPOwner{}) 236 } 237 238 func TestFilterOutputDropUDPOwner(t *testing.T) { 239 singleTest(t, &FilterOutputDropUDPOwner{}) 240 } 241 242 func TestFilterOutputOwnerFail(t *testing.T) { 243 singleTest(t, &FilterOutputOwnerFail{}) 244 } 245 246 func TestFilterOutputAcceptGIDOwner(t *testing.T) { 247 singleTest(t, &FilterOutputAcceptGIDOwner{}) 248 } 249 250 func TestFilterOutputDropGIDOwner(t *testing.T) { 251 singleTest(t, &FilterOutputDropGIDOwner{}) 252 } 253 254 func TestFilterOutputInvertGIDOwner(t *testing.T) { 255 singleTest(t, &FilterOutputInvertGIDOwner{}) 256 } 257 258 func TestFilterOutputInvertUIDOwner(t *testing.T) { 259 singleTest(t, &FilterOutputInvertUIDOwner{}) 260 } 261 262 func TestFilterOutputInvertUIDAndGIDOwner(t *testing.T) { 263 singleTest(t, &FilterOutputInvertUIDAndGIDOwner{}) 264 } 265 266 func TestFilterOutputInterfaceAccept(t *testing.T) { 267 singleTest(t, &FilterOutputInterfaceAccept{}) 268 } 269 270 func TestFilterOutputInterfaceDrop(t *testing.T) { 271 singleTest(t, &FilterOutputInterfaceDrop{}) 272 } 273 274 func TestFilterOutputInterface(t *testing.T) { 275 singleTest(t, &FilterOutputInterface{}) 276 } 277 278 func TestFilterOutputInterfaceBeginsWith(t *testing.T) { 279 singleTest(t, &FilterOutputInterfaceBeginsWith{}) 280 } 281 282 func TestFilterOutputInterfaceInvertDrop(t *testing.T) { 283 singleTest(t, &FilterOutputInterfaceInvertDrop{}) 284 } 285 286 func TestFilterOutputInterfaceInvertAccept(t *testing.T) { 287 singleTest(t, &FilterOutputInterfaceInvertAccept{}) 288 } 289 290 func TestFilterOutputInvertSportAccept(t *testing.T) { 291 singleTest(t, &FilterOutputInvertSportAccept{}) 292 } 293 294 func TestFilterOutputInvertSportDrop(t *testing.T) { 295 singleTest(t, &FilterOutputInvertSportDrop{}) 296 } 297 298 func TestJumpSerialize(t *testing.T) { 299 singleTest(t, &FilterInputSerializeJump{}) 300 } 301 302 func TestJumpBasic(t *testing.T) { 303 singleTest(t, &FilterInputJumpBasic{}) 304 } 305 306 func TestJumpReturn(t *testing.T) { 307 singleTest(t, &FilterInputJumpReturn{}) 308 } 309 310 func TestJumpReturnDrop(t *testing.T) { 311 singleTest(t, &FilterInputJumpReturnDrop{}) 312 } 313 314 func TestJumpBuiltin(t *testing.T) { 315 singleTest(t, &FilterInputJumpBuiltin{}) 316 } 317 318 func TestJumpTwice(t *testing.T) { 319 singleTest(t, &FilterInputJumpTwice{}) 320 } 321 322 func TestInputDestination(t *testing.T) { 323 singleTest(t, &FilterInputDestination{}) 324 } 325 326 func TestInputInvertDestination(t *testing.T) { 327 singleTest(t, &FilterInputInvertDestination{}) 328 } 329 330 func TestFilterOutputDestination(t *testing.T) { 331 singleTest(t, &FilterOutputDestination{}) 332 } 333 334 func TestFilterOutputInvertDestination(t *testing.T) { 335 singleTest(t, &FilterOutputInvertDestination{}) 336 } 337 338 func TestNATPreRedirectUDPPort(t *testing.T) { 339 singleTest(t, &NATPreRedirectUDPPort{}) 340 } 341 342 func TestNATPreRedirectTCPPort(t *testing.T) { 343 singleTest(t, &NATPreRedirectTCPPort{}) 344 } 345 346 func TestNATPreRedirectTCPOutgoing(t *testing.T) { 347 singleTest(t, &NATPreRedirectTCPOutgoing{}) 348 } 349 350 func TestNATOutRedirectTCPIncoming(t *testing.T) { 351 singleTest(t, &NATOutRedirectTCPIncoming{}) 352 } 353 func TestNATOutRedirectUDPPort(t *testing.T) { 354 singleTest(t, &NATOutRedirectUDPPort{}) 355 } 356 357 func TestNATOutRedirectTCPPort(t *testing.T) { 358 singleTest(t, &NATOutRedirectTCPPort{}) 359 } 360 361 func TestNATDropUDP(t *testing.T) { 362 singleTest(t, &NATDropUDP{}) 363 } 364 365 func TestNATAcceptAll(t *testing.T) { 366 singleTest(t, &NATAcceptAll{}) 367 } 368 369 func TestNATOutRedirectIP(t *testing.T) { 370 singleTest(t, &NATOutRedirectIP{}) 371 } 372 373 func TestNATOutDontRedirectIP(t *testing.T) { 374 singleTest(t, &NATOutDontRedirectIP{}) 375 } 376 377 func TestNATOutRedirectInvert(t *testing.T) { 378 singleTest(t, &NATOutRedirectInvert{}) 379 } 380 381 func TestNATOutDNAT(t *testing.T) { 382 singleTest(t, &NATOutDNAT{}) 383 } 384 385 func TestNATOutDNATAddrOnly(t *testing.T) { 386 singleTest(t, &NATOutDNATAddrOnly{}) 387 } 388 389 func TestNATOutDNATPortOnly(t *testing.T) { 390 singleTest(t, &NATOutDNATPortOnly{}) 391 } 392 393 func TestNATPreRedirectIP(t *testing.T) { 394 singleTest(t, &NATPreRedirectIP{}) 395 } 396 397 func TestNATPreDontRedirectIP(t *testing.T) { 398 singleTest(t, &NATPreDontRedirectIP{}) 399 } 400 401 func TestNATPreRedirectInvert(t *testing.T) { 402 singleTest(t, &NATPreRedirectInvert{}) 403 } 404 405 func TestNATRedirectRequiresProtocol(t *testing.T) { 406 singleTest(t, &NATRedirectRequiresProtocol{}) 407 } 408 409 func TestNATLoopbackSkipsPrerouting(t *testing.T) { 410 singleTest(t, &NATLoopbackSkipsPrerouting{}) 411 } 412 413 func TestInputSource(t *testing.T) { 414 singleTest(t, &FilterInputSource{}) 415 } 416 417 func TestInputInvertSource(t *testing.T) { 418 singleTest(t, &FilterInputInvertSource{}) 419 } 420 421 func TestInputInterfaceAccept(t *testing.T) { 422 singleTest(t, &FilterInputInterfaceAccept{}) 423 } 424 425 func TestInputInterfaceDrop(t *testing.T) { 426 singleTest(t, &FilterInputInterfaceDrop{}) 427 } 428 429 func TestInputInterface(t *testing.T) { 430 singleTest(t, &FilterInputInterface{}) 431 } 432 433 func TestInputInterfaceBeginsWith(t *testing.T) { 434 singleTest(t, &FilterInputInterfaceBeginsWith{}) 435 } 436 437 func TestInputInterfaceInvertDrop(t *testing.T) { 438 singleTest(t, &FilterInputInterfaceInvertDrop{}) 439 } 440 441 func TestInputInterfaceInvertAccept(t *testing.T) { 442 singleTest(t, &FilterInputInterfaceInvertAccept{}) 443 } 444 445 func TestFilterInputInvertDportAccept(t *testing.T) { 446 singleTest(t, &FilterInputInvertDportAccept{}) 447 } 448 449 func TestFilterInputInvertDportDrop(t *testing.T) { 450 singleTest(t, &FilterInputInvertDportDrop{}) 451 } 452 453 func TestFilterAddrs(t *testing.T) { 454 tcs := []struct { 455 ipv6 bool 456 addrs []string 457 want []string 458 }{ 459 { 460 ipv6: false, 461 addrs: []string{"192.168.0.1", "192.168.0.2/24", "::1", "::2/128"}, 462 want: []string{"192.168.0.1", "192.168.0.2"}, 463 }, 464 { 465 ipv6: true, 466 addrs: []string{"192.168.0.1", "192.168.0.2/24", "::1", "::2/128"}, 467 want: []string{"::1", "::2"}, 468 }, 469 } 470 471 for _, tc := range tcs { 472 if got := filterAddrs(tc.addrs, tc.ipv6); !slices.Equal(got, tc.want) { 473 t.Errorf("%v with IPv6 %t: got %v, but wanted %v", tc.addrs, tc.ipv6, got, tc.want) 474 } 475 } 476 } 477 478 func TestNATPreOriginalDst(t *testing.T) { 479 singleTest(t, &NATPreOriginalDst{}) 480 } 481 482 func TestNATOutOriginalDst(t *testing.T) { 483 singleTest(t, &NATOutOriginalDst{}) 484 } 485 486 func TestNATPreRECVORIGDSTADDR(t *testing.T) { 487 singleTest(t, &NATPreRECVORIGDSTADDR{}) 488 } 489 490 func TestNATOutRECVORIGDSTADDR(t *testing.T) { 491 singleTest(t, &NATOutRECVORIGDSTADDR{}) 492 } 493 494 func TestNATPostSNATUDP(t *testing.T) { 495 singleTest(t, &NATPostSNATUDP{}) 496 } 497 498 func TestNATPostSNATTCP(t *testing.T) { 499 singleTest(t, &NATPostSNATTCP{}) 500 }