Forfatterarkiv: Yngve Thoresen

Hotlinkere er som oftest fjortiser

Jeg skrev tidligere en liten innføring i hvordan jeg har stoppet hotlinkere fra å vise bilder liggende på bloggen min. Der beskrev jeg hvordan jeg brukte .htaccess filen for å hindre de jeg la til i listen. Dette fungerer glimrende og har egentlig ingen store ulemper. Jeg oppnår det jeg vil, som altså er å hindre uvedkommende i å stjele båndbredden min.

Men det kan bli så mye bedre. Jeg savner nemlig et par ting. Nemlig å se hvilke som blir fanget opp er tungvint, og ikke minst kunne kontrollere tilgang raskt og effektivt basert på data i sanntid.

Eneste måten jeg kan se hvem som snylter på er nemlig å gå gjennom logger, for så å plukke ut de som synder mest (eller bruke fantastisk lang tid på å lete i loggene…). Og ettersom jeg ønsker å kunne se hvorvidt tiltaket virker (eller bare bidrar til gratis reklame for meg) er det ingen god løsning å lete i logger som kun viser fordeling på måned.

Men det var før. Nå har jeg gjort noen små endringer som fungerer enda bedre. Kan det fungere bedre enn glimrende sier du? Javisst. Følg med.

I den nye versjonen har jeg byttet ut loggfilen med et par tabeller i databasen min. En tabell styrer tilgang og en er for logg. htacces filen er endret til å sende alle forespørsler som ikke er fra eget domene eller et fåtall andre, deriblant bildesøk fra google, til et php script som tar seg kontroll og visning av bilder. Alt som som routes til scriptet logges med nødvendig info.

Tabellen som styrer tilgang har et flagg som forteller om det aktuelle domenet skal få tilgang til bildene. Om domenet ikke ligger i tabellen fra før blir det lagt til, med tilgang. Ønsker jeg å fjerne eller gi tilgang kan jeg når som helst endre dette. Verdien fra denne tabellen brukes for å vise det riktige bildet eller denne snasne dama.

Tabellen for logging inneholder hver eneste forespørsel som blir gjort med henvisende url, bildets url, domeneid koblet til tilgangstabellen, og hvorvidt tilgang er gitt. Dermed har jeg mulighet til å trekke ut det jeg trenger av statistikk. Og statistikk liker jeg, så det viser jeg med all data jeg har tilgengelig. Jeg har derfor statistikk fordelt på domener, bilder, tilgang, tidspunkt, i topplister og siste treff. IP og denslags logger jeg ikke.

Og hvis noen lurer på overskriften kan jeg fortelle at blogg.no står for brorparten av hotlinkere mot denne bloggen, sammen med et par forum hvor brukere har hotlinket avatar bildet sitt fra bloggen min. De bytter nok ganske snart…

Se forøvrig mer om hot linking her.

Oppdatering: Koden for php scriptet er lagt ut. Husk å endre filen til php, samt legge inn server, brukernavn, passord og database. Jeg benytter samme database som for WordPress, men med annet prefix for å skille tilhørighet for tabellene fra hverandre.

PHP (scriptet i filen du finner over):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
< ?php
$hotlink['hotlinkimage'] = 'donthotlink.jpg';
 
$hotlink['url'] = '';
if(!empty($_GET['url'])) {
	$hotlink['url'] = $_GET['url'];
 
 
	$hotlink['ref_domain'] = '';
	$hotlink['referrer'] = '';
	$hotlink['fullurl'] = 'http://'.$_SERVER['HTTP_HOST'].'/'.$hotlink['url'];
 
	// mod_rewrite should have already established that it is a hot-link.
	// This is a double-check. We need to capture the referrer, anyway.
 
	if (!empty($_SERVER['HTTP_REFERER'])) {
		$hotlink['referrer'] = $_SERVER['HTTP_REFERER'];
		$hotlink['ref_domain'] = substr($hotlink['referrer'], 7, strpos($hotlink['referrer'], "/", 7) - 7);
	}
 
	// splitting the referrer into a domain part, saves us searching for multiple variations.
	// so long as your host name appears somewhere in the domain part, it's not a hot-link.
 
	if (!stristr($hotlink['ref_domain'], $_SERVER['HTTP_HOST'])) {
 
		$domain = getDomain($hotlink['ref_domain']);
 
		if($domain->allow){
			log_hotlink_to_db($domain, $hotlink['referrer'], $hotlink['fullurl'], 1);
			serveImage('../'.$hotlink['url']);
		}
		else{
			log_hotlink_to_db($domain, $hotlink['referrer'], $hotlink['fullurl'], 0);
			serveImage($hotlink['hotlinkimage']);
		}
	}else{
		serveImage($hotlink['url']);
	}
 
}else{
	// No url? Redirect them to the main site.
	header( "Location: http://" . $_SERVER['HTTP_HOST'] );
}

