We gaan nu de beveiliging van uw server beter instellen....
IP Tables FireWall
Beveiliging van een (web)server is eigenlijk niets meer en niets minder dan het beperken van de toegang. We gaan deze beperkingen toepassen dmv ip tabellen. Maak de volgende file aan door:
sudo nano /etc/iptables.firewall.rules
Plak daar de volgende regels in: (LET OP!!! wijzig hier de regel: -A INPUT -p tcp -m tcp --dport {UW SSH POORT NUMMER} -j ACCEPT vervang hier de tekst {UW SSH POORT NUMMER} in het poort nummer wat u eerder in deze handleiding heeft gebruikt)
*filter
# --------------loopback
-A INPUT -i lo -j ACCEPT
-A INPUT -d 127.0.0.0/8 -j REJECT
# --------------Already was there
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# --------------allow DHCP
-A INPUT -p udp -m udp --sport 67 --dport 68 -j ACCEPT
# -------------- LOG iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
# -------------- SSH
-A INPUT -p tcp -m tcp --dport {UW SSH POORT NUMMER} -j ACCEPT
# -------------- WEB
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
# -------------- PING
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# -------------- Outgoing
-A OUTPUT -j ACCEPT
# -------------- Drop all other inbound - default deny unless explicitly
# allowed policy
-A INPUT -j DROP
-A FORWARD -j DROP
COMMIT
Activeer de nieuwe iptables met het volgende commando. Als het goed is krijgt u hier geen foutmelding.
sudo iptables-restore < /etc/iptables.firewall.rules
Omdat we willen dat deze iptables bij iedere start van de webserver automatisch geladen worden, is het nodig om hiervoor een script te gebruiken.
sudo nano /etc/network/if-pre-up.d/firewall
Plak daarin de volgende regels:
#!/bin/sh
/sbin/iptables-restore < /etc/iptables.firewall.rules
Hierna activeren we het script:
sudo chmod +x /etc/network/if-pre-up.d/firewall
Beperken van de systeem functies.
We gaan sommige php functies uitschakelen. Dit doen we uiteraard voor de veiligheid.
wijzig het eerder aangemaakte index.php bestand.
nano /var/www/{UW-DOMEIN.COM}/public-html/index.php
Vervang de complete inhoud van dit bestand door de volgende php code:
<?php
echo("<br /><br /><br />system<br />".system("ls -l")."<br /><br /><br />");
echo("exec<br />".exec("ls -l")."<br /><br /><br />");
echo("eval<br />".eval("exec(\"ls -l\");")."<br /><br /><br />");
echo("assert<br />".assert("exec(\"ls -l\");")."<br /><br /><br />");
echo("shell_exec<br />".shell_exec("ls -l")."<br /><br /><br />");
phpinfo();
?>
Als u nu via uw browser naar het LOKALE IP adres van uw raspi webserver gaat, krijgt u een overzicht van alle functies en rechten zoals die op dit moment staan ingesteld...
Om beperkingen toe te voegen gaan we het php.ini bestand wijzigen:
sudo nano /etc/php/7.0/fpm/php.ini
Vind in dit bestand de volgende regel: (zoeken binnen nano kan eenvoudig door op CTRL+W te drukken en daarna de zoekterm in te voeren)
;open_basedir =
Wijzig deze regel in: (let op dat u de ; aan het begin van de regel ook verwijderd!)
open_basedir="/var/www/:/tmp:/dev/urandom"
Vind nu de regel die begint met:
disable_functions=
En voeg direct na het = teken deze code toe ZONDER de code die al in die regel staat te verwijderen en/of te wijzigen!!
exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,allow_url_fopen,allow_url_include,stream_select,
Nu herstarten we de webserver:
sudo webrestart
Als alles goed is krijgt u nu geen foutmelding en zal de server netjes herstarten.
Dagelijkse anti-virus scan met ClamAV
We gaan onze server voorzien van een anti-virus scanner zodat de server ook tegen virussen beveiligd is.
sudo apt-get install clamav
Omdat we de virus-scanner op gezette tijdstippen willen laten scannen hebben we een script nodig. Dit script plaatsen we in een aparte map op de server. Maak deze map aan:
sudo mkdir -p /var/script/root/
Maak het script aan met:
sudo nano /var/script/root/scan_day.sh
En plaats daar de volgende regels in:
LOG=/var/log/clamav/scan.log
MYLOG=/var/script/antivirus_daily_scan_log/scan.log
FIND="$(which find)"
DATE="$(which date)"
GREP="$(which grep)"
TIMESTAMP=`$DATE '+%Y-%m-%d %H:%M'`
if [[ ! -e /tmp/virus ]]; then
mkdir /tmp/virus
fi
check_scan () {
if [ `tail -n 12 ${LOG} | $GREP Infected | $GREP -v 0 | wc -l` != 0 ]
then
echo "############################## $TIMESTAMP VIRUS DETECTED ##############################"
1>> $MYLOG
echo "`tail -n 50 ${LOG}`" 1>> $MYLOG
echo "########################################################################################"
1>> $MYLOG
else
echo "$TIMESTAMP update/scan" 1>> $MYLOG
fi
}
clamscan -r / --move=/tmp/virus --max-filesize=600M --max-scansize=600M --exclude-dir=/sys/ --quiet --infected --log=${LOG}
check_scan
Activeer het script met:
sudo chmod +x /var/script/root/scan_day.sh
De virus scanner zal een log file aanmaken. Hiervoor moeten we de map aanmaken waarin de logfile geschreven word. (LET OP!!! Vervang in de regels {UW-USER-NAAM} voor de usernaam die u gebruikt)
sudo mkdir /var/script/antivirus_daily_scan_log
sudo chown -R {UW-USER-NAAM}:{UW-USER-NAAM}/var/script/
Om de virus scanner op gezette tijden te laten scannen, maken we gebruik van een cronjob.
sudo crontab -e
Kies in het menu wat u krijgt voor optie 2 (nano).
Voeg onderaan deze file de volgende regel toe:
0 5 * * * /var/script/root/scan_day.sh
Dit houd in dat de virus-scan iedere dag om 05:00 uur zal starten.
Fail2Ban
Om de inlog procedure verder te beveiligen, installeren we Fail2Ban. Dit stukje software zorgt ervoor dat na een bepaald aantal mislukte inlog pogingen het betreffende ip adres word geblokkeerd. Ook worden pogingen om systeem functies te gebruiken beloond met een ban.
sudo apt-get install fail2ban
Kopieer de voorbeeld configuratie file met:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Open de configuratie file met:
sudo nano /etc/fail2ban/jail.local
Zoek in deze file naar: destemail= past dit email adres aan naar een email adres van u zelf.
Controleer of de volgende regels in het bestand staan en voeg zo nodig de ontbrekende regels toe. (verwijder geen regels uit dit bestand!)
[http-get-dos]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
filter = http-get-dos
maxretry = 100
action = iptables-multiport[name=http-get-dos, port="http,https", protocol=tcp]
findtime = 60
bantime = 7200
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 2
bantime = 7200
[nginx-noscript]
enabled = true
port = http,https
filter = nginx-noscript
logpath = /var/log/nginx/access.log
maxretry = 1
bantime = 7200
[nginx-badbots]
enabled = true
port = http,https
filter = nginx-badbots
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 7200
[nginx-nohome]
enabled = true
port = http,https
filter = nginx-nohome
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 7200
[nginx-noproxy]
enabled = true
port = http,https
filter = nginx-noproxy
logpath = /var/log/nginx/access.log
maxretry = 1
bantime = 7200
Nu moeten we voor iedere regel in bovenstaand script een definitie aanmaken.
sudo nano /etc/fail2ban/filter.d/http-get-dos.conf
[Definition]
failregex = ^<HOST> -.*(GET|POST|HEAD|REQUEST).*
ignoreregex =
sudo nano /etc/fail2ban/filter.d/nginx-badbots.conf
[Definition]
badbotscustom = EmailCollector|WebEMailExtrac|TrackBack/1\.02|sogou music spider
badbots = Atomic_Email_Hunter/4\.0|atSpider/1\.0|autoemailspider|bwh3_user_agent|China Local Browse 2\.6|ContactBot/0\.2|ContentSmartz|DataCha0s/2\.0|DBrowse 1\.4b|DBrowse 1\.4d|Demo Bot DOT 16b|Demo Bot Z 16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\.4b|Educate Search VxB|EmailSiphon|EmailSpider|EmailWolf 1\.00|ESurf15a 15|ExtractorPro|Franklin Locator 1\.8|FSurf15a 01|Full Web Bot 0416B|Full Web Bot 0516B|Full Web Bot 2816B|Guestbook Auto Submitter|Industry Program 1\.0\.x|ISC Systems iRc Search 2\.1|IUPUI Research Bot v 1\.9a|LARBIN-EXPERIMENTAL \(efp@gmx\.net\)|LetsCrawl\.com/1\.0 \+http\://letscrawl\.com/|Lincoln State Web Browser|LMQueueBot/0\.2|LWP\:\:Simple/5\.803|Mac Finder 1\.0\.xx|MFC Foundation Class Library 4\.0|Microsoft URL Control - 6\.00\.8xxx|Missauga Locate 1\.0\.0|Missigua Locator 1\.9|Missouri College Browse|Mizzu Labs 2\.2|Mo College 1\.9|MVAClient|Mozilla/2\.0 \(compatible; NEWT ActiveX; Win32\)|Mozilla/3\.0 \(compatible; Indy Library\)|Mozilla/3\.0 \(compatible; scan4mail \(advanced version\) http\://www\.peterspages\.net/?scan4mail\)|Mozilla/4\.0 \(compatible; Advanced Email Extractor v2\.xx\)|Mozilla/4\.0 \(compatible; Iplexx Spider/1\.0 http\://www\.iplexx\.at\)|Mozilla/4\.0 \(compatible; MSIE 5\.0; Windows NT; DigExt; DTS Agent|Mozilla/4\.0 efp@gmx\.net|Mozilla/5\.0 \(Version\: xxxx Type\:xx\)|NameOfAgent \(CMS Spider\)|NASA Search 1\.0|Nsauditor/1\.x|PBrowse 1\.4b|PEval 1\.4b|Poirot|Port Huron Labs|Production Bot 0116B|Production Bot 2016B|Production Bot DOT 3016B|Program Shareware 1\.0\.2|PSurf15a 11|PSurf15a 51|PSurf15a VA|psycheclone|RSurf15a 41|RSurf15a 51|RSurf15a 81|searchbot admin@google\.com|ShablastBot 1\.0|snap\.com beta crawler v0|Snapbot/1\.0|Snapbot/1\.0 \(Snap Shots, \+http\://www\.snap\.com\)|sogou develop spider|Sogou Orion spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sogou spider|Sogou web spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sohu agent|SSurf15a 11 |TSurf15a 11|Under the Rainbow 2\.2|User-Agent\: Mozilla/4\.0 \(compatible; MSIE 6\.0; Windows NT 5\.1\)|VadixBot|WebVulnCrawl\.unknown/1\.0 libwww-perl/5\.803|Wells Search II|WEP Search 00
failregex = ^<HOST> -.*(GET|POST|HEAD|REQUEST).*HTTP.*"(?:%(badbots)s|%(badbotscustom)s)"$
ignoreregex =
sudo nano /etc/fail2ban/filter.d/nginx-noscript.conf
[Definition]
failregex = ^<HOST> -.*(GET|POST|HEAD|REQUEST).*(\.py|\.asp|\.exe|\.pl|\.cgi|\.scgi|\.py|\.cmd|\.sh|\.bat|\.aspx)
ignoreregex =
sudo nano /etc/fail2ban/filter.d/nginx-nohome.conf
[Definition]
failregex = ^<HOST> -.*(GET|POST|HEAD|REQUEST).*/~.*
ignoreregex =
sudo nano /etc/fail2ban/filter.d/nginx-noproxy.conf
[Definition]
failregex = ^<HOST> -.*(GET|POST|HEAD|REQUEST) (http|https).*
ignoreregex =
Activeren van de zojuist aangemaakte definities:
sudo service fail2ban restart
Controleer de status van fail2ban
sudo fail2ban-client status
Krijgt u hier een foutmelding, start dan de client van fail2ban opnieuw op met:
sudo /usr/bin/fail2ban-client start
Als alles goed gegaan is heeft u nu de beveiliging dmv van fail2ban op orde. We gaan nu een SSL certificaat installeren zodat de webserver straks via https ivp http te benaderen is. Er zijn betaalbare SSL certificaten te koop maar in dit voorbeeld maken we gebruik van een gratis certificaat van Letsencrypt.
Om een certificaat aan te vragen gebruiken we git en tmux. Als u deze handleiding vanaf het begin gevoglt heeft, zijn beide programma's al geinstalleerd. Is dat niet het geval, zo installeer je beide pakketten.
sudo apt-get install tmux git
We gaan nu eerst een zogenaamd 2048 dhparam genereren. Dit kan even wat tijd in beslag nemen op de Raspberry, dus we gaan dat doen in een tmux sessie welke op de achtergrond blijft doordraaien zodat we ondertussen verder kunnen werken.
Creëer een tmux sessie
tmux new -s dhparam
Om het dhparam bestand op te slaan moeten we een map aanmaken. In dit voorbeeld maken we een map 'template' aan waar we alle configuratie templates in op kunnen slaan.
sudo mkdir -p /etc/nginx/template
Nu gaan we het dhparam bestand aanmaken.
sudo openssl dhparam -out /etc/nginx/template/dh2048.pem 2048
Dit gaat wel even duren.Even een korte handleiding voor het gebruik van tmux.
Toon alle actieve sessies:
tmux ls
Ga naar een actieve sessie:
tmux a -t [SESSIE_NAAM]
Om terug te gaan naar de tmux dhparam sessie:
tmux a -t dhparam
Als het aanmaken van het dhparam bestand is gelukt, sluit u de sessie met:
exit
Nu het dhparam bestand aangemaakt word kunnen we putty afsluiten. Het aanmaken van het bestand loopt nu gewoon door. Open een nieuw terminal venster met Putty en maak verbinding met de Raspberry.
In dit nieuwe venster gaan de een template aanmaken, let's encrypt challenge. Middels deze template kan Letsencrypt vaststellen dat u daadwerkelijk de eigenaar bent van de server waarvoor u een SSL certificaat aanvraagt.
sudo nano /etc/nginx/template/letsencrypt.conf
Pak/type in deze nieuwe file de volgende regels:
location /.well-known/acme-challenge/ {
default_type "text/plain";
allow all;
}
Nu maken we een template aan voor de SSL configuratie:
sudo nano /etc/nginx/template/SSL.conf
Plak daar de volgende regels in: (LET OP!! Wijzig in deze regels [UW-DOMEIN-NAAM.NL] in uw eigen domeinnaam)
ssl on;
# ssl certificates
ssl_certificate /etc/letsencrypt/live/[UW-DOMEIN-NAAM.NL]/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/[UW-DOMEIN-NAAM.NL]/privkey.pem;
# Optimisation
ssl_stapling on;
ssl_stapling_verify on;
# FastCgi
fastcgi_param HTTPS on;
fastcgi_param HTTP_SCHEME https;
# enable session resumption to improve https performance
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/nginx/template/dh2048.pem;
# enables server-side protection from BEAST attacks
ssl_prefer_server_ciphers on;
# disable SSLv3(enabled by default since Nginx 0.8.19) since it's less secure than TLS
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ciphers chosen for forward secrecy and compatibility
ssl_ciphers "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS";
# enable ocsp stapling (mechanism by which a site can convey certificate revocation information to visitors in a privacy-preserving, scalable manner)
resolver 8.8.8.8 valid=360s ipv6=off; # Google DNS
resolver_timeout 15s;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload";
Om door te gaan moet git geinstalleerd zijn. Als u deze handleiding vanaf het begin gevolgd heeft, dan is git al aanwezig. Zo niet, installeer git dan zo:
sudo apt-get install git
Nu gaan we de Let's Encrypt certbot utility klonen.
sudo git clone https://github.com/certbot/certbot /etc/letsencrypt
Pas nu het Nginx website configuratie bestand aan. (LET OP!!! Wijzig in deze regel [UW-DOMEINNAAM.NL] in de door u gebruikte domeinnaam)
sudo nano /etc/nginx/sites-available/[UW-DOMEINNAAM.NL]
Plak deze regel in het zojuist geopende bestand binnen de server tags:
include /etc/nginx/template/letsencrypt.conf;
Zo ziet het er dan ongeveer uit:
server {
[...]
include /etc/nginx/template/letsencrypt.conf;
[...]
}
Sluit het bestand en sla het op.
Herstart de webserver zodat de wijziging geactiveerd word met:
sudo /etc/init.d/nginx restart
Nu kunnen we het daadwerkelijke certificaat gaan aanvragen bij Let's Encrypt.
Pas het volgende commando aan met uw eigen gegevens!!! Let vooral op de laatste vermelding in de regel dat de WWW voor uw domein-naam niet ontbreekt!
sudo /etc/letsencrypt/certbot-auto certonly --webroot --agree-tos --email [UW-EMAIL.NL] -w /web/www/[UW-WEBSITE.NL]/public-html -d [UW-WEBSITE.NL] -d [WWW.UW-WEBSITE.NL]
Als de configuratie juist is ingesteld, dan is het SSL certificaat geldig voor 90 dagen.Het certificaat moet dus regelmatig verlengd worden. Let's Encrypt staat toe dat de verlenging al na 60 dagen kan plaatsvinden. Dit proces gaan we automatiseren zodat de verlenging van het certificaat gewoon doorloopt en u er geen omkijken naar heeft. We maken hierbij gebruik van crontab.
We gebruiken de crontab van root:
sudo crontab -e
Voeg aan het eind van dit bestand de volgende regel toe, en sla op met CTRL+X en Y
0 6 * * * /etc/letsencrypt/certbot-auto renew --text >> /etc/letsencrypt/certbot/certbot-cron.log > /dev/null 2>&1 && sudo service nginx reload
Om te testen of alles goed werkt kunt u een zogenaamde dryrun uitvoeren. Hierbij word de verlenging van het certificaat gesimuleerd.
sudo /etc/letsencrypt/certbot-auto renew --dry-run
Nu het certificaat is aangevraagd, gaan we het toevoegen aan de website zodat het daadwerkelijk gebruikt kan worden. Hiervoor moeten we het website configuratie bestand van Nginx wat aanpassen.
LET OP!! Pas in deze regel [UW-WEBSITE] aan in de door u gebruikte domeinnaam (uiteraard zonder de haakjes te gebruiken!)
sudo nano /etc/nginx/sites-available/[UW-WEBSITE.NL]
Zorg ervoor dat de configuratie er ongeveer zo uitziet: LET OP!!! Pas in het onderstaande configuratie bestand de domein naam aan!!!
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name UW-WEBSITE.NL WWW.UW-WEBSITE.NL;
include /etc/nginx/template/letsencrypt.conf;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name UW-WEBSITE.NL WWW.UW-WEBSITE.NL;
index index.php index.html index.htm;
root /var/www/[UW-WEBSITE.NL]/public-html;
charset utf-8;
server_tokens off;
sendfile off;
fastcgi_intercept_errors on;
error_log /var/www/[UW-WEBSITE.NL]/logs/error.log error;
access_log /var/www/[UW-WEBSITE.NL]/logs/access.log;
include /etc/nginx/template/SSL.conf;
include /etc/nginx/template/letsencrypt.conf;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param HTTPS on;
}
}
Nu starten we Nginx opnieuw op om de configuratie te activeren:
sudo /etc/init.d/nginx restart
Nu kunt u testen of alles goed werkt door in uw browser naar uw website te gaan. Als alles goed staat, word u doorgestuurd van http naar https en ziet u een groen slotje in uw browser.
Dit werk valt onder een Creative Commons Naamsvermelding-NietCommercieel 4.0 Internationaal-licentie.