Bloker for angrebsforsøg med fail2ban

Når du har haft din første server på nettet i et par uger vil du uden tvivl opdage at alt muligt rakkerpak på nettet står og banker på døren konstant … det kan være alt fra rigtigt hackere til scriptkiddies og automatiserede bots, orme og vira … alt i alt en masse ting som vi rigtig gerne vil undgå at blive forstyrret af 🙂

Vi starter som altid med at installere software:

root@lab1:~# apt-get install fail2ban

Dernæst skynder jeg mig og white-liste min egen ip … særligt når jeg eksperimenterer med opsætningen, jeg redigerer /etc/fail2ban/jail.conf og i linie ca 15-20 ser du flg:

[DEFAULT]

# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1 
bantime  = 600

Der tilføjer jeg min egen IP:

[DEFAULT]

# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1 192.168.1.5
bantime  = 600

Derefter genstarter jeg fail2ban og starter en tail på logfilen:

root@lab1:~# tail -f /var/log/fail2ban.log 
2012-05-10 20:52:39,750 fail2ban.jail   : INFO   Jail 'ssh' stopped
2012-05-10 20:52:39,750 fail2ban.server : INFO   Exiting Fail2ban
2012-05-10 20:52:40,003 fail2ban.server : INFO   Changed logging target to /var/log/fail2ban.log for Fail2ban v0.8.4-SVN
2012-05-10 20:52:40,004 fail2ban.jail   : INFO   Creating new jail 'ssh'
2012-05-10 20:52:40,004 fail2ban.jail   : INFO   Jail 'ssh' uses poller
2012-05-10 20:52:40,016 fail2ban.filter : INFO   Added logfile = /var/log/auth.log
2012-05-10 20:52:40,017 fail2ban.filter : INFO   Set maxRetry = 6
2012-05-10 20:52:40,018 fail2ban.filter : INFO   Set findtime = 600
2012-05-10 20:52:40,018 fail2ban.actions: INFO   Set banTime = 600
2012-05-10 20:52:40,083 fail2ban.jail   : INFO   Jail 'ssh' started

Som du måske har regnet ud så handler fail2ban ligeså meget generelt om serveren som om selve Apache, og lige her i første omgang er den sat op til at tage sig af ssh-syndere … det er jo dejlig nemt at teste … jeg finder en offentlig maskine, som ikke er den jeg lige har whitelistet, og laver et ulovligt loginforsøg:

lab2:~# ssh lab1.mikjaer.com -l root
root@lab1.mikjaer.com's password: 
Permission denied, please try again.
root@lab1.mikjaer.com's password: 
Permission denied, please try again.
root@lab1.mikjaer.com's password: 
Permission denied (publickey,password).

og så modtager vi flg. på vores log:

2012-05-10 20:54:44,257 fail2ban.actions: WARNING [ssh] Ban 192.168.1.10

og mit næste forsøg resulterer i flg:

lab1:~# ssh lab1.mikjaer.com -l root
ssh: connect to host lab1.mikjaer.com port 22: Connection timed out

Kort og kontant … effektivt! Efter 600 sekunder (ban time) kommer den her automatisk:

2012-05-10 20:58:34,529 fail2ban.actions: WARNING [ssh] Unban 192.168.1.10

Lad os aktivere et af filtrene til apache, på linie ca. 152:

[apache]

enabled = false
port    = http,https
filter  = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 6

Det er meget svært og gætte hvad der skal ændres ikke? Korrekt!, enables = true:

[apache]

enabled = true
port    = http,https
filter  = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 6

Så genstarter jeg fail2ban … og forsøger at gætte mit htaccess password, og efter 6 forsøg bliver jeg blacklistet 😀

Det er nemt selv at skrive regler, og der er en masse forudefinerede relger 🙂 Så se og kom igang og vær proaktiv med sikkerheden.

Udgivet i Apache, Knowledge Base, Linux, Networking, Old Base | Skriv en kommentar

Mere om loganalysering, GoAccess og Visitors

Loganalyseringsværktøjer er langt hen af vejen en smagssag, derfor har jeg besluttet mig for at bruge en dag mere på at give dig kendskab til et par stykker mere af slagsen, jeg håber ikke indlægget bliver for langt af den årsag, men selvom det ser voldsomt ud så skyldes det nok at screenshots fylder godt til 🙂

GoAccess er et console basseret interaktivt loganalyseringsværktøj, det er rigtigt rart hvis man f.eks. står i serverrummet udelukkende med console adgang til serveren , eller generelt hvis du bare godt kan lide at console værktøjer:

root@specialhosting:~# apt-get install goaccess

Værktøjet er rimelig selvforklarende så du får et par screenshots:

Ser det ikke lækkert ud ? ? Det syntes jeg, installer det og hyg jer med det ?