En enkel klasse for domene. Kunne godt laget en klasse for referrer også, men er ikke nødvendig.

46
47
48
49
50
51
// Simple class for domain
class Domain{
	public $id;
	public $domain;
	public $allow;
}

Logge til db.

53
54
55
56
57
58
59
60
//log the attempt to db
function log_hotlink_to_db($domain, $referrer, $url, $allowed){
	$db_connection = getDBConnection();
	$statement = $db_connection->prepare("INSERT INTO hotlink_log (domain_id, referrer,url,allow) VALUES (?,?,?,?)") or die ("Failed to prepare the statement!");
	$statement->bind_param("issi", $domain->id, $referrer,$url,$allowed);
	$statement->execute();
	$statement->close();
}

Et par funksjoner for å håndtere domener.

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
function getDomain($ref_domain){
	if (preg_match("/^www./i",$ref_domain)){
		// WWW. is deprecated anyway...
		$ref_domain = preg_replace("/^www./i", "", $ref_domain);
	}
 
	$domain = new Domain();
	$domain->id = 0;
	$domain->domain = $ref_domain;
	$domain = checkDomain($domain);
	if($domain->id == 0){
		insertNewDomain($domain);
		$domain = checkDomain($domain);
	}
	return $domain;
}
 
function checkDomain($domain){
	$db_connection = getDBConnection();
	$statement = $db_connection->prepare("SELECT id, allow FROM hotlink_access WHERE domain = ?") or die ("Failed to prepare the statement!");
	$statement->bind_param("s", $domain->domain);
	$statement->execute();
	$statement->bind_result($id, $allow);
	if($statement->fetch()){
		$domain->id = $id;
		$domain->allow = $allow;
	}
	$statement->close();
 
	return $domain;
}
 
function insertNewDomain($domain){
	$db_connection = getDBConnection();
	$statement = $db_connection->prepare("INSERT INTO hotlink_access (domain,allow) VALUES (?,1)") or die ("Failed to prepared the statement!");
	$statement->bind_param("s", $domain->domain);
	$statement->execute();
	//$statement->affected_rows
 
	$statement->close();
}

Vær så god, her har du et bilde. Håper du blir fornøyd.

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
function serveImage($url){
	if (!empty($url) and file_exists($url)) {
		$hotlink['img_type'] = end(explode('.', $url));
		if (strcasecmp($hotlink['img_type'],'png') == 0 ){
			$hotlink['img'] = imagecreatefrompng($url);
			imagesavealpha($hotlink['img'],true);
		} elseif (strcasecmp($hotlink['img_type'],'jpg') == 0 || strcasecmp($hotlink['img_type'],'jpeg') == 0) {
			$hotlink['img'] = imagecreatefromjpeg($url);
		} elseif (strcasecmp($hotlink['img_type'],'gif') == 0) {
			$hotlink['img'] = imagecreatefromgif($url);
		} else {
			trigger_error("HOTLINK - Image $url is of unknown type", E_USER_ERROR);
		}
		//TODO Other file types?
 
	} else {
		// Log image not found!
		trigger_error("HOTLINK - Image $url was not found", E_USER_ERROR);
	}
 
	// send the image to the browser..
	if ($hotlink['img_type'] == 'png') {
		header('Content-type: image/png');
		imagepng($hotlink['img']) or die("there was an error. sorry about that...");
	} else {
		header('Content-type: image/jpg');
		imagejpeg($hotlink['img']) or die("there was an error. sorry about that...");
	}
	imagedestroy($hotlink['img']);
}

Skaff en connection til db. Det er her data om server, brukernavn, passord og database skal inn.

135
136
137
138
139
140
function getDBConnection(){
	$db_connection = new mysqli("server", "username", "password", "database") or die ("Failed to obtain connection to db!");
	return $db_connection;
}
 
?>

