Contributed by: Alexandr Nedvedicky
This blog entry covers the migration from IPF to Packet Filter (a.k.a. PF). If your Oracle Solaris 11.3 runs without IPF, then you can stop reading now (well of course, if you're interested in reading about the built-in firewalls you should continue on). The IPF served as a network firewall on Oracle Solaris for more than a decade (Since Oracle Solaris 10). PF on Oracle Solaris is available since Oracle Solaris 11.3 as alternative firewall. Administrator must install it explicitly using 'pkg install firewall'. Having both firewalls shipped during Oracle Solaris 11.3 release cycle should provide some time to prepare for a leap to world without IPF. If you as a SysAdmin have completed your homework and your ipf.conf (et. al.) are converted to pf.conf already, then skip reading to 'What has changed since Oracle Solaris 11.3'
On upgrade from Oracle Solaris 11.3 PF will be automatically installed without any action from the administrator. This is implemented by renaming pkg:/network/ipfilter to pkg:/network/ipf2pf and adding a dependency on pkg:/network/firewall. The ipf2pf package installs ipf2pf(7) (svc:/network/ipf2pf) service, which runs at the first boot to newly updated BE. The service inspects the IPF configuration, which is still available in '/etc/svc/repository-boot'. The ipf2pf start method uses the repository to locate IPF configuration. The IPF configuration is then moved to '/var/firewall/legacy.ipf/conf' directory. Content of the directory may vary depending on your ipfilter configuration. The next step is to attempt to convert legacy IPF configuration to pf.conf. Unlike IPF the PF keeps its configuration in single file named pf.conf (/etc/firewall/pf.conf). The service uses 'ipf2pf' binary tool for conversion. Please do not set your expectations for ipf2pf too high. It's a simple tool (like hammer or screwdriver) to support your craftsman's skill, while converting implementation of your network policy from IPF to PF. The tool might work well for simple cases, but please always review the conversion result before deploying it. As soon as ipf2pf service is done with conversion, it updates /etc/firewall/pf.conf with comment to point you to result: '/var/firewall/legacy.ipf/pf.conf'.
Let's see how the tool actually works when it converts your IPF configuration to PF. Let's assume your IPF configuration is kept in ipf.conf, ipnat.conf and ippool-1.conf:
ipf.conf
#
# net0 faces to public network. we want to allow web and mail
# traffic as stateless to avoid explosion of IPF state tables.
# mail and web is busy.
#
# allow stateful inbound ssh from trusted hosts/networks only
#
block in on net0 from any to any
pass in on net0 from any to 192.168.1.1 port = 80
pass in on net0 from any to 172.16.1.15 port = 2525
pass in on net0 from pool/1 to any port = 22 keep state
pass out on net0 from any to any keep state
pass out on net0 from 192.168.1.1 port = 80 to any
pass out on net0 from 192.168.1.1 port = 2525 to any
ipnat.conf
# let our private lab network talk to network outside
map net0 172.16.0.0/16 -> 0.0.0.0/32
rdr net0 192.168.1.1/32 port 25 -> 172.16.1.15 port 2525
ippool-1.conf
table role = ipf type = tree number = 1
{
8.8.8.8, 10.0.0.0/32
};
In order to convert ipf configuration above, we run ipf2pf as follows:
ipf2pf -4 ipf.conf -n ipnat.conf -p ippool-1.conf -o pf.conf
The result of conversion pf.conf looks like that:
#
# File was generated by ipf2pf(7) service during system upgrade. The
# service attempted to convert your IPF rules to PF (the new firewall)
# rules. You should check if firewall configuration here, suggested by
# ipf2pf, still meets your network policy requirements.
#
#
# Unlike IPF, PF intercepts packets on loopback by default. IPF does not
# intercept packets bound to loopback. To turn off the policy check for
# loopback packets, we suggest to use command below:
set skip on lo0
#
# PF does IP reassembly by default. It looks like your IPF does not have IP
# reassembly enabled. Therefore the feature is turned off.
#
set reassemble no
# In case you change your mind and decide to enable IP reassembly
# delete the line above. Also to improve interoperability
# with broken IP stacks, tell PF to ignore the 'DF' flag when
# doing reassembly. Uncommenting line below will do it:
#
# set reassemble yes no-df
#
# PF tables are the equivalent of ippools in IPF. For every pool
# in legacy IPF configuration, ipf2pf creates a table and
# populates it with IP addresses from the legacy IPF pool. ipf2pf
# creates persistent tables only.
#
table <pool_1> persist { 8.8.8.8, 10.0.0.0 }
#
# Unlike IPF, the PF firewall implements NAT as yet another
# optional action of a regular policy rule. To keep PF
# configuration close to the original IPF, consider using
# the 'match' action in PF rules, which translate addresses.
# There is one caveat with 'match'. You must always write a 'pass'
# rule to match the translated packet. Packets are not translated
# unless they hit a subsequent pass rule. Otherwise, the "match"
# rule has no effect.
#
# It's also important to avoid applying nat rules to DHCP/BOOTP
# requests. The following stateful rule, when added above the NAT
# rules, will avoid that for us.
pass out quick proto udp from 0.0.0.0/32 port 68 to 255.255.255.255/32 port 67
# There are 2 such rules in your IPF ruleset
#
match out on net0 inet from 172.16.0.0/16 to any nat-to (net0)
match in on net0 inet from any to 192.168.1.1 rdr-to 172.16.1.15 port 2525
#
# The pass rules below make sure rdr/nat -to actions
# in the match rules above will take effect.
pass out all
pass in all
block drop in on net0 inet all
#
# IPF rule specifies either a port match or return-rst action,
# but does not specify a protocol (TCP or UDP). PF requires a port
# rule to include a protocol match using the 'proto' keyword.
# ipf2pf always assumes and enters a TCP port number
#
pass in on net0 inet proto tcp from any to 192.168.1.1 port = 80 no state
#
# IPF rule specifies either a port match or return-rst action,
# but does not specify a protocol (TCP or UDP). PF requires a port
# rule to include a protocol match using the 'proto' keyword.
# ipf2pf always assumes and enters a TCP port number
#
pass in on net0 inet proto tcp from any to 172.16.1.15 port = 2525 no state
#
# IPF rule specifies either a port match or return-rst action,
# but does not specify a protocol (TCP or UDP). PF requires a port
# rule to include a protocol match using the 'proto' keyword.
# ipf2pf always assumes and enters a TCP port number
#
pass in on net0 inet proto tcp from <pool_1> to any port = 22 flags any keep state (sloppy)
pass out on net0 inet all flags any keep state (sloppy)
#
# IPF rule specifies either a port match or return-rst action,
# but does not specify a protocol (TCP or UDP). PF requires a port
# rule to include a protocol match using the 'proto' keyword.
# ipf2pf always assumes and enters a TCP port number
#
pass out on net0 inet proto tcp from 192.168.1.1 port = 80 to any no state
#
# IPF rule specifies either a port match or return-rst action,
# but does not specify a protocol (TCP or UDP). PF requires a port
# rule to include a protocol match using the 'proto' keyword.
# ipf2pf always assumes and enters a TCP port number
#
pass out on net0 inet proto tcp from 192.168.1.1 port = 2525 to any no state
As you can see the result pf.conf file is annotated by comments, which explain what happened to original ipf.conf.
If you already have experience with PF on Solaris, then you are going to notice those changes since Oracle Solaris 11.3:
firewall in degraded state
Firewall service enters degraded state, whenever it gets enabled with
default configuration shipped package. This should notify administrator,
the system enables firewall with empty configuration. As soon as you
alter etc/firewall/pf.conf and refresh firewall service, the service
will become online.
firewall in maintenance state
firewall enters maintenance state as soon as the service tries to
load syntactically invalid configuration. If it happens the smf method
inserts a hardwired fallback rules, which drop all inbound sessions
excepts ssh.
support for IP interface groups
11.4 comes with support for 'firewall interface groups'. It's a
feature, which comes from upstream. The idea is best described by its
author Henning Brauer [ goo.gl/eTjn54 ]. The S11.4 brings same feature
with Solaris flavor. The interface groups are treated as interface
property 'fwifgroup'. To assign interface net0 to group alpha use
ipadm(8):
ipadm set-ifprop -p fwifgroup=alpha net0
to show firewall interface groups, which net0 is member of use
show-ifprop:
ipadm show-ifprop -p fwifgroup net0
The firewall interface groups are treated as any other interface,
which PF rule is bound to. Rule below applies to all packets, which
are bound to firewall interface group alpha:
pass on alpha all
The firewall interface group is just kind of tag you assign to
interface, so PF rules can use it to refer to such interface(s)
using tags instead of names.
Not everything goes as planned. There is a bunch of changes, which missed the beta-release build. Those are known issues and are going to be addressed in final release.
firewall:framework SMF instacne
This is going to be removed in final release. The feature presents
yet another hurdle in upgrade path. It's been decided to postpone it.
The things are just unfortunate we failed to remove it for beta.
support for _auto/_static anchors
Those are closely related to firewall:framework instance. Support for
those two anchors is postponed.
'set skip on lo0' in default pf.conf
The 'set skip on lo0' is going to disappear from default pf.conf
shipped by firewall package. Unlike IPF
Lack of firewall in Solaris 10 BrandZ
With IPF gone there is no firewall available in S10 BrandZ.
The only solution for Solaris 10 deployments, which require firewall
protection is to move those Solaris 10 BrandZ behind the firewall, which
runs outside the Solaris 10 BrandZ. The firewall can be either another
network appliance, or it can be Solaris 11 Zone with PF installed. The
Solaris 11 Zone will act as L3 router forwarding all traffic for Solaris 10
-Zone. If such solution does not work for your deployment/scenario we hope
to hear back from you with some details of your story.
Although there are differences between IPF to PF, the migration should not be that hard as both firewalls have similar concept. We keep PF on Oracle Solaris as much close to upstream as possible, so many guides and recipes found in Internet should work for Oracle Solaris as well, just keep in mind NAT-64, pfsync and bandwidth management were not ported to Oracle Solaris. We hope you'll enjoy the PF ride and will stay tuned for more on the Oracle Solaris 11.4 release.
Oracle Solaris Documentation on IPF, PF, and comparing IPF to PF.
[ goo.gl/YyDMVZ ] https://sourceforge.net/projects/ipfilter/
[ goo.gl/UgwCth ] https://www.openbsd.org/faq/pf/
[ goo.gl/eTjn54 ] https://marc.info/?l=openbsd-misc&m=111894940807554&w=2