Dienstag, 18. November 2008

Objektorientierte Programmierung in Javascript

JavaScript objektorientiert Problematik



Javascript Projekte können leicht umfangreich und unübersichtlich werden. Insbesondere wenn man ein Webframework programmieren möchte. Problematisch erweist sich der Sachverhalt, das jeder Browser die gegebenen Internetstandards unterschiedlich implementiert. Im Worst-Case sogar Fehler mit einbringt die im Javascript abgefangen werden müssen. In der imperativen (prozeduralen, gerne auch Spaghetti-Code) Programmierung würde man If-Konstrukte verwenden um innerhalb des Quellcodes den Browser bestimmen und eine Ausnahmebehandlung durchzuführen.

An dieser Stelle bietet sich der Objekt Orientierte Programmiertstil innerhalb der Javascript Sprache an.

So kann man die einzelnen Ausnahme- bzw. Sonderbehandlungen in einer eigenen Klasse (zum Beispiel Exception_for_IE [Ausnahmebehandlung für den Internet Explorer] bzw. Explorer_for_FireFox [Ausnahmebehandlung für den Firefox]) vornehmen. Ein gutes Beispiel sind die gesonderten AJAX Implementierungen:

* im IE:
var ajax = new ActiveXObject("Microsoft.XMLHTTP");

* im Firefox:
var ajax = new XMLHttpRequest();


Hierbei lohnt es sich die diese zu Kapseln und bei der Initialisierung die benötigte AJAX Implementation zu laden.

In der Klasse für Formular- bzw. Maskenbehandlung würde man dann nur noch Platzhalter (zum Beispiel leere Funktionen) deklarieren und diese dann bei Bedarf überladen. Bei so einer Schnittstellenerstellung muss im Vorfeld natürlich klar sein, welche Ausnahmen es gibt und welche überladen werden sollen bzw. auch können. Anstelle der leeren Funktion gibt man natürlich eine Standard-Abarbeitung mit oder schreibt explizit als Hinweis "To be implemented by sub class" hinein.

Generell lohnt sich eine Kapselung der Variablen, vor allem wenn man mehrere Scripte verschiedener Autoren eingebunden hat. Im globalem Namespace kann eine Überschreibung gleichlautender Variablennamen zu ungewollten Ergebnissen führen. Dadurch lässt sich auch die Performanz steigern, in dem man dem Javascript Compiler explizite Hilfe leistet und unbenötigte Variablen damit obsolet macht.

Ein spürbarer Performanzgewinn, durch die objektorierte Herangehensweise, ist die Verteilung des initialen Javascript Parseraufwandes sowie den Initialisierungsaufwandes. Einmal objektorientiert kann man den Parallelisierungsoptimierungen der Browser vertrauen und die Initialisierungen der einzelnen Objekte innerhalb des
body onload=""
erledigen.

Objekterstellung



(Anonyme) Funktionen können als Klasse-Definitionen benutzt werden:

var objekt = function () {

alert("Objekt");

};


Hinweis: die Funtion alert() ist nicht Bestandteil des ECMA-Skript Standardes. An dieser Stelle würde man die Klasse 'objekt' zeigend auf eine anonyme Funktion erstellen.

var instanz = new objekt();


Dabei wird dann mit mittels der new Anweisung eine neue Instanz 'instanz' erstellt.

Parameter



Parameter an Klassen können einfach bei der Deklaration mit erstellt werden.

 var objekt = function (parameter1, parameter2) {

alert (parameter1+" "+parameter2);

};


Globale und lokale Variablen



Nun möchte man aber nicht freie Anweisungen in seiner Klasse haben.

 var Exception_for_IE = function (div_element) {

var _div_element = div_element;

this.init = function (div_element) {

_div_element = div_element;
};
};


Obiger Code-Schnipsel zeigt wie man lokale Variablen in der Klasse setzen kann. Nämlich direkt bei der Erzeugung. Bevorzugen sollte man allerdings die Methode mittels einer seperaten 'init' oder 'contructor' Methode.

 var Exception_for_IE = function () {

var _div_element;

this.init = function (div_element) {

_div_element = div_element;
};
};


Bei der Erzeugung einer Instanz dieser Klasse:

var exceptions = new Exception_for_IE();


müsste man also noch die init-Methoden aufrufen, um auch eine Initialisierung vorzunehmen.

exceptions.init('Formular_div');


Es wurde das Schlüsselwort 'this' eingeführt. Entscheidend für die private/public Sichtbarkeit der Variablen sind somit 'var' und 'this'. In einer Klasse mit 'var' definierte Variablen sind klassenlokal (damit auch nach einer Instanziierung objektlokal), d.h. diese sind außerhalb des Objektes nicht zugreifbar. Variablen (oder Funktionen) welche mit dem Schlüsselwort this definiert wurden sind außerhalb des Objektes (nach der Instanzierung) über den Namespace sicht- und ausführbar. Diese Ausführung findet dann

in dem Scope (Gültigkeitsbereich, in der Variablenumgebung) des Objektes statt.

Ableitung und Überschreibung (simpler Polymorphismus)



 function Exception_for_IE () {

var _self = this; var _what; var _iFr;

_self.init = function(what,iFr) {

_what = what; _iFr = iFr;
};
_self.aus = function (dummy) {

document.getElementById(_what).style.display = "none"; document.getElementById(_iFr).style.display = "none";
};
};

function Formular () {

var _self = this;

_self.aus = function () {

return "To be implemented by sub class";
};

_self.ajax_request = function () {

_self.aus(); // weiterer Code
};
};

function Maske_Auto () {

var aus = function() {

alert("Methode aus wird nicht ünterstützt.");
};

this.init = function () {

Exception_for_IE.prototype = new Formular();
var _Formular = new Exception_for_IE();
};
};


