Replacing Swisscom router by a Linux box

Vincent Bernat

I have recently moved to Lausanne, Switzerland. Broadband Internet access is not as cheap as in France. Free, a French ISP, is providing an FTTH access with a bandwidth of 1 Gbps1 for about 38 € (including TV and phone service), Swisscom is providing roughly the same service for about 200 €.2 Swisscom fiber access was available for my appartment and I chose the 40 Mbps contract without phone service for about 80 €.

Like many ISP, Swisscom provides an Internet box with an additional box for TV. I didn’t unpack the TV box as I have no use for it. The Internet box comes with some nice features like the ability to setup firewall rules, a guest wireless access and some file sharing possibilities. No shell access!

I have bought a small PC to act as router and replace the Internet box. I have loaded the upcoming Debian Jessie on it. You can find the whole software configuration in a Git repository.

This blog post only covers the Swisscom-specific setup (and QoS). Have a look at these two blog posts for related topics:

Ethernet#

The Internet box is packed with a Siligence-branded 1000BX SFP.3 This SFP receives and transmits data on the same fiber using a different wavelength for each direction.

Instead of using a network card with an SFP port, I bought a Netgear GS110TP which comes with 8 gigabit copper ports and 2 fiber SFP ports. It is a cheap switch bundled with many interesting features like VLAN and LLDP. It works fine if you don’t expect too much from it.

IPv4#

IPv4 connectivity is provided over VLAN 10. A DHCP client is mandatory. Moreover, the DHCP vendor class identifier option (option 60) needs to be advertised. This can be done by adding the following line to /etc/dhcp/dhclient.conf when using the ISC DHCP client:

send vendor-class-identifier "100008,0001,,Debian";

The first two numbers are here to identify the service you are requesting. I suppose this can be read as requesting the Swisscom residential access service. You can put whatever you want after that. Once you get a lease, you need to use a browser to identify yourself to Swisscom on the first use.

IPv6#

Swisscom provides IPv6 access through the 6rd protocol. This is a tunneling mechanism to facilitate IPv6 deployment across an IPv4 infrastructure. This kind of tunnel is natively supported by Linux since kernel version 2.6.33.

To setup IPv6, you need the base IPv6 prefix and the 6rd gateway. Some ISP are providing these values through DHCP (option 212) but this is not the case for Swisscom. The gateway is 6rd.swisscom.com and the prefix is 2a02:1200::/28. After appending the IPv4 address to the prefix, you still get 4 bits for internal subnets.

Swisscom doesn’t provide a fixed IPv4 address. Therefore, it is not possible to precompute the IPv6 prefix. When installed as a DHCP hook (in /etc/dhcp/dhclient-exit-hooks.d/6rd), the following script configures the tunnel:

sixrd_iface=internet6
sixrd_mtu=1472                  # This is 1500 - 20 - 8 (PPPoE header)
sixrd_ttl=64
sixrd_prefix=2a02:1200::/28     # No way to guess, just have to know it.
sixrd_br=193.5.29.1             # That's "6rd.swisscom.com"

sixrd_down() {
    ip tunnel del ${sixrd_iface} || true
}

sixrd_up() {
    ipv4=${new_ip_address:-$old_ip_address}

    sixrd_subnet=$(ruby <<EOF
require 'ipaddr'
prefix = IPAddr.new "${sixrd_prefix}", Socket::AF_INET6
prefixlen = ${sixrd_prefix#*/}
ipv4 = IPAddr.new "${ipv4}", Socket::AF_INET
ipv6 = IPAddr.new (prefix.to_i + (ipv4.to_i << (64 + 32 - prefixlen))), Socket::AF_INET6
puts ipv6
EOF
)

    # Let's configure the tunnel
    ip tunnel add ${sixrd_iface} mode sit local $ipv4 ttl $sixrd_ttl
    ip tunnel 6rd dev ${sixrd_iface} 6rd-prefix ${sixrd_prefix}
    ip addr add ${sixrd_subnet}1/64 dev ${sixrd_iface}
    ip link set mtu ${sixrd_mtu} dev ${sixrd_iface}
    ip link set ${sixrd_iface} up
    ip route add default via ::${sixrd_br} dev ${sixrd_iface}
}

case $reason in
    BOUND|REBOOT)
        sixrd_down
        sixrd_up
        ;;
    RENEW|REBIND)
        if [ "$new_ip_address" != "$old_ip_address" ]; then
            sixrd_down
            sixrd_up
        fi
        ;;
    STOP|EXPIRE|FAIL|RELEASE)
        sixrd_down
        ;;
esac

The computation of the IPv6 prefix is offloaded to Ruby instead of trying to use the shell for that. Even if the ipaddr module is pretty “basic,” it suits the job.

Swisscom is using the same MTU for all clients. Because some of them are using PPPoE, the MTU is 1472 instead of 1480. You can easily check your MTU with this handy online MTU test tool.

It is not uncommon that PMTUD is broken on some parts of the Internet. While not ideal, setting up TCP MSS will alievate any problem you may run into with a MTU less than 1500:

ip6tables -t mangle -A POSTROUTING -o internet6 \
          -p tcp --tcp-flags SYN,RST SYN \
          -j TCPMSS --clamp-mss-to-pmtu

QoS#

Update (2014-11)

Unfortunately, this section was incorrect, including its premise. Have a look at Dave Taht comment for more details. As an alternative, Gentoo’s wiki contains simple instructions to setup an effective traffic shaping.


  1. Maximum download speed is 1 Gbps, while maximum upload speed is 200 Mbps. ↩︎

  2. This is the standard Vivo XL package rated at CHF 169.– plus the 1 Gbps option at CHF 80.–. Meantime, the bandwidth for this package has been upgraded to 1 Gbps (symmetrical) for the same price. ↩︎

  3. There are two references on it: SGA 441SFP0-1Gb and OST-1000BX-S34-10DI. It transmits to the 1310 nm wave length and receives on the 1490 nm one. ↩︎