Til de lidt mere grafisk anlagte har vi “visitors”, det levere ud-data i form a pæn HTML du kan se i din browser:

root@specialhosting:~# apt-get install visitors
root@specialhosting:~# visitors /var/log/apache2/access.log > /var/www/test.html
--
2599 lines processed in 1 seconds
0 invalid lines, 0 blacklisted referers

og tag så et kig på http://www.specialhosting.dk/test.html (du skal selv-sagt bruge din egen servers adresse)

Det er pretty både på consol og på web … så hvad du foretrækker må være en smagssag, happy hunting ?

Udgivet i Apache, Knowledge Base, Linux, Old Base | Skriv en kommentar

Flere Apache log værktøjer

Der er mange, rigtig mange, og det vil blive for uoverskueligt at skulle lave et indlæg om hver, så derfor kommer her et par stykker som jeg bare løber hurtigt igennem.visitors /var/log/apache2/access.log > /var/www/dump.html

————–

http://goaccess.prosoftcorp.com/

———————

root@specialhosting:~# apt-get install analog

edit # vi /etc/analog.cfg

udkommenter stierne til apache config filerne, så kun /var/log/apache2/access.log er synlig, fjern udkommeringen fra OUTFILE og HOSTNAME, og kør så “analog” i den mappe du ønsker resultet skal lagres i.

Udgivet i Apache, Knowledge Base, Linux, Networking, Old Base | Skriv en kommentar

ScanErrLog, få overblik over Apache’s error-log

ScanErrLog er et lækkert lille tool der laver en let læsselig oversigt over fejl i din Apache’s error-log, og i det her indlæg vil vi efterfølgende sætte op så den bliver mailet til dig ugentligt. Det er en ret nem måde at holde øje med, og tage action på, eventuelle fejl der måtte opstå på dit website.

Først skal vi lige sikre os at din server kan sende mails:

# apt-get install postfix

1. Vælg “Internet Site”, vælg et hostname til maskinen som _ikke_ er det samme som det din e-mail ligger på … dvs hvis du har admin@eksempel.dk må du ikke væge “eksempel.dk” da mail til dig så vil blive leveret lokalt på webserveren, vælg istedet f.eks. “www.eksempel.dk”

Herefter tester vi mailudsendelse:

# echo Dette er en test | mail mikkel@eksempel.dk

Hvis du modtager en mail virker det … hvis ikke har du ikke taget udgangspunkt i en Vanilla Debian 6.0 🙂

Derudover skal ScanErrLog installeres … den ligger i Debians repositories så det er nemt:

# apt-get install scanerrlog

Lidt mere tricky er udfordringen når vi skal sætte et lille script sammen der tager output fra scanerrlog og hælder det i en e-mail, men alligevel ikke mere end at jeg har forberedt mig hjemmefra, her er det:

#!/bin/bash

MAILTO=modtager@eksempel.dk
MAILFROM=apache@afsender.dk

( cat <<HERE; ) | sendmail -oi -t
From: ${MAILFROM}
To: ${MAILTO}
Content-type: text/html
Subject: Weekly Apache Error log overview
`scanerrlog /var/log/apache2/error.log`
HERE

Åbentlyst er det vel at linie 3 og 4 skal tilrettes, ligesom at filen skal gemmes som f.eks. mailerr.sh, have execute rettigheder og udføres:

root@specialhosting:~# chmod 777 mailerr.sh
root@specialhosting:~# ./mailerr.sh

Hvorefter jeg modtager en mail med en fin rapport 🙂

Udgivet i Apache, Knowledge Base, Linux, Old Base | Skriv en kommentar

Petit Log analysis, få overblik over Apache’s access logs

Der kan være flere årsager til at ville kigge Apache i loggen, fælles for de fleste af dem er at man leder efter en lille bid information i en kæmpe fil, derfor har jeg samlet et par værktøjer her som kan hjælpe dig lidt på vej. Idag kigger vi på det som hedder petit.

Hvis du leder og du ikke rigtig ved hvad du leder efter kan du lede længe, derfor giver det mening at “hashe” en logfil, når du hasher en logfil sorterer du evt. støj fra og gruppere de enkelte forespørgsler, men først lad os få hentet værktøjet:

root@lab1:~# apt-get install petit

Derefter kører vi en petit’s hashing algoritme på apache’s logfil:

root@lab1:~# petit --hash /var/log/apache2/access.log

Lige for at illustrere kørte jeg flg. sammeligning:

root@lab1:~# petit --hash /var/log/apache2/access.log | wc -l
4512
root@lab2:~# cat /var/log/apache2/access.log | wc -l
31260

Som du kan se havde vi oprindeligt 31.000 linier og det er nu kortet ned til godt 5000 linier, jeg har redigeret lidt i outputtet:

