How to set up NAT for zones using Oracle Solaris 11.3 PF (Packet Filter)
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 enabledroot@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 networkEach 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 zoneYou 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 NATThe 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 forwardingThis 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 worksPing 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