Whitelistin käyttö roskapostin suodattamisessa

Aiemmin tänään aloittamani koe greylistd:n kanssa on vielä kesken, mutta
virusten aiheuttamia turhia bounce-viestejä se ei suodata pois. Ja
nähtävästi kohtuullinen osuus roskapostistakin osaa reagoida oikein
greylistin deferred-vastaukseen, valitettavasti. Nyt 9 tunnin jälkeen 25%
tulevasta postista jää tähän greylist-ansaan.

Nyt sitten mietin sitä vaihtoehtoa, että todella keräisin whitelistin
automaattisesti kaikista osoitteista, joihin lähetän postia ja
bounce-viesti, josta tällainen osoite löytyy, saa tulla läpi, mutta muut
kolisevat jonnekin muualle.

Jotain samantapaista löytyi täältä:

http://impressive.net/people/gerald/2000/12/spam-filtering.html

Harmaalistasuodatuksen koekäyttö

Roskapostitaistelun seuraava näytös. Spamassassin hoitaa roskapostin aika
hyvin pois ja aiemmin lisäämäni lisäsääntöpaketti suodattaa tarpeettomat
virustunnistusviestit syrjään. Jäljelle jäi vielä iso joukko
palautusviestejä viruksista, joissa palautuksen syy ei ollut virus vaan
väärä vastaanottajan osoite.

Nyt otin käyttöön greylistd:n exim4:n kylkeen. Ohjelman ideana on, että kun
postia tulee uudesta osoitteesta minulle, lähettää ohjelma vastauksen 451
(deferred) takaisin. Tavallinen postipalvelin ymmärtää viestin ja pistää
postin odotuslistalle ja lähettää myöhemmin uudelleen. greylistd päästää
postin läpi tunnin päästä ja lisää tällöin lähettäjän whitelistille, eli
tästä eteenpäin postit sieltä pääsevät suoraan läpi.

Ajatus roskapostien suhteen on tietenkin se, että roskapostitukseen käytetty
ohjelma, joka lähettää pari miljoonaa postia, ei vaivaudu vastaanottamaan
viivästysviestejä ja odottamaan tuntia. Joten roskaposti jää saapumatta.
Tietysti jossain vaiheessa roskapostittajat ottavat nämä toiminnot käyttöön,
mutta silti posti viivästyy tunnin verran, mikä tekee postittamisen
työläämmäksi ja toisaalta postittaja todennäköisemmin ehtii jollekin
julkiselle blacklistalle, jonka taas Spamassassin sitten tarkistaa ja hylkää
viestin sen perusteella.

Sinänsä tämä ei varmaankaan auta noiden virusviestien palautusten kanssa,
mutta luultavasti siivoaa liudan roskaposteja jo lähetysvaiheessa, jolloin
Spamassassin ei joudu kaikkea läpikäymään. Katsellaan. Nyt 45 minuutissa on
tullut 28 postia 17:sta eri osoitteesta.

Virusviestien suodatuksen tulosta

Noh, eilen SpamAssassiniin lisäämäni virusviestien suodatus ei ole
täydellinen, mutta tuottaa tuloksia kuitenkin.

Illan ja yön aikana virusviestejä suodatettiin pois 386 kappaletta, kun läpi
pääsi 37. Suodatetuista kohtalainen osa olisi kyllä suodattunut pois
ilmankin virussääntöjä, ne kun täyttivät spammin tunnusmerkit noin muuten.
Mutta .procmailrc:ssä säädin säännöt niin, että ensin siivotaan virusviestit
eri kansioon ja vasta sitten tavalliset spammit omaan lokeroonsa.
Läpipäässeiden viestien joukossa oli itse asiassa muutama oikea
spammi, jotka opetin SA:lle – .muttrc:ssä olevien makrojen avulla:

macro index S “<enter-command>unset wait_key\n<pipe-entry>sa-learn –spam –no-rebuild\n<enter-command>set wait_key\n<save-message>=spamassassin_manual\n”

macro index \eS “<enter-command>unset wait_key\n<pipe-entry>sa-learn –ham –no-rebuild\n<enter-command>set wait_key\n<save-message>=”

