Posts Tagged ‘Linux’

Zensursula: Teil 1 – DNS

by apoc · juni 27 2009 · one comment

“Sie werden sich noch wünschen wir wären Politikverdrossen” (@343max)

zensursula-300x292Ich hatte in den letzten Wochen den Eindruck, als ob die gesamte Internet-Gemeinschaft in Deutschland Sturm lief, überall gab und gibt es nur ein Thema: Die Internetzensur Bestrebungen der großen Koalition. Dabei hatte man am Ende den Eindruck gegen eine Mauer von Unkenntnis, Ignoranz aber vielleicht auch einfach blanker böswilliger Berechnung einfach nichts ausrichten zu können.
Besonders Enttäuschend empfand ich die Medien, überraschend war es freilich nicht dass sie praktisch ausschließlich Parteipropaganda nachplapperten und die Mainstream Meinung nach dem Willen der Regierung formten. Von investigativem Journalismus jedenfalls war in den Holzmedien nichts zu sehen, das überlässt man offenbar anderen.

Ein wenig Ironisch ist es schon, ist doch gerade das Internet die einzige breit zugängliche alternative Informationsquelle(wie wir eindrucksvoll sehen konnten), die mit der jetzt beschlossenen Infrastruktur möglicherweise schon bald stark eingeschränkt wird. Dabei geht es auch um die Frage ob wir der Regierung soweit vertrauen, nach der Installation einer bis dato einmaligen Infrastruktur für Zensur, bei der Sperrung von Kinderpornographischen Inhalten zu bleiben. In den letzten Jahren hat uns die große Koalition keinen Grund geliefert das zu glauben.

Die eigentliche Kluft wie häufig Thematisiert, liegt nicht zwischen den Internet-Natives und den “Internet-Ausdruckern” sondern vielmehr in dem Teil der Bevölkerung der sich unabhängig Informiert und dem Teil, der den großen Medien und Agenturen(auch im Internet) blind vertaut und als einzige Informationsquelle zur eigenen Meinungsbildung heranzieht, also den überwiegenden Teil der Gesellschaft.

Gestern nun hat die EU die Zensur in China gerügt(so Merkwürdig wie das auch immer ist), demnach vergessen wir einfach alles was die EU-Länder sonst so treiben und beschäftigen uns nun, offensichtlich im Wohlwollen der EU, um die aktiven technischen Möglichkeiten der Umgehung jedweder Zensur-Infrastruktur, außerdem kann es nicht schaden die von den Zensoren eingesetzte Technologie mal etwas genauer zu beleuchten.

In diesem ersten Teil soll es um die Zensur durch DNS Manipulationen gehen.

Es ist noch die leichteste Form der Zensur, die Einstiegsdroge der Staaten sozusagen, denn DNS Manipulationen lassen sich Kinderleicht aushebeln was wohl schnell den Wunsch nach härteren Mitteln wecken dürfte. Bei dieser Form der Zensur installieren die ISP’s die Sperrlisten in ihren DNS-Servern, ist doch zumindest anzunehmen, das die Mehrheit der Internet Nutzer die Server ihres Providers verwenden, wobei das bei leibe nicht immer der Fall ist. So war und ist es schon immer möglich seinen eigenen DNS-Server zu betreiben. Jetzt wo man allen Grund hat den DNS-Servern der Provider zu misstrauen, ist das eine sehr praktikable Möglichkeit, zumindest für diejenigen die sich mit dem Internet auskennen.
Doch der Reihe nach, im Prinzip reicht es statt eines Domain-Namens in der Adresszeile die Ip-Adresse einzugeben um diese Zensur zu umgehen, besser ist es da schon einen alternativen DNS-Server zu verwenden, vorzugsweise im Ausland, aber auch der CCC und der Foebud stellen unzensierte DNS-Server (noch) frei zur Verfügung. Listen mit freien Servern gibt es z.B. bei Wikileaks, dem CCC oder die Server des Open NIC Projektes.

DNS Caching Server

