Hacking DNS-323 and DNS-321 NAS

After my RAID-0 has recently failed catastrophically, the time has come to set up another pair of HDDs in my DNS-323. I figured a step-by-step howto on what I've done would not be useful only for me if I had to do it again, but to any other owner of this extremely popular unit. This is a rather long article, as it contains several smaller articles, but it is hopefully complete and suitable for a reinstall, cuz that’s the way I roll.

Since I am only replacing a pre-existing array, a few necessary steps have already been performed. I did reset the unit by holding the Reset button through the pinhole at the back of the unit. The unit had already been updated with the latest firmware – if yours is not, do so following the instructions on dlink’s page:

20101019-004-screencapI also had already setup my unit to always get the same IP from the router, based on its MAC address. The router calls this type of DHCP registration “Reserved”. This ensures that on my network the unit will always have the same address and will also get an IP automatically if plugged into another router / network. For the same reason, all other computers and devices on my network are also “Reserved”.

This rather long article contains the following (click the number to jump):

  • 0. Install Debian Lenny
  • 1. Funplug it
  • 2. set and save your password
  • 3. enable ssh, disable telnet
  • 4. private key login
  • 5. moar packages!
  • 6. installing python for advanced scripting
  • 7. installing transmission for bittorrent
  • 8. installing cron scripts for automation
  • 9. to do


In order to avoid a similarly catastrophic failure, I will be setting the two hard drives (2 x 2 TB Black Drives, i.e., WD Caviars) as “single drives” – NO RAID.  I will be relying on cron jobs to backup the very important data from one drive to the other and all the data to a similar unit offsite.


0. Install Debian Lenny

I have not gone this route, but I do plan to play with it, maybe after moving Fonz linux on a USB stick. To do so, you have to stop any apps or servers you might be using from the graphical interface, such as uPNP or iTunes Media server and remove the built-in Bittorrent client by deleting the folder /mnt/HD_a2/Nas_Prog/BT (rm –r). To get Lenny up and running, try

  1. Download debnas-0.5.tar.bz2 (link in sources)
  2. Extract the two files “fun_plug” and “linux.tar” to the root directory of your DNS-323 volume.
  3. Reboot DNS-323 then wait for a few minutes until the blue light has stopped blinking
  4. SSH into your box with login:pass root:12345678, then change your password
  5. In /etc/apt/sources.list.d/etch.list replace “etch” with “lenny”
  6. apt-get install debian-archive-keyring then apt-get update then apt-get dist-upgrade
  7. reboot then apt-get update then apt-get upgrade

You are now ready to roll with Lenny. But Lenny is a smelly hippie so I haven’t gone this route, preferring the safer Fonz, as shown below.


1. funplug it

This rather simple step gives you “root” access to the box. It involves downloading fun_plug and fun_plug.tgz to the box:

20101019-001-screencapMake sure that the file is not saved as “fun_plug.txt” – if it is, remove the extension. Then reboot.20101019-005-screencap


2. set and save your password

At a command prompt type telnet <IP of your box>. You should get a prompt almost instantaneously.

/ # uname -a
Linux dlinky #47 Mon Nov 30 12:06:02 CST 2009 armv5tejl unknown
/ # pwconv
/ # passwd
Changing password for root
Enter the new password (minimum of 5, maximum of 8 characters)
Please use a combination of upper and lower case letters and numbers.
New password:
Re-enter new password:
Password changed.
/ # usermod -s /ffp/bin/sh root
usermod: no changes
/ # login

dlinky login: root
No mail.
root@dlinky:~# store-passwd.sh
Copying files to mtd1...
Copying files to mtd2...

3. enable SSH, disable telnet

Telnet is terribly insecure, so you should disable it and enable SSH as soon as possible. To enable SSH, type at the telnet prompt:

root@dlinky:~# chmod a+x /ffp/start/sshd.sh
root@dlinky:~# sh /ffp/start/sshd.sh start
Generating public/private rsa1 key pair.
Your identification has been saved in /ffp/etc/ssh/ssh_host_key.

Your public key has been saved in /ffp/etc/ssh/ssh_host_key.pub.
The key fingerprint is:
13:4e:ce:ba:07:17:f4:d1:fc:de:a9:f4:ea:42:c2:6d root@dlinky
The key's randomart image is:
+--[RSA1 2048]----+
|           o     |
|        . . o    |
|       .o. . .   |
|       =...   .  |

This will go on for a while as 3 pairs need to be generated…

