Market Place

Breaking News

How to set up NAT for zones using Oracle Solaris 11.3 PF (Packet Filter)

By: Chris Beal | Senior Principal Software Engineer

New in Oracle Solaris 11.3 is the BSD Packet Filter firewall. Which means my previous configuration for have a single IP address for my global zone and several zones (kernel or native) configured behind a NAT firewall will need to be changed eventually to use PF rather than IPFilter (the default firewall still in 11.3 and earlier). I did spend some time reading the documentation which explains it all very well once you understand the product, but for someone who was starting from nowhere (I had help setting up the IPfilter rules) I was a bit stumped. I couldn't find any good blog posts on it either, so thought it would be worth blogging my notes.

These are the steps I found you need to follow, it includes setting up a basic zone as well:

Step 1: Make sure PF is installed and enabled

Step 2: Create VNICs for your private network

Step 3: Create a zone

Step 4: Create your PF rules for NAT

Step 5: Enable IP forwarding

Step 6: Checking it all works

Lets take these one at a time:

Step 1: Make sure PF is installed and enabled

root@S11_3_SRU:~# pkg install network/firewall           Packages to install:   1            Services to change:   1       Create boot environment:  NoCreate backup boot environment: Yes DOWNLOAD                                PKGS         FILES    XFER (MB)   SPEEDCompleted                                1/1         33/33      0.4/0.4  123k/s PHASE                                          ITEMSInstalling new actions                         92/92Updating package state database                 DoneUpdating package cache                           0/0Updating image state                            DoneCreating fast lookup database                   DoneUpdating package cache                            1/1

root@S11_3_SRU:~# svcs firewall:defaultSTATE          STIME    FMRIdisabled       14:56:38 svc:/network/firewall:defaultroot@S11_3_SRU:~# svcs ipfilterSTATE          STIME    FMRIdisabled       14:53:06 svc:/network/ipfilter:default

You want to make sure ipfilter is disabled before you enable PF:

root@S11_3_SRU:~# svcadm enable firewall:defaultroot@S11_3_SRU:~# svcs firewallSTATE          STIME    FMRIonline         15:05:13 svc:/network/firewall:default

There are no active rules that product the system in the default configuration you can check this with the pfctl command:

root@S11_3_SRU:~# pfctl -s rulesroot@S11_3_SRU:~#

This shows that no rules are configured. We'll fix that later.

Step 2: Create VNICs for your private network

Each zone is going to need a virtual NIC to attach to, and the global zone will need a VNIC on the same "network" as the zones to allow them to communicate:

root@S11_3_SRU:~# dladm create-vnic -l net0 zone1root@S11_3_SRU:~# dladm create-vnic -l net0 gz0root@S11_3_SRU:~# dladm show-linkLINK                CLASS     MTU    STATE    OVERnet0                phys      1500   up       --zone1               vnic      1500   up       net0gz0                 vnic      1500   up       net0

The one I'm going to use in the Global Zone for NAT needs an IP address on the same private network as I'm going to use for zone1:

root@S11_3_SRU:~# ipadm create-ip gz0root@S11_3_SRU:~# ipadm create-addr -a 192.160.0.1 gz0gz0/v4root@S11_3_SRU:~# ipadm show-addrADDROBJ           TYPE     STATE        ADDRlo0/v4            static   ok           127.0.0.1/8net0/v4           dhcp     ok           10.0.2.15/24gz0/v4            static   ok           192.160.0.1/24lo0/v6            static   ok           ::1/128net0/v6           addrconf ok           fe80::a00:27ff:fe35:d606/10

OK so we're good to go on the IP address front. Now lets create a zone.

Step 3: Creating a zone

You may already have zones configured, but I'm creating a new one with using our zone1 vnic as the physical layer for the network (and setting autoboot to be true):

root@S11_3_SRU:~# zonecfg -z zone1Use 'create' to begin configuring a new zone.zonecfg:zone1> createcreate: Using system default template 'SYSdefault'zonecfg:zone1> remove anet 0zonecfg:zone1> add netzonecfg:zone1:net> set physical=zone1zonecfg:zone1:net> endzonecfg:zone1> set autoboot=truezonecfg:zone1> verifyzonecfg:zone1> exit