8524:   /wp-admin/admin-ajax.php
5753:   *
1734:   /wp-includes/js/tinymce/plugins/wordpress/img/trans.gif
1:      /..%2F..%2F..%2F..%2F..%2F../winnt/repair/sam
1:      ////////../../../../../../etc/passwd
1:      /<script>alert('Vulnerable')</script>

Hver linie indeholder et tal, der modsvarer antallet af forespørgsler samt forespørgslen og dermed er det f.eks. relativt nemt at sortere alle med med færre end f.eks. 20 forespørgsler, og undersøge dem nærmere. Ovenstående er et testsite og derfor har jeg valgt at fokusere på de 3 linier med 1 gentagelse, det er tydeligt at en person der sender javascript, “/etc/passwd” og “/winnt/repair” efter vores server ikke har ret ment i posen.

Nu ville jeg typisk bruge min ny-erhvervede viden til at grave lidt dybere, nu er “passwd”, “alert” og “winnt” generelt gode søgefraser du vil identificere indbrudsforsøg, flg. kommando:

root@lab1:~# cat /var/log/apache2/access.log | egrep "sam|passwd|alert"

Giver mig en alenlang liste:

xx.xx.xx.10 - - [23/May/2012:23:40:36 +0200] "GET /iissamples/exair/howitworks/Code.asp HTTP/1.0" 404 11660 "-" "Mozilla/4.75 (Nikto/2.1.1) (Evasions:None) (Test:003352)"
xx.xx.xx.10 - - [23/May/2012:23:40:36 +0200] "GET /iissamples/exair/howitworks/Codebrw1.asp HTTP/1.0" 404 11660 "-" "Mozilla/4.75 (Nikto/2.1.1) (Evasions:None) (Test:003353)"
xx.xx.xx.10 - - [23/May/2012:23:40:36 +0200] "GET /pls/dadname/htp.print?cbuf=<script>alert('Vulnerable')</script> HTTP/1.0" 404 11660 "-" "Mozilla/4.75 (Nikto/2.1.1) (Evasions:None) (Test:003355)"
xx.xx.xx.10 - - [23/May/2012:23:40:37 +0200] "GET /pls/help/<script>alert('Vulnerable')</script> HTTP/1.0" 404 11660 "-" "Mozilla/4.75 (Nikto/2.1.1) (Evasions:None) (Test:003356)"
xx.xx.xx.10 - - [23/May/2012:23:40:37 +0200] "GET /pls/sample/admin_/help/..%255cplsql.conf HTTP/1.0" 404 11660 "-" "Mozilla/4.75 (Nikto/2.1.1) (Evasions:None) (Test:003359)"
xx.xx.xx.10 - - [23/May/2012:23:40:38 +0200] "GET /..%252f..%252f..%252f..%252f..%252f../windows/repair/sam HTTP/1.0" 404 11660 "-" "Mozilla/4.75 (Nikto/2.1.1) (Evasions:None) (Test:003361)"
xx.xx.xx.10 - - [23/May/2012:23:40:39 +0200] "GET /..%252f..%252f..%252f..%252f..%252f../winnt/repair/sam HTTP/1.0" 404 11660 "-" "Mozilla/4.75 (Nikto/2.1.1) (Evasions:None) (Test:003362)"
xx.xx.xx.10 - - [23/May/2012:23:40:39 +0200] "GET /..%252f..%252f..%252f..%252f..%252f../winnt/repair/sam._ HTTP/1.0" 404 11660 "-" "Mozilla/4.75 (Nikto/2.1.1) (Evasions:None) (Test:003363)"
xx.xx.xx.10 - - [23/May/2012:23:40:40 +0200] "GET /..%255c..%255c..%255c..%255c..%255c../windows/repair/sam HTTP/1.0" 404 11660 "-" "Mozilla/4.75 (Nikto/2.1.1) (Evasions:None) (Test:003364)"

Det er klart nu at der er tale om den Nikto scanning jeg selv udførte igår, men det er bestemt heller ikke noget jeg bryder mig om udført på min server, og jeg kunne nu f.eks. vælge at blokere synderens ip adresse.

Udgivet i Apache, Knowledge Base, Linux, Old Base | Skriv en kommentar

Sikkerhedsscanning med Nikto

Når alting kører og virker som det skal så er det på tide at ødelægget det hele igen, navnligt skal sikkerheden gennemgås, og der findes rigtig mange værktøjer der kan hjælpe dig på vej. Et af de rigtig gode er Nikto som er en Web Sårbarhedsscanner, her vil jeg gennemgå hvordan du selv kommer igang med Nikto.

Start med at tilføje non-free til dine repositories i /etc/apt/sources.list

deb http://mirrors.rackhosting.com/debian/ squeeze main non-free
deb-src http://mirrors.rackhosting.com/debian/ squeeze main non-free

