Debian on ReadyNAS Duo v2

Before the purchase I found this older teardown and HowTo, that proved that it was fully possible at least. However it was quite dated and targeted against an older Debian release. I browsed the installer files of Debian Jessie (8) and tried figure out how to apply same installation method but with a new release.

However, After a first trial install of Jessie, I noticed that the kernel (3.16.0) lacks some features (Real time clock, full Marvell CESA support etc.) I did a new test install with the upcoming Stretch (9.0) with a updated 4.9.0 kernel, and now everything seems to work.

  1. Setup a TFTP service on a host of your choice.

  2. You need to establish a bootloader serial console just as in the HowTo mentioned earlier. Beware, It's 3.3V TTL level serial.

  3. Debian unfortunally doesn't provide a ReadyNAS Duo v2 kernel image that works with the old Netgear uBoot, so we have to package our own. Grab the default kernel and the Device-Tree binary for the machine. Then stack the Device-Tree binary after the kernel image file to a new combined file.

    wget http://ftp.se.debian.org/debian/dists/stretch/main/installer-armel/current/images/kirkwood/netboot/vmlinuz-4.9.0-1-marvell
    wget http://ftp.se.debian.org/debian/dists/stretch/main/installer-armel/current/images/kirkwood/device-tree/kirkwood-netgear_readynas_duo_v2.dtb
    cat vmlinuz-4.9.0-1-marvell kirkwood-netgear_readynas_duo_v2.dtb >> vmlinuz-dtb
    

  4. Convert the vmlinuz-dtb image to a uboot image with mkimage

    mkimage -A arm -O linux -T kernel -C none -a 0x8000 -e 0x8000 -n "Debian RND2 kernel" -d vmlinuz-dtb /srv/tftp/uImage-rnd2
    

  5. I then used the installer-initrd for the Sheevaplug ESATA witch is very smilar and should work fine for the install.

    wget http://ftp.se.debian.org/debian/dists/stretch/main/installer-armel/current/images/kirkwood/netboot/marvell/sheevaplug-esata/uInitrd
    mv uInitrd /srv/tftp/uInitrd
    

  6. Bring up the bootloader console (just hit any key at startup) and do the following.

    setenv autoload no
    dhcp
    set serverip 192.168.1.3
    tftpboot 1200000 uImage-rnd2
    tftpboot 2000000 uInitrd
    set bootargs console=ttyS0,115200 earlyprintk
    bootm 0x1200000 0x2000000
    

  7. You should now end up in a Debian installer. Just follow the installer as any normal install. When you are about to finish (The question of "Go back"/"Continue"), Go back and Execute shell. The chroot to the installation target.

    mount --bind /dev /target/dev
    mount -t proc none /target/proc
    mount -t sysfs none /target/sys
    chroot /target /bin/bash
    apt-get install flash-kernel
    

  8. Use the following machine configuration in /etc/flashkernel/db

    Machine: NETGEAR ReadyNAS Duo v2
    DTB-Id: kirkwood-netgear_readynas_duo_v2.dtb
    DTB-Append: yes
    Mtd-Kernel: uImage
    Mtd-Initrd: minirootfs
    U-Boot-Kernel-Address: 0x08000
    U-Boot-Initrd-Address: 0x0
    Required-Packages: u-boot-tools
    Bootloader-Sets-Incorrect-Root: yes
    
    This basically tells whenever there is a new kernel or initrd, you should also append the DTB and create uBoot compatible images, then write those to the MTD/NAND partitions uImage and minirootfs (see dmesg or /proc/mtd) We will not alter the original MTD/NAND layout, thus no need to change uBoot environment parameters, since we have plenty of space for kernel and initrd. As long as we don't touch the 0x000000000000-0x0000001a0000 region in NAND/Flash, we can always use uBoot to load & flash new data and images. If unsure, check dmesg or cat /proc/mtd to make sure that the MTD partition layout is correctly detected. If the bootloader area is overwritten then the device is "bricked" and can only be restored with lower level JTAG of the Marvell SoC.

  9. Install kernel and build new initrd

    apt-get install linux-image-marvell
    mkinitramfs -u
    

  10. When done and you see that the kernel and initrd is written to NAND, exit out to install program again and reboot system. It should look like this:

