Verbindung zu SMTP Server ohne telnet oder nc testen

Um die Verbindung zu einem SMTP Server zu testen um zum Beispiel einen Fehler durch eine Firewall auszuschließen nutze ich normalerweise telnet:

user@host ~ $ telnet mail.example.net 25
Trying 1.2.3.4...
Connected to mail.example.net.
Escape character is '^]'.
220 mail.example.net ESMTP Postfix

Wenn telnet nicht installiert ist geht das auch noch mit netcat:

user@host ~ $ nc mail.example.net 25
220 mail.example.net ESMTP Postfix

Heute hatte ich ein System auf dem beides nicht existierte. Da habe ich eine Methode mit python gefunden die sehr gut funktioniert hat:

user@host ~ $ python
Python 2.7.9 (default, Mar  1 2015, 12:57:24) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> conn=socket.create_connection(('mail.example.net',25))
>>> input=conn.makefile()
>>> print input.readline()
220 mail.example.net ESMTP Postfix

>>> conn.sendall('QUIT')
>>> conn.close()
>>> 

iodine – IPv4 über DNS tunneln

Ich habe schon öfter über Dinge geschrieben die unterwegs nützlich sind um Zugriff aufs Internet zu bekommen. Ein Tool habe ich bereits seit langem installiert, jedoch jetzt kürzlich das erste Mal praktisch genutzt: iodine.

Zugiodine ermöglicht es einem IPv4 Traffic über DNS zu tunneln. Das ist immer dann praktisch wenn der Internetzugriff per Firewall gesperrt, DNS aber erlaubt ist.

Die Hürden für ein iodine Setup sind erst einmal groß. Um den Server zu installieren bedarf es nicht nur eines entsprechenden Hosts auf dem das Paket installiert werden kann, sondern man muss auch in seinem DNS Einstellungen machen können. Bei mir funktioniert das folgende Setup:

Auf dem gewünschten Server habe ich das iodine Paket aus den Paketquellen installiert:

aptitude install iodine

Anschließend habe ich in der Konfigurationsdatei /etc/default/iodine die folgenden Einstellungen hinterlegt:

START_IODINED="true"
IODINED_ARGS="10.9.0.123 iodine.example.net -c"
IODINED_PASSWORD="MYSECRETPASSWORD"

Nun zum DNS. Dort benötigt man zwei Einträge. Angenommen der Host auf dem iodine installiert ist hat die IP 1.2.3.4, dann bekommt dieser zuerst einen ganz normalen IN A Eintrag. host.example.net zeigt auf 1.2.3.4. Das  ist nichts besonderes sondern so einen Eintrag setzt man ja eigentlich immer.

IN A

Der zweite Eintrag ist nun der abweichende. Wie in den IODINED_ARGS angegeben benötigen wir den DNS-Eintrag iodine.example.net. Dieser bekommt aber keinen IN A Eintrag, sondern als Nameserver den host.example.net eingetragen.

IN NS

Wenn der Server eingerichtet ist, kann man sich an den Client machen. Ich nutze den Network-Manager und dafür gibt es ein praktisches Plugin. Auf dem Client:

aptitude install network-manager-iodine-gnome

Anschließend kann man den nm-connection-editor starten und dort eine neue Verbindung vom Typ VPN – Iodine VPN Tunnel  hinzufügen. Als Verbindungsname wählt man das was man will, als Toplevel Domain trägt man iodine.example.net ein, und das auf dem Server unter IODINED_PASSWORD gesetzte Passwort speichert man auch optional ab. Fertig.

Schnell ist die Anbindung nicht, das ist technisch bedingt, aber sie ist stabil, selbst wenn man von dem Hotspot alle X Minuten per DHCP eine neue IP bekommt bricht der Tunnel nicht ab. Klasse!

Puppet: ein NTP-Modul mit zwei Neuerungen

Nach und nach alle Dienste mit puppet abzudecken und dabei in der Komplexitaet immer weiter steigern. Das mache ich gerade. Heute ein Modul mit zwei Neuerungen:

  1. Sicherstellen, dass der Service auch laeuft
  2. Im Template ein Array durchlaufen

Man kann mit puppet sehr einfach sicherstellen, dass Dienste auch laufen. Dafuer reichen die drei Zeilen:

  service { 'ntp':
    ensure => running,
  }

Weiter gibt es Sinn mehrere NTP Server in der ntp.conf zu definieren. Aus diesem Grund konnte ich nicht mit der gleichen Syntax arbeiten wie bei dem apt Modul. Der entscheidende neue Abschnitt im Template ist:

<% @servers.each do |server| -%>
server <%= server %>
<% end -%>

