Modify

Opened 3 years ago

Last modified 2 years ago

#20249 new defect

firewall.user is not read on reload from LuCI

Reported by: Jérôme Poulin <jeromepoulin@…> Owned by: developers
Priority: highest Milestone: Chaos Calmer 15.05
Component: packages Version: Trunk
Keywords: Cc:

Description

When reloading the firewall from LuCI, my firewall.user is not applied in the firewall rules. However, when using /etc/init.d/firewall restart, it works and the last line read as "Running script '/etc/firewall.user'".

This can be a big security risk if you have rules to rate limit SSH or to drop packets in custom firewall rules hence why I rated it highest priority.

Attachments (0)

Change History (6)

comment:1 Changed 3 years ago by anonymous

The only risk I can see here is some user not RTFM and making all sorts of assumptions, therefore mistakes.

Check out the reload option [1] and ignore the "one possible parameter" remark, as obviously there are several parameters/options that can be passed to it (the doc really needs some updating). If you're not convinced, then if you have miniupnpd installed, this is the include section for it:

config include 'miniupnpd'
        option type 'script'
        option path '/usr/share/miniupnpd/firewall.include'
        option family 'any'
        option reload '1'

[1] http://wiki.openwrt.org/doc/uci/firewall#includes

comment:2 Changed 3 years ago by anonymous

Concerning LuCI, it must be calling /etc/init.d/firewall reload, which has the effect of just reloading the firewall configuration, thus you don't see your /etc/firewall.user being executed (because it has been executed ONCE during firewall startup. Since option reload is 0 by default, then /etc/firewall.user isn't reloaded when running /etc/init.d/firewall reload.

However, doing /etc/init.d/firewall restart from the command line has the effect of stopping then starting the firewall, thus you see your /etc/firewall.user is executed ONCE.

There's a big difference between reload and restart and you would know these things if you took the time to read up on the UCI docs for the firewall configuration.

So you see, making poor assumptions (big security risk, really?) without RTFM and understanding the underlying basics (UCI) is the only risk here.

comment:3 follow-up: Changed 3 years ago by Jérôme Poulin <jeromepoulin@…>

I must admit that I'm surprised. I've never been bitten by this before because I was always using *_rule chains for my rules in firewall.user and assumed it was executed on every restart/reload.

However, since I needed to block connections after they had gone through the firewall, it stopped working on reload since I was inserting stuff on top of zone_*_dest_ACCEPT and the reload was flushing this rule (the whole chain in fact). I always try to use hook points but I had no choice this time. Here is an example:
iptables -I zone_public_dest_ACCEPT -d 192.168.0.0/16 -j zone_public_src_REJECT

Since an options to execute a script on reload exist and I didn't event bother re-reading the firewall section of the manual before making this ticket, it can be closed as invalid or at least lowered in priority.

As for the big security risk part, it is from the fact that I (and maybe other users), assume this script is executed on every firewall reload and if not testing thoroughly, the user might miss the fact that some of its rules get wiped out in certain conditions but not on fresh boot.

With this in mind, I would like to suggest a change to the header of firewall.user from

# This file is interpreted as shell script.
# Put your custom iptables rules here, they will
# be executed with each firewall (re-)start.

to

# This file is interpreted as shell script.
# Put your custom iptables rules here, they will
# be executed with each firewall (re-)start but
# not on reload by default.

adding the by default part would hint the user to go read how to configure this behaviour.

comment:4 in reply to: ↑ 3 Changed 3 years ago by anonymous

Replying to Jérôme Poulin <jeromepoulin@…>:

I must admit that I'm surprised. I've never been bitten by this before because I was always using *_rule chains for my rules in firewall.user and assumed it was executed on every restart/reload.

However, since I needed to block connections after they had gone through the firewall, it stopped working on reload since I was inserting stuff on top of zone_*_dest_ACCEPT and the reload was flushing this rule (the whole chain in fact).

You must be restoring your settings, or else you would have noticed these lines in /etc/firewall.user as of CC 15.05-rc3:

# 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.

Firewall rules inside the user chains (*_rule) are never flushed and recreated on reload, that's why it tells you to put them into these user chains. They are flushed and recreated on restart however.

This is also the reason why you thought that /etc/firewall.user is always executed, because the firewall rules you put there (assuming you put them into those user chains) are never touched during reload.

Notice the description for option reload:

Specifies whether the include should be called on reload - this is only needed if the include injects rules into internal chains

So if you are injecting rules into the internal chains and you want them recreated every time the firewall is reloaded, then you should modify the include section in /etc/config/firewall as follows:

config include
	option path '/etc/firewall.user'
	option reload '1'

And here comes a subtle caveat that you might not be aware of...