Mit der Methode 'prototype' werden die Methoden der Klasse Formular in die Klasse Exception_for_IE eingebunden, welche dann mittels der lokalen Variable '_Formular' sichtbar sind. Hierbei ist dennoch Vorsicht geboten, gleichlautenden Methoden (wie z.B. init() würden überschrieben). Innerhalb des Objektes 'Maske_Auto' ist es möglich Methoden der eingebundenen Klassen zu explizit überschreiben. Das wird erreicht mit einer einfachen Zuweisung erreicht. In dem konkreten Fall (innerhalb der Klasse Maske_Auto)
_Formular.aus = this.aus;
.

Selbstreferenz mit this



Wer die obige erwähnte Überschreibung von Methoden einer übergeordneten (abgeleiteten) Klasse versucht wird wohl enttäuscht werden. Die erwartete Überschreibung findet nicht statt, weil this den Scope verändert. This kennt man normalerweise als Referenz zu dem umgebenden Objekt. In Javascript zeigt this immer auf den zu letzten Gültigkeitsbereich. Um nun innerhalb einer Klasse (später der Instanz) Methoden auszutauschen muss man sich also das 'aktuelle' this (aktuell zu der Erstellung der Klasse) sichern. Dies wird im obigen Beispiel mittels der Variable '_self' erledigt. Da es in vollkommen objektorientierten Programmiersprachen (wie Smalltalk) keine Anweisungen ausserhalb von Methoden gibt, sieht das analoge Beispiel so aus:

 function Formular () {

var _self = this;

_self.Formular_get_self = function () {

return _self;
};

_self.aus = function () {

return "To be implemented by sub class";
};

_self.ajax_request = function () {

_self.aus(special_div_element); // weiterer Code
};
};

function Maske_Auto () {

var aus = function(_element) {

document.getElementById(_element).style.display = "none";

};

this.init = function () {

var _Formular = new Formular();

_self_Formular = _Formular.Formular_get_self();
_self_Formular.aus = aus();

};
};


Wie man sieht wird eine Getter-Funktion (_self.Formular_get_self) benutzt um den Code innerhalb einer Funktion zu kapseln und zu lokalisieren. Ein solches Vorgehen eignet sich ebenfalls hervorragend um in übergordneten Objekten interne Variabeln zu ändern oder einen Hook (einen Sprungpunkt) zu erstellen. Ermöglicht werden soll eine nachträgliche Beeinflussung von Verarbeitungsreihenfolgen und damit eine erhöhte Code-Wiederverwendung.

Nützliche Links:


* SelfHTML: JavaScript Sprachelemente
* ECMA: Script Sprachdefinition
* Unterschiede der Browser IE zu Firefox

Donnerstag, 23. Oktober 2008

Perl Dprof and POE

Hey,
for all those who wants to use the Devel::DProf (the Perl code profiler,
perl -d:DProf
) together with POE (portable multitasking and networking framework for Perl) and are getting the error:

panic: Devel::DProf inconsistent subroutine return at /usr/lib/perl5/site_perl/5.10.0/POE/Kernel.pm line 822.


and also waiting on for the Bug fix (the label-goto-jump situation), may use the following workaround:

- change in the file /usr/lib/perl5/site_perl/5.10.0/POE/Kernel.pm the

POE::Resources->load();


with

# POE::Resources->load();
eval "package POE::Kernel; use POE::Resource::Aliases";
eval "package POE::Kernel; use POE::Resource::Events";
eval "package POE::Kernel; use POE::Resource::Extrefs";
eval "package POE::Kernel; use POE::Resource::FileHandles";
eval "package POE::Kernel; use POE::Resource::SIDs";
eval "package POE::Kernel; use POE::Resource::Sessions";
eval "package POE::Kernel; use POE::Resource::Signals";
eval "package POE::Kernel; use POE::Resource::Statistics";


Ok thats not the fine art, but it is working. Possibly the Statement:

sub load {
my $package = (caller())[0];

in file /usr/lib/perl5/site_perl/5.10.0/POE/Resources.pm triggers the DProf Bug. But that does only the maintainer know ;-)

Sonntag, 19. Oktober 2008

Wo ist die Bandbreite hin?

Hallo,
toll ist das Web 2.0 schon. AJAX auch eine gute Idee um Bandbreite zu sparen und Internetseiten zu beschleunigen (um wirklich das Gefühl zu bekommen, schnelleres Internet zu haben).

Allerdings scheinen auch einige Webseitenbetreiber (wie www.flybmi.com) dies negativ auszunutzen. Was ich auch an dieser Stelle einmal kritisieren muss, ist das diese Seite jeden einzelnen Click den der Webseitenbesucher tätigt auch tatsachlich nach Hause, zur Auswertung, schickt (Schäuble lässt grüßen, Willkommen Stasi 2.0). Mag sein das die Webprogrammierer "nur" die Applikation testen wollen (da diese Webpräsentation im "Debug"-Modus gefahren wird).
Jedoch ist das nicht die feine Art, die Bandbreite zu schmälern.

Also, wer das nicht glauben mag, der kann sich das Paket "Wireshark" (vormals Ethereal) herunterladen und während eines Webseitenbesuches bei dieser Fluggesellschaft mal den Datenverkehr mit schneiden (am Besten mit der Filtereinstellung 'http').

Wenn wir schon einmal bei der Frage nach der verlorenen Bandbreite sind, kann ich empfehlen sich den Source Code jener Beispielseite anzuschauen.
Welch Greul!

Ich verstehe schon die Argumentation für den Einsatz eines Frameworks. Aber haben sich die Webprogrammierer jemals den Quellcode angesehen?
Traurigerweise vermisst man (wie so oft) die W3C-Konformität. Schwerwiegender ist aber die Vergeudung der Bandbreite mit dem sinnfreiem Übertragen von "\n" (Newlines). Beispiel (die Ergebnisseite wird betrachtet): gibt für einen einfachen Flug 246 Zeilen (von insgesamt 398) mit Müll aus (Zeilen die nur am Zeilenanfang ein Newline haben).
Es mag durchaus nicht viel sein, doch überlegt man sich einmal die die Größenordnung für einen Tag bzw. für viele Nutzer.
So passiert es also, das man trotz steigender verfügbare Bandbreite nicht unbedingt auch schnelleres Internet bekommt.

