IPv6 on SmartOS on Hetzner

Purpose

This document explains how to use IPv6 on SmartOS on a rented dedicated server from Hetzner.

Requirements

This how-to uses rented server from Hetzner running SmartOS. Your server should have an IPv6 /64 address pool in your Robot control panel.

Process

Using IPv6 on SmartOS has two phases:

Configure IPv6 in the Global Zone

Configuring IPv6 in the Global Zone is remarkably easy. Edit the /usbkey/config file, adding your IPv6 address, gateway and DNS servers:

admin_ip6=2a01:4f8:190:9293::1/64
admin_gateway6=fe80::1

dns_resolvers=8.8.8.8,8.8.4.4,2001:4860:4860::8888,2001:4860:4860::8844

Once youʼve added these values, reboot your SmartOS server. When it comes back up, it will be able to speak IPv6. You can confirm this with a simple ping test:

[root@smartos ~]# ping -a google.com
google.com (2a00:1450:4001:815::200e) is alive
google.com (216.58.208.46) is alive

Use IPv6 in Zones

Using IPv6 from a zone is also remarkably easy. First, create the zone. If you use the JSON below, be sure to change the IP address. You may need to download the appropriate image with imgadm as we have done below:

[root@smartos ~]# cat > ipv6.json
{
  "brand": "joyent",
  "image_uuid": "b2d3c018-e6e5-11e6-9815-f7d92aad9089",
  "max_physical_memory": 256,
  "hostname": "ipv6",
  "resolvers": [
    "2001:4860:4860::8888",
    "2001:4860:4860::8844"
  ],
  "alias": "ipv6",
  "nics": [
    {
      "nic_tag": "admin",
      "ips": [
        "2a01:4f8:190:9293::2/64"
      ]
    }
  ],
  "quota": 1
}
[root@smartos ~]# imgadm import b2d3c018-e6e5-11e6-9815-f7d92aad9089
Importing b2d3c018-e6e5-11e6-9815-f7d92aad9089 (minimal-64-lts@16.4.1) from "https://images.joyent.com"
Gather image b2d3c018-e6e5-11e6-9815-f7d92aad9089 ancestry
Must download and install 1 image (67.3 MiB)
Download 1 image                                     [=========================================================================================================================>] 100%  67.30MB   4.96MB/s    13s
Downloaded image b2d3c018-e6e5-11e6-9815-f7d92aad9089 (67.3 MiB)
zones/b2d3c018-e6e5-11e6-9815-f7d92aad9089           [=========================================================================================================================>] 100%  67.30MB  29.07MB/s     2s
Imported image b2d3c018-e6e5-11e6-9815-f7d92aad9089 (minimal-64-lts@16.4.1)

Next, create the zone:

[root@smartos ~]# vmadm create -f ipv6.json
Successfully created VM 3fd7576b-731c-6851-d723-dd740f58a808

Finally, log in to the zone. Until issue 548 is fixed, you must add a route for the IPv6 gateway. Then, you should be able to use IPv6 connectivity:

[root@smartos ~]# zlogin 3fd7576b-731c-6851-d723-dd740f58a808
[Connected to zone '3fd7576b-731c-6851-d723-dd740f58a808' pts/4]
   __        .                   .
 _|  |_      | .-. .  . .-. :--. |-
|_    _|     ;|   ||  |(.-' |  | |
  |__|   `--'  `-' `;-| `-' '  ' `-'
                   /  ; Instance (minimal-64-lts 16.4.1)
                   `-'  https://docs.joyent.com/images/smartos/minimal

[root@ipv6 ~]# ping 2001:4860:4860::8888
ping: sendto No route to host
[root@ipv6 ~]# route -p add -inet6 default fe80::1
add net default: gateway fe80::1
add persistent net default: gateway fe80::1
[root@ipv6 ~]# ping 2001:4860:4860::8888
2001:4860:4860::8888 is alive
[root@ipv6 ~]# ping -a google.com
google.com (2a00:1450:4001:81c::200e) is alive
[root@ipv6 ~]# logout

[Connection to zone '3fd7576b-731c-6851-d723-dd740f58a808' pts/4 closed]

Enable IPv6 Forwarding

Weʼve found that IPv6 in zones at Hetzner works best if the global zone is configured to forward IPv6. Someone who knows IPv6 better than us can probably explain why. Do yourself a favor and enable it now so you donʼt have to wonder why it is not working in the future.

If you have a zone that is not consistently connected via IPv6, you can try this:

[root@smartos ~]# routeadm -u -e ipv6-forwarding

If that fixes the problem, youʼll want to make it permanent like this:

[root@smartos ~]# mkdir -p /opt/custom/bin
[root@smartos ~]# cat > /opt/custom/bin/enable_ipv6-forwarding.sh <<EOF
#!/bin/sh
# IPv6 forwarding
set -e

PATH=/usr/sbin:/usr/bin:/opt/local/bin:/opt/local/sbin; export PATH

. /lib/svc/share/smf_include.sh

cd /

case "\$1" in
      'start')
              routeadm -u -e ipv6-forwarding
              ;;
      'stop')
              routeadm -u -d ipv6-forwarding
              ;;
      *)
              echo "Usage: $0 { start | stop }"
              exit $SMF_EXIT_ERR_FATAL
              ;;
esac
exit $SMF_EXIT_OK
EOF
[root@smartos ~]# chmod 755 /opt/custom/bin/enable_ipv6-forwarding.sh
[root@smartos ~]# mkdir -p /opt/custom/smf
[root@smartos ~]# cat > /opt/custom/smf/enable_ipv6-forwarding.xml <<EOF
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="manifest" name="enable_ipv6-forwarding">
  <service name="network/enable_ipv6-forwarding" type="service" version="1">
    <create_default_instance enabled="true"/>
    <single_instance/>
    <dependency name="network" grouping="require_all" restart_on="error" type="service">
      <service_fmri value="svc:/milestone/network:default"/>
    </dependency>
    <dependency name="filesystem" grouping="require_all" restart_on="error" type="service">
      <service_fmri value="svc:/system/filesystem/local"/>
    </dependency>
    <exec_method type="method" name="start" exec="/opt/custom/bin/enable_ipv6-forwarding.sh %m" timeout_seconds="60"/>
    <exec_method type="method" name="stop" exec="/opt/custom/bin/enable_ipv6-forwarding.sh %m" timeout_seconds="60"/>
    <property_group name="startd" type="framework">
      <propval name="duration" type="astring" value="transient"/>
      <propval name="ignore_error" type="astring" value="core,signal"/>
    </property_group>
    <stability value="Evolving"/>
    <template>
      <common_name>
        <loctext xml:lang="C">IPv6 forwarding</loctext>
      </common_name>
    </template>
  </service>
</service_bundle>
EOF
[root@smartos ~]# svccfg import /opt/custom/smf/enable_ipv6-forwarding.xml
[root@smartos ~]# svcadm enable enable_ipv6-forwarding