Archive for the 'Linux' Category

Track your (Synology) NAS when it’s stolen

When a friend of mine recently got his MacBook stolen, I quickly verified if I had installed Prey Project on each laptop/desktop PC I have. For those who do not know Prey:

Prey lets you keep track of your phone or laptop at all times, and will help you find it if it ever gets lost or stolen. It’s lightweight, open source software, and free for anyone to use. And it just works.

Yes, I had Prey running on each PC. And then I looked at my Synology NAS (DS410, 4 disks, 8TB raw storage). It could be stolen too. And it’s basically a Linux box. And Prey is available for Linux …

So I figured out how to install Prey on a Synology box:

  1. login via ssh as root
  2. install the ipkg/’Bootstrap’ module on your NAS server – (from forum.synology.com) and this is a list of the right bootstraps for the right Synology model.
  3. install bash shell – “ipkg install bash” (from forum.synology.com)
  4. install textutils – “ipkg install textutils” (from forum.synology.com)
  5. goto /usr/share and download the latest Linux version of Prey (wget http://preyproject.com/releases/...linux.zip ) and unzip it
  6. create an account on Prey and get your API key from your Account profile.
  7. create a new device (e.g. ‘NAS8TB (Syn410)’), indicate OS as Debian (it’s close enough) and get the device key.
  8. edit the /usr/share/prey/config file and fill in the API and device key
    # you can get both of these from Prey's web service
    api_key='yyyyyyyyyy'
    device_key='xxxxxx'
  9. now run the “bash /usr/share/prey/prey.sh” a first time – you should get a “-- Got status code 200! -- Nothing to worry about. :) -- Cleaning up!” response.
  10. now edit /etc/crontab and add a line
    5-55/20 * * * * root /opt/bin/bash /usr/share/prey/prey.sh >  /usr/share/prey/lastrun.log
  11. Now restart crontab in the following (non-standard-Linux) way (from forum.synology.com):
    /usr/syno/etc.defaults/rc.d/S04crond.sh stop
    /usr/syno/etc.defaults/rc.d/S04crond.sh start
  12. And it’s running! When your Synology is stolen, you set its status in your Prey account to ‘Missing’ and you will start getting email reports every 20 minutes. Because it’s a NAS, there is no webcam and no screenshots can be taken, but the external IP address will let you see where the device turns up.
    Remote IP: 78.29.245.xxx
    Private IP: 192.168.0.108
    Gateway IP: 192.168.0.1
    MAC Address: xx:xx:xx:xx:xx:xx

Would this work on a QNAP server? I’m guessing, yes.

Redirecting with Apache’s .htaccess

When you migrate web sites from one place to another, and the URLS change, you don’t want to lose visitors that still use the old links. If your ‘old’ website ran on Apache, you can use its mod_alias/mod_rewrite functionality to automatically redirect to the new URL. This involves adding redirect rules to the .htaccess file in the base folder of the redirects. Some examples:

Generic structure of the .htaccess redirects

Redirect permanent /(old url) (new url)
Redirect ... (add all your one-2-one redirects here)
RedirectMatch permanent ^/old_stuff/.*html$ http://www.example.com/
RedirectMatch ... (add your catch-all redirects here)

RewriteEngine on
RewriteBase /blog/
RewriteRule ^([regex])$ http://blog.example.com/$1 [R,L]
RewriteRule ... (add all your variable redirects here)

EXAMPLE: old Blogger site (on your own server) to new WordPress site
I’ve done a migration from a blog published by Blogger (via FTP) onto my own webspace, to a blog run by WordPress. I’ve used the following Rewrite rules to handle the redirections.
* HOMEPAGE:
redirect /index.html and / to your new blog URL
Redirect permanent / http://blog.example.com/
Redirect permanent /index.html http://blog.example.com/

* FEED:
redirect e.g. /atom.xml to your Feedburner feed
Redirect permanent /atom.xml http://feeds.feedburner.com/(exampleblog)

* ARCHIVES:
redirect e.g. /archive/2005_03_posts.html to the new WordPress archives
RedirectMatch permanent /archive/([0-9][0-9][0-9][0-9])_([0-9][0-9])_.*$ http://blog.example.com/$1/$2/

* POST PAGES:
This is tricky, because Blogger and WordPress do not use exactly the same rules for constructing the text-like URL (the ‘post slug’). E.g a post called how-to-podcast-with-blogger-and.html on my old Blogger site became how-to-podcast-with-blogger-and-smartcast/ on the new WordPress one. So what I did consisted of 2 type of rules:
a) redirecting individual pages
Redirect permanent 2004/10/how-to-podcast-with-blogger-and.html http://blog.example.com/2004/10/how-to-podcast-with-blogger-and-smartcast/
b) a generic rule for the others (this uses Rewrite instead of RedirectMatch!): each page is redirected to a search on the WordPress blog within the correct month with the two first words of the title:
RewriteRule ^([0-9][0-9][0-9][0-9])/([0-9][0-9])/([a-z0-9]*)-([a-z0-9]*).*$ http://blog.example.com/$1/$2/?s=$3+$4 [R,L]
This method is far from perfect, but will bring visitors a lot closer to the right page. If you use pretty distinctive words for titles (e.g. “Myspace: bulletin and other spam“), chances are the right page show up first. If you start all your posts with “The ten best ways to …” then you will need a more sophisticated rule; e.g. using the 6th and 7th word:
RewriteRule ^([0-9][0-9][0-9][0-9])/([0-9][0-9])/[a-z0-9]*-[a-z0-9]*-[a-z0-9]*-[a-z0-9]*-[a-z0-9]*-([a-z0-9]*)-([a-z0-9]*).*$ http://blog.example.com/$1/$2/?s=$3+$4 [R,L]