Loput läpi päässeet viestit olivat kyllä virusten lähettämiä, mutta
palautuksen syynä ei ollut, että vastaanottajan virustutka olisi ne
palauttanut, vaan että vastaanottajan sähköpostitunnusta ei ollut olemassa
tai quota oli täynnä tai jotain muuta. Eli tavallaan ihan oikeita
palautusviestejä.

Nyt tarvitsisi varmaan rakentaa jonkinlainen pidemmän tähtäimen filtteri,
joka kirjaa ylös osoitteet, joihin olen itse lähettänyt postia ja poistaa
palautusviesteistä ne, joissa ei ole näitä osoitteita mainittu. Onkohan
sellaista valmiina?

Sähköpostihistorian siivous

Vaikka procmail-suodattimeni jakaa tulevan postin jo valmiiksi kymmeniin eri
postilaatikoihin, parissa vuodessa jotkin niistä kasvavat jo useiden
tuhansien viestien kokoisiksi. Näiden käsittely alkaa jo olla epämukavan
hidasta esimerkiksi POP:n kautta.

Ratkaisu: archivemail
(“apt-get install archivemail”) croniin pyörimään. Tämä näppärä
Python-ohjelma käy läpi sille kertomasi postilaatikot (tukee mboxia, MH:ta
ja Maildiriä) ja erottelee niistä tarpeeksi vanhat (oletusarvoisesti 180
päivää) luetut ja ei-flagatut viestit ja sijoittaa ne gzipattuun arkistoon
haluamaasi paikkaan. Kun tätä ajaa cronissa vaikka viikon tai kuukauden
välein, pysyvät postilaatikot sopivan kokoisina ja vanhat roinat siirtyvät
itsekseen arkistoon.

Viruspostien suodatus

Omalla työkoneellani käyttämä roskapostin suodatin (SpamAssassin) hoitaa
roskapostit tyylikkäästi pois näkyvistä. Niitä tuleekin nykyisin lähemmäs
100 päivittäin.

Uusi ongelma alkoi viime vuonna, kun sähköpostivirukset levisivät hullun
lailla ja sain päivittäin poistella kymmenittäin virusviestejä. Se itse
asiassa hoitui aika helposti käyttämällä SpamAssassinin Bayesiläistä oppivaa
sanasuodatinta – roskapostia ei tarvinnut näyttää kun pari kertaa SA:lle,
niin se jo oppi homman nimen. Viruspostissa kun aina on se pakollinen
liitetiedosto, josta SA antaa jo pari pistettä, joten roskapostirajan
ylittäminen ei vaadi niin paljon oppimista.

Tämän kevään ongelma on sitten ollut virusviestien aiheuttamat
palautusviestit. Virukset kun nykyisin lähes poikkeuksetta arpovat myös
lähettäjän nimen saastuneen koneen sähköpostiluetteloista, joten jos ja kun
virusviesti jää kiinni vastaanottajan virustutkaan, lähtee siitä
valitusviesti tälle satunnaisesti arvotulle lähettäjälle. Näitä viestejä
tulee minulle nykyisin myöskin noin 100 päivässä.

SpamAssassin ei ole tarkoitettu virusten poistamiseen, mutta kyllä se
siihenkin taipuu. Ensin yritin jotain suojaa procmailin säädöillä, mutta
valitettavasti noissa palautusviesteissä ei näytä olevan mitään hyvää
yleisesti käytettyä tunnistetta, josta ne voisi poimia. Mikä sinänsä on tosi
tyhmää. Mutta onneksi en ole ainoa, jolla on tämä ongelma. Hetken
googlauksen jälkeen löysin valmiin, tiheästi päivitettävän
SpamAssassinin
sääntötiedoston
, joka sisältää kaikkien tunnettujen virustutkien
palautusviestien tunnisteet. Otin sen käyttöön ja siltä tosiaan näyttää,
että nämä työläät ja turhat palautusviestit tosiaan suodattuvat nätisti
pois. Ja oikeat bounce-viestit tulevat edelleen läpi, niin kuin pitääkin.

Oman sähköpostiosoitteen julkistaminen aikoinaan on kyllä aiheuttanut vähän
(tai paljonkin) työtä, mutta toisaalta eipä tarvitse koko ajan varoa, ettei
osoite vain leviä ulkomaailmaan. Nyt vain katselemaan, kuinka paljon roskaa
vielä läpi pääsee.

