XS4ALL Fiber optic link configuration

Setup

Me

I have various Debian GNU Linux PCs hooked up to a gigabit Ethernet network.
In my setup, everything is static. There is no DHCP (at least not for NIC IP address configuration purposes) or routing daemon. Everything is configured by means of static config files; The resolvconf package is not installed. I run my own nameserver.
I get my IPv4 address and IPv6 /48 prefix from the XS4ALL website (both are static), which I then cut and paste to the various config files (convert upper case hex digits to lower case first).
I don't have systemd; I use a classic SysV boot (actually insserv).
The Ethernet interface for my LAN is 'eth0'. The link to my NTU uses 'eth1'. Both are gigabit Ethernet;

                                               ┌────────┐
                        ┌─────┐           eth1 │ Linux  │ eth0
  FttH >────────────────┤ NTU ├────────────────┤ Server ├──────────────────> LAN
         Gbit           └─────┘ Gbit           │        │ Gbit
         Fiber Optic            Ethernet       └────────┘ Ethernet
         Cable

I do not use the 'FritzBox'; The NTU is directly connected to the Linux server!
The Linux server acts as a internet router; It contains a firewall, a VOIP PBX, webserver, nameserver, mailserver, timeserver and a web proxy server.

XS4ALL

For fiber optic- and VDSL(2) links, XS4ALL uses PPPoE in VLAN 6. Baby jumbo is supported. So you can use an IP MTU of 1500, provided your NIC supports a MTU > 1500;

   ┌───────────────────────┐
   │    VLAN  MTU 1512     │
   │ ┌───────────────────┐ │
   │ │  PPPoE MTU 1508   │ │
   │ │ ┌───────────────┐ │ │
   │ │ │ IP   MTU 1500 │ │ │
   │ │ └───────────────┘ │ │
   │ └───────────────────┘ │
   └───────────────────────┘

Otherwise you need to reduce your IP MTU;

   ┌───────────────────────┐
   │    VLAN  MTU 1500     │
   │ ┌───────────────────┐ │
   │ │  PPPoE MTU 1496   │ │
   │ │ ┌───────────────┐ │ │
   │ │ │ IP   MTU 1488 │ │ │
   │ │ └───────────────┘ │ │
   │ └───────────────────┘ │
   └───────────────────────┘

To get XS4ALL to route the IPv6 /48 to you, you need to do a DHCPv6 Prefix Delegation request. To this end the Debian package 'Wide-DHCPv6-Client' is installed.

Required packages

'Quirks'

PPPD and IPv6

  1. For IPv6 the PPPD uses IPv6 link-local addresses for the PPP link ends. Which actually makes sense, but may seem a bit odd at first.
  2. These addresses may be different each time the PPP link comes up.
  3. It does not necessarily set an IPv6 route the the remote end.
  4. It does not necessarily set an IPv6 default route, even if the config file says it should!

Wide-DHCPv6-Client

  1. dhcp6c won't start if the PPP link isn't up.
  2. dhcp6c is hard to kill.
  3. You need to remove the DUID file before a (re)start.
  4. dhcp6c doesn't necessarily know where to send config requests to. You need an IPv6 route to the outside world (IPv6 default route) for dhcp6c to work. Without this it will complain: 'client6_send: transmit failed: Network is unreachable'.

The DUID (DHCP Unique Identifier) contains the media type, a mac address and a timestamp in seconds since 00:00:00 jan 1st 2000 UTC.

Config

Please note that I don't use systemd, which requires a different configuration!

Ethernet

/etc/network/interfaces;

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
	address 192.168.1.1
	netmask 255.255.255.0
	network 192.168.1.0
	broadcast 192.168.1.255

# IPv6
iface eth0 inet6 static
	address 2001:db8:1234:1::1
	netmask 64

# Fiber optic link
auto eth1
iface eth1 inet manual
	mtu 1512

# VLAN 6
# VLAN number is derived from interface name
auto eth1.6
iface eth1.6 inet manual
	pre-down ( poff provider ) &
	up ip link set eth1.6 up
	mtu 1508
	down ifconfig eth1.6 down
	post-up ( pon provider ) &