Not losing the querystring
Redirect and RedirectMatch cannot redirect to a URL with a querystring (e.g. to newpage.php?param1=val1&param2=val2). For that you will need to use the RewriteRule. An example: redirect all links like test.asp?param=value on the old domain to the new domain while keeping all querystring parameters:
RewriteRule ^tools/test.asp\??(.*)$ http://web.example.com/tools/test.asp [L,QSA]
where the QSA = (query string append) keep existing querystring, and L = (last rule) stop looking further for rule matches.

Convert Bind DNS zone into PTR records

The following script I made in order to convert the forward DNS records in a /var/named/db.[domain] file into the correct format for a reverse DNS db.[subnet prefix] file.

#!/bin/sh
(...)
DNSROOT=/var/named
PREFIX=$1
DOMAIN=$2
shift 2
DNSPRE=$DNSROOT/db.$PREFIX
DNSDOM=$DNSROOT/db.$DOMAIN
echo "; save this in $DNSPRE"
(
if [ -f $DNSDOM ] ; then
cat $DNSDOM
| grep $PREFIX
| grep -w "A"
| sed "s/$PREFIX.*//g"
| gawk "BEGIN {OFS = "t" ;} {print $4,"IN","PTR",$1 ".$DOMAIN.",";; FROM `basename $DNSDOM`" }"
fi

if [ -f $DNSPRE ] ; then
cat $DNSPRE
| grep -w "PTR"
| gawk "BEGIN {OFS = "t" ;} {print $1,$2,$3,$4,";; FROM `basename $DNSPRE` "; }"
fi )
| sort -n
| uniq --check-chars=3

You would call it as follows:
revdns.sh 192.168.110 internal.example.com > new.db.192.168.110 and then replace the records of the original db.192.168.110 with the records of the new file. The script still requires manual intervention (you cannot pipe the result straight into a live Bind config file) but saves a lot of typing!

Example of the output:

201 IN PTR james.internal.example.be. ;; FROM db.internal.example.com
202 IN PTR wilbur.internal.example.be. ;; FROM db.internal.example.com
216 IN PTR appprd1.internal.example.com. ;; FROM db.192.168.110
217 IN PTR appprd2.internal.example.com. ;; FROM db.192.168.110
218 IN PTR appprd3.internal.example.com. ;; FROM db.192.168.110
219 IN PTR appprd4.internal.example.com. ;; FROM db.192.168.110
220 IN PTR appprd5.internal.example.com. ;; FROM db.192.168.110
221 IN PTR appprd6.internal.example.com. ;; FROM db.192.168.110

Installing NTP (time synchronisation)

Set timezone (optional)
create symbolical link from /usr/share/zoneinfo/... to /etc/localtime:
ln -sf /usr/share/zoneinfo/Europe/Brussels /etc/localtime
Set UTC mode (optional)
if your hardware clock runs in UTC (Universal Coordinated Time) mode, add
UTC=true
to the /etc/sysconfig/clock file
Make sure ntpd is not running
Use service ntpd stop to stop it.
Choose the NTP server you will get your time from
it can be an internal server that has the NTP service open for clients, or an public NTP server. To be sure, use 2 servers. To check if you can access it, run ntpdate timeserver.ntp.ch
Edit the /etc/ntp.conf file
Rename the current file to ntp.bak.conf and make a small new one:
restrict default ignore
server timeserver.ntp.ch # Swiss time
server ntp.ucsd.edu # Univ of California, San Diego
restrict timeserver.ntp.ch mask 255.255.255.255 nomodify notrap noquery
restrict ntp.ucsd.edu mask 255.255.255.255 nomodify notrap noquery
server 127.127.1.0 # local clock
fudge 127.127.1.0 stratum 10 #so it only takes over if the rest fails
restrict 127.0.0.1 driftfile /etc/ntp/drift broadcastdelay 0.008 authenticate no
Set your system clock right
Run the following command a couple of times:
ntpdate -u timeserver.ntp.ch # or whatever server you want to use
You will see the initial diffence in time go away afer the 2nd or 3rd time.
Set hardware clock
/sbin/hwclock --systohc
Run the ntpd daemon
service ntpd start
Add ntpd to the services started at boot time
chkconfig ntpd on
Check the NTP results
ntpd -p
will show you what the difference is between your clock and that of the servers you added. You are looking for lines like

remote refid st t when poll reach delay offset jitter
==========================================================================
LOCAL LOCAL 10 l 30 64 377 0.000 0.000 0.004 *
192.168.246.107 192.168.246.88 3 u 41 128 177 0.313 5.598 0.345

and not lines like

remote refid st t when poll reach delay offset jitter
==========================================================================
192.168.246.126 LOCAL 11 u 37 128 375 0.204 6082.02 6069.84

Jitter is too high!