Grüße,

Freitag, 18. Juli 2008

BlobbyVolley for OpenSUSE 11.0


Finally I packaged Blobby for the distribution (after applying some small fixes, like adding the
#include <algorithm>
statement).
For those who do not know Blobby:

BlobbyVolley is the head-to-head multiplayer volleyball game. It is one of the best games to be played between some ego-shooters (like Unreal Tournament or Quake) at LAN-partys :-)

At least to play you need to change:



  • create in your home directory (e.g. mkdir /home/pkirsch/.blobby) the ".blobby" directory.
  • copy from /usr/share/games/blobbyvolley/ the data directory in your freshly created .blobby directory
  • Why? some config files are needed to start BlobbyVolley
  • If you have problems with starting the game in your OpenSUSE then change in your config.xml (located in your .blobby directory)


    <?xml version="1.0" encoding="utf-8"?>

    <userconfig>
    <var name="device" value="SDL"/>
    <var name="fullscreen" value="false"/>
    <var name="left_blobby_color_r" value="0"/>
    <var name="left_blobby_color_g" value="0"/>
    <var name="left_blobby_color_b" value="255"/>
    <var name="left_blobby_oscillate" value="false"/>
    <var name="right_blobby_color_r" value="255"/>
    <var name="right_blobby_color_g" value="0"/>
    <var name="right_blobby_color_b" value="0"/>
    <var name="right_blobby_oscillate" value="false"/>
    <var name="left_script_name" value="dumbjump.lua"/>
    <var name="right_script_name" value="simbel.lua"/>
    <var name="left_player_human" value="true"/>
    <var name="right_player_human" value="true"/>
    <var name="left_player_name" value="Left Player"/>
    <var name="right_player_name" value="Right Player"/>
    <var name="gamefps" value="75"/>
    <var name="global_volume" value="0.960000"/>
    <var name="mute" value="false"/>
    <var name="scoretowin" value="15"/>
    <var name="showfps" value="false"/>
    <var name="blood" value="false"/>
    <var name="background" value="strand1.bmp"/>
    <var name="network_side" value="0"/>
    <var name="network_last_server" value="blobby.openanno.org"/>
    </userconfig>

    change the string "OpenGL" to "SDL" and it should work (otherwise open me a bug at Novell's Bugzilla)
  • Some hint: Some libraries are needed: SDL physfs boost but they should all installable with zypper in SDL physfs boost

Sources and Wiki:


BlobbyVolley at sf.net

Mittwoch, 9. Juli 2008

Spielen unter Linux: bomberclone (Bomberman) mit Joypad

Warum der Aufwand?


Linux mit seiner Spielvielfalt kann durchaus als Nintendos WII Ersatz (alternativ auch Sonys Playstation 3) genutzt werden und da Studenten im Allgemeinen nicht so viel Geld zur Verfügung haben, muss man sich eben einen Spielkonsole-Klon selbst schaffen :-). Die Erfahrung hat gezeigt: Spielekonsolen sind oft nur für einen Monat interessant und landen danach in der Ecke. Außerdem bekommt so der alt-gediente Pentium III 800 MHz noch einmal neues Leben, in Kombination mit einem großen TFT Monitor oder Flachbildschirm.

Die WII ist eher als gesellschaftliches Party-Spielgerät orientiert und genau das will ich auch mittels Linux (in dem Fall OpenSUSE 11.0) und den Arcade Klassikern haben.

Am liebsten wäre mir eine Linux Distribution (wie Knoppix) einfach ins CDRom Laufwerk, booten und direkt auswählen, welches Spiel nun gestartet werden soll.

Dabei gibts aber Probleme:

  • es fehlt die Keypad (oder Joypad) Unterstützung in vielen Spielen (und versuche einmal auf die Schnelle deinen Freunden die "WASD" Spielesteuerung bzw. die zweifach oder vielfache belegte Tastatur/Tastenkombination zu erklären). Da ist ein USB basierendes Joypad für 5€ von Ebay schon Gold wert. Zumal wer möchte sich schon zu dritt eine Tastatur teilen, nur um ein Spiel zu bedienen (alternativ kann man jedem Mitspieler auch seine eigene USB-Tastatur geben)? Diese liegen eher unhandlich auf dem Schoß und man kann sein Bier nicht ordentlich trinken kann, eben weil man die Tastatur festhalten muss.

  • das zweite Problem der Distribution wäre die automatische Grafikkarteninstallation (out-of-the-box) ohne umständigerweise die Online-Repositories von ATI oder Nvidia zu installieren und danach die Grafikkarten erstmal einzurichten (bzw. auch den X-Server).



Bomberclone


Dieses Spiel ist Bestandteil der OpenSUSE 11.0 Distribution und kann somit ohne Probleme mit zypper in bomberclone installiert werden.

Joystick bzw. Joypad



  • nach dem Anstecken des Joypads an den USB Port sollte man in der Ausgabe von /bin/dmesg folgendes entdecken:


    usb 5-1: new low speed USB device using uhci_hcd and address 24
    usb 5-1: configuration #1 chosen from 1 choice
    input: GreenAsia Inc. USB Joystick as /devices/pci0000:00/0000:00:1d.3/usb5/5-1/5-1:1.0/input/input29
    input,hidraw1: USB HID v1.10 Joystick [GreenAsia Inc. USB Joystick ] on usb-0000:00:1d.3-1
    usb 5-1: New USB device found, idVendor=0e8f, idProduct=0012
    usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    usb 5-1: Product: USB Joystick
    usb 5-1: Manufacturer: GreenAsia Inc.

  • folgend sollte "/dev/js0" vorhanden sein (also der erste Joystick)
  • um zu prüfen ob sie Signalübertragung auch funktioniert (funktionalen Test) kann man ein "cat /dev/js0" ausführen. Anschließend sollte die Ausgabe diverse Zeichen bei Betätigung der Achsen bzw. der Aktionsknöpfe enthalten.