If you stick to the 'ethx.y' naming scheme, where 'x' and 'y' are decimal numbers, you don't need a 'vlan-raw-device ethx' statement.
'manual' means that it doesn't get configured (IP address assigned to it) right now (or ever).
You need the 'up ip link set eth1.6 up' statement to actually make the interface go up. Otherwise it just gets configured without going up. If you want to check this: 'ifconfig -a' shows all interfaces, 'ifconfig' just the ones that are actually up.
'post-up ( pon provider ) &' actually starts the PPPD.

Stretch

The processing of '/etc/network/interfaces' has become real fussy in Stretch, to the extent that I consider it broken. For instance, editing the file and then doing a '( ifdown eth0 ; sleep 1 l ifup eth0 ) &' doesn't work anymore. What does work is changing things on the commandline or putting stuff in a script.
The setup above doesn't work on Debian stretch either. Below a fix:

auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
	address 192.168.1.1
	netmask 255.255.255.0
	network 192.168.1.0
	broadcast 192.168.1.255

# IPv6
iface eth0 inet6 static
	address 2001:db8:1234:1::1
	netmask 64
	pre-down /usr/local/sbin/wan-link stop
	post-up ( /usr/local/sbin/wan-link start )

Which calls '/usr/local/sbin/wan-link';

#!/bin/bash

check_syslog()
{
	CNT=0
	while [ ${CNT} -lt 10 ]
	do
		# Wait for syslogd
		if ( netstat -an | grep ":514" > /dev/null )
		then
			break
		fi
		sleep 1
		let CNT+=1
	done
}

case "$1" in
	start)
		check_syslog
		ifconfig eth1 mtu 1512 up
		vconfig add eth1 6
		ifconfig eth1.6 mtu 1508 up
		pon provider
		;;
	stop)
		poff provider
		ifconfig eth1.6 down
		ifconfig eth1 down
		;;
	*)
		echo "usage: wan-link {start|stop}"
		;;
esac

To make sure everything is logged, the scripts waits for the syslogdaemon.
Note: the 'check_syslog()' function expects a syslog daemon listening on port 514 (syslog)! If your syslogd doesn't, you have to check in some other way. A '( netstat -anp | grep syslog | grep "dev/log" > /dev/null )' might work.

PPP

/etc/ppp/peers/provider

ifname wan
noipdefault
+ipv6 ipv6cp-use-ipaddr
defaultroute
connect /bin/true
noauth
persist
lcp-echo-interval 10
maxfail 0
debug
holdoff 10
mtu 1500
mru 1500
noaccomp
default-asyncmap
plugin rp-pppoe.so eth1.6
user "Some_User@xs4all.nl"

'ifname wan' provides the PPP interface with an unique name.
You need the appropriate entries in /etc/ppp/pap-secrets as well.

DHCPv6

/etc/default/wide-dhcpv6-client

# Defaults for dhcpv6 client initscript
# Used by /etc/init.d/wide-dhcpv6-client

# Interfaces on which the client should send DHCPv6 requests and listen to
# answers. If empty, the client is deactivated.
INTERFACES="wan"

/etc/wide-dhcpv6/dhcp6c.conf

profile default
{
  script "/etc/wide-dhcpv6/dhcp6c-script";
};

interface wan {
    send ia-pd 0;
};

id-assoc pd 0 {
   prefix-interface eth1 {
       sla-len 16;
       sla-id 0;
       ifid 1;
   };
};

You can replace 'dhcp6c-script' with a script which doesn't do anything at all;

#!/bin/bash
exit 0

'sla' means 'Site-Level Aggregation identifier'. In a prefix '2001:db8:1234::/48' it's the '1234' bit. These are four hex digits, so it's 16 bits long (sla-len).
It insists a assigning an IP address to an interface. I have no idea how to get rid of this!

Scripts

/etc/ppp/ipv6-up.d/add-rem-rt

#!/bin/sh

# Sets route to remote IPv6 address of PPP link
if ! ( ip -6 route | grep -q "${PPP_REMOTE}" )
then
	ip -6 route add "${PPP_REMOTE}" dev "${PPP_IFACE}"
fi

You don't actually need this, but it looks good in a route overview.

Called from /etc/ppp/ip-up

I don't use the regular scripts in '/etc/ppp/ip-up.d/' and '/etc/ppp/ip-down.d/'. I modified '/etc/ppp/ip-up' instead. You may need to modify the stuff below to suit your needs.