You should probably compile your custom rules that inject inside internal chains, and those that are put in the user chains into separate includes. This is because if you set option reload 1 for an include and you are putting custom rules inside user chains, then you will find that you will have redundant rules in those chains (remember that user chains are never touched during reload).

This is how I setup my firewall includes, to give you an idea:

config include
	option path '/etc/firewall.user'
	option reload '0'

config include
	option path '/etc/firewall.reload'
	option reload '1'

I hope that clears this ticket up.

/ianp ;)

comment:5 follow-up: Changed 2 years ago by anonymous

Then something is amiss or the UCI firewall documentation is misleading as to how (or where) user rules are to be written.

Here, a firewall restart -

root@OpenWrt:~# /etc/init.d/firewall restart
Warning: Unable to locate ipset utility, disabling ipset support
Warning: Section @zone[1] (wan) cannot resolve device of network 'wan6'
 * Flushing IPv4 filter table
 * Flushing IPv4 nat table
 * Flushing IPv4 mangle table
 * Flushing IPv4 raw table
 * Flushing IPv6 filter table
 * Flushing IPv6 mangle table
 * Flushing IPv6 raw table
 * Flushing conntrack table ...
 * Populating IPv4 filter table
   * Zone 'lan'
   * Zone 'wan'
   * Rule 'Allow-DHCP-Renew'
   * Rule 'Allow-Ping'
   * Rule 'Allow-IGMP'
   * Rule #7
   * Rule #8
   * Forward 'lan' -> 'wan'
 * Populating IPv4 nat table
   * Zone 'lan'
   * Zone 'wan'
 * Populating IPv4 mangle table
   * Zone 'lan'
   * Zone 'wan'
 * Populating IPv4 raw table
   * Zone 'lan'
   * Zone 'wan'
 * Populating IPv6 filter table
   * Zone 'lan'
   * Zone 'wan'
   * Rule 'Allow-DHCPv6'
   * Rule 'Allow-MLD'
   * Rule 'Allow-ICMPv6-Input'
   * Rule 'Allow-ICMPv6-Forward'
   * Rule #7
   * Rule #8
   * Forward 'lan' -> 'wan'
 * Populating IPv6 mangle table
   * Zone 'lan'
   * Zone 'wan'
 * Populating IPv6 raw table
   * Zone 'lan'
   * Zone 'wan'
 * Set tcp_ecn to off
 * Set tcp_syncookies to on
 * Set tcp_window_scaling to on
 * Running script '/etc/firewall.user'
root@OpenWrt:~# iptables -vL prerouting_lan_rule -t nat
Chain prerouting_lan_rule (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   tcp  --  any    any     192.168.1.0/24      !192.168.1.1           redir ports 80
root@OpenWrt:~#

N.B. the rule from /etc/firewall.user is targetting a *_rule chain.

With a restart, the nat table is flushed as expected and /etc/firewall.user executed.

Now, with netifd adding a bridge, br-lan, at boot -

Mon Feb  8 08:51:11 2016 user.notice DEBUG: hotplug (net): action='add' devicename='br-lan' devname='' devpath='/devices/virtual/net/br-lan' product='' type='' interface='br-lan'
Mon Feb  8 08:51:11 2016 user.notice firewall: Reloading firewall due to ifup of lan (br-lan)
Mon Feb  8 08:51:12 2016 user.notice DEBUG: hotplug (net): action='remove' devicename='wlan0' devname='' devpath='/devices/platform/ar933x_wmac/net/wlan0' product='' type='' interface='wlan0'
Mon Feb  8 08:51:13 2016 user.notice DEBUG: iptables (user): loading
Mon Feb  8 08:51:14 2016 user.notice DEBUG: hotplug (net): action='add' devicename='wlan0' devname='' devpath='/devices/platform/ar933x_wmac/net/wlan0' product='' type='' interface='wlan0'
Mon Feb  8 08:51:14 2016 user.notice DEBUG: hotplug (net): action='add' devicename='wlan0-1' devname='' devpath='/devices/platform/ar933x_wmac/net/wlan0-1' product='' type='' interface='wlan0-1'

N.B. the trace entry from /etc/firewall.user.

*_rule status after boot -

root@OpenWrt:~# iptables -vL prerouting_lan_rule -t nat
Chain prerouting_lan_rule (1 references)
 pkts bytes target     prot opt in     out     source               destination

Where is the user rule?

comment:6 in reply to: ↑ 5 Changed 2 years ago by anonymous

Replying to anonymous:
[SOLVED]
The command contained a network name requiring DNS resolution but that service is not available when /etc/firewall.user is executed.

Add Comment

Modify Ticket

Action
as new .
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.