Beispiel zur Joystickabfrage



/* Tipp: http://de.wikibooks.org/wiki/SDL:_joypad
kompilieren mit :
gcc joypad.c -o joypad `sdl-config --libs` `sdl-config --cflags` */

#include
#include "SDL.h"

int main ()
{
int i;
unsigned int n;
short a;

if ( SDL_InitSubSystem ( SDL_INIT_JOYSTICK ) < 0 )
{
fprintf ( stderr, "Unable to initialize joypad: %s\n", SDL_GetError() );
return -1;
}
printf ( "Es sind %i joypads erkannt.\n", SDL_NumJoysticks () );

/* Hier wird allerdings nur der erste joypad verwendet*/
SDL_Joystick* joypad = SDL_JoystickOpen ( 0 );
if ( joypad == NULL ) {
printf ( "joypad konnte nicht geöffnet werden.\n" );
return -2;
}

printf ( "joypad hat %i Achsen\n", SDL_JoystickNumAxes ( joypad ) );
printf ( "joypad hat %i joypads\n", SDL_JoystickNumBalls ( joypad ) );
printf ( "Joypad hat %i Köpfe\n", SDL_JoystickNumHats ( joypad ) );
printf ( "Joypad hat %i Knöpfe\n", SDL_JoystickNumButtons ( joypad ) );

SDL_JoystickEventState ( SDL_QUERY );

while ( 1 )
{
SDL_JoystickUpdate ();
for ( i=0; i < SDL_JoystickNumButtons ( joypad ); ++i )
{
n = 0;
n = SDL_JoystickGetButton ( joypad, i );
if ( n != 0 )
printf ( "Knopf gedrückt: %i\n", i );
}
for ( i=0; i < SDL_JoystickNumAxes ( joypad ); ++i )
{
a = 0;
a = SDL_JoystickGetAxis ( joypad, i );
if ( a != 0 )
printf ( "Achse %i betätigt mit Wert %d\n", i,a );
}
}
}
return 0;
}


Joypad Patch für Bomberclone


Mit Hilfe des obigen Beispiels ist/war es ein leichtes das Spiel zu erweitern. Wer mag kann Bomberclone auch einmal abends mit seinen Freunden spielen. Ich habe den Patch dem Maintainer übergeben und er dürfte bei dem nächsten Update der Distribution mit dabei sein.

Resumee
Der Spielspass mit Joypad ist einfach unübertroffen.

Dienstag, 1. April 2008

VPN with IPv6 via strongSwan

Hallo,
diesmal schreibe ich eine kurze Einleitung in die Benutzung von strongSwan, um ein kleines VPN (virtuelles privates Netzwerk) aufzubauen.

Versuchsaufbau:
- ein Hostcomputer mit VMware 1.0.4
- Basis SLES 10 SP1, alternativ auch neuere Service Pack Versionen oder OpenSUSE 10.3 verwenden
- strongswan, die "the OpenSource IPsec-based VPN Solution for Linux"

