Dynamic firewall with FirewallD
FirewallD is a service daemon with a D-BUS interface that provides a dynamic managed firewall.
Why A Firewall Daemon
The current firewall model is static and every change requires a complete firewall restart. This includes also to unload the firewall netfilter kernel modules and to load the modules that are needed for the new configuration. The unload of the modules is breaking stateful firewalling and established connections.
The firewall daemon on the other hand manages the firewall dynamically and applies changes without restarting the whole firewall. Therefore there is no need to reload all firewall kernel modules. But using a firewall daemon requires that all firewall modifications are done with that daemon to make sure that the state in the daemon and the firewall in kernel are in sync. The firewall daemon can not parse firewall rules added by the ip*tables and ebtables command line tools.
The daemon provides information about the current active firewall settings via D-BUS and also accepts changes via D-BUS using PolicyKit authentication methods. SELinux access restrictions are also planned.
Applications, daemons and the user can request to enable a firewall feature over D-BUS. Applications, daemons and the user can request to enable a firewall feature over D-BUS. A feature could either be one of the predefined firewall features like services, port and protocol combinations, trusted interfaces/hosts/network areas, port/packet forwarding, masquerading, icmp blocking or even a custom rule. The feature can be enabled for a certain amount of time or can be disabled by again.
New chains for virtualization, network settings, services, ports, masquerading, port forwarding, icmp filtering and virtualization are added to make the firewall setup more flexible, safe and robust. Adding a rule with the firewall daemon to one of these chains will most likely not interefere with rules of other chains. The order of the chains and how they are used is fixed.
The netfilter firewall helpers, that are for example used for amanda, ftp, samba and tftp services, are also handled by the daemon as long as they are part of a predefined service. Loading of additional helpers is not part of the current interface. For some of the helpers onloading is only possible after all connections that are handled by the module are closed. Therefore connection tracking information is important here and needs to get into account.
Compatibility With Static Firewall (system-config-firewall)
The actual static firewall model with system-config-firewall will still be available and usable, but not at the same time as the daemon is running. The user or admin can decide which firewall solution should be used.
At install time, firstboot or first network usage, there will be a selector for the firewall solution to use. If the firewall daemon will be used, it will diable the ip*tables services and also add the disabled option for system-config-firewall. The configuration will stay intact and s-c-fw can be enabled simply with "lokkit --enabled" again.
The firewall daemon is independent to system-config-firewall, but should not be used at the same time.
Support for ebtables
ebtables support is needed to fullfill all needs of the libvirt daemon and to prevent access problems between ip*tables and ebtables on kernel netfilter level. All these commands are accessing the same structures and therefore they should not be used at the same time.
Support for conntrack
Conntrack is needed to be able to terminate established connections for features that get disabled. For some use cases it might not be good to terminate the connection: Enabling of a firewall service for a limited time to establish a persistent external connection.
User interaction mode
This is a special mode of in the firewall the user or admin can enable. All requests of applications to alter the firewall are directed to the user to get notified and granted or denied. It is possible to set a time limit for the acceptance of a connection and to limit it to hosts, networks or connections. It can be saved to behave the same in the future without notification.
An additional feature of this mode is direct external connection attempts on preselected services or ports to the user with the same features as the application initiated requests. The limitation on services and ports will also limit the amount of requests sent to the user.
Network zones: Network security model
Network zones define the level of trust for network connections. A public WIFI network connection for example should be untrusted, a wired home network connection should be fairly trusted.
The network security model can be selected initially at installation time, firstboot or when the first network connection gets established. The model describes the trust level of the whole network environment, the host is connected to, and also defines what to do with new connections.
There are different initial models:
- Home / Work - Public - Connection specific
The home or work zone has the highest trust level. All incoming connections are allowed. The public zone on the other hand is fully untrusted. No incoming connection is allowed. The connection specific model requires that the user tunes the trust level of a connection according to the needs. The default is untrusted.
The user or administrator is able to define new zones or adapt initial zones to change the behaviour according to the needs.
The network security model makes it possible to have one trust level for all connections or to have several connections with different trust levels.
User policy support
The administrator can define which users are able to use the User Interaction Mode and can also limit the firewall features, that can be used with it.
Port metadata information (proposed by Lennart Poettering)
To have a port independent metadata information would be good to have. The current model with a static assignment of ports and protocols from /etc/services is not a good solution and is not reflecting current use cases. Ports in applications or services are dynamic and therefore the port itself does not describe the use case.
This metadata information could be used to form simple rules for the firewall. Here are some examples:
allow external access to file sharing applications or services allow external access to music sharing applications or services allow external access to all sharing applications or services allow external access to torrent file sharing applications or services allow external access to http web services
The metadata information here could not only be application specific, but also a group of use cases. For example the "all sharing" group or the "file sharing" group could match all sharing or file sharing applications, for example torrent file sharing. These are examples, therefore it might be that they are not useful.
There are two possible solutions to get metadata information in the firewall:
The first is to add it to netfilter (kernel space). This has the advantage, that it can be used by everyone, but also limits the use. To get user or system specific information into account, all these need to be implemented in kernel space also.
The other one would be to add this to a firewall daemon. These abtract rules could be used together with informations like the trust level of the network connections, the user decision to share with as specific person/host or the hard rule of the administrator to forbid sharing completely.
The second solution would have the advantage that new metadata groups or changes in incorporation of trust levels, user preferences or administrator rules would not require to push a new kernel. Adding these kind of abtract rules to a firewall daemon would make it much more flexible. Even new security levels woule be easy to add without kernel updates.
The Firewall Rules
Netfilter firewalls are always susceptible to rule ordering issues, because a rule can not have a fixed position in a chain.
In the static firewall model a firewall change is recreating a clean and sane firewall setup limited to the features directly supported by system-config-firewall / lokkit. Firewall rules created by other applications are not integrated and s-c-fw / lokkit does not know about them if the customs rules file feature is not in use. Default chains are used and there is no safe way to add and remove rules without interfering with others.
The dynamic model has additional chains for the firewall features. These specific chains are called in a defined ordering and rules added to a chain could not interfere with reject or drop rules in chains that were called before. This makes it possible to have a more sane firewall configuration.
Here are example rules created by the daemon in the filter table with ssh and ipp-client enabled:
:INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :FORWARD_custom - [0:0] :FORWARD_forward - [0:0] :FORWARD_icmp - [0:0] :FORWARD_masq - [0:0] :FORWARD_trusted - [0:0] :FORWARD_virt - [0:0] :INPUT_custom - [0:0] :INPUT_forward - [0:0] :INPUT_icmp - [0:0] :INPUT_ports - [0:0] :INPUT_services - [0:0] :INPUT_trusted - [0:0] :INPUT_virt - [0:0] :OUTPUT_custom - [0:0] :OUTPUT_virt - [0:0] -A INPUT -j INPUT_virt -A INPUT -m state --state INVALID -j REJECT --reject-with icmp-host-prohibited -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p icmp -j INPUT_icmp -A INPUT -p icmp -j ACCEPT -A INPUT -j INPUT_trusted -A INPUT -j INPUT_forward -A INPUT -j INPUT_services -A INPUT -j INPUT_ports -A INPUT -j INPUT_custom -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -j FORWARD_virt -A FORWARD -m state --state INVALID -j REJECT --reject-with icmp-host-prohibited -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -i lo -j ACCEPT -A FORWARD -p icmp -j FORWARD_icmp -A FORWARD -p icmp -j ACCEPT -A FORWARD -j FORWARD_trusted -A FORWARD -j FORWARD_forward -A FORWARD -j FORWARD_masq -A FORWARD -j FORWARD_custom -A FORWARD -j REJECT --reject-with icmp-host-prohibited -A OUTPUT -j OUTPUT_virt -A OUTPUT -j OUTPUT_custom -A INPUT_services -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT_services -p udp -m udp --dport 631 -j ACCEPT
The icmp block rules are added to INPUT_icmp and will reject icmp types. All other icmp types are accepted. Trusted interfaces and later on hosts or network areas are added to INPUT_trusted. INPUT_Forward will be used fot the INPUT filter part of pport/packet forwarding. Service rules will be placed into INPUT_services, user defined ports into INPUT_ports and custom rules into INPUT_custom. The chains for libvirt are missing and will be added later on either very early or late in the base chain. It is possible to have a INPUT_custom_early also if needed, for example for a special icmp filtering.
This model makes it more easy to add or remove rules from a specifig block without interfering with accept or drop rules from another block.
Useful System Extensions
At the moment there are sysctl settings that are not properly applied. This happens if the module providing the setting is not loaded at boot time when rc.sysinit runs or it the module gets reloaded at runtime. Another example is net.ipv4.ip_forward, which is needed for example for specific firewall settings, libvirt and also user/admin changes. If there are two apps or daemons enabling ip_forwarding only if needed, then it could happen that one of them is turning it off again without knowing that there is anotherone, that still needs it tuned on.
The sysctl daemon could solve this by having an internal use count for settings, that will make it possible to turn it off or go to the previous setting again if the requester reverted the request to change it.