Ionin käyttöä

On se vaan myönnettävä, että yksinkertainen on kaunista. Kyllä tämä Ionin
ikkunointi on sen verran toimiva, että ihan oikeasti taitaa aikaa säästyä,
kun ei tarvitse ikkunoita säädellä käsipelillä.

KDE:n ja Gnomen jälkeen kaipailin kuitenkin jonkinlaista sessionhallintaa.
Eli lähtien vaikka siitä, että Ionin dock latautuisi niillä samoilla
ohjelmilla automaattisesti. No pikaviritelmähän on jotain tämän näköistä:

~/.xsession:

display -window root Debian-background.png
bin/ion-dock.sh &
exec ion3

~/bin/ion-dock.sh:

sleep 10
wmtime &
wmweather+ &
wmspaceweather &
wmsysmon &
wmfire &
wmxmms &
wmix &

Lyhyesti sanottuna siis forkataan taustalle tuo ion-dock.sh, jossa 10
sekunnin odottelun jälkeen käynnistetään kaikki dock-sovelmat taustalle
pyörimään. Viive siksi, että ion3 ehtii käynnistyä ja sovelmilla on paikka,
johon latautua.

Tunteiden selittämisen tärkeys

Tuntuu siltä, että lasten kasvastuksessa ei ole kovin montaa absoluuttista
totuutta. Niinhän se vanha viisaus menee, että niin kauan viisaita neuvoja
riittää, kunnes saa omia lapsia ja näkee, mitä todellisuus on. Mutta jotain
kai kuitenkin voi sanoa siitä, miten voi kasvattaa tasapainoisia yksilöitä?

Ainakin yksi asia on noussut esiin minulle kognitiivis-analyyttisestä
viitekehyksestä, mutta sama teema toistunee muissakin viitekehyksissä:
tunteiden ja tilanteiden selittäminen. Kun lapsi kokee jotain negatiivista -
pelottavaa, surullista, suututtavaa – on vanhemman tehtävä auttaa tunteen
tulkitsemisessa. Jos lapsi jää yksin tämän tunteen kanssa, voi asia tuntua
liian vaikealta tai liian kivuliaalta. Vanhemman tehtävä on asettaa vaikea
tilanne perspektiiviin ja antaa lupa kokea vaikeita tunteita. Tällöin
mahdottomilta tuntuvat asiat muuttuvat haastaviksi, karmeat pelottaviksi,
kestämättömät murheellisiksi.

Se, kuinka vähän aikaa nykyiset uraohjukset ehtivät lastensa kanssa olla,
vähentää myös mahdollisuuksia olla paikalla, kun lapsi kokee jotain uutta,
jota ei itse osaa käsitellä. Ja psykologisista oireista kärsivien nuorten
määrähän kasvaa nykyisin pelottavan kovaa tahtia.

Object orientation

Object orientation is an interesting and powerful way of designing, modeling and creating not just applications but also business models and just about anything. Here I’ll explain the basics.

Classes and objects

Instead of creating insubstantial and vague procedures and functions with extensive flow control to create the best spaghetti meal in town, objects allow the creation on concrete, close-to-the-real-world things (called objects) which are classified according to what they know and how they behave.

A Bicycle, for example, can change its gear, accelerate, break and steer. It has information on how many gears it has and what its speed and heading is.

Everything in an object oriented world is an object and each object is classified and therefore is an instance of a certain class. A class describes what behaviour and information an object of said class has, and each object of that class then has that information and behaviour.

Continuing with the Bicycle example, we could create two instances of class Bicycle, which can be called objects of class Bicycle. The first object could be heading north at a speed of 10 km/h on its 3rd gear, while the second one is stopped, facing east, on gear 1. Both of these objects have the same information (heading, speed, gear), but the individual values are different and can change over time. As the second bike starts moving, its speed increases, and at some point it will probably change to a higher gear. An object can also have information that is specified when the object is created. The color of the bicycle, for example, doesn’t change very often.

Object
A single entity that is a collection of (depending on your viewpoint):

  • data and code (binary perspective)
  • variables and methods (source code perspective)
  • information and services (design perspective)
  • state and behaviour (analysis perspective)
Class
A definition of what information and services a certain type of object has. Every object is an instance of some class.

Generalization and inheritance