Aufsetzen:
- VMWare installieren und zwei virtuelle Rechner ebenfalls mit SLES 10 SP 1 installieren
- auf dem Hostsystem die bridge-utils installieren (z.B. yast -i bridge-utils
- zusätzlich in den virtuellen Instanzen das Paket "strongswan" via YaST installieren (z.B. yast -i strongswan)
- mittels der "VMWare Server Console" die Instanz A (gemeint ist die erste virtuelle Installation) an das "/dev/vmnet1" binden (Tipp: über den Dialog "Virtual Machine Settings"->"Hardware"->"Network Connection"->"Custom Specific virtual network"->"/dev/vmnet1");
den selben Schritt für die Instanz B erledigen, allerdings diese Instanz B an das "/dev/vmnet8" binden
- nun wird die Bridge auf dem Host eingerichtet:
* Bridge erstellen: brctl addbr br0
* Netzwerk Schnittstellen hinzufügen: brctl addif br0 vmnet1;brctl addif br0 vmnet8
* Bridge Einstellungen verifizieren: brctl show
* Bridge aktiv markieren: ifconfig br0 up
* ein kleiner Tipp, die Bridge braucht eine Weile bis diese aufgebaut ist, nicht wundern wenn im ersten Moment der ping-Versuch in den Instanzen nicht klappen sollte
* Ziel ist es die beiden Instanzen in einem eigenen Netz zu haben, um den Netzwerkverkehr nicht zu verunreinigen
- Wir führen nun die Definition ein:
* die Instanz A (die erste Installation) wird nun im folgenden Kontext als "sun" referenziert
* die Instanz B (die zweite Installation) wird nun im folgenden Kontext als "moon" referenziert

- Auf der Instanz A der Einfachheit halber den Dienst dhcp deaktivieren und manuell eine IP-Adresse festlegen, entweder via yast lan oder manuell mit killall dhcpcd; ifconfig eth0 192.168.1.1/24 up. Die IPv6 Adresse wird manuell mit "ifconfig add FD53:7553:4500::1/48" festgelegt, der Grund folgt.
- Auf der Instanz B ebenfalls der Einfachheit halber den Dienst dhcp deaktivieren und manuell eine IP-Adresse festlegen, entweder via yast lan oder manuell mit killall dhcpcd; ifconfig eth0 192.168.1.2/24 up. Die IPv6 Adresse wird manuell mit "ifconfig eth0 add FD53:7553:4500::2/48" festgelegt, der Grund folgt.

Zertifikate
Nun werden mittels Yast2 die benötigten Zertifikate (Public/Private Key) erzeugt. Die Zertifikate werden für die Protokolle IKEv1 sowie IKEv2 benötigt.
- auf der Instanz A yast ca-mgm aufrufen
- falls noch keine CA (Certificate Authority; hier Root-CA) existiert, eine neue erstellen
- der CA-Name kann z.B. mit "ipsec-test-ca" belegt werden, eine Email Adresse muss ebenfalls festgelegt werden sowie der allgemeine Name, vorteilhaft ist es auch das Land, die Firma sowie die Abteilung mit Daten zu füllen
- im folgenden Dialog das Passwort festlegen und noch zwei mal bestätigen
- nun wird man wieder zum CA-Baum zurückgeleitet
- die erzeugte "ipsec-test-ca" betreten
- dieses CA muss nun exportiert werden; via "Erweitert"->"In Datei exportieren"
* dazu das Format "Nur das Zertifikat in PEM-Format" auswählen und nach "/root/ipsec-test-ca.pem" speichern.
(Hinweis; dieses Zertifikat müssen alle Teilnehmer bekommen, dazu später)
- es werden die einzelnen Host Zertifikate für die Teilnehmer erstellt:
* im Yast "Zertifikate" auswählen, "Hinzufügen"->"Server-Zertifikat hinzufügen" wählen
* der folgende Dialog benötigt einen allgemeinen Namen (hier den Hostnamen wählen, z.B. "d169") und die Email Adresse eingeben, danach das Passwort festlegen und final bestätigen
* in der Übersicht erscheint nun ein neues Zertifikat, welches Yast auch schon mit dem Root-CA signiert hat
* das erstellte Zertifikat nun nach "/root/d169.pem" exportieren, diesmal in dem Dialog "Zertifikat und Schlüssel nicht verschlüsselt im PEM-Format" auswählen (die Begründung folgt später)
* für jeden Host nun diese oben gezeigte Prozedur wiederholen, d.h. für jeden Host ein Zertifikat erstellen

ipsec Konfiguration
In diesem Kontext gehen wir von einer Host-Host Verbindung aus.
- im vorigen Schritt wurde das CA Zertifikat (hier "/root/ipsec-test-ca.pem") erstellt, dieses muss nun auf die teilnehmenden Instanzen verteilt werden und dort in dem Verzeichnis /etc/ipsec.d/cacerts/ abgelegt werden.
- die jeweiligen Host Zertifikate (welche von mittels Yast erstellt worden) müssen nun zerlegt werden, am Beispiel von dem "/root/d169.pem", wie man sieht enthält diese Datei einen "CERTIFIKATE" und einen "RSA PRIVATE KEY" Abschnitt, diese müssen getrennt werden:
* der "RSA PRIVATE KEY" Abschnitt wird ausgeschnitten und in eine zweite Datei gespeichert ("d169.pem.2"), es handelt sich wie der Name schon sagt um den Private Key, der gemäß der ipsec Konfiguration in das "/etc/ipsec.d/private/" Verzeichnis kopiert cp /root/d169.pem.2 /etc/ipsec.d/private/d169.pem werden muss, Tipp der Name muss gleich sein, die Namesendung kann beliebig sein.
* der "CERTIFICATE" Abschnitt wurde in der "d169.pem" Datei belassen, diese Datei muss dann nach "/etc/ipsec.d/certs/" kopiert werden cp /root/d169.pem /etc/ipsec.d/certs/
* die eben genannte Prozedur muss nun auch für das zweite erstelle Zertifikat (also für Instanz B) erledigt werden

- Konfiguration der "/etc/ipsec.secret" auf Instanz A:

#
# ipsec.secrets
#
# This file holds the RSA private keys or the PSK preshared secrets for
# the IKE/IPsec authentication. See the ipsec.secrets(5) manual page.
#
: RSA d169.pem ""


- Konfiguration der "/etc/ipsec.secret" auf Instanz B erfolgt ähnlich lediglich muss der Zertifikatsname "d169.pem" angepasst werden.

- Konfiguration der "/etc/ipsec.conf" auf Instanz A:

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
# plutodebug=all
crlcheckinterval=180
strictcrlpolicy=no
# cachecrls=yes
# nat_traversal=yes
# charonstart=no
# plutostart=no

conn test
keyexchange=ikev1
left=192.168.1.1
leftcert=d169.pem
right=192.168.1.2
rightid="C=DE, O=ORGA, OU=QA, CN=g20, E=email@domain.de"
auto=add

- Hierbei gilt es zu beachten das "left" sich immer auf die lokale Maschine bezieht und "right" auf die entfernte
- die "rightid" muss dem subject des entfernten Keys (der Instanz B) entsprechen, Tipp: zum anschauen des subjects openssl x509 -noout -text -in /etc/ipsec.d/certs/d169.pem, es dürfen z.B. nicht die Wertezuordnungen vertauscht werden

- Konfiguration der "/etc/ipsec.conf" auf Instanz A:

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
# plutodebug=all
crlcheckinterval=180
strictcrlpolicy=no
# cachecrls=yes
# nat_traversal=yes
# charonstart=no
# plutostart=no

conn home
keyexchange=ikev1
left=192.168.1.2
leftcert=g20.pem
right=192.168.1.1
rightid="C=DE, O=ORGA, OU=QA, CN=d169, E=email@domain.de"
auto=add


Testen
- andere Netzwerkdienste deaktieren (z.B. novell-zmd, postfix), da diese den vereinfachten Test beeinflussen könnten (bzw. den tcpdump unnötig aufblähen)
- ipsec start auf beiden Instanzen
- am besten mit tail -f /var/log/messages den Startprozess beobachten und nach Fehler suchen:
* essentiell ist es, dass "loaded private key file" und "loaded host cert file" zu lesen ist und keinerlei Fehler folgt
* weiterhin muss eine Nachricht:

added configuration 'test': 192.168.1.1[C=DE, O=ORGA, OU=QA, CN=d169, E=email@domain.de]..
.192.168.1.2[C=DE, O=ORGA, OU=QA, CN=g20, E=email@domain.de]
zu finden sein

- der Test wird mit ipsec up test gestartet und sollte für dieses Beispiel so aussehen (Ausgabe von ipsec statusall):

000 "test": 192.168.1.2[C=DE, O=ORGA, OU=QA, CN=g22, E=email@domain.de]...192.16
8.1.1[C=DE, O=ORGA, OU=QA, CN=d169, E=mail@domain.de]; erouted; eroute owner: #
4
000 "test": CAs: 'C=DE, O=ORGA, OU=QA, CN=ipsec-test-ca, E=email@domain.de'...
'%any'
000 "test": ike_life: 10800s; ipsec_life: 3600s; rekey_margin: 540s; rekey_fuz
z: 100%; keyingtries: 3
000 "test": policy: RSASIG+ENCRYPT+TUNNEL+PFS+UP+MOBIKE; prio: 32,32; interfac
e: eth0;
000 "test": newest ISAKMP SA: #3; newest IPsec SA: #4;
000 "test": IKE algorithms wanted: 7_128-2-14,
000 "test": IKE algorithms found: 7_128-2_160-14,
000 "test": IKE algorithm newest: AES_CBC_128-SHA-MODP2048
000 "test": ESP algorithms wanted: 12_128-2, 3_000-1,
000 "test": ESP algorithms loaded: 12_128-2_160, 3_192-1_128,
000 "test": ESP algorithm newest: AES_128-HMAC_SHA1; pfsgroup=
000
000 #4: "test" STATE_QUICK_I2 (sent QI2, IPsec SA established); EVENT_SA_REPLACE
in 2532s; newest IPSEC; eroute owner
000 #4: "test" esp.271da22c@192.168.1.1 (0 bytes) esp.91c42a79@192.168.1.2 (0 by
tes); tunnel
000 #3: "test" STATE_MAIN_I4 (ISAKMP SA established); EVENT_SA_REPLACE in 10205s
; newest ISAKMP
000
Performance:
worker threads: 10 idle of 16, job queue load: 0, scheduled events: 0
Listening IP addresses:
192.168.1.2
fd53:7553:4500::2

