Skip to content

Instantly share code, notes, and snippets.

@baetheus
Last active December 17, 2023 14:28
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • 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

WARNING

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!

Foreword

This is a modified version of sjorge's instructions for Single IP with NAT. Those instructions can be found here: https://docu.blackdot.be/snipets/solaris/smartos-nat

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 (project-fifo.net) 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.


Instructions

From the root shell of your smartos server.

mkdir -p /opt/custom/{smf,bin}
curl https://gist.githubusercontent.com/baetheus/5e1e5ab1eb68fae3490d/raw/net-setup > /opt/custom/bin/net-setup
chmod 770 /opt/custom/bin/net-setup
curl https://gist.githubusercontent.com/baetheus/5e1e5ab1eb68fae3490d/raw/net-setup.xml > /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 https://gist.githubusercontent.com/baetheus/5e1e5ab1eb68fae3490d/raw/sample-zone.json > /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!

Commentary

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.

ChangeLog

20160226

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

20150407

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

20141225

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

20141220

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

20141210

  • 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.
#!/usr/bin/sh
## 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
EXT_IP="192.168.0.100"
EXT_IF="e1000g0"
INT_NET="10.0.0.0/24"
INT_IP="10.0.0.1"
INT_IF="gw0"
VLAN="1000"
## 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
fi
## 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 -> 10.0.0.2 port 80 tcp" >> /etc/ipf/ipnat.conf
echo "rdr $EXT_IF from any to any port = 443 -> 10.0.0.2 port 443 tcp" >> /etc/ipf/ipnat.conf
echo "rdr $EXT_IF from any to any port = 2222 -> 10.0.0.2 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>
<dependency name='filesystem' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/system/filesystem/local'/>
</dependency>
<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' />
</property_group>
<stability value='Unstable' />
</service>
</service_bundle>
{
"autoboot": true,
"brand": "joyent",
"image_uuid": "d34c301e-10c3-11e4-9b79-5f67ca448df0",
"max_physical_memory": 1024,
"cpu_cap": 100,
"alias": "sample-zone",
"quota": "5",
"resolvers": [
"8.8.8.8",
"8.8.4.4"
],
"nics": [
{
"interface": "net0",
"nic_tag": "admin",
"vlan_id": "1000",
"ip": "10.0.0.2",
"gateway": "10.0.0.1",
"netmask": "255.255.255.0"
}
]
}
@BertrandF23
Copy link

Very usefull !
But I had to change

Setup Inbound NAT

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

into

Setup Inbound NAT

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

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

@baetheus
Copy link
Author

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.

@jeanparpaillon
Copy link

Hi,
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 ?

@jeanparpaillon
Copy link

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

@baetheus
Copy link
Author

@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