splitice/IPTables.Net

Async failures using binary adapter

Closed this issue · 4 comments

Hello,

Following code passes filter table and print all rules in all chains. I ran it multiple times in a row. Sometimes it returns empty chains, see results after the function.

        private static void Print(string title)
        {
            var sys = new IpTablesSystem(new LocalFactory(), new IPTablesBinaryAdapter());
            var msg = new StringBuilder();

            try
            {
                msg.Append($"{title}. IP Tables state:{Environment.NewLine}");
                foreach (var tbl in new string[] {"filter"})
                {
                    // Two spaces indent.
                    msg.Append($"  {tbl}{Environment.NewLine}");
                    
                    var chains = sys.GetChains(tbl, 4).ToList();
                    if (!chains.Any())
                        msg.Append($"    no chain{Environment.NewLine}");

                    foreach (var chn in chains)
                    {
                        // Four spaces indent.
                        msg.Append($"    {chn.Name}{Environment.NewLine}");
                        if (chn.Rules.Count == 0)
                            msg.Append($"      no rule{Environment.NewLine}");

                        foreach (var rul in chn.Rules)
                        {
                            // Six spaces indent.
                            msg.Append($"      {rul.GetCommand()}{Environment.NewLine}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\n--\n{ex.ToString()}\n--\n".Replace("\n", Environment.NewLine));
            }

            Console.WriteLine(msg);
        }

Run 5 times, 2 of 5 failures:

(master)⚡ % sudo mono IPTables.Net.App.exe  bin                                                                                                              ~/src/Projects/IPTables.Net/IPTables.Net.App/bin/Debug
/bin/bash -c "iptables-save -c -t filter"
Bereshit. IP Tables state:
  filter
    INPUT
      -p tcp --dport 443 -i eth0 -j ACCEPT -m tcp
    FORWARD
      no rule
    OUTPUT
      -p tcp --dport 443 -j ACCEPT -m tcp

(master)⚡ % sudo mono IPTables.Net.App.exe  bin                                                                                                              ~/src/Projects/IPTables.Net/IPTables.Net.App/bin/Debug
/bin/bash -c "iptables-save -c -t filter"
Bereshit. IP Tables state:
  filter
    no chain

(master)⚡ % sudo mono IPTables.Net.App.exe  bin                                                                                                              ~/src/Projects/IPTables.Net/IPTables.Net.App/bin/Debug
/bin/bash -c "iptables-save -c -t filter"
Bereshit. IP Tables state:
  filter
    no chain

(master)⚡ % sudo mono IPTables.Net.App.exe  bin                                                                                                              ~/src/Projects/IPTables.Net/IPTables.Net.App/bin/Debug
/bin/bash -c "iptables-save -c -t filter"
Bereshit. IP Tables state:
  filter
    INPUT
      -p tcp --dport 443 -i eth0 -j ACCEPT -m tcp
    FORWARD
      no rule
    OUTPUT
      -p tcp --dport 443 -j ACCEPT -m tcp

(master)⚡ % sudo mono IPTables.Net.App.exe  bin                                                                                                              ~/src/Projects/IPTables.Net/IPTables.Net.App/bin/Debug
/bin/bash -c "iptables-save -c -t filter"
Bereshit. IP Tables state:
  filter
    INPUT
      -p tcp --dport 443 -i eth0 -j ACCEPT -m tcp
    FORWARD
      no rule
    OUTPUT
      -p tcp --dport 443 -j ACCEPT -m tcp

What do you think?

Thank you,
David

Please pull request me a failing system test case that can be replicated on the travis-ci system.

I'd also take a look at strace -ff if I were you it might expose the error you are seeing.

We don't use travis-ci, but I'll see what I can do.

Run with strace has no issue. The problem relates to async way of reading standard output. I worked around it with switch to sync way of reading standard output. Is async way is really better?

The second workaround is to add sleep 1 to each bash command:

iptables iptables-save -c -t filter; sleep1

That's not a valid command. Not only is it an invalid execution of iptables (I assume iptables-save -c -t filter, but sleep1 is not a command (did you mean sleep 1). Furthermore, this wouldn't run with Process.Start (what is used under the hood) due to it being a shell syntax, not a process.

If you truly have a bug, then submit a failing test via PR.