Keepass: Crash durch kaputte Mountpoints

Keepass ist ein quelloffener Passwortmanager, welcher Zugangsdaten verschlüsselt in einer Datei sammelt. Heute musste ich auf einem Gerät feststellen, dass sich die Software nicht mehr starten ließ: Der Passwortdialog erschien kurz, dann verschwand das ganze Programm vom Desktop. Über die Konsole ist ein absturz mit folgendem Trace zu erkennen:

Stacktrace:

  at <unknown> &lt;0xffffffff>
  at (wrapper managed-to-native) System.IO.MonoIO.FindFirstFile (string,string&,int&,int&) [0x00000]
  at System.IO.FileSystemEnumerableIterator`1<tsource_ref>.CommonInit () [0x0001d]
  at System.IO.FileSystemEnumerableIterator`1</tsource_ref><tsource_ref>..ctor (string,string,string,System.IO.SearchOption,System.IO.SearchResultHandler`1</tsource_ref><tsource_ref>,bool) [0x000d6]
  at System.IO.FileSystemEnumerableFactory.CreateFileNameIterator (string,string,string,bool,bool,System.IO.SearchOption,bool) [0x00009]
  at System.IO.Directory.InternalGetFileDirectoryNames (string,string,string,bool,bool,System.IO.SearchOption,bool) [0x00000]
  at System.IO.Directory.InternalGetFiles (string,string,System.IO.SearchOption) [0x00000]
  at System.IO.Directory.GetFiles (string,string) [0x0001c]
  at System.IO.DirectoryInfo.GetFiles (string) [0x0000e]
  at System.IO.DirectoryInfo.GetFiles (string,System.IO.SearchOption) [0x00009]
  at (wrapper remoting-invoke-with-check) System.IO.DirectoryInfo.GetFiles (string,System.IO.SearchOption) [0x00033]
  at KeePassLib.Utility.UrlUtil.GetFileInfos (System.IO.DirectoryInfo,string,System.IO.SearchOption) [0x00010]
  at KeePass.Forms.KeyPromptForm.AddKeyDriveSuggAsync (object) [0x0001c]
  at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (object) [0x00007]
  at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x00071]
  at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x00000]
  at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00021]
  at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00074]
  at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000]
  at (wrapper runtime-invoke) <module>.runtime_invoke_bool (object,intptr,intptr,intptr) [0x0001e]
</module></tsource_ref></unknown>

Die Ursache ist etwas schwer zu finden, da nicht direkt ersichtlich: Netzwerkstörungen und Dateisysteme. Keepass durchsucht offenbar beim Start alle eingehangenen Partitionen, tritt hierbei ein Fehler auf kommt es zum Absturz. Dies betrifft nicht nur jene Speicherorte, auf denen Datenbank und ggf. Keyfile hinterlegt sind. In meinem Fall war durch einen Server-Neustart ein NFS-Mount abhanden gekommen (stale file handle), ähnliches war jedoch auch mit sshfs & co zu sehen. Eine Liste der aktuell genutzten Partitionen findet sich unter /etc/mtab, kaputte Dateisysteme lassen sich auch ohne Verbindung mit „umount -l“ oder „fusermount -u“ aushängen, hierbei kann jedoch möglicherweise Datenverlust entstehen, wenn noch Dinge im Schreibcache liegen. Nach Beseitigung des Fehlers lässt sich Keepass wieder regulär starten.

BitNotice #127 – USB Datenkabel

BitNotice #127 - USB Datenkabel

(19 MB) 00:05:26

2017-11-22 22:00 🛈

Der ESP8266 und seine USB-Module wie Wemos D1 Mini oder NodeMCU mögen praktisch sein, aber Probleme zu Debuggen kann auf Grund der pingeligen Stromanforderungen schon mal zur Qual werden. Zwar lässt sich mit einem batteriebetriebenen Laptop die Serielle Schnittstelle ohne Erdreferenz mitlesen, da der Laptop aber auch 5V zuspeist kann der Anschluss das Problem verschwinden lassen. Also improvisieren wir mal ein USB-Adapter, welcher die 5V-Leitung bei Bedarf auftrennen kann.

BitBastelei #262 – Induktionskochfeld

BitBastelei #262 - Induktionskochfeld

(128 MB) 00:29:43

2017-11-19 11:00 🛈

Wer warm Essen möchte und nicht nur auf Fertigkost setzten möchte kommt um einen Herd wohl kaum herum. Inzwischen sind dort immer häufiger Induktionskochfelder zu finden, welche eine höhere Effizienz versprechen. Da ich ohenhin etwas derartiges brauchte und ein portables Gerät grade im Angebot durchlief schauen wir doch gleich mal rein.

Inhalt

01:45 Was ist Induktionskochen?
03:39 Lieferumfang des Produktes
06:05 Erster Test
11:12 Technische Beobacktungen
11:46 Öffnen des Gerätes
17:01 Blick auf die Platinen
24:42 Erste Messungen
25:29 Klassisches vs. Induktionskochfeld

Link

http://amzn.to/2j5Cykq
Affiliate-Link: Durch Nutzung erfährt Amazon, dass Ihr durch mich verwiesen wurdet. Ich erhalte einen Teil eures Einkaufswertes als Werbekosten. Für Euch ändern sich die Preise natürlich nicht.

BitBasics IT – 0x06 – Programme und PCs

BitBasics IT - 0x06 - Programme und PCs

(42 MB) 00:19:55

2017-11-12 11:00 🛈

Bisher haben wir alle Aktionen per Hand ausgelöst – im Rechner laufen diese Dings jedoch automatisch ab. Hierzu wird ein so genanntes Programm verwendet, eine Sammlung von Befehlen, welche nacheinander ausgeführt werden. Hier schauen wir in vereinfachter Form den Ablauf eines solchen Programms an.

Korrekturen und Ergänzungen

  • 07:00 Bit natürlich, nicht Byte
  • 14:35 0b…, nicht 0x…

Links zum Thema

sBild: https://www.adlerweb.info/blog/wp-content/uploads/2017/11/svgpc.svg

Serie

Vorherige Folge: BitBasics IT – 0x05 – Speicher mit Latche

Credits

BitBastics // BitBastelei
IT-Grundlagen
Florian „adlerweb“ Knodt · http://biba.adlerweb.info/ · CC-BY

Intro-Musik (verändert): Take a Chance Kevin MacLeod (incompetech.com) · Licensed under
Creative Commons: By Attribution 3.0 License http://creativecommons.org/licenses/by/3.0/

Die-Fotografie: Pauli Rautakorpi · CC BY 3.0 (http://creativecommons.org/licenses/by/3.0)
via https://commons.wikimedia.org/wiki/File:Intel_Pentium_P54C_die.jpg

[ICStation.com] BitBastelei #261 – GPS-Tracker mit Neo-6/7-Module und ESP8266

[ICStation.com] BitBastelei #261 - GPS-Tracker mit Neo-6/7-Module und ESP8266

(111 MB) 00:40:34

2017-11-05 11:00 🛈

In der letzten Woche haben wir uns angesehen, wie Satellitennavigationssysteme wie GPS funktionieren, nun wollen wir diese auch in der Praxis nutzen. Da die Berechnungen komplex sind ist es auch hier eine gute Idee spezialisierte ICs zu verwenden, welche eine einfache Schnittstelle für Mikrocontroller bereitstellen. ICStation.com bietet hierzu ein Modul auf Basis des mächtigen U-Blox Neo M6/M7 an, welches über UART angesprochen werden kann. Schauen wir mal auf das Modul, welche Optionen die Konfigurationssoftware bietet, den Aufbau des NMEA-Protokolls und bauen am Ende einen GPS-Trakcer auf Basis des ESP8266.

Links

Code

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <NMEAGPS.h>
#include <SoftwareSerial.h>

/**
 * Required libs (see manager):
 *   - SoftwareSerial
 *   - NeoGPS
 */

#define RTCMEMORYSTART 65

extern "C" {
#include "user_interface.h"
}

//WiFi
const char* ssid = "freifunk-myk.de";
const char* pass = "";

//URL of ownTracks Recorder
const char* owntracksURL = "http://adlerweb-vm-owntracks.ffmyk:8083/pub";

//User and Device for ownTracks
const char* owntracksUser   = "esp8266-1";
const char* owntracksDevice = "esp8266-1";

//Sleep between GNSS checks in minutes
//const unsigned int sleep_off = 5;
const unsigned int sleep_off = 1;

//Time for GNSS warm-up in seconds
//const unsigned int sleep_GNSS = 30;
const unsigned int sleep_GNSS = 10;

//Time to wait for 3D-Fix before reverting to 2D in seconds
const unsigned int sleep_3d  = 30;

//Time to wait for 2D-Fix before reverting to RF in seconds
const unsigned int sleep_2d  = 60;

//RF Geolocation Todo https://github.com/m0xpd/ESP8266-GeoLocation/blob/master/ESP8266_GeoLocate_2.ino

//Geo-deviation in deg-fract(?)
const unsigned int fence = 5000;

//Force update after x minutes
const unsigned int rf_force = 720;

//Time to wait for RF-Connect before giving up in seconds
const unsigned int rf_timeout = 60;

//GNSS Power Switch
#define GNSS_PWR_PIN D4
#define GNSS_PWR_ON  LOW

//Software UART for GNSS (RX, TX)
SoftwareSerial GNSSPort(D7, D8);
#define GNSS_BAUD 115200

//Hardware UART for Debug
#define DEBUG_PORT Serial
#define DEBUG_BAUD 115200

//Write all data when received
#define DEBUG_DUMP 0

NMEAGPS GNSS;
gps_fix fix;
int32_t lon=0, lat=0;
float vel=0,alt=0,cog=0;

bool delayGNSS(uint32_t dly) {
  return delayGNSS(dly, false);
}

bool delayGNSS(int32_t dly, bool direct) {
  unsigned long mstop = millis()+dly;
  bool ret = false;

  if(DEBUG_DUMP > 1) DEBUG_PORT.print(F("\nS:"));
  if(DEBUG_DUMP > 1) DEBUG_PORT.print(dly);

  do {
    if (GNSS.available( GNSSPort )) {
      fix = GNSS.read();
      ret = true;
      if(DEBUG_DUMP > 1) DEBUG_PORT.print('!');
    }
  }while(!ret && mstop > millis());

  if (fix.valid.heading) cog = fix.heading();
  if (fix.valid.speed) vel = fix.speed_kph();
  if (fix.valid.altitude) alt = fix.altitude();
  if (fix.valid.location) {
    lon = fix.longitudeL();
    lat = fix.latitudeL();
  }
  

  if(!ret) return false;
  if(!direct) {
    if(DEBUG_DUMP > 1) DEBUG_PORT.print('+');
    if(DEBUG_DUMP > 1) DEBUG_PORT.print(mstop-millis());
    delay((mstop-millis()));
  }
  return true;
}

bool getGNSS(void) {
  bool ret;
  if(delayGNSS(100, true)) {
    if(DEBUG_DUMP > 0) debugDump();
    return true;
  }
  return false;
}

bool wait_3d(void) {
  DEBUG_PORT.print(F("Waiting 3D Fix..."));
  for (unsigned int sec = 0; sec < sleep_3d; sec++) {
    if(getGNSS() && lon != 0 && lat != 0 && alt != 0) {
      DEBUG_PORT.println(F("OK"));
      return true;
    }
    Serial.print('.');
    yield();
    delayGNSS(1000);
  }
  DEBUG_PORT.println(F("NOPE"));
  return false;
}

bool wait_2d(void) {
  DEBUG_PORT.print(F("Waiting 2D Fix..."));
  for (unsigned int sec = 0; sec < sleep_2d; sec++) {
    if(getGNSS() && lon != 0 && lat != 0) {
      DEBUG_PORT.println(F("OK"));
      return true;
    }
    Serial.print('.');
    yield();
    delayGNSS(1000);
  }
  DEBUG_PORT.println(F("NOPE"));
  return false;
}

byte getBattery(void) {
  //@TODO not yet implemented
  return 100;
}

String getGeoDecimal(int32_t location) {
  unsigned long tmp1, tmp2;
  String out = "";

  if (location < 0) {
    out += '-';
    location = 0 - location;
  }

  tmp1 = location / 10000000;
  tmp2 = location - (tmp1 * 10000000);

  out += tmp1;
  out += ".";
  out += tmp2;

  return out;
}

bool getFence(void) {
  int32_t check = 0;
  DEBUG_PORT.print(F("FENCE - "));

  //Lat
  DEBUG_PORT.print(F("LAT:"));
  system_rtc_mem_read(RTCMEMORYSTART + 1, (int32_t *)check, 4);
  DEBUG_PORT.print(check);
  DEBUG_PORT.print('/');
  DEBUG_PORT.print(lat);
  if (check + fence > lat || check - fence < lat) {
    DEBUG_PORT.println('!');
    return true;
  }
  //Lon
  DEBUG_PORT.print(F(" - LON:"));
  system_rtc_mem_read(RTCMEMORYSTART + 2, (int32_t *)check, 4);
  DEBUG_PORT.print(check);
  DEBUG_PORT.print('/');
  DEBUG_PORT.print(lon);
  if (check + fence > lon || check - fence < lon) {
    DEBUG_PORT.println('!');
    return true;
  }

  DEBUG_PORT.println('_');
  return false;
}

NeoGPS::clock_t getTimestamp(void) {
  if (!fix.valid.date || !fix.valid.time) return 0;

  //This contains the seconds starting from the start of this century
  NeoGPS::clock_t seconds = fix.dateTime;

  //Guessing we're still 20xx this is the unix timestamp for 01.01.2000 00:00:00
  seconds += 946684800;

  return seconds;
}

bool rfConnect(void) {
  unsigned int rftimer;
  
  if(WiFi.status() == WL_CONNECTED) return true;
  
  DEBUG_PORT.print(F("connecting to "));
  DEBUG_PORT.println(ssid);
  if(pass == "") {
    WiFi.begin(ssid);
  }else{
    WiFi.begin(ssid, pass);
  }
  while (WiFi.status() != WL_CONNECTED && rftimer < rf_timeout) {
    delay(1000);
    DEBUG_PORT.print(".");
    rftimer++;
    yield();
  }
  if (WiFi.status() != WL_CONNECTED) {
    DEBUG_PORT.println(F("failed"));
    return false;
  }
  DEBUG_PORT.println(F("connected"));
  DEBUG_PORT.print(F("IP address: "));
  DEBUG_PORT.println(WiFi.localIP());
  return true;
}

void rfDisconnect(void) {
  /*WiFi.disconnect();
  WiFi.mode(WIFI_OFF);
  WiFi.forceSleepBegin();*/
}

bool rfSend(void) {
  String data;
  HTTPClient http;

  if (!rfConnect()) return false;
  if (lat == 0 || lon == 0) return false;

  http.begin(owntracksURL);

  http.addHeader(F("X-Limit-U"), owntracksUser);
  http.addHeader(F("X-Limit-D"), owntracksDevice);
  http.addHeader(F("User-Agent"), F("Adlerweb-ESP-Tracker"));
  http.addHeader(F("Content-Type"), F("application/json"));

  data  = "{\"_type\":\"location\",\"tid\":\"01\",\"conn\":\"m\",\"_cp\":true,\"batt\":";
  data += getBattery();
  data += ",\"lat\":";

  data += getGeoDecimal(lat);
  data += ",\"lon\":";
  data += getGeoDecimal(lon);

  if (cog != 0) {
    data += ",\"cog\":";
    data += cog;
  }

  if (vel != 0) {
    data += ",\"vel\":";
    data += vel;
  }

  if (alt != 0) {
    data += ",\"alt\":";
    data += alt;
  }

  data += ",\"tst\":";
  data += getTimestamp();
  data += "}";

  DEBUG_PORT.println(F("---"));
  DEBUG_PORT.println(data);
  DEBUG_PORT.println(F("---"));
  DEBUG_PORT.println(F("Send"));
  DEBUG_PORT.flush();
  http.POST(data);
  DEBUG_PORT.println(".");
  DEBUG_PORT.flush();
  http.writeToStream(&Serial);
  DEBUG_PORT.println(".");
  DEBUG_PORT.flush();
  http.end();
  DEBUG_PORT.println(F("OK"));
  DEBUG_PORT.flush();

  rfDisconnect();

  return true;
}

void debugDump() {
  DEBUG_PORT.print(F("Status: "));
  switch (fix.status) {
    case 1:
      DEBUG_PORT.println(F("Nährungswert"));
      break;
    case 2:
      DEBUG_PORT.println(F("Nur Zeit"));
      break;
    case 3:
      DEBUG_PORT.println(F("GNSS-Fix"));
      break;
    case 4:
      DEBUG_PORT.println(F("DGNSS-Fix"));
      break;
    default:
      DEBUG_PORT.println(F("Keiner"));
  }
  DEBUG_PORT.print(F("UTC: "));
  DEBUG_PORT.print(fix.dateTime.year);
  DEBUG_PORT.print("-");
  DEBUG_PORT.print(fix.dateTime.month);
  DEBUG_PORT.print("-");
  DEBUG_PORT.print(fix.dateTime.date);
  DEBUG_PORT.print(" ");
  DEBUG_PORT.print(fix.dateTime.hours);
  DEBUG_PORT.print(":");
  DEBUG_PORT.print(fix.dateTime.minutes);
  DEBUG_PORT.print(":");
  DEBUG_PORT.print(fix.dateTime.seconds);
  DEBUG_PORT.print(" - ");
  DEBUG_PORT.print(getTimestamp());
  DEBUG_PORT.print("/");
  //DEBUG_PORT.println(lasttime);

  DEBUG_PORT.print(F("Satellites: "));
  DEBUG_PORT.println(fix.satellites);

  DEBUG_PORT.print(F("Speed: "));
  DEBUG_PORT.println(vel);

  DEBUG_PORT.print(F("Heading: "));
  DEBUG_PORT.println(cog);

  DEBUG_PORT.print(F("Altitude: "));
  DEBUG_PORT.println(alt);

  DEBUG_PORT.print(F("Postition: "));
  DEBUG_PORT.print(lat);
  DEBUG_PORT.print(",");
  DEBUG_PORT.println(lon);

  DEBUG_PORT.print(getGeoDecimal(lat));
  DEBUG_PORT.print(",");
  DEBUG_PORT.println(getGeoDecimal(lon));
}

byte getBootMode(void) {
  byte bootMode = 0;
  system_rtc_mem_read(RTCMEMORYSTART, &bootMode, 1);
  DEBUG_PORT.print("BootMode: ");
  DEBUG_PORT.println(bootMode);
  return bootMode;
}


/////////////


void setup() {
  int32_t dummy = 0;

  pinMode(GNSS_PWR_PIN, OUTPUT);

  DEBUG_PORT.begin(DEBUG_BAUD);
  GNSSPort.begin(GNSS_BAUD);

  delay(2000);

  DEBUG_PORT.println( F("Adlerweb GNSS Tracker v0.1.1") );
  DEBUG_PORT.flush();

  byte bootMode = getBootMode();

  if(bootMode == 0 || bootMode > 5) { //Unknown or first boot
    DEBUG_PORT.println(F("Enabling GNSS Power"));
    digitalWrite(GNSS_PWR_PIN, GNSS_PWR_ON);
    bootMode=1;
    system_rtc_mem_write(RTCMEMORYSTART, &bootMode, 1);
    DEBUG_PORT.print(F("Sleeping for "));
    DEBUG_PORT.print(sleep_GNSS);
    DEBUG_PORT.println(F(" Seconds"));
    DEBUG_PORT.flush();
    ESP.deepSleep(sleep_GNSS * 1e6);
  }

  if(bootMode == 1) { //Waiting for GNSS 3D Fix
    if (wait_3d()) {
      bootMode = 4;
    } else {
      bootMode++;
    }
  }

  if(bootMode == 2) {//Waiting for GNSS 2D Fix
    if (wait_2d()) {
      bootMode = 4;
    } else {
      bootMode++;
    }
  }
  
  if(bootMode == 3) { //Waiting for RF Fix
    //@TODO Not implemented
    bootMode = 5;
  }

  if(bootMode == 4) { //Fix Aquired - sending
    system_rtc_mem_read(RTCMEMORYSTART + 3, &dummy, 4);
    if (getFence() || dummy + (rf_force * 60) <= getTimestamp()) {
      bootMode = 5;
      if (rfSend()) {
        system_rtc_mem_write(RTCMEMORYSTART + 1, &lat, 4);
        system_rtc_mem_write(RTCMEMORYSTART + 2, &lon, 4);
        dummy = getTimestamp();
        system_rtc_mem_write(RTCMEMORYSTART + 3, &dummy, 4);
        bootMode = 0;
      } else {
        DEBUG_PORT.println(F("Transfer failed"));
        bootMode = 0;
      }
    }else{
      Serial.println(F("Position unchanged, no transfer"));
      bootMode = 0;
    }
  }

  if(bootMode == 5) { //No fix
    debugDump();
    bootMode = 0;
  }
  
  system_rtc_mem_write(RTCMEMORYSTART, &bootMode, 1);
}

void loop() {
  DEBUG_PORT.println(F("Disabling GNSS Power"));
  digitalWrite(GNSS_PWR_PIN, !GNSS_PWR_ON);
  DEBUG_PORT.print(F("Sleeping for "));
  DEBUG_PORT.print(sleep_off);
  DEBUG_PORT.println(F(" Minutes"));
  DEBUG_PORT.flush();
  ESP.deepSleep(sleep_off * 60e6);
}

Inhalt

  • 00:35 Das Modul
  • 09:07 Das NMEA-Protokoll
  • 13:33 Test & Konfiguration per U-Center
  • 18:02 GPS mit ESP8266 und Arduino
  • 19:05 Test mit SoftwareSerial
  • 20:47 GPS/WiFi-Tracking mit OwnTracks

Hinweise:

Das GPS-Modul wurde mir von ICStation.com für dieses Video kostenfrei zur Verfügung gestellt.

BitBasics – Satellitennavigationssysteme (GPS, GLONASS, etc)

BitBasics - Satellitennavigationssysteme (GPS, GLONASS, etc)

(43 MB) 00:13:24

2017-10-29 11:00 🛈

Wer wissen will wo er ist, der Fragt meist sein Smartphone – aber wie kann der kleine Kasten diese Frage beantworten? In dieser Folge schauen wir auch die Techniken hinter GPS & Co.

BitBastelei #260 – TFT-LED-Steuerung

BitBastelei #260 - TFT-LED-Steuerung

(160 MB) 00:26:24

2017-10-22 10:00 🛈

Mal etwas aus der „schauen wir halt mal“-Ecke: Ein alter, kaputter Tablet-LCD aus der Restekiste. In diesen steckt auch eine LED-Beleuchtung, welche sich eventuell als Lampe eignen könnte. Schauen wir mal, ob wie die LEDs entnehmen und die Ansteuerung verstehen können.

Postfix: Alle ausgenenden Mails mit einer Absenderadresse

Standardmäßig versendet Postfix die Mails wie sie ankommen, also z.B. mit dem jeweiligen Nutzernamen als Absendeadresse. Nutzt man jedoch einen Smarthost, lässt ausgehende Mails also z.B. über den Server des Providers abwickeln, ist dies häufig nicht erlaubt, einzig die eigene E-Mail wird akzeptiert.

Mit diesen Schritten kann man Postfix anweisen alle ausgehenden Mails so umzuschreiben, dass die vorgegebene E-Mail-Adresse als Absender genutzt wird. Da so auch nicht mehr auf den ersten Blick ersichtlich ist wer die Mail versendet hat, eignen sich diese Schritte nur für Systeme, auf denen ausschließlich vertrauenswürdige Personen Zugang gewährt wurde. Weiterhin gehe ich davon aus, dass Postfix bereits funktionsfähig konfiguriert wurde und für den Versand per Smarthost eine Authentifizierung notwendig ist.

Fangen wir damit an das Passwort zu hinterlegen. Hierzu legen wir eine neue Datei /etc/postfix/relay_password an und tragen Benutzername und Passwort ein.

mail.myprovider.example myuser:mypass

Ggf. sollte die Datei über entsprechende Dateirechte vor neugierigen Blicken geschützt werden. Da Postfix üblicherweise aus geschwindigkeitsgründen Datenbankdateien nutzt müssen wir unsere Textdatei noch entsprechend umwandeln:

postmap /etc/postfix/relay_password

Nun bereiten wir noch eine Absenderersetzung vor. Die Datei sender_canonical biegt mWn den internen Absender um, welcher z.B. im Envelope verwendet wird, header_check kümmert sich um das FROM:-Feld. Je nach Provider kann es ausreichend sein nur eine der Varianten zu verwenden, beachtet jedoch, dass solche Mails gerne von SPAM-Filtern aussortiert werden.

/.+/ myuser@myprovider.example
/From:.*/ REPLACE From: myuser@myprovider.example

Hier sind die Dateien als regexp deklariert und können ohne Mapping genutzt werden.

Zuletzt machen wir diese Dateien noch in der Postfix-Konfiguration bekannt:

[...]
relayhost = mail.myprovider.example

smtp_sasl_password_maps=hash:/etc/postfix/relay_password
smtp_sasl_auth_enable=yes
smtp_sasl_security_options = noanonymous

sender_canonical_classes = envelope_sender, header_sender
sender_canonical_maps = regexp:/etc/postfix/sender_canonical
smtp_header_checks = regexp:/etc/postfix/header_check

In der ersten Zeile wird der eigentliche Server des Providers als ausgehender Server definiert – mit dieser Einstellung wird Postfix nicht mehr selbst versuchen Mails zuzustellen sondern alles an diesen weiterleiten. Im nächsten Block wird angegeben, dass für den ausgehenden Server eine Authentifizierung notwendig ist und wo die Passwörter zu finden sind. In den letzten Zeilen definieren wir unsere Filter, welche die Ersetzung vornehmen.

Nach dem nächsten Reload des MTA sollten nun alle E-Mails mit der gesetzten Absenderadresse über den angegebenen Smarthost versendet werden.

Firefox statt IE im Unternehmen – Deployment, Konfiguration und Co

In vielen Firmen gilt noch immer Microsoft Edge bzw. der Internet Explorer als Standardbrowser für Inter- und Intranet. Einer der wichtigsten Gründe ist die Verwaltbarkeit: Updates werden über die Systemfunktionen automatisch installiert, Eintellungen lassen sich komfortabel über Gruppenrichtlinien zuweisen. Was viele IT-Abteilungen nicht auf dem Schirm haben ist, dass es auch mit alternativen Browsern nicht vollkommen unmöglich ist eine solch zentrale Konfiguration einzurichten. Hier möchte ich ein paar Kniffe für den Einsatz von Firefox in größeren Installationen geben.

Deployment und Updates

Fangen wir kurz mit Deployment und Updates an: In vielen Firmen laufen Updates des IE über WSUS. Dieser ermöglicht es Aktualisierungen erst in einem Laborumfeld auf unerwünschte Nebenwirkungen zu testen und im Anschluss an die Clients zu verteilen. Prinzipitell gut, jedoch ist WSUS hauptsächlich für Microsoft-Produkte ausgelegt, wird vom Hersteller etwas stiefmütterlich behandelt und ist – zumindest nach meiner Erfahrung – nur mäßig zuverlässig. Nicht zuletzt weil nahezu kein Unternehmen ohne Drittanbietersoftware auskommt, wird in vielen Firmen ein weiteres Deployment-System wie z.B. SCCM oder das kostenfreie OPSI zum Einsatz. Über diese kann man auch Firefox recht schnell ausrollen. Hierzu benötigt man statt dem kleinen Stub-Installer, welcher für Windows üblicherweise ausgeliefert wird, den Offline-Installer, welcher z.B. auf der Sprachübersicht zu finden ist. Wer neue Funktionen gegen seltenere Wartung tauschen möchte kann alternativ auf den Extended Service Release“ (ESR) zurückgreifen. Hierbei handelt es sich um eine spezielle Version von Firefox, welche über einen längeren Zeitraum mit Sicherheitsaktualisierungen versorgt wird. Im Gegensatz zur Desktop-Version werden bei diesen Updates – soweit mögich – keine Funktionen verändert. Der Befehl für eine Silent-Installation lautet

Firefox Setup 55.0.3.exe /S

Achtung: Beim Download haben 32- und 64-Bit-Varianten aktuell, trotz unterschiedlichem Inhalt, den selben Dateinamen. Über den selben Weg kann man neuere Versionen zur Aktualisierung installieren. Möchte man die Software später wieder löschen findet sich im Installationsverzeichnis eine passende Datei

"%PROGRAMFILES%\Mozilla Firefox\uninstall\helper.exe" /S

Konfiguration

Bleibt die Konfiguration. Hier lässt sich ein Überbleibsel aus der Netscape-Zeit nutzen, welche die Ausführung von Scripten beim Start des Browsers erlaubt. Im ersten Schitt legt man eine neue Datei im Ordner „%PROGRAMFILES%\Mozilla Firefox\defaults\pref\“ an. Der Name kann frei gewählt werden, jedoch erfolgt die Ausführung alphabetisch. Als inoffizielle Konvention hat sich „autoconfig.js“ durchgesetzt. Erste Falle: Die erste Zeile. Diese wird automatisch übersprungen, dort hinterlegte Befehle also ignoriert. Als Workarround sollte man in dieser folglich besser einen Kommentar unterbringen. Zweite Falle: Zwar können in dieser Datei bereits Konfigurationen gesetzt werden, jedoch wird sie während des Browserstarts zu einem Zeitpunkt geladen, an dem noch nicht alle Subsysteme verfügbar sind. Um dies zu umgehen wird stattdessen ein Verweis auf eine weitere Konfiguration hinterlegt, welche am Ende des Starts geladen wird. In diesem Beispiel nenne ich diese „mycompany.js„. Standardmäßig sind diese nachgeladenen Dateien mir ROT13 (sic!) codiert um neugierige Blicke und Änderungen von Nutzerseite zu erschweren. Da Ersteres ohnehin auch über die Browserfunktionen möglich ist und sich Schreibzugriffe über die Berechtigungen des Dateisystems effektiver verhindern lassen, schalte ich diese Funktion aus, so sind Änderungen einfacher.

// File must start with a comment
pref("general.config.filename", "mycompany.js");
pref("general.config.obscure_value", 0);

Nun geht es daran die eigentliche Konfiguration zu erstellen. Die zuvor referenzierte „mycompany.js“ wird im Programmverzeichnis, also „%PROGRAMFILES%\Mozilla Firefox\„, erwartet. Für das Setzen von Konfigurationen stehen uns verschiedene Befehle zur Verfügung – hier die wichtigsten:

Befehle

pref()

So gesetzte Einstellungen sind identisch zu jenen, die der Nutzer in der GUI oder about:config vornimmt. Die Änderungen werden als „vom Benutzer eingestellt“ angezeigt. Benutzer können diese weiterhin ändern, da das Konfigurationsscript jedoch bei jedem Browserstart läuft werden die Änderungen nach dem Neustart des Browsers wider auf den vorgegebenen Wert zurückgesetzt.

defaultPref()

Hiermit wird die Standardeinstellung geändert. Der Nutzer hat auch hier die Möglichkeit diese selbstständig zu ändern, jedoch sind Benutzeranpassungen bei dieser Variante persistent und werden bei einem Neustart nicht automatisch zurückgesetzt.

lockPref()

Hiermit wird eine Einstellung gesetzt und gleichzeitig gesperrt. Sie kann im Anschluss nicht mehr vom Nutzer geändert werden, entsprechende Konfigurationsfelder werden ausgegraut.

unlockPref()

Hebt die Sperre wieder auf. Interessant wenn man z.B. mit einer globalen Konfiguration arbeitet, bestimmten Benutzergruppen jedoch Funktionen über eine weitere Konfigurationsdatei wieder freigeben möchte.

getPref()

Liest die Konfiguration – z.B. um ein „identisch zu X“ umzusetzen.

clearPref()

Löscht die Konfiguration

getenv()

Liest eine Umgebungsvariable

Wie am Namen zu erkennen handelt es sich um Javascript, man kann also auch eigene Logik einbringen. Auch hier nutze ich die erste Zeile zur Sicherheit als Kommentar. Die Bezeichnungen der Konfigurationsfelder kann man im Browser zu großen Teilen in about:config finden.

Beispiele

Automatische Updates ausschalten

Da Updates, wie oben erwähnt, über das zentrale Deployment laufen sollen, wird der Auto-Updater des Browsers ausgeschaltet. So wird der Nutzer nicht mit entsprechenden Aufforderungen konfrontiert und Änderungen können vor einem breiten Rollout in einer überwachten Umgebung auf Kompatibilität mit den Unternehmensanforderungen geprüft werden. Achtung: Einige der Updater-Einstellungen lassen sich nur mit lockPref() setzen.

	// Deaktiviert den Updater
	lockPref("app.update.enabled", false);

	// Stellt sicher dass er tatsächlich abgestellt ist
	lockPref("app.update.auto", false);
	lockPref("app.update.mode", 0);
	lockPref("app.update.service.enabled", false);

	// Deaktiviert die Kompatbilitätsprüfung der Add-ons
	clearPref("extensions.lastAppVersion");
	
	//Deaktiviert das 'plugin checking'
	lockPref("plugins.hide_infobar_for_outdated_plugin", true);
	clearPref("plugins.update.url");
	
	// Verhindert die Frage nach der Installation des Flash Plugins
	pref("plugins.notifyMissingFlash", false);

Branding und Telemetrie

Je nach Firmen-Policy kann ein Branding oder der Upload von Telemetrieinformationen an Mozilla unerwünscht sein.

	// Deaktiviert 'Kenne deine Rechte' beim ersten Start
	pref("browser.rights.3.shown", true);

	// Versteckt 'Was ist neu?' beim ersten Start nach jedem Update
	pref("browser.startup.homepage_override.mstone", "ignore");
	
	// Deaktiviert den 'health reporter'
	lockPref("datareporting.healthreport.service.enabled", false);

	// Disable all data upload (Telemetry and FHR)
	lockPref("datareporting.policy.dataSubmissionEnabled", false);

	// Deaktiviert den 'crash reporter'
	lockPref("toolkit.crashreporter.enabled", false);
	Components.classes["@mozilla.org/toolkit/crash-reporter;1"].getService(Components.interfaces.nsICrashReporter).submitReports = false;

Startseite

Wenn ein Intranet-Portal o.Ä. automatisch geladen werden soll kann dies als Startseite hinterlegt werden

	// Stellt eine Standart-Homepage ein
	pref("browser.startup.homepage", "https://portal.mycompany.local/");

Zertifikate

SSL-Zertifikate sind bei Drittbrowsern immer eine Qual. Statt den Systemzertifikatspeicher zu verwenden bringen die meisten Browser einen eigenen Zertifikatspeicher mit. Firmen, welche interne CAs verwenden müssen hier eine separate Konfiguration erzeugen und können sich nicht auf die Verteilung per GPO o.Ä. verlassen. Bei Firefox gibt es hier die Möglichkeit über certutil Zertifikate per Script zu importieren.
Bei neueren Installationen kann man Firefox jedoch instruieren auch Zertifikate zu akzeptieren, welche im Windows-Zertifikatspeicher hinterlegt sind.

	//Accept system certificates
	pref("security.enterprise_roots.enabled", true);

Proxy-Server

Verwendet die Firma einen Proxyserver, welcher nicht über den Router als „transparenter Proxy“ betrieben wird, kann dieser ebenfalls hier hinterlegt werden.

	//proxy
	defaultPref("network.proxy.type", 1);
	defaultPref("netword.proxy.ssl", "proxy.mycompany.local");
	defaultPref("netword.proxy.http", "proxy.mycompany.local");
	defaultPref("netword.proxy.ftp", "proxy.mycompany.local");
	defaultPref("netword.proxy.ssl_port", "3128");
	defaultPref("netword.proxy.http_port", "3128");
	defaultPref("netword.proxy.ftp_port", "3128");
	defaultPref("network.proxy.no_proxies_on", "localhost, 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, .mycompany.local");
	defaultPref("network.proxy.share_proxy_settings", true);

Lesezeichen

Das Erstellen von Lesezeichen ist etwas komplizierter, da man hier mit Datenbank und GUI interagieren muss, welche erst am Ende des Browserstarts zur Verfügung stehen. Um sicherzugehen, dass hier alle Module verfügbar sind, wird das Erstellen in eine eigene Funktion ausgelagert und mit einem Hook des Browsers verknüpft. Das Erstellen erfolgt über den nsINavBookmarksService. Dieser ermöglicht auch das Verwalten von Ordnern oder das Löschen von Elementen.

	var observer = {
		observe: function observe(subject, topic, data) {
			// DO BOOKMARKS WORK HERE
			var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
			var uri1 = ios.newURI("https://helpdesk.mycompany.local/", null, null);
			var uri2 = ios.newURI("https://nextcloud.mycompany.local/", null, null);
			var navBookmarksService = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Components.interfaces.nsINavBookmarksService);
			if (!navBookmarksService.isBookmarked(uri1)) {
				navBookmarksService.insertBookmark(navBookmarksService.toolbarFolder, uri1, navBookmarksService.DEFAULT_INDEX, "Helpdesk");
			}
			if (!navBookmarksService.isBookmarked(uri2)) {
				navBookmarksService.insertBookmark(navBookmarksService.toolbarFolder, uri2, navBookmarksService.DEFAULT_INDEX, "Nextcloud");
			}
		}
	}

	Components.utils.import("resource://gre/modules/Services.jsm");
	Services.obs.addObserver(observer, "distribution-customization-complete", false);

Alternativen

Wer weniger administriert und lieber herumklickt eine GUI der Textkonfiguration vorzieht kann einen Blick auf CCK2 werfen, welches die Konfiguration grafisch aufbereitet.

[ICStation.com] BitBastelei #259 – Audio-Frequenzweiche: Soundsystem-Recycling

[ICStation.com] BitBastelei #259 - Audio-Frequenzweiche: Soundsystem-Recycling

(84 MB) 00:18:17

2017-10-15 10:00 🛈

Es ist Laubbläserzeit – wohl dem, der Soundtechnisch dagegen halten kann. Leider sind meine Eigenbau-Mediacenter da etwas dünn aufgestellt, allerdings liegt noch ein altes, analoges 5.1-System in der Kiste. Könnte man aus dem Stereo-Ausgang des Raspberry Pi nur ein Bass-Signal für den Subwoofer erzeugen. Kann man natürlich, und eine dafür notwendige Frequenzweiche bietet ICStation.com als Bausatz an.

Links

Inhalt

00:00 Warum das Ganze?
02:26 Der Bausatz
05:36 Die Schaltung
07:10 Simulation
09:45 Erste Messung
11:46 Das fertige Modul
12:00 Blick in das Audiosystem
15:05 Frequenzweiche an der Box
16:38 Ozi-Auswertung mit Last

Hinweise

Der Bausatz wurde mir von ICStation.com für dieses Video kostenfrei zur Verfügung gestellt.

Nerd Inside