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:
root@S11_3_SRU:~# pkg install network/firewall
Packages to install: 1
Services to change: 1
Create boot environment: No
Create backup boot environment: YesDOWNLOAD PKGS FILES XFER (MB) SPEED
Completed 1/1 33/33 0.4/0.4 123k/sPHASE ITEMS
Installing new actions 92/92
Updating package state database Done
Updating package cache 0/0
Updating image state Done
Creating fast lookup database Done
Updating package cache 1/1
root@S11_3_SRU:~# svcs firewall:default
STATE STIME FMRI
disabled 14:56:38 svc:/network/firewall:default
root@S11_3_SRU:~# svcs ipfilter
STATE STIME FMRI
disabled 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:default
root@S11_3_SRU:~# svcs firewall
STATE STIME FMRI
online 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 rules
root@S11_3_SRU:~#
This shows that no rules are configured. We'll fix that later.
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, in addition if you don't want things you do in the zone to be seen on the real network you need to create a stub on which to create the vnic:
root@S11_3_SRU:~# dladm create-etherstub stub0
root@S11_3_SRU:~# dladm create-vnic -l stub0 zone1
root@S11_3_SRU:~# dladm create-vnic -l stub0 gz0
root@S11_3_SRU:~# dladm show-link
LINK CLASS MTU STATE OVER
net0 phys 1500 up --
stub0 etherstub 9000 unknown --
zone1 vnic 9000 up stub0
gz0 vnic 9000 up stub0
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 gz0
root@S11_3_SRU:~# ipadm create-addr -a 192.160.0.1 gz0
gz0/v4
root@S11_3_SRU:~# ipadm show-addr
ADDROBJ TYPE STATE ADDR
lo0/v4 static ok 127.0.0.1/8
net0/v4 dhcp ok 10.0.2.15/24
gz0/v4 static ok 192.160.0.1/24
lo0/v6 static ok ::1/128
net0/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.
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 zone1
Use 'create' to begin configuring a new zone.
zonecfg:zone1> create
create: Using system default template 'SYSdefault'
zonecfg:zone1> remove anet 0
zonecfg:zone1> add net
zonecfg:zone1:net> set physical=zone1
zonecfg:zone1:net> end
zonecfg:zone1> set autoboot=true
zonecfg:zone1> verify
zonecfg:zone1> exit
root@S11_3_SRU:~# zoneadm -z zone1 install
The following ZFS file system(s) have been created:
rpool/VARSHARE/zones/zone1
Progress 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: zone1
Installation: Starting ...
<...... Stuff Deleted.......>
Some time later we can boot it and check the installation:
root@S11_3_SRU:~# zoneadm -z zone1 boot
root@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.
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 rules
pass 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
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 net0
IFNAME PROPERTY PROTO PERM CURRENT PERSISTENT DEFAULT POSSIBLE
net0 forwarding ipv4 rw off -- off on,off
net0 forwarding ipv6 rw off -- off on,off
root@S11_3_SRU:~# ipadm show-ifprop -p forwarding gz0
IFNAME PROPERTY PROTO PERM CURRENT PERSISTENT DEFAULT POSSIBLE
gz0 forwarding ipv4 rw off -- off on,off
gz0 forwarding ipv6 rw off -- off on,off
Now check they're enabled:
root@S11_3_SRU:~# ipadm set-ifprop -p forwarding=on -m ipv4 net0
root@S11_3_SRU:~# ipadm set-ifprop -p forwarding=on -m ipv4 gz0
IFNAME PROPERTY PROTO PERM CURRENT PERSISTENT DEFAULT POSSIBLE
net0 forwarding ipv4 rw on on off on,off
net0 forwarding ipv6 rw off -- off on,off
root@S11_3_SRU:~# ipadm show-ifprop -p forwarding gz0
IFNAME PROPERTY PROTO PERM CURRENT PERSISTENT DEFAULT POSSIBLE
gz0 forwarding ipv4 rw on on off on,off
gz0 forwarding ipv6 rw off -- off on,off
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