Skip to content

E-Mail versenden von Amazon EC2 (SES mit Exim)

Wie ich bereits berichtet hatte kann es für einen Anwender der IaaS Cloud Amazon EC2 Sinn ergeben den Simple Email Service (SES) von Amazon zu verwenden um E-Mails zu versenden. Dabei kann man entweder die Amazon API/Tools verwenden, oder inzwischen auch die Mails per smtps an den Amazon Smarthost liefern. Amazon selbst bietet nur einen SMTP-SSL Server auf Port 465 an. Die meisten MTAs können dieses Protokoll nicht mehr sprechen und ziehen STARTTLS vor, deswegen empfiehlt Amazon in seiner Anleitung die Verwendung von stunnel als zwischengeschaltenen Proxy. Diese Indirektion ist aber unschön, und kann mit einer aktuellen Exim Version vermieden werden. Ab der Version 4.77 unterstützt der SMTP Transport von Exim auch das smtps Protokoll (für ausgehende Verbindungen). Mit folgenden Exim Einstellungen (Auszug) kann also ein EC2 Linux Rechner direkt an den Amazon Dienst die E-Mail ausliefern (wichtig: die Envelop-From und From: Addresse der versendeten Mails müssen in der Liste der verifizierten SES Absender sein. Als Empfänger kommen nur dann beliebige E-Mail Addressen in Frage, wenn man diese Funktion bei Amazon explizit freischalten hat lassen. 1. Alle Mails an dem Amazon Server leiten (dnslookup entfernen):
smarthost:
  driver = manualroute
  domains = ! +local_domains
  transport = remote_smtps
  route_data = email-smtp.us-east-1.amazonaws.com
  no_more
2. Einen neuen SMTP/SSL Transport definieren:
remote_smtps:
  driver = smtp
  protocol = smtps
  #port = 465
  hosts_require_auth = *
  hosts_require_tls = *
3. Zusätzlich einen Authenticator mit dem SES User/Passwort definieren:
client_login:
  driver = plaintext
  public_name = LOGIN
  client_send = : xxxxI6CIH2YIWSNxxxxx : Agcq00AEvA2ZDiQHNrDvTEODE3FWa1rxxxxx
Ich habe das ganze unter Amazon Linux mit Exim 4.77 aus dem AltCent Repository getestet:
wget http://centos.alt.ru/repository/centos/6/i386/exim-4.77-1.el6.i686.rpm
rpm -i exim-4.77-1.el6.i686.rpm
Es bietet sich an Exim so zu konfigurieren, dass nur auf localhost auf dem Submission Port E-Mails angenommen werden:
daemon_smtp_ports = 587
local_interfaces = 127.0.0.1
Dies stellt sicher, dass der Dienst nicht für Spam oder Sicherheitsangriffe ausgenutzt werden kann.

Java 7 - Probleme mit neuen JSSE Features

Mit Java 7 sind in den SSL/TLS Provider von Oracle einige neue Funktionen eingezogen. Darunter der schon lange erwartete Support für TLSv1.1 und TLSv1.2, aber auch die Unterstützung der TLS Extensions u.A. für die Server Name Indication(SNI). Letzteres wird dazu verwendet virtuelle Hosts auf einem SSL Port zu unterstützen: Bisher konnte ein SSL Server nämlich nicht wissen an welchen (der potentiell vielen) virtuellen Dienste hinter einer IP Adresse sich der SSL Client wenden will. Besonders ärgerlich ist dies im Fall von HTTP/s, dort ist es die Regel dass Hoster sehr viele Kunden-Domains hinter ein und der selben IP-Adresse betreiben. In HTTP/1.1 wird der gewünschte Servername in der Anfrage mitgegeben (Host: Header). So kann der HTTP Server entscheiden welche Webseiten er ausliefern soll. Im Falle des SSL Server Zertifikats (welches im SSL Handshake schon vor der HTTP Anfrage ausgetauscht wird), kann dies der Webserver aber nicht. Er muss raten welches Zertifikat er dem Client präsentieren soll, und das schlägt natürlich in der Regel fehl. Mit der Extension wird der Servername auch im Handshake mitgeschickt, und der Server kann sein Zertifikat passend auswählen. Problem bei der Geschichte ist: der Server darf auf eine solche Namensanfrage mit einem SSL Alert (Warning) reagieren. In dieser sagt er, dass er sich für den angefragten Host nicht zuständig fühlt. Das kommt bei aktuellen Webserver Installationen häufig vor, weil diese einfach nicht korrekt eingerichtet sind (und die modernen Browser die SNI unterstützen diese Warnung auch einfach ignorieren). Da das zurückgelieferte Default Zertifikat oftmals den richtigen Hostnamen (in einer der Attribute) enthält, klappt der gesicherte Handschlag im Alltag dennoch. Nicht jedoch mit Java 7 SSL Clients, JSSE macht daraus eine fatale Exception:
javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name
	at sun.security.ssl.ClientHandshaker.handshakeAlert
	at sun.security.ssl.SSLSocketImpl.recvAlert
	at sun.security.ssl.SSLSocketImpl.readRecord
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake
	at sun.security.ssl.SSLSocketImpl.startHandshake
	at sun.security.ssl.SSLSocketImpl.startHandshake
	at sun.net.www.protocol.https.HttpsClient.afterConnect
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect
	at sun.net.www.protocol.http.HttpURLConnection.getOutputStream
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream
Ich habe deswegen einen Bugreport aufgemacht, jedoch wurde dieser wieder kommentarlos geschlossen. Falls Sie nun trotz Oracle's widerstreben die Notwendigkeit haben mit einem Web Server zu kommunizieren der SNI nicht richtig eingerichtet hat, so bleiben nur 2 Möglichkeiten über: a) TLS aus der Liste der unterstützten Protokolle entfernen - mit einem SSLv3 Handshake wird kein Extension Record übertragen, und entsprechend klappt auch der Handshake (solange der Server SNI nicht benötigt). b) den SSL Socket so initialisieren, dass die SSLEngine den Host nicht kennt. Dieser sogenannte Host hint wird für mehrere Dinge verwendet, kann aber auch weggelassen werden. Erreichen kann man dies, indem man den Socket statt mit s=factory.createSocket(name, port); mit "s=factory.createSocket(); s.connect(name,port);" erzeugt. Übrigens ist dies ein ziemlich unerwartetes Verhalten: SSL mit Kerberos Authentifizierung würde nur auf die erste Art und Weise funktionieren, da hierfür die Identität des Servers bekannt sein muss. Der Punkt a) ist ein schneller Fix, kommt aber in der Praxis eigentlich nicht in Frage, da man mit Java 7 ja eher daran Interesse hat TLSv1.1 oder TLSv1.2 zu verwenden um Lücken wie z.B. den BEAST-Angriff auszuschließen. Daher bleibt es nur übrig entweder den Anwendungscode zu ändern (oder wenn man diesen nicht selbst geschrieben hat, wie im Falle einer häufig verwendeten URLConnection oder beim Apache HTTPClient) oder aber mindestens eine eigene SSLSocketFactory zu implementieren, die auf die 2-stufige Erzeugung des SSLSockets aufsetzt. Update: Ich habe in den Sourcen grade eine System Property gefunden, mit der man abschalten kann, dass der ClientHandshaker die SNI Extention sendet. Dies lässt sich als Work around gut verwenden: System.setProperty("jsse.enableSNIExtension", "false"); (muss vor der Verwendung von SSL Klassen im Programm, oder auf der Command Line gesetzt werden).

Eckpunktepapier der BNetzA zu Smart Grids und Markets

Die Bundesnetzagentur hat ein Eckpunktepapier zum Thema Smart Grids und Markets veröffentlicht. Damit will die Bundesbehörde
durch dieses Papier eine intensivere Diskussion der Thematik anstoßen zu können und die Veränderungen des Energieversorgungssystems weiter voran zu bringen. Dieses Eckpunktepapier soll die Diskussion zu dieser Thematik weiter befördern und besser strukturieren.
Das "Eckpunktepapier der Bundesnetzagentur zu den Aspekten des sich verändernden Energieversorgungssystems" enthält Leitgedanken und Begriffsdefinitionen und ist schon aus diesem Grund sehr lesenswert. Ob die einzelnen Thesen (Abnahme des Gesamtenergieverbrauchs) nun zutreffen wird sich zeigen, von einer Zunahme der Stromabnahme wird aber ausgegangen. Auch bei intelligenteren Verbrauchern (da zunehmend andere Energieformen verdrängt werden, was angesichts der Endlichkeit von fossilen Energieträgern nur logisch ist). Das Paper baut darauf, dass Verbraucher sich über Marktsignale (Preise) steuern lassen. Das wird sich zeigen wie gut das funktioniert... Ein wenig sehr optimistisch dürfte die Annahme der Transaktionskostensenkung bei "kleinteiliger Interaktion" sein (Fehlschläge im Smartmeter Markt wie in den Niederlanden oder Großbritannien deuten ja eher darauf hin, dass es sinnvoll sein kann alternative Lösungswege anzustreben und nicht alles über Informationstechnologie lösen zu wollen. Größtenteils wird der Smartmetermarkt von Anbietern getrieben die sich neue Einnahmequellen versprechen und die Vorteile werden in den meisten Haushalten weder gesehen - noch existieren diese). Das BNetzA Papier sieht dies aber auch (Leitgedanke 4). Was mir persönlich im Papier fehlt ist ein klarere Fokus auf das Thema Datenschutz, Schutz von kritischen Infrastrukturen und Monokultur. Die Notwendigkeit von Datendrehscheiben wird nicht hinterfragt, und eine Vermischung der Messdaten von Prosumenten oder Industrieabnehmern mit den Messstellen in Haushalten führt meiner Meinung nach zu einer Übertechnisierung der Haushalte. Für eine zuverlässige Demand-Site Prognose ist meiner Meinung nach nicht notwendig den Tagesverlauf jedes einzelnen Haushaltes zu betrachten - ganz im Gegenteil das ist eher schädlich. Der Nutzen von mehr Transparenz beim Stromverbrauch eines einzelnen Haushaltes kann auch durch eine rein lokale Informationsanwendung (deutlich besser) gelöst werden. Eine feingranulare Übermittlung von Messwerten erscheint mir nicht zwingend notwendig und vor allem nicht Ökonomisch. In dem Zusammenhang verweise ich auch auf den Artikel in der aktuellen Datenschleuder #95 (Power to the People, Das Stromnetz der Zukunft, Mathias Dalheimer, Seite 35-48) und die Projekte mySmartGrid sowie volkszaehler.org.

SQL Server JDBC Probleme

Von den Änderungen in Java SE 6.0 Update 29 zum Schutz vor SSL BEAST Angriffen hatte ich schon berichtet. Ein Opfer dieser Kompatibilitätsänderung sind die JDBC Treiber für den Microsoft SQL Server (jTDS und Microsoft JDBC Driver for SQL Server sind betroffen). Beim Aufbau der Verbindung (TCP) direkt mit dem jTDS Treiber kommt es zu folgendem Fehler:
java.sql.SQLException: I/O Error: Software caused connection abort: recv failed
  State  : 08S01
  Error  : 0
Und die folgende Exception wirft der Microsoft JDBC Driver for SQL Server:
com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset
  State  : 08S01
  Error  : 0
Wenn die Treiber durch einen Connection Pool benutzt werden, oder innerhalb einer Datasource, so kann es sogar zum Hängen (wegen Endlosschleife) kommen. Eine Möglichkeit ist es, beim jTDS Treiber anzugeben, dass man kein SSL machen möchte (sollte aber eigentlich auch der default sein, laut jTDS FAQ). Dies kann man mit dem JDBC URL Property ";ssl=no" erreichen. Wenn der Server allerdings auf "Force Encryption" konfiguriert ist, so wird er dann die Logins ablehnen. Beim Microsoft Treiber würde das property "encrypt=false" lauten, dies half aber in meinen Versuchen (mit MS SQL Server 2008 R2 Express) nicht. Eine weitere Möglichkeit ist es den SSL/TLS CBC-Fix per Java System Property abzuschalten: -Djsse.enableCBCProtection=false Dies wirkt sich aber auf alle anderen SSL Verbindungen innerhalb dieser VM ebenfalls aus. Es gibt Berichte, dass dieses Problem mit JavaSE 6.0 Update 30 behoben sei, das kann ich aber weder nachvollziehen, noch lassen die ReleaseNotes darauf schließen. Ich habe mal einen Fehlerbericht bei jTDS dazu geöffnet.