Nützlich ist auch das Einrichten eines eigenen Caching DNS-Servers der zufällig aus einer Liste, öffentliche Servern abfragt. Ich verwende dafür den pdnsd, nicht zu verwechseln mit dem vollwertigen DNS-Server, PowerDNS. Je nach Distribution sollte sich die Installation einfach gestalten, z.B. reicht ein pacman -S pdnsd um mit Arch Linux den Server zu installieren. Jetzt sollte man sich die Beispiel Konfiguration kopieren und Anpassungen vornehmen. Hier eine mögliche Beispielkonfiguration, es muss nur die server_ip angepasst werden:

global {
        perm_cache=512000; # cache groesse in KB (hier "leicht" uebertriebene 500 MB)
        cache_dir="/var/cache/pdnsd";
        run_as="nobody";
        server_ip=10.0.0.4; # ANPASSEN
        status_ctl=on;
        paranoid=on; # prevents cache poisoning
        query_method=udp_tcp;
        min_ttl=15m; # min/max TTL
        max_ttl=4w;
        timeout=15; # global timeout 15 seconds
        neg_rrs_pol=auth;
        par_queries=2; # maximale parallele abfrage von servern
}
 
server { # ein paar oeffentliche server (alle getestet)
        label = "random";
        randomize_servers = on;
        ip = 85.214.73.63, # foebud
        204.152.184.76, # ISC (USA)
        213.73.91.35, # CCC
        194.95.202.198, # DFN
        58.6.115.43, # Westnet (Australien)
        82.229.244.191, # Frankreich
        88.191.77.10, # Frankreich
	216.87.84.209, # OpenNIC
	88.191.77.10; # OpenNIC
        timeout=10; # 10 sekunden maximal
        uptest=ping;
        ping_timeout=400; #ms
        interval=30m; # uptest der server per ping
}
 
# Unveraendert aus Sample Conf:
# This section is meant for resolving from root servers.
server {
        label = "root-servers";
        root_server = on;
        randomize_servers = on; # Give every root server an equal chance
                                # of being queried.
        ip =    198.41.0.4
        ,       192.228.79.201
        ,       192.33.4.12
        ,       128.8.10.90
        ,       192.203.230.10
        ,       192.5.5.241
        ,       192.112.36.4
        ,       128.63.2.53
        ,       192.36.148.17
        ,       192.58.128.30
        ,       193.0.14.129
        ,       198.32.64.12
        ,       202.12.27.33
        ;
        timeout = 5;
        uptest = query;         # Test availability using empty DNS queries.
        interval = 30m;         # Test every half hour.
        ping_timeout = 300;     # Test should time out after 30 seconds.
        purge_cache = off;
        exclude = .localdomain;
        policy = included;
        preset = off;
}
 
# ganz praktisch, damit braucht man nur eine einzige hosts Datei im ganzen LAN zu pflegen:
source { 
        owner=localhost;
        serve_aliases=yes;
        file="/etc/hosts";
}

Ich habe alle DNS Server getestet. Eventuell die Konfiguration noch auf die eigenen Anforderungen anpassen, eine Dokumentation findet ihr hier. Die /etc/resolv.conf noch auf die lokale IP-Adresse umstellen dann den Server (neu)starten. Jetzt sollte er funktionieren, testen kann man das z.B. mit nslookup oder: dig 4poc.org [IP des DNS], dig zeigt auch wie lange er zum resolven brauchte.

Um festzustellen welche DNS-Server verwendet werden habe ich ein kleines Skript geschrieben, eigentlich passt die Thematik(siehe Anmerkung im Script) nicht direkt zum Thema aber den folgenden Artikeln sei schon mal etwas vorgegriffen: nstest.4poc.org (DNS Tester, falls jemanden einen besseren Namen dafür einfällt nur her damit.)

Tagged: , ,

Ivacy VPN unter Linux: PPTP/OpenVPN und Socks5-Gateway

by apoc · januar 24 2009 · 31 comments