Siehe dazu auch die Sektion Iteration in der Using Puppet Templates Dokumentation. Komplett sieht das ganze so aus:

  • Ordnerstruktur:
    ├── manifests
    │   └── init.pp
    └── templates
        └── ntp.conf.erb
  • init.pp:
    # make sure ntp package is installed and service
    # is running
     
    class ntp ( $servers = [
      '0.debian.pool.ntp.org',
      '1.debian.pool.ntp.org',
      '2.debian.pool.ntp.org',
      '3.debian.pool.ntp.org',
      ] ) {
     
      package { 'ntp':
        ensure => installed
      }
     
      service { 'ntp':
        ensure => running,
      }
     
      file { '/etc/ntp.conf':
        ensure  => 'present',
        owner   => 'root',
        group   => 'root',
        mode    => '0644',
        content => template('ntp/ntp.conf.erb'),
        }
    }
  • ntp.conf.erb:
    #############################################################################
    #                                                                           #
    # !!! This file is managed by puppet, all manual changes will be lost !!!   #
    #                                                                           #
    #############################################################################
     
     
    # Keep ntpd from panicking in the event of a large clock skew
    # when a VM guest is suspended and resumed.
    tinker panic 0
     
    # Local users may interrogate the ntp server more closely.
    restrict 127.0.0.1
    restrict ::1
     
    # You do need to talk to an NTP server or two (or three).
    <% @servers.each do |server| -%>
    server <%= server %>
    <% end -%>
     
    # Undisciplined Local Clock. This is a fake driver intended for backup
    # and when no outside source of synchronized time is available. 
    server  127.127.1.0
    fudge   127.127.1.0 stratum 10
    restrict 127.127.1.0
     
    # By default, exchange time with everybody, but don't allow configuration.
    restrict -4 default kod notrap nomodify nopeer noquery
    restrict -6 default kod notrap nomodify nopeer noquery
     
    # Driftfile.
    driftfile /var/lib/ntp/drift
  • Definition des nodes:
    node 'node1.example.org' inherits default {
      class { 'ntp':
        servers => [ 'ntp1.example.org', 'ntp2.example.org', 'ntp3.example.org' ],
      }
    }

Puppet: Aufsetzen der Infrastruktur

Durch die Arbeit inspiriert, habe ich nun auch fuer mich Privat einen puppet Server zur Verwaltung meiner virtuellen Maschinen aufgesetzt.

Wikipedia schreibt zu puppet:

Puppet ist ein Tool zum Konfigurationsmanagement von Computern mit Betriebssystemen 
wie Unix, Linux und FreeBSD. Ein IT-Administrator kann damit an zentraler Stelle 
die Konfiguration von Rechnern in seinem Netzwerk verwalten. Puppet eignet sich 
sowohl für einzelne Rechner als auch für große Rechnerverbünde

Als erstes wurde die generelle Infrastruktur aufsetzen. Das bedeutet fuer mich:

  1. Einen puppet master Server zu haben
  2. Auf den Clients einen puppet agent laufen zu haben der mit dem Master verbunden ist.

Alles hier beschriebene passiert auf der Basis von Debian wheezy. Auf dem Server der als puppet master dienen soll habe ich zuerst das entsprechende Paket mit seinen Abhaengigkeiten installiert:

sudo aptitude install puppetmaster

Anschliessend habe ich in der /etc/default/puppetmaster den Parameter START=yes gesetzt. Wichtig ist nun noch sicherzustellen, dass der Port 8140 von den Clients aus erreichbar ist.

Danach habe ich auf den Clients den puppet agent installiert:

sudo aptitude install puppet

Auch hier habe ich in der /etc/default/puppet wieder den Parameter START=yes gesetzt. Weiter habe ich in den DAEMON_OPTS den Parameter zu dem Server angegeben. Beispiel:

--server puppetmaster.example.org

Dann habe ich probiert mich mit dem puppet agent an den puppet master Server zu verbinden:

puppet agent --server puppetmaster.example.org --test

Auf dem puppet master konnte ich danach das unsignierte Zertifikat des Clients mit dem folgenden Befehl sehen:

puppet cert list

Danach musste es mit dem folgenden Befehl signiert werden, wobei puppetclient.example.org der FQHN des puppet clients ist:

puppet cert sign puppetclient.example.org

Alle signierten Zertifikate kann man sich uebrigens mit dem folgenden Befehl anzeigen lassen:

puppet cert list --all

Danach konnte ich den puppet agent auf dem Client erneut laufen lassen und die Verbindung war erfolgreich. Zum Ende das neu starten des puppet agents auf den Clients nicht vergessen, damit der Prozess mit den neuen DAEMON_OPTS laeuft.

Notizen:

  • Wenn es zu einer „Connection refused“ Fehlermeldung wie unten gezeigt kommt, sicherstellen, dass der Port erreichbar ist. Eventuell auch erst einmal ausprobieren mit der IP Adresse auf dem Port zu verbinden (telnet IP PORT)
    root@host:~# puppet agent --test --server puppetmaster.example.org
    err: Could not retrieve catalog from remote server: Connection refused - connect(2)
    warning: Not using cache on failed catalog
    err: Could not retrieve catalog; skipping run
    err: Could not send report: Connection refused - connect(2)
    root@host:~#
    
  • Wenn es zu einer „Server hostname did not match server certificate“ Fehlermeldung kommt, dann kann es helfen fuer den Server einen entsprechenden Eintrag in die /etc/hosts zu packen
    root@host:~# puppet agent --test --server 192.168.1.100
    err: Could not retrieve catalog from remote server: Server hostname '192.168.1.100' did not match server certificate; expected one of puppetmaster.example.org, DNS:puppet, DNS:puppet.example.org, DNS:puppetmaster.example.org
    warning: Not using cache on failed catalog
    err: Could not retrieve catalog; skipping run
    err: Could not send report: Server hostname '192.168.1.100' did not match server certificate; expected one of puppetmaster.example.org, DNS:puppet, DNS:puppet.example.org, DNS:puppetmaster.example.org
    root@host:~#