When you start defining classes for our system, you’ll quickly find out, that you have several classes that are slightly different but have meny things in common. In that case you can take advantage of class inheritance and define a superclass that has the common information and several subclasses that add to the superclass’s definition.

If we add motorcycles to the system in addition to the bicycles, we have two classes that are different, yet in many ways similar. Let’s define a superclass Vehicle that has behaviour such as accelerate, break and steer, and information on its speed and heading. We’ll then specify that class Bicycle inherits or extends Vehicle, and has additional behaviour such as changing the gear. The class Motorcycle will also inherit Vehicle and has additional behaviour like changing the gear, starting the engine and shutting down the engine, and it will also have additional information, such as the amount of petrol left in the tank.

Superclass
A class that has subclasses.
Subclass
A class that inherits all the information and behaviour from one or more superclasses. A subclass can have additional information and can have additional behaviour, or override some of the superclasses’ behaviour.

Encapsulation

One of the key features of OO is information hiding and encapsulation. Information hiding means that the information an object has is hidden from the outside, so it cannot be changed or even looked at. The only way to get the value of a piece of information is to call a method that gives out that information. Similarly, to change a value, you have to call a method that will do that for you. A method is another (more programming oriented) name for a service. An object’s behaviour is made up of its services, or methods.

Encapsulation concerns the object’s methods. Only the signature of the method is visible to the outside. The signature shows how that particular method can be used. However, what the method actually does when it is invoked, is not shown. This has quite powerful ramifications. The greatest advantage is that the method’s contents can be changed freely at any time and as long as the signature stays the same, the change will not affect any other part of the system. In traditional programming styles a change somewhere can easily break the system in a dozen other places. Encapsulation makes sure that no part of the system is dependent of a class’s inner implementation, which makes updates and bug corrections significantly easier.

Do not confuse information hiding with security. Information hiding does not protect the data in any way, but is simply there at compile time to make sure that the developers don’t directly use an object’s internal data from the outside, but do it via appropriate method calls.

Variable
Storage place for one piece of information. A variable has a type, which tells what the information is (a number, a string, an array, a GearBox…) and a name, which is used at the source code level to handle the variable.
Method
A piece of code that can be called (invoked). Calling a method executes the code it contains. A method can accept parameters which it can then use in its code. A method can return a single value of some type, which the caller can use after the call is complete.
Signature
Every method has a signature, which defines the method’s name, its visibility (who is allowed to call it), the parameters it requires and the type of value it returns. The signature contains all the information needed to make sure that the method is called in an appropriate way, but contains no reference of what the method actually does.

Polymorphism

Polymorphism is another powerful feature of object orientation. By definition it means that any object of a certain class C can be treated as if it were an object of any superclass of class C. This is quite natural, since a subclass always inherits all the information and behaviour of its superclasses. This means that an object of that class will have all the methods and variables that the superclasses’ objects need to have, and therefore it can be thought of and treated as an instance of any of those superclasses.

If we create several Bicycle objects and Motorcycle objects, they are different and have different services, but they all contain the methods defined in the superclass Vehicle. Therefore we can treat these objects as Vehicles if needed. We can, for example, create a Vehicle array and store all the Bicycles and Motorcycles there. We can further iterate through the array and tell all the Vehicles to brake and turn to the right. If we later want to differentiate between Bicycles and Motorcycles, we can check the exact class of each object.

If a subclass overrides some of its superclasses methods, then the new methods (defined in the subclass) are used instead of the superclass’s methods. However, when the object is being treated as an instance of the superclass (as in the example) and an overriden method is called, two things could happen: 1) the subclass’s method is called, or 2) the superclass’s method is called. So which will happen? Object orientatied languages have a word for this: virtual methods. If a method is declared virtual, then all overrides are effective, and whenever a method is called, the actual class of the object is checked and the subclass’s version of the method is called. If a method is non-virtual, then the method defined in the class that the object is treated as will be called. Using non-virtual methods is a potential source of bugs, but virtual methods have a higher overhead, which makes method virtualization a performance issue. C++ methods are by default non-virtual, and Java methods are always virtual.

Abstract classes and methods

To be added later.

Conclusion

This concludes my short introduction to object orientation.
Hopefully it has been useful to you. I would definitely like to hear any
comments you have