Die VPN Provider sprießen, dank der “Sicherheits-Politik” in Europa und den USA, wie Pilze aus dem Boden. Seit Juli 2008 gibt es Ivacy, einem durchaus interessanten VPN-Anbieter über den es möglich ist sich der Vorratsdatenspeicherung Europas zu entziehen. Hier geht es mir darum zu zeigen wie man Ivacy unter Linux nutzen kann, genauer gesagt wie man OpenVPN und PPTP unter Linux einrichtet, die Country-Selection Funktion von Ivacy nutzt und wie man einen Socks5 Proxy einrichtet der Verbindungen über Ivacy weiterleitet, dazu später mehr. Diese Anleitung sollte nicht nur mit Ivacy funktionieren, alle VPN-Anbieter bieten OpenVPN oder PPTP(das proprietäre VPN Protokoll von Microsoft).
Update: Habe einen OpenVPN-Abschnitt eingefügt.
Update 4.2.09@20:50: OpenVPN-Abschnitt überarbeitet.
Update 8.2.09@22:15: Artikel nochmals überarbeitet.
Update 21.4.09@22:00: Privoxy-Abschnitt eingefügt.

Bevor es losgeht sollte ich vielleicht noch erwähnen das es sich hierbei um keine Anleitung für Linux-Anfänger oder Ubuntu/Suse-”Profis” handelt. *g* Read the rest of this entry »

Tagged: , , , , , , ,

xinetd: info script

by apoc · januar 22 2009 · 2 comments

Ich wollte von unterwegs aus den Status meines Heimservers abrufen können. Dabei ging es mir vorallem um die Temperatur von CPU, Mainboard und den Festplatten. Der auf sixserv.org laufende rbot(im Freenode idled der in #sixserv) soll auf Kommando den Status anzeigen. Soweit so gut. Ein kleines Ruby-Skript das auf dem Server zuhause läuft erfasst die Temperaturen per “sensors” und “hddtemp”. Der xinetd-Daemon konfigurierte ich daraufhin so das auf einen Port das Skript gebunden wird. Es erwartet bevor es die Daten übermittelt ein Passwort, einfach zum zusätzlichen Schutz auch wenn das vielleicht gar nicht nötig ist. Jemand der einen Portscan durchführt könnte eben so informationen zum System gelangen, die Passwortabfrage verhindert dies.

Zunächst zu dem Ruby-Script(z.B. /opt/botinfo.rb):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/ruby
 
i = Kernel.gets
if i.chomp != 'DASGEHEIMEPASSWORT' then
	# puts 'Wrong Password'
	exit
end
 
puts `uptime`.lstrip
 
# HDD Temps:
matches = `cat /proc/partitions`.scan /([s|h]d[a-z])/
matches.uniq!
matches.each do |disk|
	print "#{disk}: #{`hddtemp -n /dev/#{disk}`.chomp}.0*C (#{$1}GB) "
end
puts 
 
systemp = `sensors`
 
temp1 = systemp.scan /CPU Temp:    \+([0-9]+)\.0.C/
temp2 = systemp.scan /M\/B Temp:    \+([0-9]+)\.0.C/
 
puts "System: #{temp2[0]}.0*C #{temp2[1]}.0*C | CPUs: #{temp1[0]}.0*C #{temp1[1]}.0*C"

Hier muss natürlich sensors und hddtemp installiert sein, aber dieses Script kann praktisch alles mögliche an Informationen sammeln und ausgeben.
Die Konfiguration von xinetd gestaltet sich sehr einfach, in dem Verzeichnis /etc/xinetd.d einfach eine neue Datei für das Script erstellen(z.B. “botinfo”):

1
2
3
4
5
6
7
8
9
10
11
service botinfo
{
    disable         = no
    port            = 8888
    socket_type     = stream
    protocol        = tcp
    wait            = no
    user            = apoc
    server          = /opt/botinfo.rb
    type            = unlisted
}

Den Port, User und den Skript Pfad entsprechend anpassen und xinetd neu starten. Mit netcat kann es man danach testen:

1
2
3
4
5
$ nc localhost 8888
DASGEHEIMEPASSWORT
18:40:35 up 3 days, 41 min,  4 users,  load average: 0.00, 0.02, 0.20
sda: 30.0*C (10GB) sdb: 29.0*C (10GB)
System: 39.0*C 38.0*C | CPUs: 37.0*C 36.0*C

Der Port muss ggf. vom Router geforwarded werden damit ein Entfernter Server darauf zugreifen kann. Auch ein dyndns ist hilfreich, sofern man über keine statische IP verfügt. Ein einfaches rbot-Plugin um diese Daten vom irc aus abzufragen sieht z.B. so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require 'socket'
 
class BotinfoPlugin < Plugin
  def help(plugin, topic="")
    'info => return system information'
  end
 
  def info(m, params)
    sock = TCPSocket.new('heimserver.dyndns.org', 8888)
    sock.puts('DASGEHEIMEPASSWORT')
    m.reply sock.recv(1024)
    sock.close
  end
end
plugin = BotinfoPlugin.new
plugin.map 'info'

Die Daten können ebenfalls von einem PHP-Script aus abgefragt werden. Keines Beispiel:

1
2
3
4
5
6
7
8
9
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, "heimserver.dyndns.org", "8888");
 
