Get iptables to trigger a script

I will like to create a script that start an specific process, whenever designated rule was broken in iptables.
I can use log prefix plus tail -f but how do i write that?
If i use iptable log prefix:

-j LOG --log-prefix="TRIGGER ME NOW !!!

then the structure of the command will be somehow similar with:
tail -f "itableslog" | awk '/trigger me now/ {system("run-some-command")}'
How can i obtain something similar with LEDE?

I think that iptables log to the system log, simply tail the system log:

logread | tail | awk...

or something like that

can you give me an example pls?

Nope, that was just your suggestion adapted to Openwrt/LEDE logging.

(the original for that tail/awk advice seems to be floating around on internet forums, but I have never tried that)

so, there is no way to make a script that start certain processes when a custom logo prefix is created by the Iptables?

I think that your own example should work ok, as long as you place the iptables command, create the actual script for monitoring log, and know which script you want to trigger.

I assume that you in general how to make Linux shell scripts (that will work also in Openwrt), and that you understand the firewall basics.

I think that the steps should be:

  • First run the iptables command to add that logging to the correct chain there. the correct place/chain depends on if you are targeting wan or LAN
    After you can see from the system log that the iptables logging works, then you You might add the command into /etc/rc.local or /etc/firewall.user to get it run at boot.

  • Then you can start crafting the monitoring command.
    logread | tail in my example above could actually be replaced with logread -f
    So your script command should be:
    logread -f | awk '/trigger me now/ {system("SOMETHING")}'
    And you could place that command into /etc/rc.local. You likely need to place it into a detached subshell, like
    ( logread -f | awk '/trigger me now/ {system("SOMETHING")}' )&

  • The third part is then the scipt to be run, SOMETHING. Note that it will run headless, so you can't provide any output or so.

But like said above, I have not tested that. So this is just based on your own message above plus general scripting experience.

Is exactly what i need it. Some one to give me a direction. Thank you.

Well, here is the full implementation:

I tested setting an iptables log rule for accessing a specific wan web site from lan (forwarding_lan_rule):

iptables -A forwarding_lan_rule -d 130.230.137.61 -j LOG --log-prefix="TRIGGER ME NOW"

I then checked with the logread command, and the command properly worked the packet:

root@OpenWrt:~# logread -f | grep TRIGGER
Thu Feb  8 18:55:18 2018 kern.warn kernel: [156303.420648] TRIGGER ME NOWIN=br-lan OUT=eth0.2 MAC=dc:ef:09:ef:f3:e4:78:24:af:3a:80:1c:08:00 SRC=192.168.1.180 DST=130.230.137.61 LEN=40 TOS=0x00 PREC=0x00 TTL=127 ID=7583 DF PROTO=TCP SPT=52161 DPT=80 WINDOW=63093 RES=0x00 ACK URGP=0

Trying that awk command, and trigger another log item to be written:
logread -f | awk '/TRIGGER ME NOW/ {system("logger test1")}'
And after accessing the web page, the log contains now also the test1 items:

Thu Feb  8 18:59:41 2018 user.notice root: test1
Thu Feb  8 18:59:41 2018 user.notice root: test1
Thu Feb  8 18:59:43 2018 kern.warn kernel: [156568.040939] TRIGGER ME NOW IN=br-lan OUT=eth0.2 MAC=dc:ef:09:ef:f3:e4:78:24:af:3a:80:1c:08:00 SRC=192.168.1.180 DST=130.230.137.61 LEN=40 TOS=0x00 PREC=0x00 TTL=127 ID=9556 DF PROTO=TCP SPT=52198 DPT=80 WINDOW=64240 RES=0x00 ACK FIN URGP=0

And then finally testing detaching the logread/awk process:

root@OpenWrt:~# ( logread -f | awk '/TRIGGER ME NOW/ {system("logger test1")}' )&
root@OpenWrt:~#
root@OpenWrt:~# ps
  PID USER       VSZ STAT COMMAND
    1 root      1340 S    /sbin/procd
...
19505 root      1072 S    -ash
19506 root      1128 S    logread -f
19507 root      1080 S    awk /TRIGGER ME NOW  {system("logger test1 )}
19508 root      1068 R    ps
root@OpenWrt:~#

And the log shows the items, both the original iptables log line and my trigger script's test1 line:

Thu Feb  8 19:03:10 2018 kern.warn kernel: [156774.960275] TRIGGER ME NOW IN=br-lan OUT=eth0.2 MAC=dc:ef:09:ef:f3:e4:78:24:af:3a:80:1c:08:00 SRC=192.168.1.180 DST=130.230.137.61 LEN=40 TOS=0x00 PREC=0x00 TTL=127 ID=9571 DF PROTO=TCP SPT=52215 DPT=80 WINDOW=64240 RES=0x00 ACK URGP=0
Thu Feb  8 19:03:10 2018 user.notice root: test1

So, adding two lines into /etc/rc.local should be ok:

root@OpenWrt:~# cat /etc/firewall.user
# This file is interpreted as shell script.
# Put your custom iptables rules here, they will
# be executed with each firewall (re-)start.

# Internal uci firewall chains are flushed and recreated on reload, so
# put custom rules into the root chains e.g. INPUT or FORWARD or into the
# special user chains, e.g. input_wan_rule or postrouting_lan_rule.

iptables -A forwarding_lan_rule -d 130.230.137.61 -j LOG --log-prefix="TRIGGER ME NOW"
( logread -f | awk '/TRIGGER ME NOW/ {system("logger test1")}' )&

But I also noticed that the log gets flooded quite rapidly and may choke router performance badly. So, e.g. adding a large website rule this way can be dangerous.

And you need to look carefully for a proper iptables chain, depending a bit which kind of traffic will trigger things.

EDiT: I tried adding the rules to /etc/firewall.user, and looks like that affected the boot process negatively. May be better to have it ni the /etc/rc.local, or might be even better to manually run the commands after a proper boot.

Ps.
But if you are just trying to get a single packet to some individual port to trigger things, you might actually also check the port knocking options. e.g. the fwknop
https://github.com/openwrt/packages/blob/master/net/fwknop/Makefile