Now we need to install some software in the zone:

root@S11_3_SRU:~# zoneadm -z zone1 installThe following ZFS file system(s) have been created:    rpool/VARSHARE/zones/zone1Progress being logged to /var/log/zones/zoneadm.20171113T145423Z.zone1.install       Image: Preparing at /system/zones/zone1/root.  Install Log: /system/volatile/install.3974/install_log AI Manifest: /tmp/manifest.xml.ojc6sa  SC Profile: /usr/share/auto_install/sc_profiles/enable_sci.xml    Zonename: zone1Installation: Starting ...<...... Stuff Deleted.......>

Some time later we can boot it and check the installation:

root@S11_3_SRU:~# zoneadm -z zone1 bootroot@S11_3_SRU:~# zlogin -C zone1

We'll see the usual System Configuration Tool, this is where I will (for now) set up the IP addresses etc, but you can to this in the zone at any time (Have a look at the docs here if you want to know how to reconfigure a zone to use vnics).

This is a screen shot of the zone1 Network Configuration screen

From this we can log in to the zone and ping various places, but obviously nothing out side of the box I'm using. So it's time to set up the PF firewall rules.

Step 4: Create your PF rules for NAT

The NAT rules in PF are really simple. For our example it's just this:

pass out on net0 from 192.160.0.0/24 to any nat-to (net0)

I add this to the end of /etc/firewall/pf.conf, and refresh the smf service with:

root@S11_3_SRU:~# svcadm refresh firewall:default

Analysing what this rule does it says (from left to right):

Allow out bound packets on net0 from anything on my private network to any ip address, but then rewrite the source address to be that of net0. The brackets around the last net0 simply say to PF to update the rule if the IP address of net0 changes.

You can add other firewall rules obviously.

Checking it's configured correctly:

root@S11_3_SRU:~# pfctl -s rulespass out on net0 inet from 192.160.0.0/24 to any flags S/SA nat-to (net0) round-robin

This is how I expect it to look

Step 5: Enable IP forwarding

This is the one I forgot to do and was scratching my head for a while. As always I should have read the docs first:

root@S11_3_SRU:~# ipadm show-ifprop -p forwarding net0IFNAME      PROPERTY        PROTO PERM CURRENT    PERSISTENT DEFAULT    POSSIBLEnet0        forwarding      ipv4  rw   off        --         off        on,offnet0        forwarding      ipv6  rw   off        --         off        on,offroot@S11_3_SRU:~# ipadm show-ifprop -p forwarding gz0IFNAME      PROPERTY        PROTO PERM CURRENT    PERSISTENT DEFAULT    POSSIBLEgz0         forwarding      ipv4  rw   off        --         off        on,offgz0         forwarding      ipv6  rw   off        --         off        on,off

Now check they're enabled:

root@S11_3_SRU:~# ipadm set-ifprop -p forwarding=on -m ipv4 net0root@S11_3_SRU:~# ipadm set-ifprop -p forwarding=on -m ipv4 gz0

IFNAME      PROPERTY        PROTO PERM CURRENT    PERSISTENT DEFAULT    POSSIBLEnet0        forwarding      ipv4  rw   on         on         off        on,offnet0        forwarding      ipv6  rw   off        --         off        on,offroot@S11_3_SRU:~# ipadm show-ifprop -p forwarding gz0IFNAME      PROPERTY        PROTO PERM CURRENT    PERSISTENT DEFAULT    POSSIBLEgz0         forwarding      ipv4  rw   on         on         off        on,offgz0         forwarding      ipv6  rw   off        --         off        on,off

Step 6: Checking it all works

Ping now works, but name services don't as I've not restarted the name-services service, so I simply rebooted it, just to make it clean

root@zone1:~# ssh user@somehost

This now works as expected. So all is good.

I've done this very roughly mostly to jog my memory, but hopefully someone else will find it useful

No comments