- sollte man den Fehler "INVALID_ID_INFORMATION" in /var/log/messages lesen, so sollte man die Konfiguration prüfen (im Besonderen den rightid String auf Schreibfehler prüfen und vor allem mit dem subject String des Zertifikates vergleichen [siehe oben, openssl Befehl])
- folgend die Konfiguration mit IPv6 Adressen:
* dabei sind eigentlich nur auf Instanz A und B in der "/etc/ipsec.conf" die Tags left und right mit den jeweiligen IP-Adressen zu versehen:
* Instanz A, "/etc/ipsec.conf":

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
# plutodebug=all
crlcheckinterval=180
strictcrlpolicy=no
# cachecrls=yes
# nat_traversal=yes
# charonstart=no
# plutostart=no

conn test
keyexchange=ikev1
left=FD53:7553:4500::1
leftcert=d169.pem
right=FD53:7553:4500::2
rightid="C=DE, O=ORGA, OU=QA, CN=g20, E=email@domain.de"
auto=add

* Instanz B, "/etc/ipsec.conf":

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
# plutodebug=all
crlcheckinterval=180
strictcrlpolicy=no
# cachecrls=yes
# nat_traversal=yes
# charonstart=no
# plutostart=no

conn test
keyexchange=ikev1
left=FD53:7553:4500::2
leftcert=g20.pem
right=FD53:7553:4500::1
rightid="C=DE, O=ORGA, OU=QA, CN=d169, E=email@domain.de"
auto=add

* in diesem Beispiel muss ipsec neu gestartet werden ipsec stop; ipsec start, danach sollte die Kommunikation auch über die IPv6 Adresse funktionieren:

IKE_SA 'test' established between C=DE, O=ORGA, OU=QA, CN=g22, E=email@domain.de
[fd53:7553:4500::2]...[fd53:7553:4500::1]C=DE, O=ORGA, OU=QA, CN=d169, E=email
@domain.de
CHILD_SA 'test' established successfully

* Hinweis: die Ausgabe von ifconfig eth0 auf den Instanzen gibt schon eine vordefinierte IPv6 Adresse aus, diese ist allerdings link lokal. Es muss für diesen IPv6-Test eine globale Adresse gewählt werden um den Verbindung erfolgreich durchführen zu können (obwohl die link lokalen IPv6 Adressen untereinander [zwischen den Instanzen A und B] ping-bar sind).

Zum Abschluss noch den Verweis auf die strongSwan Dokumentation:
Host zu Host
IPv6 Results

Mittwoch, 27. Februar 2008

Network failover with quagga (ospfd)

Hallo,

diesmal in Deutsch.
Für das erfolgreiche ausweichende Routing (das Benutzen anderer Netzwerkkarten, bekannt als failover, einfache Hochverfügbarkeit) kann man das Paket quagga (z.B. in der OpenSUSE 10.3 Distribution) nutzen.

Quagga (vormals Zebra)
hierbei ist "Free Routing Software (for BGP, OSPF and RIP, for example)".

Hier ein Beispiel mit zwei virtuellen Instanzen (via Xen) auf einem Hostsystem. Ziel ist es die ICMP -'ping' Aufforderung bei dem Ausfall einer Netzwerkroute auf die andere umzuleiten.

Konfiguration:
- einen Xen Host, mit zwei virtuellen Instanzen,
- die Instanz A ist mit drei virtuellen Netzwerkkarten, die Instanz B ist mit zwei Netzwerkkarten ausgerüstet,
- beide sind über das Xen Domain0 Routing miteinander verbunden (das ist Standard)
- beide Instanzen verfügen über eine OpenSUSE 10.3 Standardinstallation mit zusätzlichem Paket quagga

Instanz A:
Nun müssen die Dateien ospfd.conf und zebra.conf editiert werden:
linux-ynzp:~ # cat /etc/quagga/ospfd.conf
hostname node1-ospf
password quagga
enable password quagga
debug ospf zebra
log file /var/log/quagga/ospfd.log debugging
!
!
!
interface eth2
!
interface eth4
!
interface lo
!
interface eth3
!
router ospf
redistribute connected
!passive-interface eth3
!passive-interface eth4
!passive-interface eth2
network 192.168.1.0/24 area 0.0.0.0
network 192.168.2.0/24 area 0.0.0.0
network 192.168.3.0/24 area 0.0.0.0
network 172.16.1.0/24 area 0.0.0.0
!
line vty
!

