Raspberry Pi als server

Raspberry Pi LogoRaspberry Pi, de $25 Linux computer? OK, de zaak ligt iets genuanceerder, maar het is toch een heel interessant project. Meer info op mijn algemene RaspberryPi pagina (ook over instellingen, eerste gebruik, en zo voort), deze pagina is specifiek voor het gebruik als home server (files, veilig toegang via internet, etc) en niet echt bedoeld voor beginners. Voor I/O-experimenten zie mijn Raspberry hardware pagina.

De beginners-presentatie gehouden op 21 augustus 2012 bij EmSE (Embedded Systems Eindhoven, een hobby-club) over mijn bevindingen met de Raspberry Pi is hier te downloaden: EmSE_RaspberryPi.pdf

Daarnaast heb ik daar op 20 augustus 2013 een lezing gehouden over mijn in aanbouw zijnde Home Control systeem.

Deze pagina is gestart met de Raspberry Pi 1, ondertussen aan het overgaan naar de Raspberry Pi 3, er kunnen kleine verschillen zijn!

Ik heb nu onder andere de volgende services draaien (met nog genoeg ruimte voor meer):

Raspberry Pi is voor mij ideaal als een server, want:

  • Moet 24 uur per dag, 365 dagen per jaar aanstaan, en dus is energiegebruik van belang, de Raspberry Pi gebruikt maar een Watt of 2..3 (dus zo'n €6 per jaar)
  • Is gebaseerd op standaard Debian, dus heeft heel veel (server-) toepassingen kant-en-klaar beschikbaar, als de samba file server, web server, secure shell server, en zo voort
  • Is snel genoeg om voor mij de meeste klussen goed aan te kunnen, vooral als NAS (netwerk-schijf) voor backup's en zo
  • Is klein, en kan dus in een klein hoekje ingebouwd worden (heeft geen monitor en toetsenbord nodig, ik bedien hem op afstand); staat bij mij met een harde schijf in de meterkast

SD slijtage voorkomen

Raspberry Pi board

"Raspberry Pi" is a trademark of the Raspberry Pi Foundation

Een server staat continue te werken. Je wilt niet dat de SD-card snel slijt, doordat er te veel te vaak naar toe geschreven wordt. Ditzelfde probleem had ik ook al bij de USB-flash op de NSLU2, waar ik een aantal stappen genomen heb om het schrijven naar de systeemdisk te verminderen. Het goede bij de Raspberry Pi is dat /run en /run/lock (en daarmee ook /var/lock en /var/run, zijn daarheen gelinkt) al standaard op het tmpfs gemount zijn. Dit is het 'temporary file system', een soort RAM-disk. Ze schrijven dus niet naar de SD-card (zie ook het artikel Using tmpfs to Minimize Disk IO). Nog kijken of ik ook mijn logfiles in /var/log naar tmpfs wil hebben... Er wordt toch nog wel wat geschreven in rust.

Oops, met de recentere versies van raspbian is /tmp etc niet standaard op een tmpfs filesystem gemount... Daar moet ik dus nog wat aan doen, zie de link hierboven! Zal later de tekst nog bijwerken. Let op, tmpfs filesysteem (ramdisk) gaat wel van je werkgeheugen af (al wordt het geswapt).

Huidige grootte van /tmp is onder de 100 kB (command du -hs /tmp ), /var/log is 2.4 MByte.

Hoe veel wordt er nu daadwerkelijk geschreven? Dat is te checken met /proc/diskstats, wat een reeks getallen uitspuugt die het lezen en schrijven naar je 'disks' weergeven. Het 7e veld na de naam van het device is het aantal sectoren dat is geschreven, de verandering hierin wil je minimaal houden. Een commando dat elke 10 minuten de huidige stand van de '/'-partitie op de SD-card afdrukt (één regel); bij wordt ongeveer elke 20 minuten in rust nog iets geschreven:

while [ 1 ]; do cat /proc/diskstats | grep mmcblk0p2; sleep 600; done

Vinden welke files er recentelijk geschreven zijn kan door eerst een marker-file te maken (touch marker.txt), en dan na verloop van tijd te kijken welke files nieuwer zijn dan die marker. Op die manier vind je mogelijk andere files die je op tmpfs wilt mounten (in mijn geval wordt er bijvoorbeeld een keer per uur een regel naar /var/log/auth.log geschreven door cron, en er gebeurt nog iets in /tmp):

sudo find /var/ -xdev -newer marker.txt -print

Met het programma iotop (vergelijkbaar met top voor CPU/memorygebruik) kan je (soms) terugvinden welk programma daadwerkelijk naar disk bezig is (tip: gebruik opties -o -a). Hiermee kwam ik er achter waarom mijn harde schijf niet in slaap viel: squid leest er regelmatig van (tja, had zelf de cache van squid naar de HD verplaatst in de /etc/squid/squid.config file...). Kijken of het nu beter gaat.

Opzetten als Samba file server

Een van de belangrijkste taken is het werken als netwerkdisk, met name voor backup maar ook voor centrale opslag van bijvoorbeeld foto's. De eerste stap hiervoor is het opzetten van een server om de files op de disk via het netwerk te benaderen, voor zowel Windows als Linux. Ik installeer hiervoor een 'samba server, net als eerder op mijn NSLU2: zie mijn samba en NSLU2 pagina's, de eLinux R-Pi NAS pagina en ook deze Raspberry Samba pagina. Eerste stap is natuurlijk het installeren en configureren van de server:

Vervanging voor NSLU2

Veel van de configuratie lijkt op die van mijn oude NSLU2, dus kijk daar voor meer gegevens

sudo mkdir /mnt/data
sudo apt-get install samba samba-common-bin
# pas in de edit-sessie je configuratie aan (zie hieronder):
sudo nano /etc/samba/smb.conf
# smbpasswd vraagt om wachtwoord (en gelijk even user 'pi' er uit gooien):
sudo smbpasswd -a kees
sudo smbpasswd -d pi
sudo smbpasswd -d nobody
# check of de configuratie correct is:
sudo testparm -s
sudo /etc/init.d/samba restart

Vergeet niet de (vanwege security = user) de bestaande gebruikers aan samba toe te voegen met smbpasswd -a <user> (lijst bestaande users opvragen: pdbedit -w -L )

Toevoegen extra Linux users gaat met (evt met --uid <100x>):
adduser <user>; usermod -g users <user>

Wil je zonder wachtwoord in kunnen loggen? Zie Samba: How to share files without user/password

Samba configuratie

In de /etc/samba/smb.conf heb ik onderstaande sectie opgenomen aan het einde als gezamenlijke disk share (zie ook Samba.org en de Samba Setup Guide for Linux). Ook heb ik alles in [printers] en [print$] uitgecommentarieerd en bij printing ook even printing = bsd en printcap name = /dev/null gezet; voorkomt traagheid en foutmeldingen in de logs. security = user aangezet, en in de [homes] sectie browseable = no gezet zodat alleen de shared folder zichtbaar is. Vergeet niet na een aanpassing in de configuratie samba te herstarten (hoewel, samba herlaadt de smb.conf file elke 60 seconden?): /etc/init.d/samba restart.

[shared]
    comment = Gezamenlijke files
    path=/mnt/data/public
    force group = users
    valid users = @users
    wide links = no
    create mask = 0660
    force create mode = 0660
    force directory mode = 0770
    writable = yes
    browsable = yes

NetBIOS uitzetten

Netbios is niet echt veilig, en ook niet meer nodig... Kan je uitschakelen met in de global sectie op te nemen:

[global]
disable netbios = yes
smb ports = 445

De folder /mnt/data/public heb ik op mijn SD-card aangemaakt met daarin enkele files, om al te kunnen testen zonder dat de USB-disk is aangesloten. Later wordt dit vervangen door de public directory op mijn externe USB-disk, door deze over /mnt/data te mounten (zie mijn nslu debian pagina). Dit gaat via een zelfgemaakt init.d script, mount_data.sh met bijhorende configuratiefile mount_data.conf. Voor de installatie zie de .sh file. In mijn geval gaat de USB-disk automatisch in slaap als'ie een tijdje niet gebruikt wordt; voor andere disks moet je dit mogelijk in software doen: zie mijn NSLU pagina.

Snelheid: 6.8 MB/s (55 Mbit/s) lezen en 5.8 MB/s schrijven van grote files, denk dat dit met name door mijn lokale netwerk bepaald wordt (100 mbit/s) gezien de USB disk 27 MB/s leessnelheid heeft op de Raspberry, en de CPU belasting op de raspberry maar 55% is (bij schrijven).

Disk encryptie

Wil je niet dat mensen er zo maar met je data vandoor gaan, bijvoorbeeld bij diefstal van de schijf? Encrypt je disk dan. Dit kan op meerdere manieren, bijvoorbeeld met het encrypten van de hele disk met bijvoorbeeld LUKS/dm-crypt of TrueCrypt, of alleen bepaalde directories met eCryptFS of encFS. Heb voor het laatste gekozen omdat ik er al veel op heb staan, en geen reservedisk bij de hand heb om de data tijdelijk op te zetten terwijl ik de disk encrypt (data gaat daarbij verloren). Bij installatie wordt gevraagd om wachtwoord en opties, voor mij: cipher:<aes>, key:<32-bit>, plaintext passthrough:<no>, file name encryption:<kies maar>; hangt van je doel af maar bedenk dat filenamen gevoelige info kunnen bevatten, omdat ze aangeven om welke file het gaat (dus non-encrypted file names 'lekken' informatie). De commando's voor het opzetten:

mkdir /path/to/encrypted; # als die nog niet bestaat
mkdir /path/to/decrypted; # als die nog niet bestaat
sudo apt-get install ecryptfs-utils; # install ecryptfs
sudo mount -t ecryptfs "/path/to/encrypted" "/path/to/decrypted"; # schrijf de FNEK signature op!

By eCryptfs file system hoef je niet van te voren ruimte te reserveren, de files staan 'gewoon' per stuk op disk. Je kan ze ook gewoon kopieren, bijvoorbeeld voor backup. Let wel op: per file is er een verschillende random seed gebruikt (due in een stukje 'metadata' aan het begin van de file bewaard wordt, zie deze heel technische eCryptfs design beschrijving, sectie 4.3); zo hebben twee dezelfde files in gecrypte vorm niet dezelfde checksum (als je ze ontcijfert bekijkt natuurlijk weer wel).

Unmounten gaat gewoon met sudo umount /path/to/decrypted. Opnieuw mounten is lastiger, en je hebt de eerder gegenereerde FNEK signature nodig! Als je de filenames niet encrypt heb je de ecryptfs_fnek_sig parameter overigens niet nodig. Onderstaande is één regel. Zet alle opties na de -o aan elkaar zonder spaties!!!

sudo mount -t ecryptfs "/path/to/encrypted" "/path/to/decrypted" -o ecryptfs_sig=<fnek_signature>,ecryptfs_fnek_sig=<fnek_signature>,ecryptfs_cipher=aes, ecryptfs_key_bytes=32,ecryptfs_unlink_sigs,ecryptfs_passthrough=no,key=passphrase

En er wordt uiteraard om het wachtwoord gevraagd... Kan ik dus alleen doen als ik ben ingelogd op de Raspberry, want ik wil het wachtwoord niet in een file zetten. Let op; iemand met fysieke toegang tot je systeem kan alles, zolang het systeem aan staat is niets veilig. Maar als de disk wordt gejat en/of als het systeem wordt uitgezet zijn de gecrypte folders voor anderen onbruikbaar. Je kunt de ge-encrypte folder back-uppen; maar ik backup de unencrypted versie omdat mijn long-term backup disk zelf een encrypted partitie heeft.

Het heeft overigens wel behoorlijk performance impact, schrijfsnelheid over het netwerk gaat omlaag van 5.8 MB/s naar 2.4 MB/s (2.75 MB/s bij een 16-bit key). Maar, omdat het hier vooral om de korte-termijn backups gaat is dat voor mij niet zo'n punt. Whole-disk encryptie met LUKS/dm-crypt heeft wat dat betreft betere performance, heb ik begrepen. Heb overigens de SD-card niet gecrypt, alleen dus (gedeelten van) de USB disk.

DNS/DHCP Server dnsmasq

En toen was ik verhuisd, en had een nieuw modem/router (Docsis 3 van UPC). Mooi, met wireless en zo, maar met veel minder mogelijkheden voor instellingen vergeleken met mijn vorige gepimpte LinkSys (met Tomato software). Wat ik het meest mis is is het uitdelen van vaste IP-adressen aan de hand van het MAC-adres, en het geven van duidelijke apparaatnamen aan de hand van het IP-adres. Zo wil ik dat mijn Raspberry niet 192.168.1.5 heet, maar raspberry (of raspberry.lan)...

Nu kan ik het UPC modem niet zo makkelijk upgraden qua software. En ik heb ook geen zin mijn oude Linksys router achter het UPC modem te hangen (weer een apparaat dat 24/7 aan moet staan)... Kan mijn Raspberry daar niet helpen? Jawel, door die als DNS (Domain name Server, koppelt IP-adressen aan namen en zoekt ze zo nodig op internet op) en DHCP server (Dynamic Host Configuration Protocol, deelt de IP-adressen uit) te laten werken. En daarvoor is er een programma beschikbaar: dnsmasq

Nu moet dnsmasq wel goed geconfigureerd worden; anders werkt je internet niet meer. Dus maar eens op zoek gegaan, in de dnsmasq man-pages en andere dnsmasq links. En ook in LXF170 (pagina 92) staat er een duidelijk stuk over. Eerst maar eens installeren, en gelijk stoppen om het vervolgens te configureren:

sudo apt-get install dnsmasq
sudo service dnsmasq stop

Welke services lopen er eigenlijk? Met netstat -el --numeric-ports kan je kijken op welke poorten je Raspberry luistert.

Dan de instellingen in /etc/dnsmasq.conf:

# De lokale domainnaam
expand-hosts
domain=lan
#resolv-file=/etc/resolv.dnsmasq
min-port=4096
# De DNS servers in geval dnsmasq het niet zelf weet: UPC, OpenDNS, Google
#server=213.46.228.196
server=192.168.1.1
server=208.67.222.222
server=8.8.8.8
# Max cache size die dnsmasq aan kan is 10000
cache-size=10000
# Onderstaande instellingen zijn voor dhcp.
# Comment out als je niet wilt dat dnsmasq de IP adressen uitdeelt
dhcp-range=192.168.1.100,192.168.1.149,255.255.255.0,1440m
dhcp-option=option:router,192.168.1.1
# En de vaste IP-adressen (of via /etc/ethers, /etc/hosts met --read-ethers)
dhcp-host=00:22:15:41:5A:33,dualcore,192.168.1.200,infinite
txt-record=dualcore,"Dit is mijn dual-core PC"

Je kan de correctheid van de configuratiefile testen met de --test optie. De lijst met externe DNS servers staat vaak in /etc/resolv.conf, als het eerste adres daarin 127.0.0.1 (localhost) is weet dnsmasq dat de rest voor hem is maar deze eerste genegeerd moet worden (is'ie zelf), en is een aparte /etc/resolv.dnsmasq niet nodig.

Nu natuurlijk nog op je systemen instellen dat ze de Raspberry gebruiken als DNS server, in plaats van bijvoorbeeld je router. Dit gaat in in Ubuntu in de /etc/network/interfaces file, voeg daar in je netwerkinstelling de regel '    dns-nameservers <ip_van_je_raspberry> 208.67.222.222 <eventueel_nog_meer_DNS_servers>' toe (let op, vul de goede adressen in, en de regel is ingesprongen).

DNS slaat ook eerdere zoekopdrachten op in een cache zodat een volgende opdracht sneller gaat. geprobeerd (met dig <sitenaam> vanuit mijn Ubuntu PC): inderdaad gaat de zoektijd (na de eerste keer) van 12 ms via openDNS naar 1 ms via mijn Raspberry.

Veilig Access van Buiten

Raspberry als veilig internet access
Raspberry als veilige gateway naar het netwerk

Veilig internetten op reis is belangrijk, bijvoorbeeld als je op een terras of in een hotel wilt internet-bankieren. Het schijnt vrij makkelijk te zijn om een 'access point' over te nemen of na te maken, en daarmee je verbinding af te tappen. Met een beveiligde internetpagina (https) is dit iets moeilijker, maar een 'man-in-the-middle' attack is soms toch mogelijk. Ik zet dan liever zelf een beveiligde verbinding op naar mijn huisnetwerk, en laat mijn internetverkeer daarover lopen, als extra beveiliging.

Daar zijn verschillende mogelijkheden voor, waaronder:

  • Een VPN (Virtual Private Network) verbinding, een versleutelde verbinding ofwel 'tunnel' naar je huisnetwerk waar alle internetverkeer over heen loopt (maar daarvoor heb je op een PC/laptop wel administrator-rechten nodig)
  • Een SSH tunnel met proxy, waarover je geselecteerd internetverkeer, met name web verkeer, kunt laten lopen; maar is wat lastiger in gebruik dan een VPN.
Zie ook het plaatje rechts, met rood de onveilige situatie, en daarnaast groen als beveiligde tunnel met in geel het verkeer daarover: gaat pas vanaf mijn vertrouwde thuisnetwerk het internet op.

OpenVPN server

Met een VPN zet je een beveiligde (encrypted) tunnel op naar je huisnetwerk, en laat alle internetverkeer over die tunnel gaan. Ik heb hiervoor OpenVPN gebruikt, omdat dit goed ondersteund wordt op zowel de Raspberry (als server) als op Android (als client).

Indien van toepassing: Zorg wel dat op je Raspberry de firewall goed ingesteld staat, met name voor forwarding van tun0

Ook moet je op je modem/router de gekozen VPN poort (standaard udp port 1194) forwarden naar je Raspberry.

Een uitgebreid artikel over OpenVPN/Raspberry met handleiding (in de appendix) en achtergrondinformatie over security etc is te vinden als "SOHO Remote Access VPN. Easy as Pie, Raspberry Pi..." al zitten er wat kleine foutjes in; dus goed lezen en bij foutmeldingen nadenken. Ook op de openVPN how-to pages (en de FAQ) en op 16 tips on OpenVPN security staat veel uitleg. Na installatie (of op andere momenten) checken dat alles goed werkt: kijk in de logfile /var/log/openvpn.log of er fouten en/of waarschuwingen staan. 

Nu nog een nieuwe gebruiker aanmaken en de resulterende <username>.ovpn file veilig kopiëren naar het apparaat van de gebruiker (bijvoorbeeld via SD-card of USB-stick, of een lokale FTP-verbinding). Op Android kan je daarna met OpenVPN Connect en je .ovpn file een veilige verbinding opzetten. Ook vanuit Windows, iOS of Linux kan je uiteraard een OpenVPN verbinding gebruiken.

sudo su;   # gebruiker maken; handigst dit als super-user te doen
cd /etc/openvpn/easy-rsa; source vars; ./build-key-pass <username>; # geen challenge password!
openssl rsa -in keys/revoke1.key -des3 -out keys/revoke1.3des.key; cd keys;
../MakeOVPN.sh; # En kopieer de <username>.ovpn naar je client (bv Android mobiel)

Is de folder ..../examples/easy-rsa niet aanwezig (loop je vast op pagina 17 in de SOHO handleiding)? Dan heb je waarschijnlijk een nieuwere versie van Debian, en is het pakket easy-rsa niet geinstalleerd. Zie Error installing OpenVPN, en ook Installing OpenVPN on Ubuntu waarbij tussen versie 12 en 14 hetzelfde probleem op trad...

Je kan OpenVPN normaal al op je lokale netwerk testen dus je kunt checken of alles qua keys en zo goed is geïnstalleerd. Wel moet je in je <username>.ovpn file even de configuratie aanpassen; vervang in de regel met keyword remote de naam van je server door het IP-adres van de Raspberry op je lokale netwerk. Veel dingen werken, maar niet alle programma's zullen helemaal goed werken: omdat je vanuit je eigen netwerk op je eigen netwerk inlogt is er soms wat verwarring...

Certificaat terugtrekken ('revoke'), bijvoorbeeld omdat je denkt dat iemand er ten onrechte gebruik van maakt? Zorg wel dat je eerst (een keer) aan de hand van de handleiding dit goed hebt geconfigureerd en openvpn hebt gerestart ( service openvpn restart )! Daarna, per certificaat dat je wilt terugtrekken. Let op: het revoke-full commando hoort een error melding 'error 23 at 0 depth lookup:certificate revoked'  te geven; dit is een teken dat het certificaat inderdaad niet meer werkt:

sudo su;   # Revoke: handigst dit als super-user te doen
cd /etc/openvpn/easy-rsa; source vars; ./revoke-full <username>
cp keys/crl.pem /etc/openvpn/

O ja, ik heb onderstaande regels aangepast in de server.conf file ten opzichte van het voorbeeld op pagina 30 van de SOHO handleiding, en natuurlijk waar nodig IP-adressen en zo aangepast.

# De 'push' meldt de client netjes af (minder foutmeldingen in de log), 'mute' houdt kopiën van dezelfde melding beperkt, en 'verb' zet het loglevel op 4
push "explicit-exit-notify 3"
verb 4
mute 20
crl-verify /etc/openvpn/crl.pem

Test! Hoe weet je nu of het goed werkt? Test onderweg in je browser door je IP-adres op te vragen via bijvoorbeeld WhatIsMyIP (ook voor https). Je zou nu het externe IP-adres van je netwerk thuis te zien moeten krijgen, omdat het verkeer daar pas het internet op gaat (moet je je IP-adres natuurlijk wel een keer thuis opgevraagd hebben, of met een Dynamic DNS service op naam op kunnen vragen). En verstuur eens een test-mail en kijk thuis in de headers (bijvoorbeeld in Thunderbird: View -> Message Source): hier zou je in de eerste 'Received:'-regel in de header ook weer je eigen IP-adres als afzender moeten herkennen.

SSH server

SSH en Android

Voor Android gebruik ik ConnectBot om de SSH tunnel op te zetten, inclusief proxy port forwarding. Met ProxyDroid kan ik vervolgens de proxy aanzetten (zie mijn HTC pagina).

SSH staat voor Secure SHell. Secure (veilig) betekent hier dat alle communicatie versleuteld (encrypted) is; zelfs het inlogproces. Meer info op mijn SSH pagina en natuurlijk op de SSH manual pages. SSH biedt een aantal mogelijkheden:

  • Het op een beveiligde manier een command-prompt op een remote computer openen (en ook zelfs grafische programma's kunnen draaien, mits je een X-server hebt wat onder Windows niet standaard het geval is).
  • Het op zetten van een beveiligde tunnel tussen specifieke programma's op verschillende computers (bijvoorbeeld tussen je email-programma en de email-server van je provider, als die SSH support; of naar je samba file server)
  • SFTP, Secure FTP; een vervanging voor FTP waarbij alle gegevens versleutelt over het internet gaan, inclusief je inloggegevens en SCP, Secure copy; een veilige variant van het Linux CP (copy).

SSH configuratie: nog te beschrijven, maar aardig gelijk aan mijn NSLU2 pagina. In de /etc/ssh/sshd_config in ieder geval 'inloggen als root' uitzetten, en ik heb ook password authenticatie uitgezet (werk alleen met private/public key files). Ik heb ook de poort van de standaard 22 naar een andere waarde verzet, scheelt een boel aanvallen van buitenaf. Zet deze poort vervolgens op je firewall/router open met port forwarding naar het I/O adres van je Raspberry: klaar!

Squid Proxy server (met SSH)

Voor veilig internet-browsen vanaf een terrasje is OpenVPN de makkelijkste methode. Een alternatief is surfen over een veilige tunnel opgezet met SSH(zie plaatje hierboven). Gaat niet zo maar, je hebt hiervoor ook een 'proxy' nodig, een programma waartegen een browser aanpraat alsof het het werkelijke internet is. Alle verkeer gaat dan gecodeerd naar huis, en pas vanaf daar normaal het internet op. Dit kan met de combi SSH en squid, een proxy-pakket. De opzet hiervan is nog aardig gelijk aan die op mijn oude NSLU, zie mijn NSLU2 pagina...

Het idee is een veilige SSH tunnel op te zetten waarbij je de poort naar de proxy als port-forwarding opzet (-L3128:localhost:3128), en over die tunnel dan de proxy te gebruiken om te surfen etc. Dit kan (afhankelijk van je systeem waarop je surft) of per programma door in het programma een proxy in te stellen (bijvoorbeeld bij Firefox browser), of door dit globaal op je systeem als proxy in te stellen. Vanuit Ubuntu kan je op de volgende manier vanaf een andere lokatie een tunnel opzetten, inclusief forwarding van je proxy plus forwarding van je samba filesysteem. De tweede regel laat zien hoe je vervolgens de drive mount als /media/remotedrive (zie mijn samba pagina). Let op, 2 regels:

ssh -p 11122 -L 3128:localhost:3128 -L 12345:localhost:445 <username>@<je_huis-ip_adres>
sudo mount -t cifs //netdisk/shared /media/remotedrive -o credentials=/home/<username>/credentials,ip=127.0.0.1,port=12345,rw,uid=<username>

Hoe weet je of squid goed werkt? Om dit echt te testen moet je op een ander netwerk dan je normale netwerk zitten (bijvoorbeeld op je werk), en vanaf daar de SSH-verbinding naar huis opzetten. Ga dan naar je browser en stel deze zo in (via opties -> netwerk) dat deze via de proxy naar het internet gaat. Check dan met bijvoorbeeld WhatIsMyIP wat je IP-adres is (en hier voor https). Dit zou het IP adres van je huisnetwerk (waar je raspberry staat) moeten zijn, en niet dat van het netwerk vanaf waar je test...

Enige probleem: Android op mijn oude mobiel kent standaard geen proxies, in ieder geval niet in Android versie 2.x... En dat voor een Linux-based OS, slordig. Hebben meer mensen al over geklaagd maar geen antwoord van Google. Firefox op Android kan er wel mee overweg; en met de Proxy Mobile extensie is er redelijk snel te wisselen. Om alle Android 2.x apps via de proxy te laten lopen moet je een proxy-app als ProxyDroid hebben, en daarvoor heb je wel een geroote Android nodig. In latere Androids (in ieder geval 4.x) zijn proxies wel mogelijk, en gebruik ik Proxy Settings om makkelijk tussen met en zonder te wisselen. Ps: een SSH tunnel opzetten gaat handig met het gratis ConnectBot.

Jailkit

Voor gevorderden: Om anderen bij de harde schijf te laten (met sftp), maar niet ook gelijk alles met het systeem te kunnen laten doen is een 'chroot jail' handig. Als iemand hiermee via SSH op je Raspberry inlogt krijgt diegene beperkte mogelijkheden. Je kan zelf bijvoorbeeld instellen welke programma's wel of niet beschikbaar zijn, de gebruiker zit dus als het ware in een 'jail' (gevangenis) op de Raspberry, waarvan jij de bewaker bent. Ik gebruik dit om mijn studerende zonen 'op afstand' veilig de netwerk/backup disk te laten benaderen.

Download jailkit en pak uit op je Raspberry (tar -xvf jailkit-2.15.tar.gz). In de nieuwe folder jailkit-2.15 vind je een install.txt met uitleg over hoe te compileren en installeren. En vervolgens volgens het voorbeeld een jail opzetten, maar wel overal voor zover nodig 'sudo' voor zetten.

Helaas ging dit niet helemaal zonder problemen:

  • het voorbeeld is verouderd; in plaats van jk_addjailuser moet je jk_jailuser gebruiken:
    sudo jk_jailuser -m -j /home/jailroot <user>
  • Vergeet niet de gebruiker toe te voegen met sudo nano /home/jailroot/etc/jailkit/jk_lsh.ini
  • Vervolgens bleken er ook nog libraries te missen (foutmelding "cannot find user info for USER"): kopieer /lib/arm-linux-gnueabihf/libnss* en /lib/arm-linux-gnueabihf/libnsl* naar /home/jailroot/lib/arm-linux-gnueabihf/ en chmod 755 ze (welke zijn er precies nodig?).
  • Toen de melding dat de gebruiker sftp-server probeerde te draaien, wat standaard niet is toegestaan: wijzig /usr/lib/sftp-server naar /usr/lib/openssh/sftp-server in /home/jailroot/etc/jailkit/jk_lsh.ini.
  • En nu kan de gebruiker er met FileZilla via het secure ftp protocol bij!

Nu kan een jailed user natuurlijk niet uit de jail, en dus (ook al is sftp toegestaan) nog steeds niet bij de harde schijf... En, je kan geen link leggen naar een map buiten de jail. Moet dus net andersom (zie ook de jailkit FAQ): mount als root de disk (of map) binnen de jail. In mijn geval gaat het om de map /public:
    mkdir /home/jail/public; mount -o bind /mnt/data/public /home/jail/public
Eventueel in home directories zichtbaar maken mag niet met absolute paden, maar bv met sudo ln -s ../../public harddisk.

Om echt een ssh prompt met beperkte toegang te geven moet je nog wat meer doen: /home/jail/etc/passwd bewerken (gebruiker voorzien van de goede shell, /bin/bash). De standaard limited jk_lsh is namelijk bruikbaar voor sftp/scp én voor remote samba mounten, maar niet voor een interactieve ssh shell. Wel jk_lsh.ini danwel jk_chrootsh.ini verder invullen met toegestane commando's (zie b.v. jk_lsh doc)!

Firewall

Als je Raspberry de ingang tot je thuisnetwerk is, is het misschien goed er ook een firewall op te zetten. Hiermee heb je copntrole over wat er via Ethernet (en internet) in en uit gaat.

In eerste instantie gekozen voor ufw, Uncomplicated FireWall. OK, eigenlijk is het zelf geen firewall, maar slechts een front-end om de in Linux ingebouwde iptables op te zetten. Uitleg is te vinden op de UFW community help. In een versimpeld geval: alle inkomende verkeer laten blokkeren en het uitgaande toestaan (dit is de standaard instelling), dan alles van het lokale netwerk weer toestaan met sudo ufw allow from 192.168.1.0/24 (of alleen de poorten die je gebruikt). Bij complexer werk: éérst de specifieke regels als sudo ufw allow OpenSSH, dan pas de algemenere regels. Status: sudo ufw status verbose. Zorg wel dat je jezelf niet buitensluit tijdens het configureren; kan bijvoorbeeld handig zijn om in een aparte shell een commando te starten dat na een half uur de firewall uitzet (sleep 1800 && sudo ufw disable &), kan je testen en in noodgevallen kan je na een half uur weer verder... Handig om je commando's in een script te zetten, kan je snel je default configuratie weer terug zetten (begin met sudo ufw reset).

Maar later overgegaan naar het direct instellen van iptables, heb je toch een beter gevoel wat er gebeurt, en kan je preciezer instellen (was ook handig omdat ik een VPN wilde gaan opzetten, heeft specifieke regels nodig). iptables is iets lastiger, ik heb er daarom een stuk aan gewijd op mijn firewall pagina.

File Synchronisatie en Backup

Er zijn nogal wat methodes om backups te maken. Een tijd lang heb ik rsync gebruikt, die een backup van mijn 'Documents' folder op mijn desktop naar de Raspberry maakte. Maar, nu ik ook meer mijn laptop gebruik, heb ik behoefte aan een tool die meerdere computers in sync kan houden. Ik heb daarvoor Unison gekozen. Deze houdt van de opgegeven mappen per computer de wijzigingen bij, en ziet zo wanneer files gewijzigd zijn; en stuurt dan de juiste files heen en weer. Ook als files weggegooid worden wordt dit goed afgehandeld.

Probleem was alleen wel dat op alle systemen dezelfde versie van Unison moet worden gebruikt... En de meest recentere versie (zoals in Ubuntu gebruikt) is blijkbaar moeilijk op de Raspberry werkend te krijgen. Ik heb er voor gekozen overal de versie 2.40.102 als op de Raspberry te draaien, en deze versie 'vast te zetten' om te voorkomen dat een computer door een update uit de pas gaat lopen. 'How to install Unison 2.40 on Ubuntu 16.04' heeft geholpen [link naar binary]. Gedownload op Ubuntu (op Raspberry kan je gewoon 'apt-get install' gebruiken), en gelijk gezorgt dat'ie niet door nieuwere versies wordt overschreven:

sudo dpkg --install ./unison-gtk_2.40.102-2ubuntu1_amd64.deb
sudo apt-mark hold unison-gtk
sudo apt-mark hold unison

Je kan Unison via SSH laten werken (een beveiligde verbinding, nuttig als een van je computers elders op de wereld staat), of via een lokale tcp socket (niet beveilidg dus!). Gekozen voor de simpeler tcp-socket op poort 12345. Wel de firewall op je lokale netwerk/PC's openzetten, maar uiteraard niet die naar de buitenwereld/het internet toe! Configuratiefile unison.prf in de map ~/.unison opzetten, in mijn geval ongeveer als in deze unison configuratie-file. En, op de Raspberry unison als server draaien:

unison -socket 12345 &

Draai Unison nu nog met de hand (even checken of alles goed gaat), maar wil dit later automatisch doen in start-up en afsluitscripts.

Media Server mediatomb

UPnP Inspector

Met upnp-inspector is het mogelijk te scannen op upnp servers, mocht je de Raspberry niet vinden (ziet daarnaast ook bv mijn TV als zowel een mediaRenderer als een RemoteControlReceiver)

Ik ben niet direct van plan er ook een volwaardige media-player als XBMC (zie bv Raspbmc, XBian en OpenELEC) van te maken, maar het serveren van media (met name audio en foto's aan mijn 'slimme' TV met Samsung AllShare) is zeker iets wat ik van plan ben (via DNLA/UPnP), en ben daarvoor naar mediatomb aan het kijken.

Installatie gaat op de standaard manier met apt-get, en daarna kan je vanuit je web browser op je lokale netwerk mediatomb vertellen welke media hij beschikbaar moet stellen als server (standaard op http://<raspberry_ipaddress>:49152). Na installatie werkt het niet gelijk samen met mijn TV, en moeten er wat aanpassingen in de configuratiefile plaats vinden. Zo heeft een Samsung TV problemen met de standaard http headers (zie deze mediatomb configuratie pagina), moeten er wat extra mediatypes toegevoegd, en zo voort.

Maar, toen werkte het nog niet. Ik had blijkbaar op een of andere manier tijdens het proberen mijn mediatomb database om zeep gekregen, want na het verwijderen en opnieuw laten maken werkte het opeens wel: zowel op mijn TV, mijn Android phone (MediaHouse), en mijn PC met VLC (al vind die mediatomb soms pas na een lange tijd). Door de autoscan optie in mijn /etc/mediatomb/config.xml bouwt mediatomb automatisch ook de goede database weer op.

sudo /etc/init.d/mediatomb stop
sudo rm /var/lib/mediatomb/mediatomb.db
sudo /etc/init.d/mediatomb start

VLC en DLNA

Met VLC kan je met een DLNA server als mediatomb verbinden via View --> Playlist -->Local Network -->Universal Plug’n Play. Wel even geduld hebben, duurt even voordat de servers gevonden worden.

Zowel een mpeg4 als een avi video speelden goed af (ondanks verhalen dat Samsung TV's met AllShare nogal kritisch zijn wat betreft ondersteunde DLNA formaten, ik had blijkbaar geluk en hoef niet te transcoden). Streamen van een 1280 x 720 H.264 movie (1.5 Mb/s) koste slechts rond de 2% CPU load. MP3 audio gaat ook prima (mijn TV kan geen wma files aan: omzetten naar MP3 met wma2mp3). Alleen de folderstructuur op mijn TV is niet helemaal duidelijk, vooral met foto's... Sommige series lijken op verschillende plaatsen voor te komen, maar soms met maar een gedeelte van de foto's. In een andere folder is die serie dan wel weer helemaal te zien. Vreemd, nog eens uitzoeken.

Home Control

Een van de taken van mijn home server wordt ook home control en automation (domotica). Maar, voor je wilt controleren: meten is weten... Vandaar mijn interesse om ook bijvoorbeeld I²C sensoren (als een temperatuursensor in de huiskamer) aan te kunnen sluiten, zie mijn Raspberry Pi hardware pagina. Een simpel voorbeeld van meten: hoe vaak en lang staat mijn PC eigenlijk aan? En mijn TV (met internet)? Geen sensoren voor nodig; je kan dit gewoon met het ping-commando: als je een antwoord terug krijgt (in $?, 0=OK) staat het apparaat aan. Ik test dit een keer per 10 minuten in een script, en schrijf de resultaten naar file. Een simpele variant van dat script, dat ik start met sudo nice bash -c '/home/kees/scripts/TraceTV.sh > /tmp/TraceTV.log' & (let op: '0' is aan):

#!/bin/bash
while true; do
    # Only try once, with a one-second timeout; approx every 10 minutes
    ping -c 1 -W 1 192.168.1.143 >/dev/null
    echo "$?"
    sleep 600
done

Dit kan natuurlijk veel slimmer... Een voorbeeld daarvan is het uitlezen van de 'slimme energiemeter', zodat je je energiegebruik goed in de gaten kunt houden. Je kan dit natuurlijk 'uitbesteden', maar ik wil eigenlijk niet dat anderen mij in de gaten kunnen houden. Bovendien is zelf doen leuker en leerzamer. Ik heb mijn slimme energiemeter met zijn P1-poort via een serieel-naar-USB kabeltje aangesloten op de Raspberry. Daar komt nu elke 10 seconden een datagram volgens de DSMR (Dutch Smart Meter Requirements) 4.2 standaard met de gebruiksgegevens van elektra en gas binnen. Op de Pi loopt een klein servertje, die deze gegevens opvangt. Via UDP kan nu elke computer op mijn netwerk dit weer op ieder moment opvragen. Op de Pi loopt ook mijn logging (vraagt het zelf ook op die manier van zichzelf op), zodat ik 'mooie' verzichten krijg, geeft best inzicht in waar je elektriciteit blijft. Ps: hier een overzicht voor diverse smart meters (onderaan pagina).

Langzaam begint er ook een écht home control netwerk te ontstaan. Hierbij wordt niet alles direct door de Raspberry bestuurd, maar heb ik 'lokale intelligentie'; slimme kleine nodes gebaseerd op de AVR ATtiny (zou ook met b.v. Arduino Nano kunnen). Deze hangen dan via een 3-draads seriële bus aan de Raspberry (Ethernet is veel te 'zwaar' voor dit doel). Je kan het het best vergelijken met hoe een lichaam werkt: de Raspberry is het centrale brein, maar een heleboel taken worden lokaal door reflexen afgehandeld, en de zintuigen zijn daarmee verbonden. Voordeel is dat deze reflexen doorlopen ook als het brein tijdelijk met iets anders bezig is (of plat ligt). Ook hier weer een klein servertje die de afhandelng van de seriële verbinding doet, en via UDP vanaf het hele lokale netwerk commando's kan krijgen.

Een voorbeeld hiervan is de afzuiging in de douche: een ATtiny is een lokale node, met daarop als 'zintuig' een I2C temperatuursensor aan de warmwatertoevoer (handiger dan via de lamp). Als er gedoucht wordt wordt de leiding warm, en schakelt de ATtiny zelfstandig de afzuiger aan via een solid state schakelaar: de reflexreactie van de ATtiny. De ATtiny regelt ook de 'nalooptijd': hoe lang moet de ventilator doorlopen als er gestopt is met douchen. Maar, dit alles wordt ook doorgegeven aan het brein, en dat kan bijvoorbeeld besluiten de reflex te onderdrukken, of de nalooptijd aan te passen. Ook is het geheugen in het brein: de temperatuur wordt hier weer gelogd (en nu en dan centraal opgevraagd).

Ik heb over de eerste opbouw van het systeem en het netwerk een lezing gehouden op 20 augustus 2013 bij EmSE (Embedded Systems Eindhoven, een hobby-club); hier de Home Control presentatie (pdf). Web pagina's met details maak ik nog wel eens.

Minimale Mail Server exim4

Soms is het ook handig als je Raspberry server je een emailtje kan sturen, voor wekelijkse statusrapporten of als er bijvoorbeeld iets mis is. Heb een scriptje in /etc/cron.weekly gezet die me wekelijks op maandag een mail stuurt, met bijvoorbeeld het geheugengebruik (free), de vrije SDcard-ruimte en zo voort. Ik wilde het programma mail hiervoor gebruiken; blijkbaar moet je hiervoor een mail server als exim4 of sendmail draaien:

sudo apt-get install mailutils
sudo rm /var/log/exim4/paniclog
sudo dpkg-reconfigure exim4-config

Problemen: zie de logfile /var/log/exim4/mainlog en eventueel /var/log/exim4/paniclog.

Soms worden mails vastgehouden als er iets niet werkt. Dan is het handig vanaf nul te beginnen, queue legen als in clear outgoing exim4 queue: exim -bp | awk '/^ *[0-9]+[mhd]/{print "exim -Mrm " $3}' | sh (als root). xxx

exim4-config stelt een aantal vragen; zie hiervoor Send-only Mail Server maar kies 'mail send by smarthost; no local mail' en verwijder het IPv6 adres in 'IP addresses to listen on...'. Na configuratie moet je ook de file /etc/email-addresses updaten met in ieder geval root: <je_username>@upcmail·nl (voor mail verzonden als root, in ieder geval UPC vind het niet leuk als je mail verzend waarbij de zender niet een geldig @upcmail·nl emailadres vermeld). En nu werkt bijvoorbeeld (één regel):

echo "Dit is een test" | mail -s Testing <mijn_emailadres>@keesmoerman·nl

Om disk-access te reduceren misschien goed om het interval waarmee exim4 de queue verwerkt wat hoger te zetten (bv van 30 minuten naar 4 uur), als je geen tijd-kritische mail hebt: sudo update-exim4defaults -f --queuetime 4h, scheelt in het schrijven van de log file. Nog eens uitzoeken waar ik log_level moet zetten; zo lang maar even met de hand naar /tmp/exim4 verhuisd, wel terugverhuizen voor je afsluit als je ze nog ooit wil lezen (nog een keer automatiseren; en exim4_old is een kopie van /var/log/exim4 na installatie):

sudo mv /var/log/exim4 /var/log/exim4_old
sudo cp -rap /var/log/exim4_old /tmp/exim4
sudo ln -s /tmp/exim4 /var/log/exim4

Wil je de configuratie handmatig aanpassen (zonder dpkg-reconfigure), dan kan je de file met settings wijzigen:

sudo service exim4 stop
sudo nano /etc/exim4/update-exim4.conf.conf
sudo update-exim4.conf
sudo service exim4 start

Web server lighttpd

Als web-server (dus om webpagina's beschikbaar te maken) gebruik ik het lichtgewicht lighttpd. Apache is uiteraard krachtiger, maar ook zwaarder voor die arme Pi... Mooi is dat lighttpd ook naar Python (en Perl) kan interfacen volgens de CGI-standaard, zodat ik dynamische webpages kan maken met Python scripts om zo ook een interface te hebben naar mijn home control systeem. Installatie staat goed uitgelegd op ' Installing Lighttpd with Python CGI support' en op 'How to get Python to work with Lighttpd?' (inclusief Python voorbeeldje). Had natuurlijk ook een Python server kunnen gebruiken, maar dit is denk ik toch minder werk. Ps: ik heb deze webpages alleen beschikbaar op mijn lokale netwerk; niet direct van buitenaf (maar zie SSH met port forwarding) dus aanvallen heeft geen zin.

Volgens mij kan het aanzetten van (Python voor) CGI (Common Gateway Interface) scripts eenvoudiger dan beschreven, volgens de welkom-page: "CGI scripts are looked for in /usr/lib/cgi-bin, which is where Debian packages will place their scripts. You can enable cgi module by using command "lighty-enable-mod cgi". Maar, ik had de eerste methode al gebruikt...

En dan natuurlijk: hoe werkt Python met CGI (meer uitleg)? Ik heb nog weinig ervaring met Python, maar wel veel met Perl CGI programming. Blijkt niet zo heel veel verschil in te zitten, CGI is natuurlijk toch een standaard interface. Enige lastige is dat fouten niet in de error log (sudo cat /var/log/lighttpd/error.log) terecht komen, maar je kunt ook vanuit een terminal testen en dan krijg je de fouten gewoon daarin. Alternatief: met de onderstaande code in je Python CGI-script komt de foutmelding in je webbrowser te staan:

import cgi       # Dit natuurlijk sowieso voor cgi programming
import cgitb     # voor de foutmeldingen
cgitb.enable()   # of naar file: cgitb.enable(display=0, logdir="/path/to/logdir")

Dynamic IP adres

Tja, nu heb je je server netjes ingesteld, maar hoe kunnen anderen die nu van buitenaf vinden? Normaal hebben servers een domeinnaam (b.v. keesmoerman.nl). Via deze naam kunnen anderen dan het IP-adres van de server opvragen, en dan via dat IP adres contact leggen. Maar, de meeste mensen hebben meestal geen domein naam voor de thuiscomputer; alleen maar een IP als toegewezen door de provider. En dat is vaak dynamisch; dat wil zeggen het kan zonder melding wijzigen. Voor tijdelijk gebruik is dit goed te doen; geef naar anderen je IP adres door. Maar, mooier is via een 'dynamic DNS service' je huisnetwerk ook een naam te geven.

Er zijn heel wat providers voor Dynamic DNS. Ik ben zelf nu overgestapt naar een gratis dynamic IP address updater van dynu.com (dyndns is niet meer gratis), dus mijn thuissysteem is nu van buitenaf te bereiken via <mijnnaam>.dynu.com. In het kort: meld je aan bij dynu, en zet na bevestiging je Raspberry op om regelmatig te checken en door te geven aan dynu of je IP-adres veranderd is, via ddclient. Je krijgt dan zelfs een mailtje als je IP-adres is veranderd! In het kort:

sudo apt-get install ddclient   # installeren
sudo /etc/init.d/ddclient stop  # stoppen vóór het configureren
sudo nano /etc/ddclient.conf    # edit config (user name/passwd), download defaults van dynu.com
sudo ddclient -daemon=0 -debug -verbose -noquiet  # debug: check of de zaak wel werkt
#sudo /etc/init.d/ddclient restart  # Alles OK? --> final start (op de oude manier)
sudo service ddclient start     # Alles OK? --> final start

Niet nodig

Er lopen ook vast services die niet nodig zijn. Zo kwam ik modem-manager tegen, die zorgt voor telefooncommunicatie via USB. Ik hang toch geen GSM modem aan mijn raspberry, dus die heb ik gestopt met de onderstaande regel (één regel). Alleen killall modem-manager werkt namelijk niet; wordt automatisch weer gestart door de network manager...

sudo mv /usr/share/dbus-1/system-services/org.freedesktop.ModemManager.service /usr/share/dbus-1/system-services/org.freedesktop.ModemManager.service.disabled