X

News, tips, partners, and perspectives for the Oracle Solaris operating system

  • January 31, 2018

Migrating from IPF to Packet Filter in Solaris 11.4

Guest Author

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'

IPF is gone, what now?

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.

What has changed since Oracle Solaris 11.3?

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.

Known Issues

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.

Links

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

Join the discussion

Comments ( 1 )
  • Matt Mefferd Thursday, February 7, 2019
    Alexandr, I am migrating to S11.4 but am running into your known issue with IPF no longer functional on the S10 zone. Can you please give me some guidance as to how to configure PF on the S11.4 GZ to serve as a firewall for the S10 NGZ? Thanks
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha