Executing scripts at boot time

A few questions...
I am just beginning to use OpenWRT and not all things are running as expected.

In our network have a number of similar scripts across different Linux platforms that I would like to re-use in OpenWRT.
I therefore prefer simple iptables rules to the OpenWRT firewall. (My understanding is that the firewall utility in OpenWRT is a layer on top of iptables.)

Disabling the firewall in Luci works fine. But I have a problem running scripts at startup to create my own set of rules.

If I place a script in /etc/rc.local it does not get executed after a reboot.
(I placed a shebang as first line, it is executable, and runs ok when executed from command line)

If I put the scipt in cron with @reboot directive, it dioes not get executed either.
(It does get executed if I let it run via cron at a specific time).

I also tried to edit the firewall file in /etc/config. There is not a one-to-one relation betyween this file and the iptables rules generated by OpenWRT.

What am I doing wrong?

/etc/rc.local is the place to add the scripts for startup.
Check that the commands are correct and with the full path preferably.
Otherwise paste the script here, maybe you have missed something else.

3 Likes

Hello trendy,
Below is the script. I'm not sure I need the shebang at line 1. The original script did not have it.
(I also tried #!/bin/sh )
If I execute it by typing /etc/rc.local it runs fine.
The logger message does not make it either - it appears to me the script is not executed.
(I removed the comment lines - they appear in bold and large characters on the forum...)

root@OpenWrt:~# cat /etc/rc.local
#!/bin/ash -e
logger ' executing rc.local'

/etc/config/fwSetup 
exit 0

It is procd that starts everything at boot and it is /etc/rc.local that is just about the last thing that gets run.

However everything runs concurrently and almost always when rc.local runs, the network interfaces have not yet come up so any iptables commands in rc.local will fail.

The firewall service waits for the network to finish coming up before setting its rules.

If you want to add your own "raw" iptables commands, firewall has its own special script that it runs in a similar way to rc.local, but the network interfaces will guaranteed to be up.
This script file is /etc/firewall.user.

Try putting your iptables commands in there (or run another script from there).

4 Likes

I would strongly advise against disabling the openwrt firewall. You're likely to break the functionality of a lot of things, both zoning and package functionality.

It would be better to add your own rules on top.

In /etc/config/firewall you can add an arbitrary number of user firewall scripts that can do custom rules using the following syntax

config include
        option type 'script'
        option path '/etc/firewall.d/myscript'
        option family 'any'
        option reload '1'
2 Likes

Thanks buewaveplanet.
I tried this - not sure if I am doing this right. I simply copied the line /etc/config/fwSetup in the firewall.user script. Did not work. I saw no entries in the (remote) log file.
I get your point about interfaces not being up, but surely the 'logger' command would work?

Thanks for your advice. But as I said, we'd like to stick to our own iptables scripts that we use throughout our network.
In the end - it all boils down to a set of iptables rules, correct?

You will have to keep firewall enabled for it to work..... As @dl12345 says, other things will break if the firewall is not running. You can have it do the minimum and still run your script.

Revert to the default #!/bin/sh

1 Like

You can also do this via /etc/init.d/ scripts. You can specify the execution position and make such that it launches at the end of the queue. But it is important to note that while the execution order is obeyed, the order is the beginning of executing each script... the system does not wait for each script to complete to begin executing the next in queue. This means that dependencies on earlier entries may not yet be ready if those scripts have not yet completed execution. Therefore, if you use this method, you may need some additional logic and sleep states to prevent issues.

If you want to guarantee that things are fully up and running with no additional logic required, rc.local or firewall.user would be the correct place to put your scripts.

1 Like

I've tried #!/bin/sh as well. Also without shebang.
I wonder if the rc.local script is being called at all.
Is there a way I can check that? (I've added logger statement, a simple cat to file and various other things)

If the logger isn't working, you could always try a simple touch command. I sometimes do this from the calling script (in this case rc.local) as well as the script that is called (when using an external script) so that I can trace through with some tangible file artifacts.

1 Like

If you really insist on setting up the firewall using your own custom iptables rules, this is the working (but totally not recommended) way.
Please, keep in mind, that it will be entirely up to you to properly secure your router!

  1. Leave the firewall service enabled.
  2. Comment or remove everything in /etc/config/firewall, except:
config defaults
        option input 'ACCEPT'
        option forward 'ACCEPT'
        option output 'ACCEPT'

config include
        option  path  '/etc/firewall.user'
  1. Insert your iptables rules in /etc/firewall.user, using the standard syntax, e.g.

iptables -I INPUT 1 -i eth1 -j DROP

Your custom rules will be applied after each firewall or router restart.

There is a very simple method to use your own iptable rules, only:
Build a custom image, and drop the firewall during "make menuconfig".
Using quite some "non-standard" software packages, which also need special firewall settings, this works for me like a charm. Calling the iptable-cmds from rc.local, of course.

1 Like

I tried touch - that appears to work just fine.
The logger, nor the iptables script works, but the sscipt is being executed. Must be the order of things, then, as was suggested.

The clearing of the rules works fine as you described.
But the rules in firewall.user do not appear to be processed.

This is what the file looks like:
(I've removed the lines beginning with # - they appear in very large font in the forum message)

root@OpenWrt:/etc# cat firewall.user

iptables -t nat -A POSTROUTING -o wan -j MASQUERADE
iptables -I FORWARD 1 -i eth1 -j ACCEPT

iptables (for filter table) is empty (as is the nat table):
root@OpenWrt:/etc# iptables -nvL
Chain INPUT (policy ACCEPT 109K packets, 162M bytes)
pkts bytes target prot opt in out source destination

Chain FORWARD (policy ACCEPT 277 packets, 22308 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 20670 packets, 1108K bytes)
pkts bytes target prot opt in out source destination

So far I'm happy this image works - it is a Xiaomi 4A Gigabit. Not really ready to try on homebuilts...

Use the pre-formatted text/backtick feature, as shown below.

Without pre-formatted text:

this is a test

With pre-formatted text:
# this is a test

1 Like

This is the standard output only when the firewall service is stopped. When it is started, you should see some additional default rules, even if there is no content in /etc/config/firewall

root@OpenWrt:~# iptables -nvL INPUT

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0            /* !fw3 */
   20  1376 input_rule  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* !fw3: Custom input rule chain */
   19  1336 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED /* !fw3 */

Execute

/etc/init.d/firewall enable && /etc/init.d/firewall start
and check again

Hello Pavel,
Don't know what went wrong last night - perhaps there was another script still active.
Tried again this morning and the rule from /etc/firewall.user got processed OK.

Also tried to delay the script which was executed from rc.local. That also worked.
So I have two ways.

Our main firewall is at the head of the network and very protective. These routers are used internally (and behind a Ubiquiti radio with active nat) - we typically leave them open.

Thanks for thinking along, guys!

1 Like