Hi Darren and all,
As part of the Visual Panels project,
http://opensolaris.org/os/project/vpanels
we're proposing a generic firewall framework for Solaris. The framework
utilizes IPfilter to provide a simple mechanism to configure a firewall
on Solaris systems.
The firewall framework is functionally complete on which the Visual
Panels project will provide a panel, a configuration UI. Attached is the
current firewall framework design which I'm soliciting feedback by next
Monday, August 25th.
Thanks in advance,
-tony
1. Introduction
This document describes a framework that simplifies system and service
firewall configuration. Currently, Solaris has IPfilter which allows user to
set up system and service firewall policies.
IPfilter uses a set of ipf rules from which it determines whether an IP
packet should be allowed in or out of the system. Although ipf rule syntax
is fairly simple and straightforward, it still demands good understanding of
networking and security concepts, a non-trivial learning curve for 'casual'
Solaris users. Moreover, the task of creating and testing ipf rules are
mostly manual and can become a management burden in systems where large
number of rules are used.
The proposed framework aims to simplify user model by allowing users to
express firewall policy at system and service level. Given the user defined
firewall policy, the framework generates a set of IPfilter rules to enforce
the desired system behavior. Users specify system and service firewall
policies that allow or disallow network traffic from certain hosts, subnets,
and interface(s). The policies can be translated into a set of active ipf
rules to enforce the specified firewall policies.
It's important to note the proposed framework isn't a full IPfilter
configuration tool, thus it won't generate every possible IPfilter
configuration. However, users can specified a custom ipf rule set to be used
if the framework can't provide the desired IPfilter configuration.
2. Design
Model: The proposed firewall framework provides a simple mechanism to
restrict incoming network traffic to a Solaris machine. Network traffic is
normally from remote servers and clients to local clients and servers(local
network services), respectively. Other types of network traffic include
broadcasts and ICMP messages. The goal of any firewall is to block unwanted
incoming network traffic and/or restrict access to certain source(s) while
allow local client programs to work seamlessly.
A three layer approach with different precedence levels helps us achieve the
desired behaviors.
Global Default - default system-wide policy. This policy is
automatically inherited by all services unless services modify their
firewall policy.
Network Services - higher precedence than Global Default. A service's
policy allows/disallows traffic to its specific ports, regardless of
Global Default policy.
Global Override - another system-wide policy that takes precedence over
the needs of specific services in Network Services layer.
Global Override
|
|
Network Services
|
|
Global Default
A firewall policy includes a firewall mode and an optional set of network
sources. Network sources are IP addresses, subnets, and local network
interfaces, from which a system can receive incoming traffic. The basic set
of firewall modes are:
None - no firewall, allow all incoming traffic
Allow All Except - allow all incoming traffic but deny traffic from
specified source(s).
Deny All Except - deny all incoming traffic but allow from specified
source(s)
Layers in Detail: The first system-wide layer, Global Default, defines a
firewall policy that applies to *any* incoming traffic, e.g. allowing or
blocking all traffic from an IP address. This makes it simple to have a
policy that blocks all incoming traffic or all incoming traffic from
unwanted source(s).
The Network Services layer contains firewall policies for local programs
that provide service to remote clients, e.g. telnetd, sshd, and httpd. Each
of these programs, a network service, has its own firewall policy that
controls access to its service. Initially, a service's policy is set to
inherit Global Default policy, a "Use Global Default" mode. This makes it
simple to set a single policy, at the Global Default layer, that can be
inherited by all services. When a service's policy is different from Global
Default policy, the service's policy has higher precedence. If Global
Default policy is set to block all traffic from a subnet, the SSH service
could be configured to allow access from certain hosts in that subnet. The
set of all policies for all network services comprises the Network Service
layer.
The second sytem-wide layer, Global Override, has a firewall policy that
also applies to any incoming network traffic. This policy has highest
precedence and overrides policies in other layers, specifically overriding
the needs of network services. The example is when it's desirable block
known malicious source(s) regardless of services' policies.
User Interaction: This framework leverages IPfilter functionality and is
only active when svc:/network/ipfilter is enabled. Similarly, a network
service's firewall policy is only active when that service is enabled. A
system with an active firewall has IPfilter rules for each running/enabled
network service and for system-wide policy(s) with firewall mode other than
"None". User's enabling and disabling action for a service corresponds to
firewall policy activation and deactivation for that service. A user changes
firewall settings by modifying a service and/or system-wide firewall policy.
At a high level, the firewall framework composes of policy configuration and
a mechanism to generate ipfilter rules from the policy and applying those
rules to get the desired IPfilter configuration. A quick summary of the
design:
- system-wide policy(s) are stored in network/ipfilter
- network services' policies are stored in each SMF service
- firewall is only activated when network/ipfilter is enabled.
- enabling/disabling a network service activates/deactivates a
service's firewall policy
- changing a global or per-service firewall policy results in an update
to the system's firewall rules
3. Configuration
Customizable configuration: Firewall policies comprising a mode and two
lists of network sources, strings, are stored as SMF properties. A
per-service firewall policy allows each SMF network service to store its
policy as a property group. Thus, the Network Services layer is made up of
all SMF network services and their corresponding firewall policies. A new
per-service property group, firewall_config, is used to store its firewall
policy. The system-wide policies, Global Default and Global Override, are
stored as separate property groups, firewall_config and firewall_config_ovr,
respectively, in svc:/network/ipfilter since this service controls firewall
activation for the entire system.
A policy is stored in a property group, firewall_config or
firewall_config_ovr, with the following properties and values:
policy - "none", "allow_all_except", "deny_all_except"
allow_except_list - a list of IP addresses and network interface names
deny_except_list - similar to allow_except list property
For individual services only:
policy - can also be set to "use_global"
For the Global Default only:
policy - can also be set to "custom"
custom_policy_file - if policy is "custom", a file path
client{N} - protocol and port(s) tuple in the form
"{tcp | udp}:{PORT | PORT-PORT}"
"none" policy mode: no access restriction. For a global policy, this mode
allows all incoming traffic. For a service policy, this mode allows all
incoming traffic to its service.
"allow_all_except" policy mode: more restrictive than "none". This mode
allows incoming traffic from all sources except those specified in the
"allow_except_list" property.
"deny_all_except" policy mode: most restrictive mode. This mode blocks
incoming traffic from all sources except those specified in the
"deny_except_list" property.
"allow_except_list" property: a multi-value property listing sources to be
blocked when the policy is "allow_all_except". The syntax for possible
values are:
host: host:IP "host:192.168.84.14"
subnet: network:IP/netmask "network:129.168.1.5/24"
interface: if:interface_name "if:e1000g0"
"deny_except_list" property: a multi-value property listing sources that are
allowed access when the policy is "deny_all_except". Possible values are the
same as allow_all_except property.
"use_global" policy mode: This mode is only valid for policies in Network
Services layer. Services with "use_global" policy mode inherits the Global
Default firewall policy.
"custom" policy mode: Users preferring to use a custom ipfilter
configuration, e.g. existing ipfilter configuration or configurations that
can't be provided by the framework can choose the custom policy. This Global
Default only policy mode allows users to supply a text file containing the
complete set of ipfilter rules. When "custom" mode is selected, the
specified set of ipfilter rules is *complete* and the framework will not
generate additional ipfilter rules. The Global Default policy property group
has an additional custom_policy_file property to store the complete file
path.
"client" properties: Only Global Default policy has these optional
properties. A non-service client requiring allowance of its incoming traffic
can request the firewall to allow traffic to its communication ports. This
per client property contains value of the form
"{tcp | udp}:{PORT | PORT-PORT}"
The properties are stored in firewall_config property group in
network/ipfilter.
Initially, system-wide policies are set to "none" and network services'
policies are set to "use_global". Enabling network/ipfilter activates the
firewall with an empty set of ipfilter rules, since system-wide policy is
"none" and all services inherit that policy. This behavior is compatible
with prior systems when network/ipfilter is initially enabled. To configure
a more restrictive policy, user needs to modify policy(s) for network
services or a system-wide policy.
Static configuration: Network services may need additional information to
help translate a firewall policy into IPfilter rules. Additionally, some
services may require a mechanism to generate and supply their own rules to
the framework. An optional per-service property group, firewall_context,
provides the necessary service information and allows custom rule
generation. The Implementation section will explain how these properties are
consumed but brief definitions are provided here.
- firewall_context/name, IANA name for non-inetd service, equivalent to
inetd/name property
- firewall_context/isrpc, a boolean property where a "true" value
indicates an RPC service, equivalent to inetd/isrpc property. This
property adds contextual information for non-inetd RPC services but
doesn't affect the meaning of firewall_context/name property.
- firewall_context/ipf_method, a command, normally a script that
generates ipf rules for a service. The framework does not generate
rules for services with this property definition but expect these
services to provide their own rules.
A service's ipf_method specifies a command that takes an additional
argument, its own fmri and generates the service's firewall rules and
output the rules to stdout. To generate rules for a service with
ipf_method property, the framework execs the command specified in
ipf_method, passing the service fmri as the additional argument and
stores the rules for that service by redirecting the command output,
the rules, to the service's rule file. Because an ipf_method is
exec'ed from the context of either network/ipfilter start or refresh
method process, it inherits the execution context and runs as root.
4. Implementation
The implementation consists of additions of SMF property groups to store
firewall configuration, network/ipfilter modifications to activate,
deactivate firewall settings, a new daemon to monitor and update per-service
firewall setting, and a mechanism to generate ipfilter rules given a
firewall policy.
Configuration store: The above Confguration section described in detail
firewall policy and other information are stored as SMF property groups.
network/ipfilter: The SMF network/ipfilter service drives the rule
generation process as the firewall active and inactive states are directly
tied to network/ipfilter service's enabled state. network/ipfilter start
method is modified to read the system-wide firewall policies and each
enabled service's firewall policy, generate and load all the rules. The
refresh method also performs the same steps as a complete regeneration is
necessary. The existing stop method disables IPfilter, unloading all the
rules, doesn't need any modification.
svc.ipfd: The above process sets up and tears down the entire system's
firewall configuration. However, it's necessary to be able to react to
changes in the system's configuration and do so in an incremental fashion. A
service's firewall policy is activated when it's enabled, deactivated when
it's disabled, and updated when its configuration property group is
modified.
In order to configure the firewall for individual services, we need to know
when a service is enabled or disabled, or when its configuration has changed
and invoke the rule generation process to carry out the service's firewall
policy. We will implement this by introducing a new deamon,
/lib/svc/bin/svc.ipfd, that monitors the repository for relevant changes.
This daemon is started by the network/ipfilter service.
Rules Generation: IPfilter rules generation uses the firewall policy to
create the appropriate ipf rules that allow or disallow network packets from
specified network source(s). The configuration the firewall framework
permits the user to express can be mapped into a subset of the IPfilter
language. Configuration in system-wide layers map to rules of the form:
{block|pass} in from SOURCE to DESTINATION
{block|pass} on INTERFACE to DESTINATION
where DESTINATION is the local machine. Note that for system-wide layers, we
do not specify a port. In contrast, a service's configuration will map to
rules of the form:
{block|pass} in from SOURCE to DESTINATION on port = PORT
{block|pass} on INTERFACE to DESTINATION on port = PORT
where PORT is the service's port. A firewall policy configuration is a set
of block and pass rules on the same destination and (optionally) port.
IPfiler rules are order sensitive so some planning is necessary to correctly
implement a firewall policy. For a policy configuration, there is a primary
rule to allow or deny all and zero or more exception rules to deny or allow
specific source(s). The exception rules by definition will have higher
priority. Thus, exception rules are always on top of primary rule and the
"quick" keyword is added to tell IPfilter to take action on the first
matched rule.
To clarify the ordering discussion, let's see some examples of how rules can
be generated from different policies. The network service of interest is
network/ssh whose sshd listens on port 22.
- "None" or no firewall policy simply allows all incoming packets
destined to port 22 with the rule
"pass in log quick from any to any port = 22"
- "Allow All Except" policy with the 1.2.3.4 address in the
allow_except_list will generate the following rules:
"block in log quick from 1.2.3.4 to any port = 22"
"pass in log quick from any to any port = 22"
- "Deny All Except" policy with the 1.2.3.4 address in the
deny_except_list will generate the following rules:
"pass in log quick from 1.2.3.4 to any port = 22"
"block in log quick from any to any port = 22"
The Global Default policy has a boilerplate rule
pass out log quick all keep state
which allows incoming traffic if communication session is locally initiated.
This rule allows most client programs to carry out their communication and
is generated when Global Default policy isn't "none".
Starting the firewall: Firewall activation is done by enabling
network/ipfilter whose start method is modified to do the following:
- create Global Default rules based on its firewall policy
- create network services' rules for enabled services with firewall
policy
- create Global Override rules based on its firewall policy
- load rules from Global Default, Network Services, and Global
Override, in that order
Since the start method sets up the system firewall configuration, it also
configures the system firewall on boot and whenever network/ipfilter is
refreshed.
Partial update: While the system is running, the set of IPfilter rules
need to change as services get enabled or disabled, or when a policy is
modified. We want to update the IPfilter rules without reloading all the
rules. Network services are independent of each other so we can add and
remove each service's rules as needed. Global Override rules are reloaded
whenever there's an update to the rules in Network Services layer to
maintain their highest priority in the system rule set.
A change in system-wide policy will cause regeneration and reloading of
rules from all three layers. While not the most efficient approach, this
complete regeneration takes care of all policy inheritance and rule
ordering. In practice, it's reasonable because most policy changes happen at
the service policy level and system-wide policies are seldom changed.
Each policy has its rules stored in a separate and temporary file whose
content is loaded or unload by IPfilter to activate or deactivate the
policy. An update to the policy requires unloading the stored rule(s) and
regenerate and load the new rule(s).
Continuing the network/ssh service example, let's say the user would like to
add the IP address "1.2.3.10" to the deny_except_list, thus policy mode is
"Deny All Except", the following steps will take place:
- Global Override rules stored in its rule file are unloaded
- Unloading service's current rules which are
"pass in log quick from 1.2.3.4 to any port = 22"
"block in quick from any to any port = 22"
- Generating new rules
"pass in log quick from 1.2.3.10 to any port = 22"
"pass in log quick from 1.2.3.4 to any port = 22"
"block in quick from any to any port = 22"
- service's updated rule set above is loaded to enforce its new policy
- Global Override rules stored in its rule file are reloaded
Complicated services: Some services have rules that can't be generated by
the proposed model and require another mechanism. network/ftp uses both port
21 and 20 so its configuration will need rules that specify each port.
Moreover, client programs such as nis/client, network/autofs, and
network/ntp requires the system to allow their communication with remote
servers when a system-wide policy is "Deny All Except".
A service whose rules can't be generated by the framework can provide a
script that generate its IPfilter rules and outputs the rules to stdout. The
firewall_context/ipf_method property contains the script's path and
argument, similar to SMF method properties. During rule generation, the
service's script is invoked with the service FMRI as an additional argument
and the expected output is redirected that service's rule file. The file can
be loaded as if it were generated by the framework.
Example: network/ftp and firewall_context/ipf_method
- policy mode is "Deny All Except" with an empty except list
- ipf_method is "firewall_context/ipf_method astring
/lib/svc/method/svc-ftp\ ipfilter"
- script is invoked as "/lib/svc/method/svc-ftp ipfilter
network/ftp:default >>/var/run/ipfilter/ftp.ipf"
- the resulting content of /var/run/ipfilter/ftp.ipf is
block in log quick proto tcp from any to any port = 21
block in log quick proto tcp from any to any port = 20
The example shows the 'script' defined as an SMF 'ipfilter' method, thus
potentially small modification to existing service's method script.
Example: network/ntp running as a client, ntp.conf specifies the server
129.144.134.19 and multicastclient group 224.0.1.1. Its ipf_method script
generates the following rules:
pass in quick from 129.144.134.19 to any port = 123
pass in log quick from any to 224.0.1.1
Non-service client software: We also need to allow non-SMF client programs
such as BitTorrent & video conferencing peers/servers to carry out their
communication, allowing incoming traffic to certain local ports. A
firewall_config/client property value in the form
"{tcp | udp}:{PORT | PORT-PORT}" can generate rules
pass in quick proto {tcp | udp} from any to any port = PORT
pass in quick proto {tcp | udp} from any to any port = port range
which should be sufficient to support these client programs.
RPC services: These services are problematic because they may use
dynamically chosen ports and clients may also require access to rpbind,
(network/rpc service). Initially, network/rpc and all RPC services inherit
the same Global Default policy so there isn't a conflict. But if an RPC
service's policy is modified, it is important to note the policy for
network/rpc, unless it is less restrictive than the RPC service's, some
clients may not be able to access the RPC service as intended.
For a service, the value of inetd/isrpc or firewall_context/isrpc property,
or the lack of those properties indicates whether a service is an RPC
service. For RPC services, the framework queries rpcbind to get their port
information.
5. Putting it all together
Some simple but more complete examples to show the entire system firewall
configuration and the interactions of IPfilter rules at all three layers.
Each example building on previous examples, briefly describes the firewall
policy(s) and show the resulting firewall configuration, rule set.
Example 1 - Global Default policy is "None", all network services' policies
are "use_global", and Global Override policy is "None". This is the initial
configuration which corresponds to the initial empty ipf.conf file, thus an
empty set of IPfilter rules.
Example 2 - set a strict system-wide policy by changing Global Default
policy to "Deny All Except". This policy generates rules for Global Default
system-wide policy and any enabled network services. In this case, the only
enabled network service is network/ssh which by default inherits Global
Default policy. The resulting firewall configuration blocks all incoming
traffic:
block in log quick from any to any port = 22
block in log quick from all
Example 3 - resume normal operation for network/ssh by changing its policy
to "Allow All Except" and enable network/ftp service. This new policy
generates a different set of rules for network/ssh and network/ftp policy is
activated. Below is the new firewall configuration with a less than useful
network/ftp service since it doesn't allow any connection.
block in log quick from any to any port = 20
block in log quick from any to any port = 21
pass in log quick from any to any port = 22
block in log quick from all
Example 4 - restrict network/ftp access to two IP addresses "10.253.195.57"
and "10.253.195.60" by setting policy mode to "Deny All Except" and
deny_except_list to contain the two IP address. This new policy generates
set of rules for network/ftp and results in the below firewall configuration
pass in log quick from 10.253.195.60 to any port = 21
pass in log quick from 10.253.195.60 to any port = 20
pass in log quick from 10.253.195.57 to any port = 21
pass in log quick from 10.253.195.57 to any port = 20
block in log quick from any to any port = 20
block in log quick from any to any port = 21
pass in log quick from any to any port = 22
block in log quick from all
Example 5 - a malicious host, "10.253.195.66", is discovered which no
service should accept incoming traffic. This is accomplished by changing
system-wide Global Override policy from "None" to "Allow All Except" and set
its allow_all_except list to contain "10.253.195.66". The below new firewall
configuration blocks all incoming packets from 10.253.195.66
block in log quick from 10.253.195.66 to any
pass in log quick from 10.253.195.60 to any port = 21
pass in log quick from 10.253.195.60 to any port = 20
pass in log quick from 10.253.195.57 to any port = 21
pass in log quick from 10.253.195.57 to any port = 20
block in log quick from any to any port = 20
block in log quick from any to any port = 21
pass in log quick from any to any port = 22
block in log quick from all
_______________________________________________
networking-discuss mailing list
[email protected]