1 Principles

The FreeBox is configured :

  • in router mode (with a local IPv4 network on 192.168.0.x/24)
  • with IPv6 support activated (by convention, we'll use the 2a01:e35:1234:5678::/64 prefix below, to represent the IPv6 prefix provided by the FreeBox)

Behind the FreeBox, I have connected a DreamPlug computer (running Debian wheezy with a dual-boot setup as sold by NewIT) on its eth0 etherlink port.

Behind the DreamPlug, I have connected a switch (to its eth1 ethernet port), on which the LAN's machines will be connected, on a dual IPv4/IPv6 network. The IPv4 will be on 192.168.4.0/24 (addresses for machines connected to the switch will be static) while the IPv6 will use the addresses auto-generated on the FreeBox's prefix.

The DreamPlug will also provide a wifi network (in master mode, through its uap0 interface), only IPv4 on 192.168.3.0/24.

On the DreamPlug, the outgoing IPv4 traffic will be masqueraded, while the IPv6 traffic will be bridged so that machines on the LAN can be reached from the Internet directly, passing through the eth0 eth1 bridge.

The DreamPlug will also act as a filter/firewall to only allow selected traffic to reach the LAN machines (in particular for the IPv6, since the machines may be reached directly from the Internet otherwise).

1.1 Alternatives

There are a lot of howtos describing the setup of FreeBox + IPv6, but I couldn't find one that was exactly reflecting the kind of setup I have.

Some dealt with a FreeBox setup in bridge mode (i.e. not the router mode), but in case the DreamPlug isn't so much reliable, or I've messed with the config, I'm tempted to keep the possibility to connect directly to the FreeBox.

Others didn't use the same setup with a router distributing both wired and wifi networks.

And none described exactly the setup for a DreamPlug running Debian wheezy and using ferm as a firewall.

No, there's no NIH syndrom here ;)

2 DreamPlug router configuration

2.1 Interfaces configuration

The /etc/network/interfaces on the DreamPlug looks like the following (kudos to Dag Bertelsen's Setting up Dreamplug as a router with Shorewall firewall for the wifi configuration bits):

# Note: Order of the interfaces declarations matters

auto lo
iface lo inet loopback

auto uap0
iface uap0 inet static
post-up /usr/bin/uaputl sys_cfg_ssid dream-uAP-XXXX
# Modus WPA2
post-up /usr/bin/uaputl sys_cfg_protocol 32
# WLAN password
post-up /usr/bin/uaputl sys_cfg_wpa_passphrase "WHATEVER PASSWORD"
# Set the Cipher
post-up /usr/bin/uaputl sys_cfg_cipher 8 8
# automatic channel
post-up /usr/bin/uaputl sys_cfg_channel 0 1
post-up /usr/bin/uaputl bss_start
# we deliver addresses for the Wifi with DHCP
post-up /usr/sbin/service udhcpd start
address 192.168.3.1
netmask 255.255.255.0

# Only IP6 traffic passes through the router between the Freebox on eth0 and the LAN on eth1
auto br0
iface br0 inet manual
bridge_ports eth0 eth1
bridge_maxwait 0
pre-up ebtables -t broute -A BROUTING -p ! ipv6 -j DROP
down ebtables -t broute -F

# Connected to the FreeBox, with DHCP in IPv4, masquerading outgoing IPv4 traffic
auto eth0
iface eth0 inet dhcp
up iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
down iptables -t nat -F
post-up sysctl -q -w net.ipv4.ip_forward=1
iface eth0 inet6 auto

# Connected to the LAN with a static IPv4 address
auto eth1
iface eth1 inet static
address 192.168.4.1
netmask 255.255.255.0

2.2 DHCP server configuration

The DHCP config for udhcpd is as such (in /etc/udhcpd.conf):

start 192.168.3.100
end 192.168.3.200
interface uap0
opt lease 86400
opt router 192.168.3.1
opt subnet 255.255.255.0
opt dns 192.168.3.1
opt domain localdomain
max_leases 101
lease_file /var/lib/udhcpd.leases
auto_time 5

2.3 Firewall configuration

The firewall I use is ferm.

Here's the /etc/ferm/ferm.conf configuration (YMMV). Thanks to René Garcia's Règles de firewall pour un pont IPv6 for inspiration :

## Interfaces of the router

# Our LAN on a switch
@def $DEV_PRIVATE = eth1;

# The ISP router
@def $DEV_WORLD = eth0;

# Our Wifi LAN
@def $DEV_WIFI = uap0;


## IP networks of our LAN

# IPv4 (includes ethernet switch and wifi)
@def $NET_PRIVATE = 192.168.0.0/16;

# IPv6 (the prefix granted by the ISP)
@def $NET6_PRIVATE = 2a01:e35:1234:5678::/64;

# IPv6 Local link
@def $LINK6 = fe80::/10;

# Specific machines on the LAN
@def $MACHINE_MYDESKTOP = 2a01:0e35:1234:5678:1234:5678:9abc:def0;

# Special function to log dropped packets
@def &DROP() = {
    mod limit limit 1/second limit-burst 10 LOG log-prefix "$DOMAIN-$CHAIN: ";
    DROP;
}

# IPv4 iptables rules
table filter {
    chain INPUT {
        policy DROP;

        # connection tracking
        mod state state INVALID DROP;
        mod state state (ESTABLISHED RELATED) ACCEPT;

        # allow local packet
        interface lo ACCEPT;

        # respond to ping
        #proto icmp ACCEPT;
        proto icmp icmp-type echo-request ACCEPT;

        # allow IPsec
        proto udp dport 500 ACCEPT;
        proto (esp ah) ACCEPT;

        # allow SSH connections from the private network and from some
        # well-known internet hosts
        #saddr ($NET_PRIVATE 123.45.67.89) proto tcp dport ssh ACCEPT;
        saddr $NET_PRIVATE proto tcp dport ssh ACCEPT;

        # we provide DNS and SMTP services for the internal net
        interface $DEV_PRIVATE saddr $NET_PRIVATE {
            proto (udp tcp) dport domain ACCEPT;
            proto tcp dport smtp ACCEPT;
        }

        interface $DEV_WIFI {
            # DHCP
            proto udp dport 67:68 ACCEPT;
            proto (udp tcp) dport domain ACCEPT;

            proto udp dport netbios-dgm DROP;
        }

        # LOG all dropped packets
        proto (udp tcp) &DROP();

    }

    # outgoing connections are not limited
    chain OUTPUT policy ACCEPT;

    chain FORWARD {
        policy DROP;

        # connection tracking
        mod state state INVALID DROP;
        mod state state (ESTABLISHED RELATED) ACCEPT;

        # connections from the internal net to the internet or to other
        # internal nets are allowed
        interface $DEV_PRIVATE ACCEPT;
        interface $DEV_WIFI ACCEPT;

        # LOG all dropped packets
        proto (udp tcp) &DROP();
    }
}

# IPv4 masquerade / NAT support

table nat {
    chain POSTROUTING {
        # masquerade private IP addresses
        saddr $NET_PRIVATE outerface $DEV_WORLD MASQUERADE;
    }
}

## IPv6:

domain ip6 {
    table filter {

        chain INPUT {
            policy DROP;

            # Internal traffic authorized
            saddr $NET6_PRIVATE ACCEPT;
            saddr $LINK6 ACCEPT;

            # accept multicast
            daddr ff00::/8 ACCEPT;

            interface lo ACCEPT;

            # For public traffic
            # Only DNS resolution + NTP acceped for UDP
            interface br0 {
                proto udp {

                    sport domain ACCEPT;

                    dport ntp ACCEPT;

                    &DROP();
                }

                # TCP on ports < 1024 forbidden except for SSH
                proto tcp {

                    dport ssh ACCEPT;

                    dport 0:1023 DROP;
                }

                # Accepted established traffic
                mod state state INVALID DROP;
                mod state state (ESTABLISHED RELATED) ACCEPT;

                # incoming connections forbidden
                proto tcp syn DROP;

                # Accept ping
                proto icmpv6 ACCEPT;
            }

            proto (udp tcp) &DROP();
        }
       chain FORWARD {
            policy DROP;

            # All local traffic accepted
            saddr $LINK6 ACCEPT;

            # All ping accepted unless coming from internet
            saddr ! $NET6_PRIVATE proto icmpv6 icmp-type echo-request DROP;
            proto icmpv6 ACCEPT;

            # Allow SSH to specific machines
            proto tcp daddr $MACHINE_MYDESKTOP dport ssh ACCEPT;

            # Accept established traffic
            mod state state INVALID DROP;
            mod state state (ESTABLISHED RELATED) ACCEPT;

            # Accept outgoing traffic
            saddr $NET6_PRIVATE ACCEPT;

            # Accept local outgoing traffic
            saddr ::1 ACCEPT;

            proto (udp tcp) &DROP();
        }
    }
}

# ebtables
domain eb chain FORWARD {
    policy DROP;

    # Only accept bridged traffic for IPv6
    logical-in br0 logical-out br0 {
        #ebtables -t broute -A BROUTING -p ! ipv6 -j DROP
        proto IPv6 ACCEPT;
    }
}

2.4 DNS config

The DreamPlug will run bind9 to cache the DNS for the wifi network (default config is OK out of the box).

3 Configuration for the LAN machines

3.1 Connection with Wifi

Machines connected with the WPA wifi network should get an IPv4 only address via DHCP on the 192.168.3.0/24 network. There's nothing to be configured specifically.

3.2 Ethernet connection on the switch

Machines connected via ethernet cables to the switch can run either with IPv4 config, in which case they should be configured statically for the 192.168.4.0/24 network, using the router on 192.168.4.1 as a gateway, or with IPv6 auto config.

On wheezy, the /etc/network/interfaces will look like :

auto eth1
iface eth1 inet static
        address 192.168.4.42
        netmask 255.255.255.0
        gateway 192.168.4.1
        dns-nameservers 212.27.40.241 212.27.40.240

iface eth1 inet6 auto

4 To do list

The setup works fine, but there are a few things I'd like to improve :

  • running a regular Debian distro on the DreamPlug (the kernel used at the moment is patched for the wifi driver in master mode support), possibly using only Free Software.
  • using subnets for the IPv6 machines (but that seems not exactly obvious, requiring NDP proxying and stuff), so that the privacy is improved (the IPv6 auto generated global addresses depend on the MAC addresses… hmmm… probably not optimal).
  • adding more stuff to the DreamPlug router so that it becomes a full fledged FreedomBox.

5 References

Date: 2012-11-09 16:30:34 CET