og kør en:

# apt-get update

efterfulgt af:

apt-get install nikto

og så er vi faktisk klar til at køre en scanning:

# nikto -h xxxxxxx.com
- Nikto v2.1.1
---------------------------------------------------------------------------
+ Target IP:          10.10.10.10
+ Target Hostname:    xxxxxxx.com
+ Target Port:        80
+ Start Time:         2012-05-24 23:18:57
---------------------------------------------------------------------------
+ Server: Apache/2.2.16 (Debian)
+ robots.txt contains 2 entries which should be manually viewed.
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ DEBUG HTTP verb may show server debugging information. See http://msdn.microsoft.com/en-us/library/e8z01xdh%28VS.80%29.aspx for details.
+ Retrieved X-Powered-By header: PHP/5.3.3-7+squeeze9
+ Uncommon header 'x-pingback' found, with contents: http://xxxxxxx.com/xmlrpc.php
+ OSVDB-12184: /index.php?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000: PHP reveals potentially sensitive information via certain HTTP requests which contain specific QUERY strings.
+ OSVDB-12184: /some.php?=PHPE9568F36-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests which contain specific QUERY strings.
+ OSVDB-12184: /some.php?=PHPE9568F34-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests which contain specific QUERY strings.
+ OSVDB-12184: /some.php?=PHPE9568F35-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests which contain specific QUERY strings.
+ OSVDB-561: /server-status: This reveals Apache information. Comment out appropriate line in httpd.conf or restrict access to allowed hosts.
+ OSVDB-3092: /old/: This might be interesting...
+ OSVDB-3092: /readme: This might be interesting...
+ OSVDB-3268: /icons/: Directory indexing is enabled: /icons
+ OSVDB-3299: /forumscalendar.php?calbirthdays=1&action=getday&day=2001-8-15&comma=%22;echo%20'';%20echo%20%60id%20%60;die();echo%22: Vbulletin allows remote command execution. See http://www.securiteam.com/securitynews/5IP0B203PI.html
+ OSVDB-3299: /forumzcalendar.php?calbirthdays=1&action=getday&day=2001-8-15&comma=%22;echo%20'';%20echo%20%60id%20%60;die();echo%22: Vbulletin allows remote command execution. See http://www.securiteam.com/securitynews/5IP0B203PI.html
+ OSVDB-3299: /htforumcalendar.php?calbirthdays=1&action=getday&day=2001-8-15&comma=%22;echo%20'';%20echo%20%60id%20%60;die();echo%22: Vbulletin allows remote command execution. See http://www.securiteam.com/securitynews/5IP0B203PI.html
+ OSVDB-3299: /vbcalendar.php?calbirthdays=1&action=getday&day=2001-8-15&comma=%22;echo%20'';%20echo%20%60id%20%60;die();echo%22: Vbulletin allows remote command execution. See http://www.securiteam.com/securitynews/5IP0B203PI.html
+ OSVDB-3299: /vbulletincalendar.php?calbirthdays=1&action=getday&day=2001-8-15&comma=%22;echo%20'';%20echo%20%60id%20%60;die();echo%22: Vbulletin allows remote command execution. See http://www.securiteam.com/securitynews/5IP0B203PI.html
+ OSVDB-724: /ans.pl?p=../../../../../usr/bin/id|&blah: Avenger's News System allows commands to be issued remotely.  http://ans.gq.nu/ default admin string 'admin:aaLR8vE.jjhss:root@127.0.0.1', password file location 'ans_data/ans.passwd'
+ OSVDB-724: /ans/ans.pl?p=../../../../../usr/bin/id|&blah: Avenger's News System allows commands to be issued remotely.
+ OSVDB-3092: /xmlrpc.php: xmlrpc.php was found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ /wp-content/plugins/akismet/readme.txt: The WordPress Akismet plugin 'Tested up to' version usually matches the WordPress version
+ /readme.html: This WordPress file reveals the installed version.
+ 3818 items checked: 23 item(s) reported on remote host
+ End Time:           2012-05-24 23:42:58 (1441 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Og nu har du så en tjekliste du kan gå igennem, skridt for skridt og sikre din side. Det er vigtigt at huske at ikke alle alarmerne er rigtige og at ikke alle fejl findes, men det her er en rigtig god start. Men lad os gå igennem et par stykker.

Hvis du ser på linie 15 til 32 ser du at de alle starter med OSVDB efterfulgt af en række tal, Osvdb står for “Open Source Vulnerability Database” og er en database med kendte sårbarheder, det betyder at vi kan slå dem op og ofte få mere information. Det gøres ved at konstruere flg. url : http://osvdb.org/show/osvdb/3092 du kan selvfølgelig også søge på siden, men når man kommer ind i rutinen er det langt nemmest at gå direkte ind på adresserne.

Andre steder som f.eks. i linie 12 er der direkte en URL, lige i det her tilfælde er det en false positive, fordi serveren åbenlyst ikke kører ASP.Net og derfor kan vi se bort fra den. Mange af linierne i denne her scanning vil uden tvivl vise sig at være false-positives når man går i dybden, men jeg kan allerede se et par stykker som vi skal have gjort noget ved.

Håber du kan bruge det til noget 🙂

Udgivet i Apache, Knowledge Base, Linux, Old Base | Skriv en kommentar

Hold dit CDN i sync med GlusterFS

GlusterFS er et netværks filsystem, der blandt andet tillader os at holde mapper i sync på tværs af netværket, der er meget mere i Gluster end det … nok til at jeg kunne lave en hel måned kun med det … men vi holder os til emnet lidt endnu 🙂

Vi tager udgangpunkt i det CDN vi lavede igår, og lægger GlusterFS ovenpå det. Det giver muligvis ikke særlig meget mening når vi kun har 2 noder, men når vi kommer meget over 2 begynder det at være svært at holde styr på at de er i sync, og der er virkelig ingen forskel på at sætte GlusterFS op til to eller til tyve noder.

Gluster findes godtnok i Debian’s pakkesystem, mén det er for at sige det mildt en gammel og ikke særlig brugbar version derfor bruger vi den .deb pakke som Gluster selv stiller til rådighed, flg. udføres på begge noder (lab1 og lab2)

root@lab1:~# wget http://download.gluster.org/pub/gluster/glusterfs/3.1/3.1.7/Debian/glusterfs_3.1.7-1_amd64.deb
root@lab1:~# apt-get install nfs-common libibverbs-dev fuse-utils
root@lab1:~# dpkg -i glusterfs_3.1.7-1_amd64.deb
root@lab1:~# update-rc.d glusterd defaults
root@lab1:~# update-rc.d fuse defaults
root@lab1:~# /etc/init.d/glusterd start
root@lab1:~# echo fuse >> /etc/modules

Og det var faktisk det der skulle til for at installere Gluster, nu skal vi have sat en storage pool op, en storage pool er en fællesbetegnelse for en række sammenknyttede Gluster nodes med tilhørende diskplads.

Først opretter vi /data på begge maskiner:

root@lab1:~# mkdir /data
root@lab2:~# mkdir /data

Dernæst beder vi de to maskiner forbinde til hinanden og dermed danner vi vores storage pool:

root@lab1:~# gluster peer probe lab2.mikjaer.com
Probe successful

og for at verificerer kører vi:

root@lab2:~# gluster peer status
Number of Peers: 1

Hostname: 109.202.159.61
Uuid: b11650fa-1a38-41ff-8f11-e681e93db4aa
State: Peer in Cluster (Connected)

og får bekræftiget at maskinerne har fat i hinanden, så langt så godt 🙂

Nu skal vi have oprettet en gluster-volume og have den startet, og det er ligeså nemt som det hidtil har været:

root@lab1:~# gluster volume create cdn-data lab1.mikjaer.com:/data lab2.mikjaer.com:/data
Creation of volume cdn-data has been successful. Please start the volume to access data.
root@lab1:~# gluster volume start cdn-data
Starting volume cdn-data has been successful

Jeg har valgt at kalde min volume for “cdn-data” og lade den benytte diskplads på hhv. lab1 og lab2 fra mappen /data, og så runder vi af med at starte den … hvilket vil sige at Gluster gør den tilgængelig til f.eks. at blive mounted, hvilket sjovt nok er næste skridt. Men lad os lige starte med at gemme vores gamle /var/www, just in case:

root@lab1:~# mv /var/www/ /var/www-old
root@lab1:~# mkdir /var/www

og nu vil jeg mounte vores Gluster volume på den /var/www, det gøres således:

root@lab1:~# modprobe fuse
root@lab1:~# mount -t glusterfs 127.0.0.1:/cdn-data /var/www

og på lab2:

root@lab2:~# modprobe fuse
root@lab2:~# mount -t glusterfs 127.0.0.1:/cdn-data /var/www

og så flytter vi indholdet af lab1:/var/www-old til lab1:/var/www … som jo så nu burde være en mounted GlusterFS volume og dermed øjeblikkeligt være tilgængelig på den anden node også, nemlig lab2:/var/www, lad os se:

root@lab1:~# cp /var/www-old/test.iso /var/www
root@lab2:~# ls /var/www/
test.iso
root@lab1:~# md5sum /var/www/test.iso
b663727d7f5b572c329cea8e2ff5e29c  /var/www/test.iso
root@lab2:~# md5sum /var/www/test.iso
b663727d7f5b572c329cea8e2ff5e29c  /var/www/test.iso

Og mindsanten om ikke det virker 🙂

Nu mangler vi bare lige at sikre opsætningen ved boot, og på grund af en mindre fejl i Debian pakkerne skal det gøres ved at tilføle linien “mount -a” i /etc/rc.local:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
mount -a
exit 0

Derudover skal dit nye share selvfølgelig tilføjes til /etc/fstab, den linie du skal tilføjes ser sådan her ud:

127.0.0.1:/cdn-data  /var/www    glusterfs       defaults        0       0

Reboot begge maskiner og se det hele komme op af sig selv … du har nu et CDN der selv syncer web-root 🙂

Udgivet i Apache, Knowledge Base, Linux, Networking, Old Base | Skriv en kommentar

Lav dit eget CDN (Content Delivery Network)

Hvis du har mange statiske filer som folk tit downloader kan det give mening at opbygge en speciel konstruktion til formålet kaldet et Content Delivery Network, som i princippet blot er en række servere optimeret til at levere ligepræcis det indhold du ønsker, rasende hurtigt, fra forskellige lokationer.

Vi vil selvfølgelig lave det med Apache, og her i dette indlæg vil jeg starte med et simpelt setup som jeg i efterfølgende indlæg vil bygge videre på. Jeg ønsker at bruge mine lab maskiner som base for CDN’et:

lab1.mikjaer.com : 109.202.159.61
lab2.mikjaer.com : 109.202.159.62

Begge maskiner er installeret med Debian og Apache, hverken MySQL eller PHP skal bruges her, vi skal nemlig udelukkende hoste statisk indhold. I det her tilfælde har jeg valgt at hoste et par store .iso filer for at have noget at teste med.

Selve “tricket” ligger i DNS Opsætningen, vi benytter noget som kaldes en RRD( Round Robin DNS) Opsætning, som i princippet blot handler om at oprette flere A-Records for den samme adresse, så vil navneserverne selv sørge for at blande dem og sende dem ud i forskellig rækkefølge. Det betyder at forskellige brugere vil tilgå forskellige adresser. Fordelingen vil være, givet et stort nok grundlag, nogenlunde ligeligt fordelt mellem adresserne.

Den eksakte opsætning af dine A Records afhænger af din DNS Udbyder, så det vil jeg ikke gennemgå, men resultatet skulle gerne ende med at se således ud:

root@lab1:~# host -t a cdn.mikjaer.com
cdn.mikjaer.com has address 109.202.159.62
cdn.mikjaer.com has address 109.202.159.61

Som du kan se får du nu en liste over alle ip adresserne istedet for blot én som normalt, i teorien kan du oprette så mange du vil. I realiteten skal du holde dig omkring max 10. da du ellers kan få problemer med blandt andet caching og pakke-fragmentering.

For at demonstrere princippet med den tilfældige rækkefølge har jeg kørt den to gange direkte mod navneserveren (min lokale navneserver cache’r resultatet og derfor vil du ikke se rækkefølgen ændre sig så længe vi bruger den)

root@lab1:~# host -t a cdn.mikjaer.com ns1.mikjaer.com | grep has\ address
cdn.mikjaer.com has address 109.202.159.61
cdn.mikjaer.com has address 109.202.159.62
root@lab1:~# host -t a cdn.mikjaer.com ns1.mikjaer.com | grep has\ address
cdn.mikjaer.com has address 109.202.159.62
cdn.mikjaer.com has address 109.202.159.61

Dertil skal det nævnes at flere nyere browsere genkender RRD og i tilfælde af udfald automatisk vil spørge en af de andre servere.

Nu er der faktisk ikke så meget andet at gøre end at lægge data på dit nye CDN, lad os uploade en ISO:

mike$ scp debian-6.0.3-amd64-netinst.iso root@lab1.mikjaer.com:/var/www/test.iso
root@lab1.mikjaer.com's password:
debian-6.0.3-amd64-netinst.iso                        100%  168MB   1.1MB/s   02:35
mike$ scp debian-6.0.3-amd64-netinst.iso root@lab2.mikjaer.com:/var/www/test.iso
root@lab2.mikjaer.com's password:
debian-6.0.3-amd64-netinst.iso                        100%  168MB   1.1MB/s   02:37

For at teste lidt på det har jeg åbnet 2 vinduer der kører en Apache Status:

root@lab1:~# watch -n 1 apachectl status

og for at generere lidt trafik til mit screenshot kører jeg flg. kommando på 2 andre maskiner:

root@lab3:~# watch wget --delete-after http://lab1.mikjaer.com/test.iso

Resultatet ser således ud:

Hvert “W” repræsenterer en process der bliver serviceret, og den ene af dem vil altid være Apachestatus selv, og dermed er der altså to processer igang, i og med at det er en lukket test kan jeg roligt antage at begge processer er mine egne. Evt. kan jeg stoppe dem og se at de forsvinder hvis jeg vil være helt sikker.

Nu åbner jeg apachestatus på begge servere og kører den her fra én server:

root@lab3:~# watch wget --delete-after http://cdn.mikjaer.com/test.iso

og kan nu se hvordan download processen på Apachestatus hopper fra den ene til den anden skærm, hvilket jo viser at RRD virker, som en sidste finale vil jeg skrive et hurtigt script der illustrere det endnu bedre:

test.sh:

#!/bin/bash
for (( c = 1; c<=100; c++))
do
        wget --delete-after http://cdn.mikjaer.com/test.iso &
done

Sæt execute permissions og kør scriptet:

root@lab3:~# chmod 755 test.sh
root@lab3:~# ./test.sh

På begge, eller flere, klient maskiner, og så på dine Apachetop vinduer hvordan processerne fordeler sig jævnt ud på dit CDN:

Og du kan se, i løbet af ingenting har vi opbrugt de 12MB/s som et 100mbit netkort kan levere, og belastningen bliver fint fordelt på de to noder i vores CDN.

Hvis det ikke virker for dig skyldes det typisk at du bruger en lokal DNS som cacher resultaterne, det gør Google’s DNS’er f.eks. Det vil ikke udgøre et reelt problem fordi at dine besøgende typisk vil være geografisk spredt ud over landet/verden og dermed også flere forskellige DNS Caches. Dertil skal lægges at nyere browsere (dvs. ikke wget) selv tager højde for RRD og håndterer det korrekt.

Hvis det her virkelig skal batte noget skal du selvfølgelig ikke bruge virtuelle servere som jeg har gjort, du skal bruge fysiske servere der sider på hver deres forbindelser – eller ihvertfald på en så stor forbindelse at du ikke ender med en flaskehals der ?

ps. Hvis du får brug for at stoppe test.php scriptet igen, så log ind på maskinen med en anden terminal og skriv:

root@lab1:~# killall -9 test.sh
root@lab1:~# killall wget

 

Udgivet i Apache, Knowledge Base, Linux, Networking, Old Base | Skriv en kommentar

Installer Apache, PHP, MySQL og WordPress på Debian 6.0

Der skal også være lidt til dem der ikke har prøvet så meget, så et godt sted at starte må være med at installere skidtet. Jeg vil have flyttet min WordPress installation fra specialhosting.dk webhotellet over på en dedikeret virtuel server, fordi det har jeg brug for til næste indlæg. Derfor tager vi lige en nem en idag 🙂

Start med en ny frisk-installeret Debian 6.0 maskine, og installer følgende pakker:

root@specialhosting:~# apt-get install apache2 mysql-server phpmyadmin
libapache2-mod-php5 php5-mysql php5-gd vim

Du bliver bedt om at indtaste root password til din MySQL server, det er vigtigt at du vælger et sikkert password, brug evt. sikkeradgangskode.dk. Password skal tastes to gange.

Herefter skal du vælge hvilken webserver du vil benytte til phpmyadmin, her vælger du selvfølgelig “apache2”.

Phpmyadmin beder om tilladelse til at installere nogle databaser, det må den selvfølgelig gerne. For at gøre det skal den bruge Mysql root password, når den har fået det vil den oprette en account til sig selv og beder dig foreslå et password, det plejer jeg IKKE at gøre men derimod trykker jeg bare ENTER og lader installeren selv generere et password.

… Så er selve installationen faktisk færdig, og ved at taste din servers ip i en browser vil du kunne se en besked om at den nyinstallerede webserver virker. Det er fedt nok, men for lige at lære dig lidt mere om opsætningen vil jeg tage flytningen af WordPress med også.

Først logger jeg ind på den gamle server og laver et dump af databasen:

old-server# mysqldump -pPASSWORD DATABASE --hex-blob > specialhosting.sql

Så pakker vi alle filerne sammen: (mens du står i dit webdir)

old-server# tar zcpf specialhosting.tgz * .htaccess

og til sidst flytter vi filen:

old-server# scp specialhosting.tgz root@specialhosting.mikjaer.com:/root
The authenticity of host 'specialhosting.mikjaer.com (109.202.159.47)' can't be established.
RSA key fingerprint is 38:0e:7e:6a:35:8d:04:94:ca:7a:f4:a3:e4:92:69:eb.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'specialhosting.mikjaer.com,109.202.159.47' (RSA) to the list of known hosts.
root@specialhosting.mikjaer.com's password:
specialhosting.tgz                                                        100%  140MB  17.5MB/s   00:08

Ovre på den nye server pakker vi filen ud og gør web-root klar til brug:

root@specialhosting:~# cd /var/www/
root@specialhosting:/var/www# ls
index.html
root@specialhosting:/var/www# rm index.html
root@specialhosting:/var/www# tar zxf /root/specialhosting.tgz
root@specialhosting:/var/www# chown -R www-data:www-data *

Nu starter vi med at slå op hvilket brugernavn og password WordPress forventer at bruge til databasen:

root@specialhosting:/var/www# cat wp-config.php | grep DB_
define('DB_NAME', 'DATABASE');
define('DB_USER', 'USERNAME');
define('DB_PASSWORD', 'PASSWORD');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

og så opretter vi behørig database og useraccount:

root@specialhosting:/var/www# mysql -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 49
Server version: 5.1.61-0+squeeze1 (Debian)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database DATABASE;
Query OK, 1 row affected (0.00 sec)

mysql> grant all privileges on DATABASE.* to USERNAME@localhost identified by "PASSWORD";
Query OK, 0 rows affected (0.00 sec)

Til sidst importerer vi database dumpet, således:

root@specialhosting:/var/www# mysql -u USERNAME -pPASSWORD DATABASE < specialhosting.sql

… og til allersidst skal vi lige have aktiveret mod_rewrite så vi kan få pæne URL’s på WordPress, først redigerer du: /etc/apache2/sites-enabled/000-default

<VirtualHost *:80>
        ServerAdmin webmaster@localhost

        DocumentRoot /var/www
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>

        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Og retter linie 11, fra “AllowOverride none” til “AllowOverride all” og slutter af med at aktivere modulet og genstarte Apache:

root@specialhosting:/var/www# a2enmod rewrite
Enabling module rewrite.
Run '/etc/init.d/apache2 restart' to activate new configuration!
root@specialhosting:/var/www# /etc/init.d/apache2 restart
Restarting web server: apache2 ... waiting .

Og nu skulle WordPress gerne virke på den nye server, det gjorde min ihvertfald 🙂

Udgivet i Apache, Knowledge Base, Old Base | Skriv en kommentar

Performancetest af Apache med Apache Benchmark

Når vi skal teste ydelse på webservere og webapplikationer er værktøjet “ab” bedre kendte om Apache Benchmark uundværligt, der findes mange forskellige og jeg vil ikke gennemgå dem i dybden her, jeg vil bare “lægge værktøjet” i dine hænder og vise dig basal brug af det … så går jeg ud fra at dig og “man” selv finder ud af resten 😉

Alternativt laver jeg nok en follow-up på et tidspunkt hvor jeg bruger det til en eller anden konkret opgave.

Til testformål opretter jeg 2 filer på specialhosting.dk, først slow.php:

<?
         sleep(1);
?>

og fast.php:

<?
        // Do nothing
?>

Altså et script der laver ingenting og et andet der lavet ingenting i 1 sekund. Så lad os få installeret httperf og ab på vores testmaskine:

root@lab1:~# apt-get install httperf apache2-utils

Vi starter med at køre ab mod begge scripts, først fast.php:

root@lab1:~# ab http://www.specialhosting.dk/fast.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.specialhosting.dk (be patient).....done

Server Software:        Apache/2.2.16
Server Hostname:        www.specialhosting.dk
Server Port:            80

Document Path:          /fast.php
Document Length:        0 bytes

Concurrency Level:      1
Time taken for tests:   0.023 seconds
Complete requests:      1
Failed requests:        0
Write errors:           0
Total transferred:      210 bytes
HTML transferred:       0 bytes
Requests per second:    43.88 [#/sec] (mean)
Time per request:       22.792 [ms] (mean)
Time per request:       22.792 [ms] (mean, across all concurrent requests)
Transfer rate:          9.00 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       21   21   0.0     21      21
Processing:     2    2   0.0      2       2
Waiting:        2    2   0.0      2       2
Total:         23   23   0.0     23      23

og så slow.php:

root@lab2:~# ab http://www.specialhosting.dk/slow.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.specialhosting.dk (be patient).....done

Server Software:        Apache/2.2.16
Server Hostname:        www.specialhosting.dk
Server Port:            80

Document Path:          /slow.php
Document Length:        0 bytes

Concurrency Level:      1
Time taken for tests:   1.002 seconds
Complete requests:      1
Failed requests:        0
Write errors:           0
Total transferred:      210 bytes
HTML transferred:       0 bytes
Requests per second:    1.00 [#/sec] (mean)
Time per request:       1001.661 [ms] (mean)
Time per request:       1001.661 [ms] (mean, across all concurrent requests)
Transfer rate:          0.20 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:  1001 1001   0.0   1001    1001
Waiting:     1001 1001   0.0   1001    1001
Total:       1002 1002   0.0   1002    1002

You see? En masse dejlige tal man kan bruge til at lave sammenligninger med, husk og spørg din server-administrator om lov før du kører Benchmark mod dit webhotel 🙂

Udgivet i Apache, Knowledge Base, Old Base | Skriv en kommentar