Skip to content

Instantly share code, notes, and snippets.

Last active December 17, 2023 14:28
Show Gist options
  • Save baetheus/5e1e5ab1eb68fae3490d to your computer and use it in GitHub Desktop.
Save baetheus/5e1e5ab1eb68fae3490d to your computer and use it in GitHub Desktop.
SmartOS Single IP with NAT using VLAN


These intructions might work, but they need a bit of attention. I've been reading through ipf and smf documentation and have found a few ways to improve this process. When I have time I'll add that information here, until then, be sure to look into the ipf settings if you're having issues with routing. Good luck!


This is a modified version of sjorge's instructions for Single IP with NAT. Those instructions can be found here:

The primary difference is that this version does not rely on etherstubs for internal switching, but instead uses a vlan configuration. The benefits of this method over using etherstubs are:

  1. Project Fifo ( can create vms and zones with vlans, but does not currently have etherstub support.
  2. Vlan switching is supposedly more efficient than creating an etherstub to handle switching. I have not tested this statement.

I've tested this setup on servers at both Kimsufi and SoYouStart (Both subsidiaries of OVH). I highly recommend these hosts. In other lab tests, this setup was used as the starting point for private vlan over vpn tunnel configurations.

Make sure to look at the net-setup shell script and to modify it to your settings. If you leave the current settings it will likely break things.


From the root shell of your smartos server.

mkdir -p /opt/custom/{smf,bin}
curl > /opt/custom/bin/net-setup
chmod 770 /opt/custom/bin/net-setup
curl > /opt/custom/smf/net-setup.xml

The above commands will create new directories in opt and download a shell script that sets up the vlan and nat and an smf service manifest. At this point you can either run svccfg import /opt/custom/smf/net-setup.xml or reboot. Be sure to look at the two files associated in this gist and to change whatever you feel needs changing.

I've also included a sample zone config. To get started with that

mkdir /opt/zones
imgadm update
imgadm import d34c301e-10c3-11e4-9b79-5f67ca448df0
curl > /opt/zones/sample-zone.json
vmadm create -f /opt/zones/sample-zone.json

After running this you should be able to ssh to your sample zone like so: ssh -l root -p 2222 <external-ip>.

Good Luck!


Firewall: I've done a small amount of work locking down most of the basic networking holes with ipf, but I am by no means a network administrator. If you really wanted to lock down your stuff, here is where I'd start:

  • Most internal vlan'd traffic should never be broadcast outside of the host. So vlans should be enough to segment internal hosts from external networks. But this is still not a great amount of protection.
  • You may wish to block traffic between zones or to only allow certain outbound port traffic.
  • Additionally, it would be more secure to add a second IP and to perform this routing inside of a zone plumbed to that ip, allowing only ssh traffic through the primary ip.



  • Updated to net-setup to reflect a current working and stripped down ipf/ipnat config
  • Removed insecure curl flags as ssl is now handled by most root cert chains.


  • Update links to point to baetheus github user account instead of slashtact.


  • Updated net-setup script to be a bit simpler.
  • Reorganized README and fixed some minor mistakes.


  • Updated curl links in README to always link to newest file revisions in gist.


  • Fixed the net-setup script to actually include the example ssh tunnel for the example zone.
  • Added some commentary on the firewall config, disclaimerish in nature.
## Warning, comment out once settings are edited.
echo 'WARNING!!! Edit the net-setup script with your settings and comment out this warning to proceed.' && exit 1
## Settings
## Setup vlan and gateway
if [ `dladm show-vnic | grep $INT_IF | wc -l` -ne 1 ]; then
/usr/sbin/dladm create-vlan -l $EXT_IF -v $VLAN
/usr/sbin/dladm create-vnic -l $EXT_IF $INT_IF -v $VLAN
/usr/sbin/ipadm create-addr -T static -a $INT_IP $INT_IF/v4
## Turn on ip forwarding
/usr/sbin/routeadm -u -e ipv4-forwarding
## Clear previous ipfilter and ipnat
[ -e /etc/ipf/ipnat.conf ] && rm /etc/ipf/ipnat.conf
[ -e /etc/ipf/ipf.conf ] && rm /etc/ipf/ipf.conf
## Setup Firewall
echo "## Allow Inbound Ports" >> /etc/ipf/ipf.conf
echo "pass in quick on $EXT_IF proto tcp from any to any port = 22 keep state" >> /etc/ipf/ipf.conf
echo "pass in quick on $EXT_IF proto tcp from any to any port = 80 keep state" >> /etc/ipf/ipf.conf
echo "pass in quick on $EXT_IF proto tcp from any to any port = 443 keep state" >> /etc/ipf/ipf.conf
echo "pass in quick on $EXT_IF proto icmp from any to any icmp-type echo" >> /etc/ipf/ipf.conf
## Outbound can be buttoned down further, try using snoop to determine your traffic profile.
echo "## Allow Out Ports" >> /etc/ipf/ipf.conf
echo "pass out quick on $EXT_IF all keep state" >> /etc/ipf/ipf.conf
echo "## Block all else" >> /etc/ipf/ipf.conf
echo "block in quick log first on $EXT_IF all" >> /etc/ipf/ipf.conf
echo "block out quick log first on $EXT_IF all" >> /etc/ipf/ipf.conf
## Setup Inbound NAT examples for web traffic and ssh forwarding.
echo "rdr $EXT_IF from any to any port = 80 -> port 80 tcp" >> /etc/ipf/ipnat.conf
echo "rdr $EXT_IF from any to any port = 443 -> port 443 tcp" >> /etc/ipf/ipnat.conf
echo "rdr $EXT_IF from any to any port = 2222 -> port 22 tcp" >> /etc/ipf/ipnat.conf
## Setup Outbound NAT
echo "map $EXT_IF from $INT_NET to any -> 0/32 proxy port ftp ftp/tcp" >> /etc/ipf/ipnat.conf
echo "map $EXT_IF from $INT_NET to any -> 0/32 portmap tcp/udp auto" >> /etc/ipf/ipnat.conf
echo "map $EXT_IF from $INT_NET to any -> 0/32" >> /etc/ipf/ipnat.conf
## Enable Firewall and NAT
/usr/sbin/ipf -E -Fa -v -f /etc/ipf/ipf.conf
/usr/sbin/ipnat -C -v -f /etc/ipf/ipnat.conf
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='site:net-setup'>
<service name='site/net-setup' type='service' version='1'>
<create_default_instance enabled='true' />
<single_instance />
<dependency name='net-physical' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/network/physical'/>
<dependency name='filesystem' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/system/filesystem/local'/>
<exec_method type='method' name='start' exec='/opt/custom/bin/net-setup' timeout_seconds='0' />
<exec_method type='method' name='stop' exec=':true' timeout_seconds='0' />
<property_group name='startd' type='framework'>
<propval name='duration' type='astring' value='transient' />
<stability value='Unstable' />
"autoboot": true,
"brand": "joyent",
"image_uuid": "d34c301e-10c3-11e4-9b79-5f67ca448df0",
"max_physical_memory": 1024,
"cpu_cap": 100,
"alias": "sample-zone",
"quota": "5",
"resolvers": [
"nics": [
"interface": "net0",
"nic_tag": "admin",
"vlan_id": "1000",
"ip": "",
"gateway": "",
"netmask": ""
Copy link

Very usefull !
But I had to change

Setup Inbound NAT

echo "rdr $EXT_IF from any to any port = 2222 -> port 2222 tcp" >> /etc/ipf/ipnat.conf


Setup Inbound NAT

echo "rdr $EXT_IF from any to any port = 2222 -> port 22 tcp" >> /etc/ipf/ipnat.conf

And I had to comment ipf because neither ping nor ssh access worked with it.

Copy link

Thanks for the info BertrandF23. I've been using a different version of the ipf/ipnat config for quite awhile. I've updated the gist to reflect the changes I've made.

Copy link

Thanks for your gist !
I'm using it for setting up a server with single IP. I can't ping external IP from the created zone (nor outside of course).
ipv4-forwarding is enabled and routes looks ok, how can I check config is ok ?

Copy link

Solved: I was doing some routing in the zone and forgot to enable ip_spoofing

Copy link

@jeanparpaillon Glad you figured it out. If you find any issues with this documentation let me know so I can keep it updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment