Go to main content

Securing the Network in Oracle® Solaris 11.4

Exit Print View

Updated: May 2021
 
 

Examples of Converting IPF Rules to PF Rules

The following examples are linked, and show more complex conversions than the examples in IP Filter to Packet Filter Rules Conversion Tool. Several examples illustrate how you can optimize the PF rule sets that ipf2pf generates.

Example 13  Blocking All IPv6 Traffic in PF

If your host does not handle IPv6 traffic, then it is good practice to block the IPv6 protocol at the firewall.

If you have IPv6 rules in the /etc/ipf/ipf6.conf file to block everything, as in the following /etc/ipf/ipf6.conf file, then you run the ipf2pf command on both files to convert them.

    ## IP Filter Sample ipf6.conf File
    #
    # block IPv6 completely
    #
    block in all
    block out all
$ ipf2pf -4 ipf.conf -6 ipf6.conf

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

    block drop in 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 inet proto tcp from any to any port = 22 flags any keep state (sloppy)
    pass out inet all flags any keep state (sloppy)
    block drop in inet6 all
    block drop out inet6 all

Note -  The ipf2pf conversion deliberately relaxes stateful policy to sloppy by specifying a keep state (sloppy) rule that is not visible in the file. This policy keeps firewall behavior close to IPF behavior.

If your policy requires a strict state inspection for TCP, you can change it to keep state on lo0. This might be your first customization of the ipf2pf conversion.


Example 14  Converting IPF IPv4 and IPv6 Policies That Are Identical to PF

If your network policy for IPv6 is to be same as for IPv4, that is, block every remote packet coming in except ssh, and allow everything out. The following output is the result of conversion of those rules:

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

    block drop in 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 inet proto tcp from any to any port = 22 flags any keep state (sloppy)
    pass out inet all flags any keep state (sloppy)
    block drop in inet6 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 inet6 proto tcp from any to any port = 22 flags any keep state (sloppy)
    pass out inet6 all flags any keep state (sloppy)

The output of the ipf2pf command creates a rules file that duplicates IPv4 and IPv6 policy like IPF does. Because PF treats IPv4 and IPv6 rules in one rule set, you could manually optimize the ipf2pf rule set file to remove the address family (inet and inet6) at pass and block rules, as shown in the following example.

Example 15  Removing inet and inet6 Address Families From ipf2pf Output
    ## Streamlined ipf2pf output to remove inet/d references
    # 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

    block drop in 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 proto tcp from any to any port = 22 flags any keep state (sloppy)
    pass out all flags any keep state (sloppy)
Example 16  Converting IPF NAT Rules to PF Rules

Unlike PF, IPF also uses separate rules for NAT from the /etc/ipf/ipnat.conf file. The following shows a typical ipnat.conf configuration:

    ## IP NAT Configuration File, ipnat.conf
    # Translate SRC address of LAN to IP address bound to net0
    #
    map net0 from 198.51.100.0/24 to any -> 0.0.0.0
    #
    # redirect ssh sessions from internet to SSH gate (198.51.100.22)
    #
    rdr net0 from any to 203.0.113.15 port = 22 -> 198.51.100.22 port 22

To add the preceding NAT PF policy to you IPv4 and IPv6 IPF policy, run the following command:

$ ipf2pf -4 ipf.conf -6 ipf6.conf -n ipnat.conf

    This command generates the following output when you add the NAT rules if your network policy:

  • Blocks inbound IPv6 completely

  • Allows IPv4 ssh inbound sessions only

  • Allows unrestricted outbound IPv6 traffic

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

    #
    # 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 198.51.100.0/24 to any nat-to (net0)
    match in on net0 inet proto tcp from any to 203.0.113.15 port = 22 rdr-to 198.51.100.22 port 22
    match in on net0 inet proto udp from any to 203.0.113.15 port = 22 rdr-to 198.51.100.22 port 22


    #
    # 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 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 inet proto tcp from any to any port = 22 flags any keep state (sloppy)
    pass out inet all flags any keep state (sloppy)
    block drop in inet6 all
    block drop out inet6 all
Example 17  Optimizing Converted IPF NAT Rules in PF

NAT rules that ipf2pf generates can be optimized. For example, if the IP address of the net0 interface (203.0.113.15) is statically assigned, then the 'pass out quick...' rule, which deals with DHCP, is unnecessary. You can also merge rdr-to actions in match rules to pass in rules to clarify the rule set further, as shown in the following optimization of the NAT rules in Example 16, Converting IPF NAT Rules to PF Rules:

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

    match out on net0 inet from 198.51.100.0/24 to any nat-to (net0)
    pass out all
    pass in all
    block drop in inet all
    pass out inet all flags any keep state (sloppy)
    pass in on net0 inet proto tcp from any to (net0) port = 22 rdr-to 198.51.100.22 port 22
    block drop in inet6 all
    block drop out inet6 all
Example 18  Implementing the Correct NAT Policy

The remaining match rule with the nat-to action can be merged to a 'pass out' rule, too. However, before merging it, consider that the pass out rule matches two sets of packets: packets that are forwarded for all LAN hosts in the 198.51.100.0/24 network, and local outbound packets from the firewall host itself, that is, local outbound traffic.

    A change in the NAT rule can implement a different network policy.

  1. If the firewall host is not supposed to talk to the public network, that is, to the network attached to net0, then you can merge the nat-to rule to the pass rule as you did for rdr-to:

    pass out on net0 inet from 198.51.100.0/24 to any nat-to (net0)
  2. If the firewall host must talk to the network, then you can optimize the rule, although the conversion rule is sufficient:

    pass out on net0 inet from any to any nat-to (net0)

    This rule also allows the firewall host to talk to the Internet. Also note that the nat-to action is not applied to packets with the same address as the address that is bound to net0. For those packets, NAT translation is not applied. Also keep in mind that the preceding rule matches all outbound packets at net0 NIC, including packets which might be coming from networks other than the 198.51.100.0/24 network.