@@ -214,7 +214,7 @@ where
214
214
/// IP tables chain names, and they are in danger of conflicting with each-other
215
215
///
216
216
/// returns `true` if iptables are clean and the agent can proceed, other returns `false`
217
- pub async fn ensure_iptables_clean ( ipt : IPT ) -> IPTablesResult < bool > {
217
+ pub async fn ensure_iptables_clean ( ipt : & IPT ) -> IPTablesResult < bool > {
218
218
let ipt = Arc :: new ( ipt) ;
219
219
tracing:: trace!( "checking for leftover or existing iptable chains..." ) ;
220
220
for name in [ IPTABLE_PREROUTING , IPTABLE_MESH , IPTABLE_STANDARD ] {
@@ -524,4 +524,72 @@ mod tests {
524
524
525
525
assert ! ( ipt. cleanup( ) . await . is_ok( ) ) ;
526
526
}
527
+
528
+ /// Check that dirty ip tables fail the ['SafeIpTables::ensure_iptables_clean'] check
529
+ /// If there are any chains in the IP table with names used by the agent, the check should fail.
530
+ /// A fresh IP table, or one with only non-agent names, should pass the check
531
+ #[ tokio:: test]
532
+ async fn fail_on_dirty ( ) {
533
+ let mut mock = MockIPTables :: new ( ) ;
534
+
535
+ // CASE 1: check that a fresh IP table passes cleanliness check
536
+ mock. expect_list_rules ( )
537
+ . with ( eq ( "OUTPUT" ) )
538
+ . returning ( |_| Ok ( vec ! [ ] ) ) ;
539
+
540
+ let expected_success = SafeIpTables :: ensure_iptables_clean ( & mock) . await ;
541
+ assert ! (
542
+ expected_success. is_ok( ) ,
543
+ "Fresh IP table should pass cleanliness check"
544
+ ) ;
545
+
546
+ // CASE 2: check that an IP table with one of mirrord's static chain names will fail the
547
+ // cleanliness check
548
+ mock. expect_create_chain ( )
549
+ . with ( eq ( IPTABLE_PREROUTING ) )
550
+ . times ( 1 )
551
+ . returning ( |_| Ok ( ( ) ) ) ;
552
+
553
+ mock. expect_insert_rule ( )
554
+ . with (
555
+ eq ( IPTABLE_PREROUTING ) ,
556
+ eq ( "-m tcp -p tcp --dport 69 -j REDIRECT --to-ports 420" ) ,
557
+ eq ( 1 ) ,
558
+ )
559
+ . times ( 1 )
560
+ . returning ( |_, _, _| Ok ( ( ) ) ) ;
561
+
562
+ let expected_failure = SafeIpTables :: ensure_iptables_clean ( & mock) . await ;
563
+ assert ! ( expected_failure. is_err( ) , "IP table that contains chain with name {IPTABLE_PREROUTING} should fail cleanliness check" ) ;
564
+
565
+ // CASE 3: check that an IP table with only rules that were not created by mirrord will pass
566
+ // the cleanliness check
567
+ mock. expect_remove_chain ( )
568
+ . with ( eq ( IPTABLE_PREROUTING ) )
569
+ . times ( 1 )
570
+ . returning ( |_| Ok ( ( ) ) ) ;
571
+
572
+ // add a non-mirrord chain
573
+ let non_mirrord_chain = "MY_PET_CHAIN_NAME" ;
574
+
575
+ mock. expect_create_chain ( )
576
+ . with ( eq ( non_mirrord_chain) )
577
+ . times ( 1 )
578
+ . returning ( |_| Ok ( ( ) ) ) ;
579
+
580
+ mock. expect_insert_rule ( )
581
+ . with (
582
+ eq ( non_mirrord_chain) ,
583
+ eq ( "-m tcp -p tcp --dport 69 -j REDIRECT --to-ports 420" ) ,
584
+ eq ( 1 ) ,
585
+ )
586
+ . times ( 1 )
587
+ . returning ( |_, _, _| Ok ( ( ) ) ) ;
588
+
589
+ let expected_success = SafeIpTables :: ensure_iptables_clean ( & mock) . await ;
590
+ assert ! (
591
+ expected_success. is_ok( ) ,
592
+ "IP table that contains no chains with mirrord name should pass cleanliness check"
593
+ ) ;
594
+ }
527
595
}
0 commit comments