0
 iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  10.10.10.10          anywhere            tcp dpt:6379
ACCEPT     tcp  --  10.10.10.10          anywhere            tcp dpt:6379

I know iptables-save | awk ' !x[$0]++' | iptables-restore will do the work in shell, but I want to eliminate duplicate IP table entries through python script which runs every 30 seconds.

Jayaram18
  • 9
  • 1
  • 8
  • Why Python? If you have a shell script that does the work just set up a cron job – DarkKnight May 25 '22 at 07:50
  • Python script is the one which will add the iptable rules, so it is a requirement that it checks for duplicates before adding and maintain the table intact. – Jayaram18 May 25 '22 at 07:51

1 Answers1

1

Something like this?

import subprocess

old_rules = subprocess.run(
    ["iptables-save"], capture_output=True, text=True, check=True)
new_rules = "".join(f"{rule}\n" for rule in set(old_rules.stdout.splitlines()))
saved = subprocess.run(
    ["iptables-restore"], text=True, check=True, input=new_rules)

The middle line is slightly compact; it could be rephrased more readably as

new_rule_lines = set(old_rules.stdout.splitlines())
new_rules = "\n".join(new_rule_lines) + "\n"

The set operation is what removes duplicates here; a Python set is defined as a collection of items where no duplicates are possible.

The final newline is important for some applications, while others will happily read input which lacks the final newline (though it is required by POSIX for text files and streams).

If keeping the original order is a requirement, set() in recent versions of Python should do that, but you might want to explore e.g. Does Python have an ordered set? for a discussion.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • I can't use this in Python 2.6.8 – Jayaram18 May 25 '22 at 11:19
  • You are unlikely to get a useful answer for such an old Python version. Python 2.7 went out of support over a year ago, and 2.6 is definitely insecure. You can use `subprocess.call` or bare `subprocess.Popen` but upgrading your Python version seems like the only sane way forward. (And highlighting your requirements in the question text is definitely recommended, especially if they are crazy.) Sorry for not noticing the [tag:python-2.6] tag. – tripleee May 25 '22 at 11:45
  • Perhaps see https://stackoverflow.com/questions/4256107/running-bash-commands-in-python/51950538?r=SearchResults&s=1%7C140.0847#51950538 for some background and ideas for how to approach this in Python 2.6. – tripleee May 25 '22 at 11:46
  • old_rules = must_check_output("iptables-save") new_rule_lines = set(old_rules.splitlines()) new_rules = "\n".join(new_rule_lines) + "\n" with this I'm able to get a string How to run iptables-restore in python2.6 with this as input ? – Jayaram18 May 25 '22 at 14:22
  • You can use `p = subprocess.Popen` to start a subprocess and `p.communicate(input)` to pass it input. We can't know what your `must_check_output` looks like but typically it would be quite similar. – tripleee May 25 '22 at 14:53
  • Will try and let you know. Thanks – Jayaram18 May 25 '22 at 15:31
  • /bin/sh: iptables-restore: command not found Unique output is obtained but not able to pass it as input to subprocess and it says command not found. – Jayaram18 May 26 '22 at 04:13
  • If you don't have the command installed, your shell script version won't work, either. If you don't have the binary on your `PATH`, you need to add it there. This is a common FAQ about running things from `cron` so I'm guessing that's what you're asking really. See e.g. https://stackoverflow.com/questions/2388087/how-to-get-cron-to-call-in-the-correct-paths – tripleee May 26 '22 at 07:16
  • It's weird if `iptables-save` works and `iptables-restore` doesn't, though; I would expect them both to be installed in the same directory. – tripleee May 26 '22 at 07:24
  • Next you'll ask how to get a `cron` job to run every 30 seconds. You can't, but you can run it twice a minute with `sleep 30` before the second one. – tripleee May 26 '22 at 07:26
  • I know that we need to give ***** for running every minute and then run a second instance with sleep 30 . I've done that. I know very little as I'm starting with hands-on implementation. Thanks you for the help. – Jayaram18 May 26 '22 at 07:36
  • I checked the path using "type iptables-save" and "type iptables-restore" they are present in /sbin . I think I need to find out where to add this PATH. – Jayaram18 May 26 '22 at 07:52
  • Put something like `PATH=/sbin:/usr/local/bin:/usr/bin:/bin` at the top of your `crontab`. You could also update the `PATH` inside your script with something like `os.environ["PATH"] = "%s:%s" % ("/sbin", os.environ["PATH"])`. The question I linked in a previous comment has much more information about this. – tripleee May 26 '22 at 08:02