After enabling SSH you might want to reboot and ensure you can login, either by typing ssh root@192.168.x.x (substituting x for your box octets) or by using a terminal program, such as Putty. Once you are sure you can login with ssh, go ahead and disable telnet login:

root@dlinky:~# chmod -x /ffp/start/telnetd.sh

You don’t need to keep your telnet session open any longer, but you might, if it makes you feel comfortable. Once you reboot however, you will no longer be able to telnet. If you have holes (port forwarding) on your router, you might want to reboot right away.

If you ever lose SSH access, you need to install a telnet-only funplug, then execute a chsh command to set the root shell to sh ( chsh -s /ffp/bin/sh ) and then execute a store-passwd.sh to make the change permanent. This could happen if you ever “Restore to factory defaults” as the root password will be erased from the NVRAM. As a precaution, make sure you enable telnet (chmod +x /ffp/start/telnetd.sh) before making an upgrade, especially if you are not going to follow the point below.

One last tip I collected but never got to apply is that if you login to DNS-323 but there is no shell prompt, write 5784468 to get it (?!).

Many people like to the default SSH port from 22 to something much higher. Note that only root can access ports up to 1024, which means that in a sort of counterintuitive way, you may be making it easier for a data thief by setting a port higher than 1024. The port setting can be found in sshd_config, which is a file normally residing in /etc/ssh/, but on ffp is in /ffp/etc/ssh.


4. private key login (autologin)

PuTTYPortableNext, I set up automated login with my Putty key. Essentially, you will create a pair of keys: a public key residing on the host you are connecting to (here, the DNS-323 box) and a private key connected to your client (i.e., Putty on your computer). Only the private key can open the public key and to use the private key you will have to enter a (hopefully) long and complicated password that only you can remember but others would never guess. This way, access is more secure and convenient – a good combination, since usually increased security results in less usability. To access the box you will need something you know (your long password) and something you have (your private key). Note that I am using Putty Portable, which I can take with me on a USB key, but you don’t have to if you will only access your box from your computer.