linux-ynzp:~ # cat /etc/quagga/zebra.conf
hostname node1-quagga
password quagga
enable password quagga
log file /var/log/quagga/quagga.log
!
interface eth2
ipv6 nd suppress-ra
!
interface eth1
ipv6 nd suppress-ra
!
interface lo
!
interface eth3
ipv6 nd suppress-ra
!
interface eth4
ipv6 nd suppress-ra
!
interface eth0
ipv6 nd suppress-ra
!
ip forwarding
!
line vty
!

Instanz B
die Konfigurationsdaten:
linux-5c5k:~ # cat /etc/quagga/ospfd.conf
hostname node2-ospf
password quagga
enable password quagga
debug ospf zebra
log file /var/log/quagga/ospfd.log debugging
!
!
!
interface eth0
!
interface eth1
!
interface lo
!
interface eth2
!
router ospf
redistribute connected
network 192.168.1.0/24 area 0.0.0.0
network 192.168.2.0/24 area 0.0.0.0
network 192.168.3.0/24 area 0.0.0.0
line vty

linux-5c5k:~ # cat /etc/quagga/zebra.conf
hostname node2-quagga
password quagga
enable password quagga
log file /var/log/quagga/quagga.log
!
interface eth2
ipv6 nd suppress-ra
!
interface eth1
ipv6 nd suppress-ra
!
interface lo
!
interface eth0
ipv6 nd suppress-ra
!
ip forwarding
!
line vty

Zusammendfassend
Es müssen auf beiden Instanzen der ospfd sowie der zebra Dienst laufen:
rcospfd start
rczebra start

Versuchsaufbau der Instanzen

Ergänzung: die Benennung der Interfaces (eth2-eth4) ist beliebig, wichtig ist nur:

eth4 eth2, eth3 eth0, eth1
------------- 192.168.1.1/24 --- 192.168.1.2/24 -------------
172.16.1.0 -- Instanz A- - Instanz B-
------------- 192.168.2.1/24 --- 192.168.2.2/24 -------------

Das Instanz A ein Netzwerk hat, welches nur Instanz A kennt.



Netzwerkausfall Simulation
Wichtig ist es die Netzwerkarten hochzufahren:
linux-ynzp:~ # cat setup.sh
#!/bin/bash -x
#ifconfig eth0 down
#ifconfig eth1 down
ifconfig eth2 down
ifconfig eth3 down
ifconfig eth4 down

#ifconfig eth0 192.168.1.1/24 up
#ifconfig eth1 192.168.2.1/24 up
ifconfig eth2 192.168.1.1/24 up
ifconfig eth3 192.168.2.1/24 up
ifconfig eth4 172.16.1.1/16 up
ifconfig

Auf Instanz A nutzt man hierbei folgenden Skript:
linux-ynzp:~ # o interface_cycle.sh
#!/bin/bash -x
ifconfig eth2 up
ifconfig eth3 up
while true; do
echo "neustart";
sleep 1;
ifconfig eth2 down;
sleep 20;
ifconfig eth2 up;
sleep 1;
ifconfig eth3 down;
sleep 20;
ifconfig eth3 up;
sleep 3;
ifconfig eth2 down;
ifconfig eth3 down;
sleep 3;
ifconfig eth3 up
ifconfig eth2 up
ps aux | grep ospf
done

Wie man leicht sehen kann, es schaltet periodisch einzelne Netzwerke ab und zwingt damit den OSPF Dienst dieses bei den Partnersystem (Instanz B) bekannt zu machen.


Auf der Instanz B:
fährt man ebenfalls die Netzwerkkarten hoch:
linux-5c5k:~ # cat setup.sh
#!/bin/bash -x
ifconfig eth0 down
ifconfig eth1 down
ifconfig eth2 down

ifconfig eth0 192.168.1.2/24 up
ifconfig eth1 192.168.2.2/24 up
ifconfig eth2 192.168.3.2/24 up
ifconfig

Danach erfolgt dann die Ping-Aufforderung:
ping 172.16.1.1
Zeitgleich kann man sich das Ergebnis anschauen:
while true; do route -n | grep 172; sleep 2;done
Mit der Schleife sieht man die Veränderung der Routingschnittstelle.

Dazu startet man auf der Instanz das Skript interface_cycle.sh, danach kann man die Veränderung der Routingschnittstelle auf der Instanz B verfolgen.

Ergebnis:
bei der Abschalten der Netzwerkarte auf Instanz A erfolgt ein Routingwechsel auf Instanz B:

64 bytes from 172.16.1.1: icmp_seq=3 ttl=64 time=0.110 ms
64 bytes from 172.16.1.1: icmp_seq=4 ttl=64 time=0.082 ms
172.16.0.0 192.168.1.1 255.255.0.0 UG 20 0 0 eth0
64 bytes from 172.16.1.1: icmp_seq=5 ttl=64 time=0.096 ms
64 bytes from 172.16.1.1: icmp_seq=6 ttl=64 time=3.64 ms
172.16.0.0 192.168.1.1 255.255.0.0 UG 20 0 0 eth0
64 bytes from 172.16.1.1: icmp_seq=7 ttl=64 time=0.072 ms
64 bytes from 172.16.1.1: icmp_seq=8 ttl=64 time=0.104 ms
172.16.0.0 192.168.2.1 255.255.0.0 UG 20 0 0 eth1
64 bytes from 172.16.1.1: icmp_seq=9 ttl=64 time=3.18 ms
64 bytes from 172.16.1.1: icmp_seq=10 ttl=64 time=0.105 ms
172.16.0.0 192.168.2.1 255.255.0.0 UG 20 0 0 eth1
64 bytes from 172.16.1.1: icmp_seq=11 ttl=64 time=0.101 ms
64 bytes from 172.16.1.1: icmp_seq=12 ttl=64 time=0.081 ms

CUDA, part2

Hey,
here is only a small update on the CUDA example . The idea behind this is available on idea.opensuse.org.

Bye