Databasetruktur (SQL) er som følger:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE TABLE hotlink_access (
  id INT(11) NOT NULL AUTO_INCREMENT,
  DOMAIN VARCHAR(50) NOT NULL,
  allow INT(11) NOT NULL,
  PRIMARY KEY  (id)
)
 
CREATE TABLE hotlink_log (
  id INT(11) NOT NULL AUTO_INCREMENT,
  domain_id INT(11) NOT NULL,
  referrer VARCHAR(200) NOT NULL,
  url VARCHAR(100) NOT NULL,
  allow tinyint(1) NOT NULL,
  TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY  (id)
)

Egentlig er det også en timestamp i access tabellen også, men den trengs strengt tatt ikke da samme data ligger i loggtabellen.

Til slutt den delen som gjør selve redirekten: .htaccess filen:

1
2
3
4
5
6
7
8
# BEGIN Hotlink stopper
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?xmasb\. [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://((.+)\.)?google\.(.+imgres) [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://((.+)\.)?google\.(.+reader) [NC]
RewriteRule ^(.*)\.(gif|jpe?g|png)$ http://%{HTTP_HOST}/hotlink/hotlink.php?url=$1.$2 [R,NC,L]
# END Hotlink stopper

Alle request som ikke er direkte på bildene (gif|jpe?g|png), via xmasb, google’s bildesøk eller google reader blir sendt til scriptet. Scriptet sørger for resten. Her kan alle tillatte domener legges inn, så det ikke brukes unødig prossesering på tillatte domener. Eksempel på andre domener som kanskje bør ligge her er RSS lesere (Google, Bloglines, Netvibes f.eks) og andre sider for bildesøk. Det fine med denne fremgangsmåten er at det er lett å oppdage disse underveis, uten at de er utestengt i mellomtiden.

Det er lett å bare legge inn Google som tillatt domene i htaccess filen, men husk at det også eksisterer noe som heter sites.google.com. Scriptet får et par treff om dagen derfra.

Oppdatering 2: Har gjort en liten endring til på scriptet mitt. Ettersom blant annet blogg.no er kraftig overrepresentert i loggene er det like greit å sperre de ute med en gang. Jeg kunne selvsagt gjort dette via htaccess filen, men får å få med loggingen tar jeg de via scriptet likevel. For å gjøre dette har jeg gjort følgende endring i insertNewDomain funksjonen:

138
139
140
141
142
143
144
145
146
147
148
149
150
function insertNewDomain($domain, $allow = 1){
	global $hotlink;
	if(anyNeedleInString($domain->domain, $hotlink['blockedBaseDomains'])){
		$allow = 0;
	}
	$db_connection = getDBConnection();
	$statement = $db_connection->prepare("INSERT INTO hotlinkaccess (domain,allow) VALUES (?,?)") or die ("Failed to prepared the statement!");
	$statement->bind_param("si", $domain->domain, $allow);
	$statement->execute();
	//$statement->affected_rows
 
	$statement->close();
}

AnyNeedleInString ser slik ut:

187
188
189
190
191
192
193
194
function anyNeedleInString($haystack, $needle){
	foreach($needle as $key => $search_needle) { 
		if(stristr($haystack, $search_needle)) { 
			return true;
		}
	}
	return false;
}

Og så er det bare å definere en array som inneholder de domener man ikke vil ha med:

3
$hotlink['blockedBaseDomains'] = array('blogg.no', 'nettby.no');

Her illustrert med blogg.no og nettby.no. Dermed slipper jeg å håndtere de som tilhører diverse plattformer. Smart, ikke sant?

Hvordan jeg stopper hotlinkere – og får gratis reklame for xmasb.com

En gang i blant sjekker jeg statistikk for bloggen. Etter som årene har gått (og hyppigheten på bloggingen har gått noe ned) har jeg sluttet å lese statistikk annen hver dag. Men det hender jeg sjekker litt, mest for å se etter endring i mønsteret, og hvilke poster og sider som mottar mest trafikk. En sjelden gang iblant går jeg litt dypere til verks og sjekker da hvilke ressurser på serveren som får mest trafikk, sånn som bilder.

Når jeg gjorde dette i går fant jeg ut, ikke overraskende, at det er mye trafikk fra diverse nettsider som henter bilder fra meg. Begrepet hotlinking har jeg vært innom før, for snart tre år siden satte jeg i gang tiltak. Men som så mye annet krever det en viss vedlikehold, så det var på tide å gjøre noen grep igjen. Etter tre år skulle det vise seg å være mange som stjeler båndbredde av meg.

Mens jeg tidligere har tatt i bruk et bilde som forteller at det er slemt å hotlinke syntes jeg dette var en gyllen mulighet for to ting: å spre reklame for bloggen min (selv om jeg har cirka null kontroll over hvor den blir vist), og en mulighet for å være litt morsom på andres bekostning. Sistnevnte fikk umiddelbart høyest prioritet av åpenbare grunner.

Her er et bilde jeg tidligere har brukt for de som hotlinker fra meg: Hotlink Text

Det har jo absolutt gjort nytten sin. De færreste ønsker å vise det fremfor det de egentlig ville ha, som kanskje var en søt valp eller et juletre. Så de bytter til noe annet, eller kopierer bildet fra meg. Å kopiere bilder fra bloggene til andre er et tema vi ikke trenger å gå inn på nå. Så lenge det ikke er bilder jeg selv har tatt/laget tar jeg det uansett ikke så tungt.

Fremgangsmåten for å hindre hotlinkere var omtrent som forrige gang, men med en liten tvist: nytt bilde og logging av misbrukere. Loggingen er ikke så viktig i seg selv, og jeg kommer nok til å endre litt hvordan den virker også, men det kan være grei info å ha når jeg vil vite omfanget av hotlinking.

Det morsomme er bildet. Nedenfor følger et par eksempler på bilder som ofte blir hotlinket til på xmasb.com:

Jeg kan godt forstå at disse bildene kan være attraktive å bruke. Men jeg synes da bildet jeg serverer i stedet er mye morsommere. Det ser slik ut:

Don't hotlink xmasb.com!

Nå vil det ikke spare noe særlig på båndbredden i seg selv ved å servere et annet bilde, men de fleste velger å ikke bruke dette bildet av en eller annen grunn… Jeg kunne servert for eksempel «403 Forbidden» til requestet, og dermed spart hele båndbredden, men det er jo ikke noe moro. Og det gir meg litt ekstra reklame også. I oktober hadde bloggen like over 10000 visninger av bilder fra xmasb.com på andre domener. De fleste av sidene viser nå forrige viste bilde, eller har byttet.

Så hvordan har jeg egentlig gjort dette? Det er ikke vanskelig. Akkurat som forrige gang endret jeg .htaccess filen for å få effekten jeg ville ha. I slutten av denne filen la jeg til følgende:

BEGIN Hotlink stopper

RewriteEngine on RewriteCond %{HTTP_REFERER} ^(.+.)?blogg.no/ [NC,OR] RewriteCond %{HTTP_REFERER} ^(.+.)?blogspot.com/ [NC,OR] RewriteCond %{HTTP_REFERER} ^(.+.)?clublife.no/ [NC,OR] RewriteCond %{HTTP_REFERER} ^(.+.)?livejournal.com/ [NC,OR] RewriteCond %{HTTP_REFERER} ^(.+.)?myspace.com/ [NC,OR] RewriteCond %{HTTP_REFERER} ^(.+.)?nettby.no/ [NC,OR] RewriteCond %{HTTP_REFERER} ^(.+.)?trykker.com/ [NC,OR] RewriteCond %{HTTP_REFERER} ^(.+.)?wordpress.com/ RewriteRule ^(.*).(gif|jpe?g|png)$ http://%{HTTP_HOST}/hotlink/hotlink.php?url=$1.$2 [R,NC,L]

END Hotlink stopper

For bedre lesbarhet har jeg fjernet de fleste fra listen. Kort fortalt gjør denne lille snutten at alle forsøk på å vise bilder fra oppgitte domener/sider fører til et kall av hotlink.php, som igjen serverer dama over og logger requestet. Jeg logger da url for siden som kaller, IP for besøkende av siden, tidspunkt og hvilket bilde som er forsøkt hotlinket. Mest sannsynlig kommer jeg også til å endre oppsettet senere til også å logge de som får lov til å vise bilder, for å kunne få en oversikt over disse og eventuelt lett blokkere flere.

Dersom logging ikke trengs eller er ønskelig kan det lett byttes ut med et bilde istedet for php script, men da er det viktig å legge til en linje som tillater bruk av det ene bildet hos de som egentlig ikke skal kunne se bilder fra bloggen. Følgende linje kan da legges inn rett før Rewriterule:

RewriteCond %{REQUEST_URI} !http://%{HTTP_HOST}/wp-content/uploads/hotlink.jpg

Denne tillater visning av bildet hotlink.jpg. Husk også å legge til en OR for siste i listen før denne.

Tidligere har jeg forsøkt å stoppe alle requests bortsett fra et knippe jeg tillatter, men dette har ikke fungert så godt som håpet. Problemet er blant annet lesere av feeden. Det er ikke noe problem å tillate Google, men hva med alle andre? Hvor mange og hvilke er det? Jeg har ihvertfall ikke en god oversikt. Tidligere forsøkt på dette har bare ført til frustrasjon da bilder i feeden hos for eksempel en som bruker Outlook som leser er vanskelig å ta høyde for. Stikkordet med løsningen jeg har valgt må være «godt nok». Det krever en viss vedlikehold, men ikke verre enn at jeg går inn i loggen en gang iblant og luker ut de verste.

Som oftest er det ikke de bloggene som har to besøkende om dagen som er problemet, men forum og andre sider med høy aktivitet. I mitt tilfelle har jeg nok av båndbredde foreløpig, så da kan jeg godt servere et annet bilde istedet. Men jeg har sørget for at bildet er komprimert så mye som mulig likevel. Dersom du har tenkt å bruke tekst kan det være verdt å sjekke forskjellen i størrelse mellom flere formater (gif/jpg først og fremst).

Et siste tips. Når du tester om dette virker, typisk ved å se om bildet vises eller ikke på den siden som har hotlinket, vil gjerne nettleseren bruke det bildet du allerede har i cahe. De fleste nettlesere kan tvinges til å hente på ny ved å trykke ctrl-F5 eller tilsvarende.

Oppdatering: Jeg har gjort dette mye smidigere ved hjelp av litt enkel koding.

En uke med Chrome

For cirka en uke siden byttet jeg nettleser fra Firefox til Google Chrome. Ikke fordi jeg var misfornøyd med Firefox på noen som helst måte, men det er noe ved Chrome som appelerer til meg (kan det være at jeg for lengst har solgt sjelen min, og all informasjon som følger med, til Google for lenge siden?).

Så jeg la inn Chrome igjen. Jeg har med andre ord forsøkt tidligere, men den gang var det ikke mye å skryte av. Nå er alt så mye bedre!

Det første som imponerte meg var det minimalistiske designet. Mer plass til innhold. Videre var det en lek å få inn informasjon fra Firefox. Et par tastetrykk og Chrome hadde full kontroll over bokmerker, historie, søkemotorer og annet snacks som er uunnværlig for meg.

Hva gjelder bokmerker har jeg vært en ekstremt fornøyd bruker av Xmarks, men denne har en noe usikker fremtid i møte. Jeg foretrekker uansett å holde meg til en nettleser av gangen, og da tilbyr ihvertfall både Firefox og Chrome synkronisering mellom flere maskiner. For passord benytter jeg LastPass, så det slipper jeg å tenke på hvordan nettleseren håndterer.

Etter å brukt Chrome noen få minutter la jeg merke til noe uvanlig. Reklame. Så det er altså slik mange opplever internett, tenkte jeg. Stakkars folk. Ingen krise, det var bare å legge inn adblock først som sist, så var det i orden. Jeg registrerer at den er noe hissigere enn på Firefox, men da slipper jeg søppelet i siden på VG også da, reklame eller ei. (VG er forøvrig et nettsted jeg sjelden oppsøker frivillig, da jeg liker å lese nyheter i en nyhetsavis, og ikke siste sprell fra OsloGirls og annet tull.)

Etter å brukt Chrome en uke er altså konklusjonen klar. Jeg beholder den, men avinstallerer ikke Firefox enda. Faktisk er jeg fortsatt avhengig av Firefox også. På jobb blir det mye XML og der er Chrome for dårlig. Faktisk viser den ikke XML i det hele tatt. Jeg har forsøkt et par extensions, men endte fort tilbake i Firefox. Chrome har også en del andre irritasjonsmomenter, som for eksempel at det ikke finnet et valg for å sette et bilde som skrivebordsbakgrunn. Ikke noe jeg gjør veldig ofte, men et valg som på en måte alltid har vært der i alle tidligere nettlesere. Jeg forstår ikke hvorfor Google ikke har inkludert noe så basic.

Et veldig vanlig argument for å bytte vekk fra Firefox er hastighet. Firefox er ikke alltid den raskeste nettleseren, men som oftest kommer dette av mange addons som brukeren har installert. Ved tester hvor Firefox kommer veldig godt ut er det gjerne en ren installasjon uten noen addons som blir testet. Kanskje vil det samme skje med Chrome, men i skrivende stund er jeg ikke veldig imponert over de extensions jeg har testet i Chrome. Så jeg kommer heller ikke til å installere så mange av de.

Jeg savner ikke å restarte nettleseren fordi jeg har installert en extension! Her er Chrome inne på noe.

I skrivende stund har jeg 5 extensions installert: – AdBlock – Browser Button for AdBlock (jupp, en knapp for ablock ettersom det ikke fulgte med AdBlock…) – Google Chrome to Phone (var mer imponerende på Firefox faktisk) – LastPass (jeg elsker LastPass) – RSS Subscription Extension (hvorfor dette ikke er en del av Chrome ut av pakken fatter jeg ikke)

Det blir sikkert flere etterhvert, men jeg prøver altså å holde det på et minimum. Alt i alt er jeg kjempefornøyd med Chrome, men savner altså noen småting fra Firefox (som ofte kommer via en addon. Det er sikkert en grunn til at jeg har 15 addons installert i Firefox, og da har jeg fjernet mange).

Nei, du får ikke skjegg!

Det ble en liten krise under morgenritualet i dag. Jeg står og barberer meg da jeg hører en veldig trøtt stemme bak meg. Det er datteren min som har våknet. Med smale øyne står hun lenge og ser på meg.

«Hva gjør du?» er naturligvis spørsmålet som kommer. Hun har nok spurt meg dette spørsmålet, i nøyaktig denne sammenhengen, minst tjue ganger før. «Jeg barberer meg» svarer jeg. Og hun spør meg om jeg har skjegg, noe jeg egentlig ikke helt vet hva jeg skal svare på med tanke på den lille skjeggveksten jeg faktisk har. Men joda, jeg har skjegg, og nå barberer jeg meg. Hun vil låne barbermaskin, og selvsagt får hun det.

Etter en liten stund spør jeg om å få den tilbake, så jeg kan bli ferdig. Men hun er motvillig, og vil gjerne barbere seg mer. Maskinen er ikke engang skrudd på, men det er ikke så nøye, her skal det barberes. Jeg forteller henne at pappa må barbere seg ferdig, og legger til «du har jo ikke skjegg, vennen». Hun stopper opp, og tenker litt, før hun svarer bekreftende. Men så kommer det. «Men når jeg blir stor, da får jeg skjegg!». Pappa ler, og hun smiler. «Nei», sier jeg, «du er jente du, og jenter får ikke skjegg». «Å! Jeg vil også ha skjegg!», svarer hun med stemmen som kommer rett før gråt. Det er viktig å tenke godt gjennom svaret pappa skal gi nå, for dette vil avgjøre om gråten skal komme eller ei.

«Er du heldig, så får du skjegg. Så kan du jobbe i sirkus!», svarer jeg. «Ja!» roper hun og ler.

Nærmer meg 10.000

WordPress pluginen XmasB Quotes har rukket å bli gammel. Og det har jaggu denne bloggen også.

Jeg begynte å skrive i 2006. Etter et års tid fikk jeg lyst til å ha sitater på siden min. Tilfeldige sitater skulle det være. Jeg gikk utifra at det fantes cirka en dullion plugins å velge blant, men slik var det ikke. De får jeg prøvde var enten for kompliserte (det er ingen kompleks oppgave), enkle eller fulle av bugs. Så jeg skrev min egen, kanskje først og fremst for å lære PHP bedre. Når jeg ser over koden idag har jeg selvsagt mest lyst til å skrive om alt sammen, men den virker og gjør det den skal, så jeg lar det prosjektet ligge. Tid har jeg for lite av allerede.

I skrivende stund har XmasB Quotes blitt lastet ned 7047 ganger. Med litt godvilje er det nesten 10.000 nedlastinger! Faktisk har den blitt lastet mer ned de siste to månedene enn noen gang. Når den bikker 10.000 skal jeg bruke alt jeg har tjent på den (via donations) og kjøpe meg noe fint. Foreløpig ligger det an til å bli en tre-pakk sokker. Ikke den dyreste varianten, men slettes ikke den billigste heller.

Forsinket vårrengjøring av leselista

Ettersom jeg uansett følger altfor mange blogger (beklager at jeg sjelden kommenterer) føler jeg iblant for å rydde opp litt, så idag har jeg fjernet en ganske stor andel blogger som baserer seg på blogger/blogspot. Det var godt.

Jeg er veldig glad i Google (søk, docs, analytics, chat, mail, android osv osv), men blogger kan jeg bare ikke fordra. Det vil si, blogger er greit nok, men sett ihvertfall opp kommentarfeltet så jeg slipper å bruke så utrolig lang tid på å velge profil, taste kode og lukke popupen som ikke hører noensteds hjemme.

Jeg har selvsagt ikke fjernet bloggen om den er skikkelig god eller ikke har innstillinger med popup og annet tull. 🙂

Er passordene dine sikre?

I løpet av en vanlig dag benytter jeg mange passord og pinkoder for å verifisere meg mot ulike systemer. Jeg husker de aller fleste passord, men har funnet noen ulike metoder for å håndtere den uoversiktlige mengden av påloggingsinfo som er nødvendig gjennom både jobb og privat. For passord på jobb har jeg et passordbeskyttet regneark for de mindre kritiske passordene. Dette er delt med et par andre utviklere. Det største problemet er faktisk å huske passordet til regnearket, da dette ikke brukes i noen annen sammenheng.

Privat bruker jeg, dessverre, ofte det samme passordet. Jeg har rundt regnet 10 ulike passord jeg benytter privat, de fleste følger det samme mønsteret – alle er kryptiske. Etter at noen misbrukte PayPal kontoen min har jeg endret passord for alle nettsider som kan tappe kredittkortet mitt for penger. Passordene er genererte strenger bestående av masse bokstaver, tall og tegn, som jeg ikke kjenner til. De ligger lagret i et eget program som krever enda et passord for å logge seg inn i. Trenger jeg tilgang til en av disse nettsidene må jeg gå gjennom dette programmet, eller få tilsendt et nytt passord. De aller fleste private passord ligger i dette programmet. Mister jeg nøkkelen inn i programmet, må jeg resette de fleste passord.

Jeg er opptatt av sikkerhet, men også opptatt av brukervennlighet. Ofte blir det et kompromiss for at vil ta i bruk en løsning. For noen systemer og nettsider er ikke sikkerheten like kritisk, og jeg velger å ta i bruk et standard passord. For andre steder velger jeg et autogenerert passord eller en variant av tidligere passord.

Når jeg da velger å ta i bruk smarte løsninger for å ta vare på sikkerheten blir jeg veldig skuffet når store og små leverandører ikke ser ut til å ta sikkerhet på alvor. Min sikkerhet. Et eksempel på dette er strømleverandøren min, Vitel (Tidligere strømleverandør. De har som kjent sluttet med strøm nå.). Som de fleste andre leverandører tilbyr de en mulighet for å få tilsendt innloggingsinformasjon dersom brukeren har glemt dette. Og som så mange andre gjør de den samme feilen og sender en epost med brukernavn og passord jeg registrerte meg med. Som om det ikke er nok finner jeg den samme informasjonen på hver eneste faktura.

Nå er det ikke slik at man kan gjøre spesielt stor skade ved å logge seg inn hos en strømleverandør, men passordet er nok for mange det samme som brukes mange andre steder. Sammen med epostadressen kan dette misbrukes i stor skala.

Så hvordan bør dette løses? Mange har skjønt det, og oppbevarer ikke passord i klartekst. Ei heller kan de hente ut passord når brukeren har glemt det. Man kan kun sjekke inntastet passord mot det som er registrert, ved å gjøre den samme kryptering på inntastet passord som ble gjort når passordet ble lagret første gang. Dersom brukeren har glemt passordet må nytt passord settes, enten ved at et passord genereres automatisk eller at brukeren setter nytt via en link som kan brukes en gang. Uansett bør brukeren kunne velge seg et nytt passord et sted i prosessen. De aller fleste gjør det på denne måten, men veldig mange slurver.

Jeg har for lengst send en epost med min mening til min strømleverandør og flere andre. Gjør det du også, så kanskje de endrer sin praksis!

Dette er eposten jeg sendte dem:

Jeg har en forespørsel angående deres praksis med å lagre og sende passord i klartekst over epost. I tillegg er også mitt passord skrevet i klartekst på alle fakturaer tilsendt meg. Hvorfor har dere behov for å lagre mitt personlige passord i klartekst? Jeg stiller meg skeptisk til at dere har tilgang på mitt personlige passord og er bekymret over muligheten for at noen av deres ansatte eller andre tredjeparter kan få tilgang på passordet med å lytte på nettverket, lese mine faktura eller andre metoder. Når dere sender mitt passord på epost, blir det overført over nettverket i klar-tekst og er lett leselig på ulike nettverks-rutere og lokasjoner. Det burde ikke være noen tekniske eller funksjonelle behov som gjør at dere må lagre mitt personlig passord i klartekst eller med en reversibel kryptering. Det bør være nok med en ikke-reversibel hash av passordet. Håper dere tar forespørselen til etterretning og forstår min bekymring for mitt privatvern.

Oppdatering! Jeg har fått svar på min henvendelse til Vitel:

Hei Vi har hatt oppe denne saken før med post og teletilsynet og vi har gjort endel endringer i vårt system som post og teltilsynet har funnet tilfredstillende godt nok. Jeg lister opp en del punkter under som viser hva som er gjort. – Ved å gå inn på «Mine sider» kan man velg bort at passord vises på faktura – Ingen ansatte i Vitel har tilgang til å se ditt passord – du kan selv velge passord på «Mine sider» Når det gjelder at passord blir sendt over nettverk via epost eller sms så er dette helt vanlig praksis og informasjonen som evt. kan leses kan skjelden være av interesse for en tredjepart. Vi har gått gjennom våre rutiner sammen med pt og dette skal være sikret tilstrekkelig godt nok. Håper dette var et beroligende svar. Med vennlig hilsen Kundesenter

De opererer med andre ord etter «godt nok»-taktikken. Jeg er ikke spesielt beroliget av en slik taktikk. Selvfølgelig har ansatte hos Vitel adgang til passord om de ønsker det, de sitter jo på dataene. Hvem som helst med tilstrekkelig adgang til riktige databaser kan hente ut denne informasjon. Utro tjenere finnes det mange av, og den beste måten å sikre seg mot disse er å ikke legge frem muligheter som dette. Nå er ikke jeg kunde hos Vitel lenger, da de ikke klarer levere strøm til meg uansett, men jeg endret fort passordet mitt når jeg fant ut av praksisen deres. Da er det greit med et kryptisk passord som jeg ikke kan selv engang. Eksempel på et slikt passord er (tilfeldig generert for meg nå): «cHQ^smX9G#sW».

Jeg jobber i et miljø hvor sikkerhet er utrolig viktig. Dårlige løsninger kan eksponere personsensitive og medisinske data. Skikkelig dårlige løsninger kan gi ledere en grunn til å pakke sammen på dagen, og utvikler følger nok med skulle det skje. Ofte må derfor det vurderes hvor godt disse dataene skal beskyttes. Vi kan velge å gjøre dette «godt nok» for å tilfredsstille lover og regler, eller vi kan sørge for å gjøre det så bra at vi sover godt om natten. Vi velger alltid sistnevnte, fordi det ikke koster så mye mer og fordi vi har et rykte å tenke på. Det finnes (dessverre) mange eksempler på brukernavn og passord på avveie, fordi løsningen har vært «god nok». Hva med å bare gjøre det bra med en gang? Så er også risikoen for feil fantastisk mye mindre!

«Fiks» hvordan faner oppfører seg i Firefox 3.6

I nåværende versjon av Firefox, versjon 3.6, har Mozilla funnet ut at det er smart å åpne nye faner ved siden av den som er aktiv. De fleste andre nettlesere jeg vet om gjør også dette, men jeg vil ha nye faner åpnet helt til høyre. Slik det var, med andre ord. Og det kan jeg heldigvis fikse ganske lett. Dersom du liker at fanene åpnes ved siden av aktiv gjør du selvsagt ingenting med det. På mange måter er det jo mer fornuftig, men jeg liker den gamle innstillingen med nye faner helt til høyre best.

Først må innstillingene i Firefox finnes frem. Det gjør du ved å skrive about:config i adresselinjen og trykker enter:

Deretter må den riktige innstillingen hentes frem. Skriv browser.tabs.insertRelatedAfterCurrent i feltet «Filter»:

Du vil nå få opp linjen med innstillinger for browser.tabs.insertRelatedAfterCurrent. Dobbeltklikk denne for å endre mellom true og false. Verdien true vil få faner til å åpne seg ved siden av aktiv fane, mens false vil åpne faner helt til høyre slik jeg vil.