$pass = "DASGEHEIMEPASSWORT\n\n";
socket_write($socket, $pass, strlen($pass));
 
echo socket_read($socket, 2048);
?>

Vielleicht findet das ja irgendjemand interessant ;)

Tagged: , , , , , , , , ,

opengl-background unter compiz

by nks · september 19 2008 · 3 comments

Eine weitere nette Spielerei für Leute mit zu viel Ressourcen :D

Ich hab sie nicht aber das ganze läuft auch auf einem 700Mhz Duron flüssig.

Ihr benötigt “xscreensaver” (und auch das Paket “fireflies” falls ihr es wie auf den Screenshots haben wollt, wobei sich “pong” auch ganz gut macht) und “xwinwrap” (xwinwrap does teh magic)

nks@hydra ~ $ nice -n 15 /usr/bin/xwinwrap -ni -argb -fs -s -st -sp -b -nf -- /usr/lib/misc/xscreensaver/fireflies -window-id WID

Das ganze sieht dann so aus:

Für mehr Infos:

Man kann neben xscreensaver auch Videos als Hintergrund laufen lassen

nks

Tagged: , , , , , ,

software-kvm mit synergy

by nks · september 19 2008 · leave a comment

Mir ist gestern die Fernbedienung meiner Sourround-Anlage auf den Boden gefallen – jetzt ist sie unbrauchbar. Also dachte ich mir: “Hey, mach doch den eee-pc zu deiner neuen Fernbedienung!”.

Also wenn ich im bett liege und die lautstärke regeln will, schnell per ssh auf den Rechner verbinden und alsamixer nutzen. Aber dafür is der eee ja schon bisl overkill. Dann erinnerte ich mich an meine Experimente vor einem Jahr die beiden desktop-pcs miteinander zu verbinden.

Ich hatte es auch mit synergy versucht, aber es war ziemlich buggy. Aber die neue Version läuft wesentlich stabiler. Also schnell auf allen 3 boxen synergy gemerged und ab an die config:

# nks's synergy configuration file
# eeerr0r is the synergy-server
# infected and hydra are the clients
 
section: screens
infected:
hydra:
eeerr0r:
end
 
section: links
# larry is to the right of moe and curly is above moe
infected:
right = eeerr0r
eeerr0r:
left = infected
right = hydra
hydra:
left = eeerr0r
end
section: aliases
infected:
192.168.178.30
hydra:
192.168.178.32
eeerr0r:
192.168.178.25
end

Das ganze dann auf dem System welches Tastatur und Maus bereitstellen soll unter “/etc/synergy.conf”
und dann ab in die shell:

nks@eeerr0r ~ $ synergys -f --config /etc/synergy.conf
nks@infected ~ $ synergyc -f eeerr0r
nks@hydra ~ $ synergyc -f eeerr0r

Und schon kann ich vom eee-pc aus beide Rechner kvm-style fernsteuern :D
das ganze funktioniert auch unter windows und mac os.

Besonders schön is das ganze in Kombination mit compiz weil man dann vom Bett/anywhere aus ranzoomen kann :D

Informationen & links:

ps: chase & status releasen demnächst ihr neues Album, zwar ziemlich die uk-kommerz schiene, aber “hurt you” und “pieces” laufen atm ja fast in jedem set, also man kann gespannt sein (wobei “hurt you” auch auf dem neuem Album ist)

pps:Ich hatte damals auch mit xdmx ruexperimentiert, hehe.. vll. probier ich demnächst auch wieder etwas damit rum, allerdings mit compiz etwas zu lahm, in Kombination mit chromium funktioniert es vll besser.

nks

Tagged: , , , , , ,

kernel mode sockets part 2 (the clean way)

by nks · august 30 2008 · 3 comments

Version 0.3 -  23.01.2009

Willkommen zu teil 2 der linux kernel mode socket Serie. Nun befassen wir uns mit einem sauberem weg der socketcalls vom kernel aus. Auch hierfür gibt es noch andere Wege. In einem der nächsten Teile bauen wir uns eine socket()-Funktion selber, aber nun zum sauberem socket :D

Auch hier müssen wir wieder set_fs/get_fs (man kann sie auch weglassen, aber in diesem Fall garantiere ich für NICHTS, bzw das Modul lässt sich kompilieren aber die Funktion funktioniert im besten Fall nicht…) nutzen da file-Operationen im kernelmode nicht gestattet sind, der Zugriff auf sockets ist ein Dateizugriff. Die Funktion inet_addr müssen wir uns nicht extra schreiben, hab ich zwischenzeitlich herausgefunden in der “linux/inet.h” gibt es in_aton() :D

Die Hauptschwierigkeit besteht in den neuen Strukturen iovec und msghdr. Die ich allerdings anhand von Kommentaren erklären werde, soweit wichtig, bzw unter den beiden links steht alles was man wissen muss (obwohl es nicht spezifisch um die linux Strukturen geht).

Ab an den Code:

/*
 * lkm_clean_socket.c - nks
 */
 
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <net/sock.h>
#include <asm/uaccess.h>
 