Donnerstag, 14. Februar 2008

Aircrack speed up with CUDA

Hey,
recently I created a patch (better a aircrack trunk), which is capable of using NVIDIA's CUDA interface.

So what changed?
- parts of the function body of "crack_wep_thread" changed to separate the KoreK attack steps in a (in real that are 32 ) GPU thread.

For now, the negative part?
- maximal 16KByte local variables transmission towards GPU, due to this at the moment only 15 of 17 Korek attacks possible (error message: "Entry function '_Z13KoreK_attacksPlS_PiS0_S0_PhS0_S1_S0_' uses too much local data (0x40 bytes + 0x4700 bytes system, 0x4000 max)"
- the votes matrix is (sadly) serialized for transmission to GPU (sadly on CPU)
- at least, I do not know, how the GPU threads are working, so is there really a loop unrolling towards the threads?
-> If not, then the for-loop has to be parallelized too
- probably there is a mutex problem, if max_cpu is too small the program exits, I tried it with max_cpu=1 and the program stops with the message not enough IVs present, but from debug messages I see, that it did not try all the whole read IVs
- Still do not know if the calculated values are correct (better: valid), for the moment it is only interesting, that there is speed up.

What is the benefit (performance)?
Some data*:
- this aircrack
airrack + GPU + 03:
~8480.5 keys/s
[00:00:07] Tested 62206 keys
[00:00:18] Tested 151153 keys
[00:01:01] Tested 504845 keys
[00:01:42] Tested 852933 keys

- aircrack Aircrack-ng 0.9.2
~5644.9 keys/s
[00:00:06] Tested 28673 keys
[00:00:19] Tested 123649 keys
[00:01:02] Tested 350977 keys
[00:02:01] Tested 681473 keys

-> round about 50% faster, by transferring one calculation-intensive function to GPU
* Colfax, 2x Dual-Core AMD Opteron(tm) Processor 2218, 8GB DRAM ECC, Tyan S2915 MCP55, GeForce 8800 GT, SLES-10-SP1

What will be changed?
- the function "do_wep_crack1" is a real good candidate for transferring it on GPU . The functions includes a lot of for-loops which seems pretty promising for speed up.

Mittwoch, 23. Januar 2008

Gaming with Linux, speed up

Btw, here is my configuration (instruction) for games (hardware: my good old Intel Pentium III, 786 MByte RAM, OpenSUSE 10.2, Nvidia Geforce MX2 400 32MByte):
* first do a init 1
* /etc/rc.d/boot.udev start
udev is needed for sound card device creation ("/dev/dsp")
* /etc/init.d/alsasound start
this starts your sound card
* dhcpd eth0
of course start the ethernet network, you probably want to play online
* chmod 0777 /dev/dsp
so you can use your sound card
* X & xterm -display :0.0 &
this starts a X-server, most games like America's Army need a running X server
* with the started xterm, you can start your preferred game
of course you should now change from root user to your day-by-day user
* su yourusername

The noticed performance benefit is overwelming. A nearly empty process table, excellent. So for America's Army v2.5 in runlevel 5 with Gnome the game judders, within the minimalistic it runs fluid. Sadly I cannot provide any frames per second.
But with this, my good old P III is still competive.

Samstag, 5. Januar 2008

Privacy!

Hi,
i can only encurage everybody to run tor+privoxy+squid for your (web) anonymity. As of the 1st January 2008 in Germany the "Vorratsdatenspeicherung"/1/ /2/ started and every IP based access is logged from your internet service provider and can be used against you. So be aware if you are surfing torrent sites :-) . One good solution is tor (the onion router), tor is a set of proxy hosts, where your request is routed between a huge set of tor-hosts. This makes your surfing slower of course. The benefit is that in the tor cloud there is no logging, so in past it is not (as current date) possible which way a request has gone. Important to remember is, that this kind of networking is still a Point to Point connection
.

OpenSUSE 10.3 provides the neccessary open source projects packets (source: http://download.opensuse.org/distribution/10.3/repo/oss/suse/x86_64/ for AMD64 X86_64[Hammer architecture]) privoxy-3.0.6-71.x86_64.rpm, squid-2.6.STABLE14-22.x86_64.rpm and torcs-1.3.0-81.x86_64.rpm but no fear you can install it out of the box via Yast2 :-).

In here the OpenSUSE 10.3 helps you:
- use Yast2 software installation and install privoxy, tor and squid
- do following configuration:
* enable in file "/var/lib/privoxy/etc/config" the line 1053 "forward-socks4a / localhost:9050", this is important for other services that they can use the SOCKS v4 protocol for transfver,
* copy the sample configuration file "/etc/tor/torrc.sample" to "/etc/tor/torrc" to default enable the tor
* create in your home directory the file "~/.kde/Autostart/tor", this one is for automatic starting the tor service with KDE start (if you use KDE), edit this file that it contains "#!/bin/bash
tor &", and make it executeable via chmod u+x tor
* now edit the file /etc/squid/squid.conf (ok it is a lot):
line 1034 "cache_dir ufs /var/cache/squid 100 16 256"
line 2544 "http_access allow localhost"
line 594 "cache_peer localhost parent 8118 7 no-query default"
line 2864 "visible_hostname localhost"
line 3777 "never_direct allow all"
- now start these services with rctor start, rcsquid start, rcvivoxy start (you need root priviledges)
- if you want these services be started with every boot time, do:
chkconfig privoxy on;chkconfig tor on; chkconfig squid on or configure it via Yast2 (of course as root)
- last but not least, configure your browser to use the proxy at 127.0.0.1:3128, for Firefox at configuration->network->connection
- do not forget, if you have other applications which uses internet to point them to use the local proxy to use tor, probably you have to set the SOCKS usage.

/1/ see the CCC (chaos computer club), http://chaosradio.ccc.de/cre051.html
/2/ http://www.vorratsdatenspeicherung.de/, http://de.wikipedia.org/wiki/Vorratsdatenspeicherung


More links:
- Tor FAQ
- Firefox Tor Button