puttygenTo generate the pair of keys with Putty you need puttygen.exe, which you can download from the Putty site (link in Sources). It looks something like photo. You will be prompted to move your mouse randomly for a while, letting your pent up Parkinson loose. Try to make your passphrase as long and varied as possible. One way you can do this is take a long phrase, poem or paragraph you can remember and enter it. If it is long enough, you could even use the first letter of each word (or even the second one, if you are so inclined). Perform some substitutions you can remember if you need to (such as a->4, or e->3 or even s->$). Make sure you do not generate SSH 1 as that is obsolete and easily breakable, and optionally replace the Key comment with your email address (it can be anything, really). Save both the public and (you can always get the public key from the private key with puttygen, so you don't need to save the public key; you can also save a private key with password or one without, depending on how comfortable you are with somebody else finding it and using it) the private key by clicking on its corresponding buttons but don’t close the window yet. Copy the public key field – it’s essentially what you could have saved, but this is a more useable format, as it is on one line.

SSH requires your public key to be in a specific location in your home directory (~/.ssh/authorized_keys, set in /etc/ssh/sshd_config), but that is not that simple on DNS-323, as the entire file system is ephemeral, recreated on each reboot. You could bypass that by either mounting /home on a permanent location or recreating the files with a login script. I chose the latter approach. Here’s the script I’m using:

# ----[ setssh.sh ]----
# script to set autologin for SSH with keys (e.g. after reboot)
# NOTE:  put this in /mnt/HD_a2/ffp/start/ and make it executable.
# w 20/10/10 inbonobo http://www.ConsumedConsumer.org
# ref/credit: http://goo.gl/Bg4Y

# ssh
mkdir /home/root/.ssh
touch /home/root/.ssh/authorized_keys
chmod -R og= /home/root/.ssh
echo ssh-rsa therestofyourkey > /home/root/.ssh/authorized_keys

I called it setssh.sh, but it doesn’t really matter, you can call it anything. Create it in the /ffp/start directory, so that it is executed at every start-up. Paste the public key copied from the puttygen window on the last line of the script make sure it stays on one line only, after echo (on top of ‘ssh-rsa’ as your key should contain that), save, chmod +x setssh.sh to make it executable and Bob’s your uncle.

LE: Some of the settings that I normally use in setting up SSH on a Linux box may not work with Fonz. I've found that uncommenting more settings beyond Port, Protocol, MaxAuthTries, PasswordAuthentication, PermitEmptyPasswords causes the SSH daemon to refuse connections.

Note that you could install other proggies that may be better in some ways, such as less resource-intensive (dropbear) or more up-to-date (openssh), but I prefer to keep things simple. Once you are comfortable with this login fashion, you could disable the login without a key altogether, making your box immune to brute force attacks.


5. moar packages!

Once you get a device to run linux, virtually all the software developed for linux can be ported and this has already happened with tones of software. You can certainly do it yourself, but there are many people who have already done it for you. To download such packages to your box, make a directory, then use rsync or wget:

cd /mnt/HD_a2
rsync -av inreto.de::dns323/fun-plug/0.5/packages .
cd packages
funpkg -i *.tgz

The last line installs everything; I only install what I need, but I prefer to have them handy. Here’s how you can use funpkg:

  • Install: funpkg -i <packages...>
  • Reinstall: funpkg -I <packages...>
  • Upgrade: funpkg -u <packages...>
  • Remove: funpkg -r <packages...>

You might also add the –-delete switch to rsync, especially if you plan on adding the command to your crontab. Other similar repositories are uli’s and plord’s – links in sources. Here’s what the wiki-1stS suggests (but I haven’t done that):

# cd /ffp/
# mkdir pkg ; cd pkg ; rsync -av --delete inreto.de::dns323/fun-plug/0.5/packages .
# rsync -av --delete wolf-u.li::ffp/additional .
# rsync -av --delete inreto.de::dns323/fun-plug/0.5/extra-packages .

The latest and greatest packages are however optware. Here’s how to get it using wget (again, you can also use rsync):

cd /mnt/HD_a2/packages
mkdir ipkg
cd ipkg
wget http://ipkg.nslu2-linux.org/feeds/optware/dns323/cross/unstable/ipkg-opt_0.99.163-10_arm.ipk
tar -xzf ipkg-opt_0.99.163-10_arm.ipk ./data.tar.gz
tar -xzf data.tar.gz
mkdir -p /opt
mount --bind /mnt/HD_a2/packages/ipkg/opt /opt
export PATH=/opt/bin:/opt/sbin:$PATH

I prefer to keep all additional packages in subdirectory in the main packages, but you don’t have to; the default instructions will create the ipkg directory in the root of HD_a2.

You now have ipkg installed and in the path so that you can install other packages. To add the above link as a source, type the following (one line):

echo src dns323 http://ipkg.nslu2-linux.org/feeds/optware/dns323/cross/unstable >> /opt/etc/ipkg.conf

Then launch ipkg update. Other subcommands include:

update                  Update list of available packages from <src> defined in /etc/ipkg.conf
upgrade                 Upgrade all installed packages to latest version
install <pkg>           Download and install <pkg> (and dependencies)
remove <pkg>            Remove package <pkg>
list                    List available packages and descriptions
files <pkg>             List all files belonging to <pkg>
search <file>           Search for a packaging providing <file>
info [pkg [<field>]]    Display all/some info fields for <pkg> or all
status [pkg [<field>]]  Display all/some status fields for <pkg> or all
depends <pkg>           Print uninstalled package dependencies for <pkg>

Good and wholesome as they may be, the optware install won’t survive a reboot because the paths would be lost. More precisely, the last three lines from the install sequence will not be repeated at bootup unless you place them in a script. I tried a few ideas, but the only one that seemed to work is adding the following at the end of /ffp/etc/profile (making a script executable and placing it in profile.d should also work but I had no luck with that):

# optware bind
mkdir -p /opt
mount --bind /mnt/HD_a2/packages/ipkg/opt /opt

You might also use that PATH statement to add any other directories you may keep scripts you run from the prompt. I have installed nano (can’t stand damn vi, could never remember the modes and commands) and python. Installing nano a walk in the park – ipkg install nano while Midnight Commander funpkg -i mc-*.tgz failed, but I didn’t care much for it. Installing python was a bit more difficult.


6. installing python for advanced scripting

Python is part of the Uli repo, but it’s unclear what version is in there. I thus decided to install the optware version, where several releases, including the 2.7 are visible. It’s as easy as ipkg install python. Unfortunately, that installed python 2.5, so it was necessary to ipkg remove python. This did not remove the binaries for some reason, nor did it remove the symbolic links, so I had to remove the binaries, specifically give the command ipkg install python2.7 then recreate the symbolic links toward the 2.7 version with ln –s realtarget symlink.

There were two more things needed. Firstly, I discovered that one of my script resulted in some dbm error. Further investigation uncovered a bug and a suggested resolution, renaming dbm.so xdbm.so. Finally, there’s no env in Fonz linux, so I had to replace the /usr/bin/env python statement with /opt/bin/python. The same goes for anything using env – replace with the actual app path.


7. installing transmission for bittorrent

Transmission is not the only bt client available, (there’s also rtorrent and even MLDonkey for all P2P networks) but it is in my judgment better suited for this. As this is presumably the first time you’re installing it, you first need to install curl:

$ funpkg -i curl-7.18.1.tgz 
$ funpkg -i Transmission-2.11-1.tgz

These are the current versions, but later on you might want to simply replace the numbers with wildcards: curl-*.tgz and Transmission-*.tgz especially when performing an upgrade, in which case you first have to wait for T to shut down cleanly before upgrading:

$ /ffp/start/transmission.sh stop
$ funpkg -u Transmission-2.11-1.tgz
$ /ffp/start/transmission.sh start

Check your existing version with $ transmission-daemon –version and error messages with $ transmission-daemon –log-error

Transmission is quite finicky about who’s accessing it (one of the reasons I like it), so you’ll have to set up a login and password as well as a whitelist of IP addresses that are allowed to admin it through the web interface. The –w switch is very important as it sets the default download directory; if not set, everything will go into ~ which is virtual and very small, causing errors. Consider all these constraints, make the appropriate substitutions then run it for the first time with the following command:

$ su nobody -c "transmission-daemon -f -g /mnt/HD_a2/.transmission-daemon -w /mnt/HD_a2/<downloads> -t -u <username> -v <password> -a,192.168.*.* –b –c /mnt/HD_a2/<torrents> –gsr 1.0"

After running this setup command you will get some messages; if everything’s alright, you may quit with Ctrl+C. Since on my LAN the addresses of important clients are fixed to their respective MAC addresses (so for all intents and purposes they never change), I can be very specific when it comes to the whitelist and list every possible address. The command above will also get transmission to watch the <torrents> directory and download them to <downloads> – make sure you make the appropriate substitutions.

I panicked at first when I noticed 4 instances of transmission-daemon in my ps | grep trans, but upon searching the transmission forum I realized that this is normal. There’s even a ticket (3403) with this problem. Note that you can run two (real) transmission-daemons at once for a multiuser scenario. Just create two different config files with different download paths and different RPC port and you're good to go.

Further customization is possible and recommended – type transmission-daemon --help to see your options. When calling transmission directly make sure you use the –g switch pointing transmission to its config folder – the default being, as above, –g /mnt/HD_a2/.transmission-daemon . The --port option refers to the port of the GUI (9091 by default). If you want to change the BT port, see transmission-remote --help for details or use –P <port> or –-peerport <port>. After the first setup, you start it with $ /ffp/start/transmission.sh start and stop it with $ /ffp/start/transmission.sh stop (duh!).

If you get “Access denied” or “invalid folder”, do

$ /ffp/start/transmission.sh stop   (wait a while after this)
$ chown -R nobody /mnt/HD_a2/.transmission-daemon
$ chown -R nobody /mnt/HD_a2/Downloads

Some people claim that it's easier to edit settings.json directly, while others state that they could not get the changes to stick:

I got it to stick with
kill -SIGHUP `pidof transmission-daemon`
The only reason it would not have worked is if one or more of the threads were not shutdown. It is always a good idea to check using ps -ef or ps -ef|grep transmission-daemon.

Access the GUI at http://<your NAS IP>:9091/ 

If you want to modify the tracker list of an existing torrent, that's possible with transmission-remote:

$ transmission-remote --help |grep -i "tracker"
   -it  --info-trackers                      List the current torrent(s)' trackers
   -ta  --tracker-add            <tracker>   Add a tracker to a torrent
   -tr  --tracker-remove         <trackerId> Remove a tracker from a torrent

I generally limit my upload speed as my connection is severely asymmetrical. This can be accomplished from the GUI and I recommend it to everyone. If you don’t know your upper limit, try to measure it with speedtest.net in the morning when nothing is being uploaded or downloaded and set your maximum u/l speed in Transmission to half or less your maximum.

LE: A blocklist can be obtained from http://list.iblocklist.com/?list=bt_level1&fileformat=p2p&archiveformat=gz but I found that for some reason it may cause transmission to stall, so I did not enable it.


8. installing cron scripts for automation

Although you can load all torrents from the GUI, you might also want to get Transmission to watch specific folders and download at night so that downloading does not interfere with work (and also costs less). We’ll be storing the scripts in the /ffp/var/scripts directory.

mkdir directory
cd directory
nano <script>.sh
[paste the script from the window below]
chmod 755 <script>.sh

You must repeat the above for:

  • rbackup.sh, torrentwatchdog.sh and unpacker.sh (and cron python scripts) in /ffp/var/scripts or possibly /ffp/etc/examples
  • login_status.sh, optwarepath.sh and root-prompt.sh reside in /ffp/etc/profile.d
  • editcron.sh and setssh.sh goes into /ffp/start

If some of your directories contain spaces, you might want to use gho’s workaround when modifying the scripts:

$SOURCEROOT/Pictures \

If, for some reason (as some user has reported), although executable, the scripts in profile.d are not executed, add this at the end of your /ffp/etc/profile:

# include custom profile files
for profile_script in /ffp/etc/profile.d/*.sh; do
if [ -x $profile_script ]; then
. $profile_script
unset profile_script

The scripts can be found in the window below. The original link is in round brackets while the main link, in square brackets, contains my own modifications.


9. What’s left to do and how I did it I’ll show in a future article, but in case you’re wondering what my list is, you can find it below.

Sources / More info: debnas, wiki-debnas, debnas-0.5.tar.bz2, horto, wiki-dns323, dns-323, fun-plug, ssh-tut, ssh-host-key, dropbear, save-key, putty, cryptolaw, .ssh-workarounds, fun-telnet, automatic, Transmission, Transmission-2.11-1.tgz, regain-telnet, uli’s repo, uli-PACK, plord-packs, autologin-bat, py-bug, optware-alternative, regain-ssh, wiki-1stS, wiki-bt, torrentflu-b4rt-auto, t-3403, godsyn-bm, kentyman-bm, forum-settings-stick

Scripts: [editcron.sh (h)] [torrentwatchdog.sh (h)] [unpacker.sh (h)] [rbackup.sh (h)]  [loginstatus.sh (h)] [root-prompt.sh (m)] [bookmarklets] [email from prompt (0)] [TODO and proces list]


..::!NF3RNO>> said…
What firemware are you using? Does everything you have installed on your dns work after reboot? I as many others who followed hortos posts, have had issues with more recent firmwares. I got to the point where I couldn't even ssh into my box. As a result, transmission won't load and cronjobs aren't running. I will have to format my drive to start fresh—and I'm not looking forward to it.

Thanks for putting this together.
InBonobo said…
I'm always using the latest firmware, 1.09 (which is really not that much different from 1.08).
If this did not work, I would not have published it :)
Fromu2e said…
Following your guide for making a private key, I have two questions:

1.When I paste my key on the last line:

echo ssh-rsa > /home/root/.ssh/authorized_keys

Should I delete the entire line except echo or just "" leaving everything including the > before /home?

2. Once the configuration is set (and I assume I do a reboot) how does one ssh into the NAS with putty?

InBonobo said…
1. Go with the second option, i.e., replace with what you copied from puttygen, but you leave just one ">" before /home..
The ">" sign tells the echo command to pipe everything into the file that follows, replacing it.
2. You have to import the private key you saved (*.ppk) into your Putty config: http://goo.gl/QzcnQ then save the Session (so that you don't have to do this every time).
Here's how the detailed unixwiz guide (save-key, linked above) describes it: Navigate to Connection : SSH : Auth in the Category pane on the left, then populate the Private key file for authentication field by browsing to the .ppk file saved previously.

In Connection -> Data you might also want to enter "root" as the Auto-login name, but this is something I've done even before switching to PK login.
Fromu2e said…
Works perfectly. Thanks.
Joe Consultant said…
I'm new to remote administration (been maintaining my Linux desktop and notebook for years).  How exactly do I get started here?  I have a DNS-321 with 1.03 firmware (latest).  I tried a few ssh commands like:

bigbird@sananda:~$ ssh admin@
ssh: connect to host port 22: Connection refused
bigbird@sananda:~$ ssh login passroot:12345678
ssh: Could not resolve hostname login: Name or service not known
bigbird@sananda:~$ ssh -l passroot:12345678
ssh: connect to host port 22: Connection refused

bigbird@sananda:~$ telnet -l admin 23
telnet: Unable to connect to remote host: Connection refused

and it won't let me in.  I'm probably using ssh incorrectly.

Right now, I'm no trying to replace the OS, I'd just like "normal" access (getting to a command line) so I can delete a couple of directories.  The darn system lets you create them, but has no option to delete them.

Any ideas appreciated.
InBonobo said…
I suggest you start with 1 - "funplug it" :)
chickenboy said…
Just bought a use dns-321 and hope to use your tutorial to modify it and make it work more like it should have in the first place.  I admire your detailed description.  I have no doubts I'll be able to make this go.   Thank you for your effort!

Popular posts from this blog