update-initramfs: Generating /boot/initrd.img-4.9.0-1-marvell

Using DTB: kirkwood-netgear_readynas_duo_v2.dtb
Installing /usr/lib/linux-image-4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb into /boot/dtbs/4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb
Taking backup of kirkwood-netgear_readynas_duo_v2.dtb.
Installing new kirkwood-netgear_readynas_duo_v2.dtb.
Installing /usr/lib/linux-image-4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb into /boot/dtbs/4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb
Taking backup of kirkwood-netgear_readynas_duo_v2.dtb.
Installing new kirkwood-netgear_readynas_duo_v2.dtb.
flash-kernel: installing version 4.9.0-1-marvell
flash-kernel: appending /usr/lib/linux-image-4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb to kernel
Generating kernel u-boot image... done.
Erasing 128 Kibyte @ 7f631f5c00000064 -- 48 % complete 
Writing data to block 0 at offset 0x0
...8<...
Writing data to block 15 at offset 0x1e0000
done.
Generating initramfs u-boot image... done.
Erasing 128 Kibyte @ 7f5d0f5c00000064 -- 128 % complete 
Writing data to block 0 at offset 0x0
...8<...
Writing data to block 43 at offset 0x560000
done.

The system is fully capable to run BorgBackup and actually performs a decent ~60Mbps SSH traffic with some tweaks. To take advantage of the Marvell CESA cryptographic accelerator, use the following configuration in /etc/ssh/sshd_config

# Custom ciphers to use marvell_cesa
Ciphers             aes128-cbc,aes192-cbc,aes256-cbc,3des-cbc
MACs                hmac-sha1,hmac-md5

You also need to specify this in you client configuration (~/.ssh/config)

G762 fan driver

arno@natisbad.org have also done some great work to make the G762 fan driver chip. This is unfortunally missing from the standard Debian kernel image. I didn't feel like recompiling a custom kernel, so I've just extracted the the module from a kernel build a did.

You can find it here:
http://files.adamwesterberg.se/linux/netgear_rnd2/stretch/modules/

Put it under /lib/modules/4.9.0-1-marvell/kernel/drivers/hwmon/ and run depmod -a, then add it to /etc/modules

Further explanation

The stock MTD/NAND layout looks like this:

Creating 5 MTD partitions on "nand_mtd":
0x000000000000-0x000000180000 : "u-boot"
0x000000180000-0x0000001a0000 : "u-boot-env"
0x000000200000-0x000000800000 : "uImage"             ~6M
0x000000800000-0x000001800000 : "minirootfs"         ~16M
0x000001800000-0x000008000000 : "jffs2"              ~10M

The bootcmd parameter of uBoot says:

nand read.e 0x1200000 0x200000 0x600000
nand read.e 0x2000000 0x800000 0x1000000
bootm 0x1200000 0x2000000

You see the connection? :)

References

IPsec VPN - RouterOS and FreeBSD

FreeBSD suggests using Racoon as the IKE daemon, and I buy that recommendation since RouterOS also uses racoon internally (hint: look at the ipsec,debug)

But this "simple"-tunnel method of RouterOS it a bit tricky to replicate on a default racoon setup. In this example I will use a IP-in-IP tunnel (also called ipencap) and has IP Protocol 4 (IP/4), but using a GRE (IP/47) should also be fine.

  • Route-based tunnel - not Proxy/Policy-based
  • Using IP-in-IP tunnel type ("ipencap" / IP Protocol 4)
  • Site A tunnel endpoint - 192.168.254.1/32
  • Site A local network - 192.168.1.0/24
  • Site B tunnel endpoint - 192.168.254.2/32
  • Site B local network - 192.168.2.0/24

SITE_A_IP and SITE_B_IP is the corresponding public IP-addresses. This howto doesn't cover any required firewall openings.

This is what I found out and works.

Site A - RouterOS

1. Setup tunnel interface on RouterOS, and setup a linknet

/interface ipip
add name=tun1 ipsec-secret=XXXXXXXXXX local-address=SITE_A_IP remote-address=SITE_B_IP
/ip address
add address=192.168.254.1/30 interface=tun1
/ip route
add dst-address=192.168.2.0/24 gateway=192.168.254.2