# Take care of the (default) route(s)
case $PPP_LOCAL in
	"Your_XS4ALL_IPv4_address")
	# Xs iface
	# Restart NTPD
	/etc/init.d/ntp restart 2>&1 | mail -s "NTPD restarted" root@Your_Domain
	# IPv6 stuff
	# Make sure link works
	ping -c5 $PPP_REMOTE
	# Default route
	if ! ( ip -6 route | grep -q default )
	then
                ip -6 route add default dev wan
	fi
	# Restart DHCPv6
	( /etc/init.d/wide-dhcpv6-client stop ) &
	sleep 2
	killall dhcp6c
	sleep 2
	killall -9 dhcp6c
	sleep 2
	rm /var/lib/dhcpv6/dhcp6c_duid
	sleep 2
	/etc/init.d/wide-dhcpv6-client start

	;;
esac

Notes

IPv6 uses IPv6 link-local (fe80::/10) - and IPv6 multicast addresses (ff02::/16) for internal housekeeping and configuration. If you firewall these to heavy, some things will not work.
It can be handy to enable debugging. In '/etc/wide-dhcpv6/etc/init.d/wide-dhcpv6-client' add '-D' (shown red);

case "$1" in
	start)
		log_daemon_msg "Starting $DESC" "$NAME"
		start-stop-daemon --start --quiet --pidfile $DHCP6CPID \
			--oknodo --exec $DHCP6CBIN -- -D -Pdefault $INTERFACES
		sleep 2

With Debian Stretch you can set the debug level in /etc/default/wide-dhcpv6-client (shown red);

# Defaults for dhcpv6 client initscript
# Used by /etc/init.d/wide-dhcpv6-client

# Interfaces on which the client should send DHCPv6 requests and listen to
# answers. If empty, the client is deactivated.
INTERFACES="wan"

# Verbose level for syslog. Default is 0 (0: minimal; 1: info; 2: debug)
VERBOSE=2

If things don't work, have a look at '/var/log/syslog'.

Test

Ping

sput:~$ ping(4) www.xs4all.nl
PING www.xs4all.nl (194.109.6.92) 56(84) bytes of data.
64 bytes from www.xs4all.nl (194.109.6.92): icmp_seq=1 ttl=62 time=2.91 ms
64 bytes from www.xs4all.nl (194.109.6.92): icmp_seq=2 ttl=62 time=2.90 ms
64 bytes from www.xs4all.nl (194.109.6.92): icmp_seq=3 ttl=62 time=2.86 ms
64 bytes from www.xs4all.nl (194.109.6.92): icmp_seq=4 ttl=62 time=2.84 ms
64 bytes from www.xs4all.nl (194.109.6.92): icmp_seq=5 ttl=62 time=2.92 ms

sput:~$ ping6 www.xs4all.nl
PING www.xs4all.nl(www.xs4all.nl) 56 data bytes
64 bytes from www.xs4all.nl: icmp_seq=1 ttl=62 time=2.86 ms
64 bytes from www.xs4all.nl: icmp_seq=2 ttl=62 time=2.90 ms
64 bytes from www.xs4all.nl: icmp_seq=3 ttl=62 time=2.86 ms
64 bytes from www.xs4all.nl: icmp_seq=4 ttl=62 time=2.89 ms
64 bytes from www.xs4all.nl: icmp_seq=5 ttl=62 time=2.86 ms

Speed test

I found that the most reliable way of testing things, is file up- and download with shell.xs4all.nl. A 'wget --no-proxy URL' will get you the speed in bytes per second. Multiply by eight to get bits per second.

Additional notes on booting

A boot might 'hang' with considerable timeouts on the following;

  1. All interfaces need to be up.
  2. All NFS volumes need to be mounted.

The 1st I fixed by calling the PPP-link from /etc/network/interfaces instead of putting the PPP interface directly in /etc/network/interfaces. If the PPP-link doesn't come up, all the services are still started. Alternatively you might want to try 'allow-hotplug' instead of auto for the wan interface (This is based on experiences from the 1990-ies. Things might be different now).

The 2nd I fixed by using IP addresses instead of hostnames for NFS mounts in /etc/fstab: If the nameserver is down, the remote discs are still mounted. I also mount in the background (bg option in /etc/fstab). This way if a remote disc can't be mounted, the boot still proceeds.

IPv6 Ready