int init_module(void)
{
	struct socket *socket;
	struct sockaddr_in saddr;
	int errno;
	char buffer[1024];
	struct msghdr msg;
	struct iovec iov;
	mm_segment_t old_fs;
 
	printk(KERN_INFO "#sixserv/sixserv.org presents:\n");
	printk(KERN_INFO "simple & clean kernel mode socket - nks\n");
 
	if ((errno = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&socket))<0)
	{
		printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
		printk(KERN_INFO "-- ERRNO: %d..\n",errno);
		return 0;
	}
	else
        {
		printk(KERN_INFO "++ Kernel Mode Socket is up ...\n");
		printk(KERN_INFO "++ ERRNO: %d..\n",errno);
        }
 
	saddr.sin_addr.s_addr = in_aton("79.140.33.153");
	saddr.sin_port = htons(80);
	saddr.sin_family = AF_INET;
 
 
	if ((errno = socket->ops->connect(socket,(struct sockaddr*)&saddr,sizeof(saddr),0))<0)
	{
		printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
		printk(KERN_INFO "-- ERRNO: %d..\n",errno);
		return 0;
        }
        else
        {
		printk(KERN_INFO "++ Kernel Mode Socket is up an connected...\n");
		printk(KERN_INFO "++ ERRNO: %d..\n",errno);
        }
 
	iov.iov_base = "GET / HTTP/1.0\r\n\r\n";
	iov.iov_len = sizeof("GET / HTTP/1.0\r\n\r\n");
 
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_flags	= 0;
 
	old_fs = get_fs();
	set_fs(KERNEL_DS);	
 
	if ((errno = sock_sendmsg(socket,&msg,sizeof("GET / HTTP/1.0\r\n\r\n")))<0)
	{
		printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
		printk(KERN_INFO "-- ERRNO: %d..\n",errno);
		set_fs(old_fs);
		return 0;
        }
        else
        {
                printk(KERN_INFO "++ Kernel Mode Socket is sending stuff...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
		set_fs(old_fs);
        }	
 
	iov.iov_base = buffer;
	iov.iov_len = 1024;
 
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
 
	old_fs = get_fs();
	set_fs(KERNEL_DS);
 
	if ((errno = sock_recvmsg(socket,&msg,1024,0))<0)
        {
                printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
                set_fs(old_fs);
                return 0;
        }
        else
        {
                printk(KERN_INFO "++ Kernel Mode Socket is recieving stuff...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
                printk(KERN_INFO "++ Recieved: %s..\n",buffer);
		set_fs(old_fs);
 
        }
	return 0;
}
 
void cleanup_module(void)
{
	printk(KERN_INFO "Goodbye world.\n");
}
 
MODULE_LICENSE("GPL");

Ein weiteres mal passen wir unsere Makfeile an:

obj-m += lkm_clean_socket.o
 
all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
 
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Nach einem make ist das modul fertig und liegt unter dem namen “lkm_clean_socket.ko” im aktuellem verzeichnis.
Wenn alles geklappt hat machen wir folgendes:

# modinfo lkm_clean_socket.ko
filename:       lkm_clean_socket.ko
license:        GPL
depends:
vermagic:       2.6.25-gentoo-r7 SMP mod_unload PENTIUM4
# insmod lkm_clean_socket.ko
# dmesg
....
 
++ Kernel Mode Socket is up ...
++ ERRNO: 0..
++ Kernel Mode Socket is up an connected...
++ ERRNO: 0..
++ Kernel Mode Socket is sending stuff...
++ ERRNO: 19..
++ Kernel Mode Socket is recieving stuff...
++ ERRNO: 1024..
++ Recieved: HTTP/1.1 200 OK
Date: Sat, 30 Aug 2008 00:18:58 GMT
Server: Apache
X-Powered-By: PHP/5.2.0-8+etch11
X-Pingback: http://sixserv.org/xmlrpc.php
Connection: close
Content-Type: text/html; charset=UTF-8
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="de-DE">
<head profile="http://gmpg.org/xfn/11"&gt;
<title>sixserv blog</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="description" content="welcome to teh #sixserv!" /&gt;
<meta name="generator" content="WordPress 2.6.1" /> <!-- leave this for stats please -->
<link href="http://sixserv.org/wp-content/themes/journalist/style.css" rel="stylesheet" type="text/css" media="screen" />
<link rel="alternate" type="application/rss+xml" title="sixserv blog RSS Feed" href="http://sixserv.org/feed/" />
<link rel="shortcut icon" type="image/x-png" href="http://sixserv.org/wp-content/the
....
# rmmod lkm_clean_socket.ko

Wie man sehen kann ist unser buffer ein wenig zu klein, und die errnos kann man sich eigtl. auch sparen wenn kein Fehler auftritt.

Seid gespannt auf den nächsten teil der kernel mode Serie :D

nks

quellen:

ps:
cuil.com und metager2.de lassen sich beide in die Suchleiste integrieren (klickt einfach auf den namen dann fragt euch FF). Nach einigem testen gefällt mir metager2 wesentlich besser weil es VIEL mehr findet. Allerdings gefällt mir die Aufmachung von cuil.com, ich sehe noch einiges an potenzial.

pps:
Mal wieder ein musikalischer Tipp:
http://www.myspace.com/blue_nine

edit: Unterschiede zu Version 0.1 haben nur mit der Rechtschreibung zu tun!

Tagged: , , , ,

kernel mode sockets part 1 (the dirty way)

by nks · august 29 2008 · one comment

Version 0.3 – 23.01.2009

Kernel mode sockets sind hoch-interessant. Im ersten teil befasse ich mich mit einer einfachen Implementierung eines ziemlich simplen kernel mode sockets, das ist nicht der Weg wie man es machen sollte allerdings hilft es erstmal dem grundsätzlichem Verständnis von lkm – also kernel modulen unter linux.

Es ist natürlich trotzdem möglich diesen Code in einem rootkit zu verwenden etc. aber ich finde das dieser Code nichts in einem produktiven Umfeld zu suchen hat, man öffnet keine Dateien aus derm kernel mode.

Wir beginnen mit den Basics eines lkm.

Zu erst das klassische “Hello world.”:

/*
*  lkm_hello_world.c
*/
#include <linux/module.h>
#include <linux/kernel.h>
 
int init_module(void)
{
printk(KERN_INFO "Hello world.\n");
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world.\n");
 
}

Zum kompilieren des Moduls legen wir nun ein Makefile an:

obj-m += lkm_hello_world.o
 
all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
 
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Vielleicht hat der ein oder andere versucht die sys/socket.h (etc.) einzubinden, aber das geht nicht. man sollte das auch nicht machen da das user-mode includes sind. Also machen wir weiter, wir erstellen wir einen simplen (dirty) socket im kernel mode. Ich hab mich dazu entschieden das wir den socket über den syscall “socketcall()” erstellen. Um syscalls aus dem kernel aufrufen zu können gab es bis kernel 2.6.19 die syscall macros (für alle mit einem neuerem kernel habe ich einen kleinen header mit den macros hoch geladen), allerdings kann man eigtl keine syscalls vom kernel aus machen, damit wir das können müssen wir aus dem kernel-space Adressraum in den user space Adressraum, das geschieht hier per set_fs(). und schon kann man userspace calls ausführen.

/*
*  lkm_dirty_socket.c - nks
*/
#include "syscall_macros.h" /* auskommentieren wenn die kernel version
unter 2.6.19/18 ist! */
 
#include <linux/module.h>
#include <linux/kernel.h>
 
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/netdevice.h>
 
#include <linux/init.h>
#include <linux/syscalls.h>
 
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <linux/unistd.h>
 
int errno; /* needed by socketcall() */
 
/*
int socketcall(int call, unsigned long *args);
wie wir sehen koennen werden der funktion socketcall() 2 call uebergeben,
also benutzen wir das _syscall2-makro:
*/
static inline _syscall2(int, socketcall, int, call, unsigned long *, args);
int init_module(void)
{
        unsigned long arg[3];
        int socket;
        mm_segment_t old_fs;
        struct sockaddr_in addr;
        struct sockaddr_in saddr;
 
        printk(KERN_INFO "#sixserv/sixserv.org presents:\n");
        printk(KERN_INFO "simple kernel mode socket - nks\n");
 
        old_fs = get_fs();
 
        /* die argumente fuer socketcall vorbereiten*/
        arg[0] = PF_INET;
        arg[1] = SOCK_STREAM;
        arg[2] = 0;
 
        set_fs(KERNEL_DS);
        if ((socket = socketcall(1, arg)) == -1) // SYS_SOCKET = 1
        {
                printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
                printk(KERN_INFO "-- ERRNO: %d..\n",errno);
                set_fs(old_fs);
                return 0;
        }
        else
        {
                printk(KERN_INFO "++ Kernel Mode Socket is up ...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
        }
 
        return 0;
}
 
void cleanup_module(void)
{
        printk(KERN_INFO "Goodbye world.\n");
}

nun muessen wir die Makefile an das neue modul anpassen

obj-m += lkm_dirty_socket.o
 
all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
 
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Nun können wir mit einem

# make
#insmod lkm_dirty_socket

das Modul bauen und laden, mit dmesg sollte man dann die Meldungen sehen ob es geklappt hat sieht man wenn der folgende text in der debug Ausgabe erscheint:

++ Kernel Mode Socket is up …

Aber nur ein socket alleine ist ja bekanntlich ziemlich langweilig :D
Also verbinden wir uns mit einem http Server. Hierfür müssen wir noch ein paar Anpassungen an unserem bestehendem Code tätigen:

/*
*  lkm_dirty_socket.c - nks
*/
#include "syscall_macros.h" /* auskommentieren wenn die kernel version unter 2.6.19/18 ist! */
 
#include <linux/module.h>
#include <linux/kernel.h>
 
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/netdevice.h>
 
#include <linux/init.h>
#include <linux/syscalls.h>
 
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <linux/unistd.h>
int errno; /* needed by socketcall() */
 
/*
int socketcall(int call, unsigned long *args);
wie wir sehen koennen werden der funktion socketcall() 2 parameter uebergeben,
also benutzen wir das _syscall2-makro:
*/
static inline _syscall2(int, socketcall, int, call, unsigned long *, args);
int init_module(void)
{
        unsigned long arg[3];
        int socket;
        mm_segment_t old_fs;
        struct sockaddr_in addr;
        struct sockaddr_in saddr;
        unsigned long arg1[3];
        unsigned long args[4];
        char buffer[1024];
 
        printk(KERN_INFO "#sixserv/sixserv.org presents:\n");
        printk(KERN_INFO "simple kernel mode socket - nks\n");
 
        old_fs = get_fs();
 
        arg[0] = PF_INET;
        arg[1] = SOCK_STREAM;
        arg[2] = 0;
 
        set_fs(KERNEL_DS);
        if ((socket = socketcall(1, arg)) == -1) // SYS_SOCKET = 1
        {
                printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
                printk(KERN_INFO "-- ERRNO: %d..\n",errno);
                set_fs(old_fs);
                return 0;
        }
        else
        {
                printk(KERN_INFO "++ Kernel Mode Socket is up ...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
        }
 
        saddr.sin_addr.s_addr = inet_addr("79.140.33.153");
        saddr.sin_port = htons(80);
        saddr.sin_family = AF_INET;
        /* argumente fuer connect():
            int connect(int sockfd, struct sockaddr *serv_addr, int addrlen );
        */
        arg1[0] = socket;
        arg1[1] =  (unsigned long)&saddr;
        arg1[2] =  (unsigned long)sizeof(saddr);
 
         if ((socketcall(SYS_CONNECT, arg1)) == -1)
        {
                printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
                printk(KERN_INFO "-- ERRNO: %d..\n",errno);
                set_fs(old_fs);
                return 0;
        }
        else
        {
                printk(KERN_INFO "++ Kernel Mode Socket is up an connected...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
        }
 
        /* argumente fuer send():
            send(int s, const void *buf, size_t len, int flags);
        */
        args[0] = socket;
        args[1] = "GET / HTTP/1.0\r\n\r\n";
        args[2] = strlen("GET / HTTP/1.0\r\n\r\n");
        args[3] = 0;
 
         if ((socketcall(SYS_SEND, args)) == -1)
        {
                printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
                printk(KERN_INFO "-- ERRNO: %d..\n",errno);
                set_fs(old_fs);
                return 0;
        }
        else
        {
                printk(KERN_INFO "++ Kernel Mode Socket is sending stuff...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
 
        }
 
        /* argumente fuer recv():
            int recv(int s, void *buf, size_t len, int flags);
        */
        args[0] = socket;
        args[1] = (unsigned long) buffer;
        args[2] = 1024;
        args[3] = 0;
 
        if ((socketcall(SYS_RECV, args)) == -1)
        {
                printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
                set_fs(old_fs);
                return 0;
        }
        else
        {
                printk(KERN_INFO "++ Kernel Mode Socket is recieving stuff...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
                printk(KERN_INFO "++ Recieved: %s..\n",buffer);
 
        }
 
       set_fs(old_fs);
       return 0;
}
 
void cleanup_module(void)
{
        printk(KERN_INFO "Goodbye world.\n");
}
 
unsigned int inet_addr(char *str)
{
        int a,b,c,d;
        char arr[4];
        sscanf(str,"%d.%d.%d.%d",&a,&b,&c,&d);
        arr[0] = a; arr[1] = b; arr[2] = c; arr[3] = d;
        return *(unsigned int*)arr;
}

Wieder ist eine neue Funktion hinzugekommen inet_addr, aber viel interessanter sind die neuen socketcalls, beim lesen kann man anhand des call-Arguments gut sehen welche socket-Funktion nun aufgerufen wird. zur Übergabe der Parameter verwenden wir ein char array bzw zwei da recv und send jeweils 4 Argumente haben.

Die syscall macros hab ich für euch hochgeladen

quellen:

Bei fragen etc. kommt doch einfach ins irc (#nullserv/#sixserv im freenode)

nks

ps:
benutzt öfters mal google-alternativen.. :D   http://cuil.com oder http://metager2.de

pps:
chillig, und wie ich finde sehr geil: http://www.myspace.com/17thboulevard
bin gespannt auf das album…

Tagged: , , , ,