You're done on RouterOS.

Site B - FreeBSD

1. Setup tunnel interface and services on your FreeBSD (or similar system)

/etc/rc.conf:

cloned_interfaces="gif0"
ifconfig_gif0="inet 192.168.254.2 192.168.254.1 netmask 255.255.255.255 tunnel SITE_B_IP SITE_A_IP"
racoon_enable="YES"
ipsec_enable="YES"
ipsec_file="/usr/local/etc/racoon/setkey.conf"

gateway_enable="YES"
static_routes="net1"
route_net1="-net 192.168.1.0/24 192.168.250.1"

2. Configuration for racoon. Please note the "address SITE_B_IP 4 address SITE_A_IP 4" where the 4 is for ipencap (IP/4) tunnel packets.

/usr/local/etc/racoon/racoon.conf:

path pre_shared_key "/usr/local/etc/racoon/psk.txt";
log notify;

listen {
    isakmp          SITE_B_IP [500];
}

remote SITE_A_IP [500] {
    exchange_mode       main;
    proposal_check      obey;

    # phase 1
    proposal {
        encryption_algorithm    aes 128;
        hash_algorithm          sha1;
        authentication_method   pre_shared_key;
        lifetime time           3600 secs;
        dh_group                2;
    }
}

# phase 2
sainfo (address SITE_B_IP 4 address SITE_A_IP 4) {
    pfs_group                       2;
    lifetime                        time 3600 sec;
    encryption_algorithm            aes 128;
    authentication_algorithm        hmac_sha256, hmac_sha1;
    compression_algorithm           deflate;
}

3. This one is tricky, the IPsec kernel policy configuration. This tells the kernel IP-stack - that traffic from SITE_B_IP to (out) SITE_A_IP that is of type ipencap (IP/4) shall be of encrypted with IPsec transport type ESP. The next line is for the opposite direction.

/usr/local/etc/racoon/setkey.conf:

flush;
spdflush;
spdadd SITE_B_IP SITE_A_IP ipencap -P out ipsec esp/transport/SITE_B_IP-SITE_A_IP/require;
spdadd SITE_A_IP SITE_B_IP ipencap -P in ipsec esp/transport/SITE_A_IP-SITE_B_IP/require;

4. And of course the shared secret.

/usr/local/etc/racoon/psk.txt:

SITE_A_IP    XXXXXXXX

Then of course restart services or do a full reboot.

I prefer route-based tunnels since they work almost like a physical link, and you can use traceroute and standard tools. Your routes decide whats reachable. Policy based tunnels are a bit magic and bypasses standard routing, and I find them hard to troubleshoot.

The theory of operation here is that the tunnel itself gets encrypted, not the specific packets going trough it.

  1. Packet arrives at Site A router. Router makes route lookup and the decision to forward packet to tunnel inteface.
  2. Tunnel encapsulates packet.
  3. Packet then matches Source, Destination and Protocol number defined in IPsec kernel policy (setkey.conf), witch applies the transport encryption.
  4. Encrypted payload leaves router

ifconfig gif0 should display:

gif0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1280
    options=80000<LINKSTATE>
    tunnel inet SITE_B_IP --> SITE_A_IP
    inet 192.168.254.2 --> 192.168.254.1  netmask 0xffffffff 
    inet6 fe80::a3d9:9ef1:721c:a309%gif0 prefixlen 64 scopeid 0x4 
    nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
    groups: gif

A tcpdump should show the something like:

19:04:14.700751 IP SITE_A_IP > SITE_B_IP: ESP(spi=0x06b57eb9,seq=0x12), length 136
19:04:15.706837 IP SITE_B_IP > SITE_A_IP: ESP(spi=0x02a7da91,seq=0x10), length 136
19:04:15.707011 IP SITE_A_IP > SITE_B_IP: ESP(spi=0x06b57eb9,seq=0x13), length 136
19:04:16.715800 IP SITE_B_IP > SITE_A_IP: ESP(spi=0x02a7da91,seq=0x11), length 136

Good luck!