Archive for Juni, 2009

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: , ,

Kleine Ruby Logger Klasse

by apoc · juni 13 2009 · leave a comment

Normalerweise sind die Artikel hier ja ziemlich umfangreich, was ja auch gut ist schließlich geht das Sixserv Blog ja schon sehr ins technische Detail. Doch diesmal wird es eher kurz, ich möchte eine kleine Logger Klasse vorstellen die ich in Ruby geschrieben habe und seither häufiger benutze.

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
44
class Logger
  def self.init
    @logfile = LOG_FILE
    @buffer = [] # logging lines for buffering
  end
 
  def self.<< msg
    msg = format msg
 
    # append message to buffer
    @buffer << msg
 
    # flush the buffer if possible
    self.flush
  end
 
  def self.flush
    return if @buffer.empty?
 
    # try to lock the file for writing
    log = File.new(@logfile, 'a+')
 
    if log.flock(File::LOCK_EX | File::LOCK_NB) == false
      # Logfile is locked
      puts "Logfile is locked!"
      log.close
      return false
    end
 
    # ==> not locked, write buffer to logfile
    while @buffer.length > 0
      log.puts @buffer.shift
    end
 
    log.flock(File::LOCK_UN)
    log.close
  end
 
  private
  def self.format msg
    time = Time.now.strftime '%H:%M:%S - %d.%m.%Y'
    "[#{time}] #{msg}"
  end
end

Nichts großes also, es gibt z.B. keine Log-Level usw. Außerdem kann man sich, wenn man etwas mehr Features braucht, auch eine Logging Bibliothek aus dem Gems bedienen. Die Anwendung ist ganz einfach:

1
2
3
4
5
6
7
8
require '/pfad/zu/logger.rb'
Logger.init
# das kann man dann überall im Code verteilen:
Logger << "Irgendeine Nachricht!"
# hat man eine große Anwendung mit vielen Prozessen/Threads
# kann man auch an strategischen Stellen ein
Logger.flush
# einbauen :)

Hier noch eine kleine Erweiterung die einen Log-Server implementiert. Er öffnet einen TCP Port, jeder der sich verbindet(z.B. per Telnet/Netcat) kann daraufhin die Log-Nachrichten mitlesen:

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class Logger
  def self.init
    ...
    @port = LOG_PORT
    @query = []
    @query_mutex = nil
    @running = false
    @server = nil
  end
 
  def self.start_server
    @query_mutex = Mutex.new
    puts "Start logging console @ #{LOG_HOST}:#{LOG_PORT}"
 
    @server = TCPServer.new(LOG_HOST, LOG_PORT)
    clients = []
    @running = true
    Thread.start do
      client = []
      while @running do
        begin
          client = @server.accept_nonblock
          clients << client if client != nil
        rescue
        end
 
        begin
          message = nil
          @query_mutex.synchronize { message = @query.pop }
          if message != nil
            clients.each do |client|
                begin
                    client.puts message
                rescue
                    clients.delete client
                end 
            end
          end
        end while not @query.empty?
        sleep LOG_SERVER_INTERVAL
      end
      clients.each { |client| client.close }
      @server.close
      @server = nil
    end
  end
 
  def self.destroy
    @running = false
    @fs.close
 
    # wait until server closed
    true while @server != nil
  end
 
  def self.<< msg
    if @query_mutex != nil
      @query_mutex.synchronize do
        @query << format(msg)
      end
    end
    puts ">>> #{msg}"
  end  
 
  def self.flush
    # just wait until everything is sent/written
    if @query.length > 0
      true while @query.length != 0
    end
  end
 
  ...
end

So das wars schon, ich hoffe das ich das mit dem Mutex richtig gemacht habe und das hier überhaupt notwendig war, ich habe auf dem Gebiet nicht viel Erfahrung und würde mich über einen entsprechenden Kommentar freuen.
// I’m not sure I used the Mutex in this example correctly, I would appreciate a comment about this.

Tagged: , , ,