Newsserver einrichten
INN2
InterNetNews ist ein nntp Server für Linux. Die nachstehende Anleitung zeigt, wie man mit inn2 einen Newsserver für Freifunk aufsetzt.
Installation
Unter Debian:
sudo aptitude install inn2 suck
Konfiguration
Alle Konfigurationsdateien liegen in /etc/news/
- Zuerst einmal muß die Hauptconfig angepasst werden. Diese liegt als /etc/news/inn.conf vor.
Die Parameter organization und pathhost sollten auf jeden Fall angepasst werden.
organization: "Freifunk Leipzig" pathhost: news.leipzig.freifunk.net
Auf Systemen mit mehreren IP Adressen ist es zusätzlich sinnvoll, den inn2 an eine bestimmte Adresse zu binden:
bindaddress: 88.198.44.10
- Anschließend zur /etc/news/expire.ctl hinzufügen:
freifunk.*:A:never:never:never
Dies sorgt dafür, daß die Nachrichten nicht auslaufen und dauerhaft vorgehalten werden. Andere Werte sind natürlich auch möglich, falls der Speicherplatz begrenzt ist.
- Zur /etc/news/control.ctl hinzufügen:
# freifunk newgroup:*:freifunk.*:doit rmgroup:*:freifunk.*:doit
Damit wird das automatische Erzeugen und Löschen von Gruppen durch control Nachrichten innerhalb der freifunk.* Hierarchie erlaubt.
- /etc/news/actsync.ign anlegen mit folgendem Inhalt
# Don't touch control groups, etc. i control i control.* i local.* i general i junk
Diese Datei stellt sicher, dass beim Abgleich der Liste der Gruppen lokalen Systemgruppen nicht gelöscht werden.
- mit /etc/news/readers.conf wird der Zugriff auf den Newsserver reguliert
# Clients die aus einem der in "hosts" angegebenen Adressbereiche connecten # erhalten den pseudo Usernamen "freifunk" ... auth "freifunk" { hosts: "104.0.0.0/8" default: "freifunk" } # ... diesen wird dann einfacher lesender und schreibender Zugriff auf # die freifunk.* Hierarchie erlaubt. access "freifunk" { users: "freifunk" newsgroups: "freifunk.*" }
Wichtig: Der letzte passende Eintrag gilt, d.h. allgemein gefasste Einträge müssen vor spezifischen Einträgen stehen. Dies gilt insbesondere auch für eventuelle Server, wie weiter unten gezeigt.
Benutzerauthentifizierung
Mit diesem Perl Script kann man eine Benutzerauthentifizierung gegen die FFsomething Benutzerdatenbank durchführen.
Dazu muss in die readers.conf Folgendes vor den anderen Einträgen hinzugefügt werden:
# Login mit FFsomething Benutzerkennung auth "freifunk" { auth: /etc/news/filter/ffsomething_auth.pl }
SSL Verschlüsselung
Obwohl die SSL Funktionen von inn2 nicht mit Thunderbird und möglicher Weise anderen Clients kompatibel sind, kann man optional einen SSL Verschlüsselung für die Benutzer mit Hilfe von stunnel und inetd realisieren.
- in /etc/inetd.conf eintragen
nntps stream tcp nowait root /usr/bin/stunnel stunnel -p /usr/lib/news/cert.pem -s news -g news -r nntp
Synchronisation
Es gibt zwei Möglichkeiten einen INN zu füttern. Entweder man syncronisiert passiv durch pull der Nachrichten, oder man wird gefüttert von einem Upstream (statische IP nötig).
Die Gegenstelle muß euch erlauben, die Nachrichten abzuholen bzw. sie Euch zuschicken. Daher müsst ihr auf einem der großen Newsserver nach einem Upstream fragen. Am besten von zwei, damit eine gewisse Redundanz entsteht.
Pull
Fürs pullen am Besten suck installieren.
- /etc/cron.d/inn2 eintragen
# update active list every day 3 3 * * * news /usr/lib/news/bin/actsync -A localhost UPSTREAM -v 1 -p 0 -o x -i /etc/news/actsync.ign # suck new articles every five minutes */5 * * * * news suck UPSTRAM -U LOGIN -P PWD -bp -hl localhost -q -s -A -c 2>/dev/null >/dev/null
falls eine Meldung wie diese kommt:
200 UPSTREAM InterNetNews server INN 2.5.2 ready (transit mode) GROUP <freifunk.de.berlin.discuss>, unexpected response, 401 Broken connection, aborting Elapsed Time = 0 mins 0.00 seconds Closed connection to <UPSTREAM>
muss suck im Cronjob um die Option -M ergänzt werden. Damit teilt man dem Server mit, dass er
*/5 * * * * news suck UPSTRAM -U LOGIN -P PWD -bp -hl localhost -q -s -A -c -M 2>/dev/null >/dev/null
Newsfeeds
Newsfeeds sind eigentlich eine saubere Lösung. Die meisten Newsserver auf diesem Planeten verwenden reguläre Newsfeeds um ihren Datenbestand auszutauschen. Allerdings funktionieren Newsfeeds nur mit statischen IP Adressen größtenteils ohne Probleme. Bei Servern mit dynamischen IP Adressen sollte man keine Newsfeeds einsetzen, da es regelmäßig zu Verbindungsabbrüchen kommt und der Austausch von Daten nicht gewährleistet werden kann.
Man kann einen ausgehenden Feed entweder mittels nntpsend (zeitverzögert) oder innfeed (echtzeit) konfigurieren.
Empfang
- in /etc/news/readers.conf hinter den allgemeinen Einträgen
# Den hier in der "hosts" Zeile eingetragenen Rechnern wird # der pseudo Username "server" zugewiesen ... auth "server" { hosts: "peer-1.fqdn.tld, peer-2.fqdn.tld, ..." default: "server" } # ... welcher erhöhte Privilegien erhält. access "server" { users: "server" newsgroups: "*" access: "RPIAN" }
Hier wird allen Peers der Pseudo-User "server" zugewiesen. Dieser User hat mehr Berechtigungen welche z.B. zum Synchronisieren und Feeden gebraucht werden.
Möglicher Weise gibt es Probleme mit Reverse Lookup, weshalb die Verwendung von IP Adressen anstelle von Hostnamen hier eigentlich die bessere Wahl ist.
- in /etc/news/incoming.conf
group freifunk { peer peer1 { hostname: "peer-1.fqdn.tld" } peer peer2 { hostname: "peer-2.fqdn.tld" } ... }
Als Peer trägt man einen beliebigen Bezeichner ein und als Hostnamen den jeweiligen FQDN oder die IP Adresse. Auch hier sind die IP Adressen eventuell besser, um Probleme zu vermeiden.
Versand (echtzeit)
- in /etc/news/newsfeeds
innfeed!\ :!*\ :Tc,Wnm*:/usr/lib/news/bin/startinnfeed peer1:*,!junk,!local*:Tm:innfeed! peer2:*,!junk,!local*:Tm:innfeed!
Hier wird zunächst ein Sammelfeed ("funnel") definiert, der über das externe Programm innfeed versendet wird. Anschließend wird festgelegt, dass für die genannten Peers alle News-Gruppen außer "junk" und "local.*" an diesen funnel übergeben werden sollen.
- in /etc/news/innfeed.conf
group freifunk { peer peer1 { ip-name: "peer-1.fqdn.tld" } peer peer2 { ip-name: "peer-2.fqdn.tld" } }
In dieser Datei werden die vollständigen Hostnamen bzw. IP Adressen für jeden Peer (Ziel) konfiguriert.
Versand (zeitversetzt)
Wenn ihr feeds in bestimmten Intervallen zu anderen Servern schicken möchtet:
- in /etc/news/newsfeeds:
peer1:*,!local*,!junk:Tf,Wnm: peer2:*,!local*,!junk:Tf,Wnm: peer3:*,!local*,!junk:Tf,Wnm: ...
Die einzelnen Zeilen legen fest wohin lokale Posts verteilt werden sollen, gefiltert nach Gruppen. In unserem Beispiel werden alle lokalen Gruppen außer die internen "junk" und "local.*" Gruppen an alle Peers verteilt. Die Nachrichten werden zunächst in eine lokale Datei geschrieben.
- in /etc/news/nntpsend.ctl:
peer1:peer-1.fqdn.tld::-t180 peer2:peer-2.fqdn.tld::-t180 peer3:peer-3.fqdn.tld::-t180 ...
Hier wird festgelegt welche Peers vom eigenen Server versorgt werden. "peer-n.fqdn.tld" wird hierbei durch den voll qualifizierten Hostnamen oder die statische IP-Adresse des jeweiligen Peer-Servers ersetzt.
- in /etc/news/passwd.nntp
peer1:user:password peer2:user:password
Dieser Eintrag wird nur benötigt, falls der Zielserver ein Passwort verlangt. Der Benutzernamen und das Passwort zum Synchronisieren muss beim jeweiligen Betreiber des Peers erfragt werden.
- in /etc/cron.d/inn2
*/5 * * * * news /usr/lib/bin/nntp-send peer1 peer2 peer3
Dieser Eintrag sorgt dafür, dass die lokal gesammelten Nachrichten alle fünf Minuten an den/die Zielserver gesendet werden. Die Zielserver können alle in einer Zeile hintereinander aufgeführt werden.
Letzte Schritte
- Starten des inn2 Servers
/etc/init.d/inn2 start
- Beim ersten Start sollte noch mit einem der Upstreams synconisiert werden. Als root eingeben:
su - news /usr/lib/news/bin/actsync -A localhost UPSTREAM -v 1 -p 0 -o x
Dies aktualisert das active file, also die Liste aller auf dem Newsserver aktiven Newsgroups.
- bisher vorhandene Artikel holen
suck UPSTREAM -U LOGIN -P PWD -bp -hl localhost -q -s -A -c 2>/dev/null >/dev/null
füllt erstmal den Newsserver mit allen Nachrichten vom Upstream, damit er nicht so leer ist :)
- suck evtl. um -M ergänzen (siehe #Pull)
- um alle historischen Artikel vom Upstream zu bekommen, muss in inn.conf der Parameter artcutoff auf 0 gesetzt werden. Alle anderen positiven Zahlen zeigen das maximale Alter der zu importierenden Artikel an.
- suck lädt standardmäßig nur die 100 neuesten Artikel, so dass man zusätzlich -i 0 als Parameter anhängen muss, um alle Artikel zu laden
Verschlüsselung einrichten
Als erstes brauchen wir ein Certifikat. Ein self-signed erstellt man einfach so
openssl req -new -x509 -nodes -days 365 -keyout /etc/news/nnrpd-key.pem -out /etc/news/nnrpd-cert.pem
Um dieses Cert für TLS zu verwenden muß man es nur noch einbinden:
/etc/news/inn.conf
tlscapath: /etc/news tlscertfile: /etc/news/cert.pem tlskeyfile: /etc/news/key.pem
Nach einem innd Neustart solltre TLS funktionieren.
Um nntps ans laufen zu bringen muß man etwas weiter ausholen. die Lösung mit stunnel funktioniert zwar, ist aber ein Sicherheitsloch - denn auf einmal kommen alle Verbindungen von localhost - der meistens mehr Berechtigungen hat als ein normaler User. Sauberer ist es innd über xinetd zu starten mit der Option für SSL ( -S ).
/etc/xinetd.d/nntpd
service nntps { disable = no socket_type = stream protocol = tcp user = news wait = no server = /usr/lib/news/bin/nnrpd server_args = -S per_source = 4 instances = 200 log_on_success += DURATION HOST USERID }
xinetd neustarten und es sollte funktionieren.
Newsgroup Anlegen
ctlinnd newgroup freifunk.de.NAME
Synchronisation mit Mailinglisten
Die bequeme Art
Wird die Mailingliste von Mailman verwaltet, kann man dort im Administrationsmenü eine Kopplung zu einer Newsgroup einrichten. Es reicht, die Newsgruppe und den Newsserver anzugeben. Auf INN2-Seite muss die IP-Adresse oder der DNS-Name des Mailmanservers in der Konfiguration der Newsfeeds beschrieben in /etc/news/readers.conf sowie in /etc/news/incoming.conf eingetragen werden.
Pferdefuß an diese Lösung ist, das in vielen Mailman-Installationen ein Cron-Job nicht gestartet wird, der neue Nachrichten aus den Newsgruppen abholt. Entweder hostet man Mailman selbst, man kann seinen Mailman-Admin überzeugen oder man greift auf Lösung 2 zurück.
Für Listen auf @freifunk.net ist der Cron-Job aktiviert und diese Listen können synchronisiert werden. Falls ihr euren Mailman-Admin bekehren wollt, er/sie muss nur diese Einstellung ändern (Info von In-Berlin):
Das relevante Skript dafür ist cron/gate_news, bei uns konkret sieht der Eintrag so aus ($mailmandir ist das Verzeichnis, in dem Mailman installiert ist, z.B. /usr/local/mailman):
*/5 * * * * mailman /usr/bin/python -S $mailmandir/cron/gate_news
Die funktionierende Lösung
Diese Lösung erfordert deutlich mehr Aufwand zur Einrichtung, aber hier hat der Adminitrator des Newsservers die Synchronisation in der Hand. Mit dieser Lösung wird in Weimar und Hamburg gearbeitet.
Voraussetzungen Software
- Procmail und Postfix müssen installiert sein
- Newsserver ist fertig konfiguriert
- Newsgruppen für die zu synchronisierenden Mailinglisten sind angelegt
Voraussetzungen Mailingliste
- Eine Emailadresse, die der Server empfangen kann registriert man für jede Mailingliste, die man synchronisieren möchte bei der jeweiligen Mailingliste, z.B. <listenname>@<serverdomain>.<tld>. Wichtig ist, dass es jeweils andere Adressen sind.
- in der Mailingliste konfiguriert man die Emailadresse so, dass sie alle Nachrichten als Einzelnachrichten bekommt, nur die eigenen Nachrichten lässt man sich nicht zusenden
Anpassungen von INN2-Skripten
Die Skripte für das posten von Mails auf Newsgruppen und das Versenden von Newseinträgen auf Mailinglisten müssen etwas angepasst werden. Die Anweisungen und Diffs sind in http://batleth.sapienti-sat.org/projects/news2mail/news2mail-FAQ-en.html zu finden. Da die Versionen recht alt sind kann das Patchen fehlschlagen oder ungültige Dateien erzeugen. Wendet euch bei Fragen an Andibraeu (Diskussion)
- /usr/lib/news/bin/mailpost
- path enthält dann mailpost, als Kennzeichen für news2mail, dass die Mail von der Liste kam und nicht nochmal hingeschickt werden muss
- leere Subjects werden aufgefüllt
- cc und reply-to werden gesetzt
- organization wird gesetzt
- /usr/lib/news/bin/news2mail
- Korrektur von Headerfeldern
Konfiguration des Newsservers
In /etc/news/newsfeeds muss diese Zeile genau einmal auftauchen: news2mail!:!*:Ac,Tc,Wn*:/usr/lib/news/bin/news2mail
Eventuell existiert sie schon oder beginnt mit n2m. Für jede zu synchronisierende Mailingliste sind diese beiden Konfigurationsschritte notwendig:
- ans Ende von /etc/news/newsfeeds kommt
absenderemail@adresse.de/mailpost:!*,<newsgroup>:Tm,Ac:news2mail!
- die Absenderemail entspricht der oben registrierten Emailadresse
- für newsgroup wählt man die Gruppe aus, die mit der Mailingliste synchronisiert werden soll, z.B. freifunk.de.<stadtname>
- ans Ende von /etc/news/news2mail.cf kommt
absenderemail@adresse.de zieladresse@mailingliste.com
- die Absenderadresse entspricht der in newsfeeds angegebenen Adresse
- die Zieladresse ist die, mit der man normalerweise an die Mailingliste schreibt
Einrichten eines Aliases
Eingehende Emails werden von Postfix entgegengenommen und können dann weiter verarbeitet werden. Mit einem Alias kann man Emails an bestimmte Adresse z.B. per Pipe weiterverarbeiten, was wir hier ausnutzen.
- in /etc/aliases trägt man nun den Alias mit dem auszuführenden Kommando ein:
listenname: "| sed -e 's/\\[Freifunk[^]]*]//g' | /usr/bin/formail -f -c -z -U Content-Transfer-Encoding: -I X-Trace: -I X-Complaints-To: | /usr/lib/news/bin/mailpost newsgroup"
- listenname entspricht der anfangs registrierten Emailadresse
- der sed-Befehl entfernt in diesem Fall Ergänzungen im Subject, die mit [Freifunk beginnen
- formail entfernt störende Header
- mailpost schickt den Artikel dann an die newsgroup
- zuletzt muss noch
newaliases
ausgeführt werden, um den neuen Alias wirksam werden zu lassen
Um die Kiddies daran zu hindern, das Passwort für den Mailinglistensubscriber auf die Liste zu posten, kann man in Postfix header_checks einbauen:
- postfix-pcre nachinstallieren
- Datei /etc/postfix/header_checks anlegen
/^From: bounces-adresse@mailman/ REDIRECT user@domain
/^From: request-adresse@mailman/ REDIRECT user@domain
- /etc/postfix/main.cf um
header_checks = pcre:/etc/postfix/header_checks
ergänzen - postfix neustarten
- fertig
Dokumentation
Dokumentation zu Inn2 findet sich u.A. unter http://www.eyrie.org/~eagle/software/inn/
Peeringliste
Server welche zum Peering offen sind und die Freifunk Hierarchie beinhalten.
Server | Admin | Peerings |
news.leipzig.freifunk.net | freifunk [ät] poelzi {dot} org | news1.halle, news2.leipzig, news.hannover, news.weimar |
news2.leipzig.freifunk.net | freifunk {at} wwsnet {dot} net | news1.halle, news.leipzig |
news1.freifunk-halle.de | se nada1 de | news.leipzig, hannover |
news.weimarnetz.de | freifunk andi95 de | leipzig, hamburg, gronau |
news.hamburg.freifunk.net | andre hamburg freifunk net | weimar |
Nur Mesh-Intern:
Name | IP | Admin | Peerings |
news.gronau.ff | 10.244.16.1 | freifunk ! liztv.net | news.weimar |
Mailman 2.1.9 Patch für Message-ID-Handling
Mailman ändert standardmäßig die Message-IDs von NNTP-Postings um Duplikate zu vermeiden. Das hat den Nebeneffekt, das das Threading zwischen News und Mail nicht mehr sauber funktioniert da die Nachrichten ihre Bezüge zueinander verlieren. Zusätzlich haben NNTP-Postings, die in Mailinglisten erscheinen, zusätzlich einen Newsgroups-Header gesetzt, welcher manche Mail-Clients veranlasst die Antwortadresse auf die Ursprungs-Newsgroup statt auf die Liste zu setzen.
Der folgende Patch behebt die Probleme:
Index: mailman-2.1.9/cron/gate_news =================================================================== --- mailman-2.1.9.orig/cron/gate_news 2009-04-17 02:41:00.000000000 +0200 +++ mailman-2.1.9/cron/gate_news 2009-04-17 02:41:11.000000000 +0200 @@ -171,6 +171,7 @@ msg['X-Originally-To'] = msg['To'] del msg['To'] msg['To'] = mlist.GetListEmail() + del msg['Newsgroups'] # Post the message to the locked list inq = get_switchboard(mm_cfg.INQUEUE_DIR) inq.enqueue(msg, Index: mailman-2.1.9/Mailman/Queue/NewsRunner.py =================================================================== --- mailman-2.1.9.orig/Mailman/Queue/NewsRunner.py 2009-04-17 02:39:54.000000000 +0200 +++ mailman-2.1.9/Mailman/Queue/NewsRunner.py 2009-04-17 02:41:11.000000000 +0200 @@ -59,6 +59,8 @@ def _dispose(self, mlist, msg, msgdata): # Make sure we have the most up-to-date state mlist.Load() + if msg['X-Mailman-ID']: + return False if not msgdata.get('prepped'): prepare_message(mlist, msg, msgdata) try: @@ -143,8 +145,7 @@ if lname == mlist.internal_name() and hname == mlist.host_name: hackmsgid = False if hackmsgid: - del msg['message-id'] - msg['Message-ID'] = Utils.unique_message_id(mlist) + msg['X-Mailman-ID'] = Utils.unique_message_id(mlist) # Lines: is useful if msg['Lines'] is None: # BAW: is there a better way?
Hier ist eine sauberere Variante das obigen Patches, welche allerdings noch nicht getestet wurde.
Das Messgae-ID-verhalten ist jetzt konfigurierbar und standardmäßig wie im orignalen Mailman eingestellt:
Index: mailman-2.1.9/Mailman/Queue/NewsRunner.py =================================================================== --- mailman-2.1.9.orig/Mailman/Queue/NewsRunner.py 2009-04-17 05:18:00.000000000 +0200 +++ mailman-2.1.9/Mailman/Queue/NewsRunner.py 2009-04-19 12:04:35.000000000 +0200 -59,6 +59,13 @@ def _dispose(self, mlist, msg, msgdata): # Make sure we have the most up-to-date state mlist.Load() + if not mm_cfg.NNTP_MANGLE_MSGID: + xtrace = msg['x-mailman-nntp-trace'] + xlstid = mlist.internal_name() + '@' + mlist.host_name + if xtrace: + for xid in re.split('\s*,\s*', xtrace): + if xid == xlstid: + return False if not msgdata.get('prepped'): prepare_message(mlist, msg, msgdata) try: -134,17 +141,27 @@ # looping. # # Our Message-ID format is <mailman.secs.pid.listname@hostname> - msgid = msg['message-id'] - hackmsgid = True - if msgid: - mo = mcre.search(msgid) - if mo: - lname, hname = mo.group('listname', 'hostname') - if lname == mlist.internal_name() and hname == mlist.host_name: - hackmsgid = False - if hackmsgid: - del msg['message-id'] - msg['Message-ID'] = Utils.unique_message_id(mlist) + if mm_cfg.NNTP_MANGLE_MSGID == True: + msgid = msg['message-id'] + hackmsgid = True + if msgid: + mo = mcre.search(msgid) + if mo: + lname, hname = mo.group('listname', 'hostname') + if lname == mlist.internal_name() and hname == mlist.host_name: + hackmsgid = False + if hackmsgid: + del msg['message-id'] + msg['Message-ID'] = Utils.unique_message_id(mlist) + else: + xtrace = msg['x-mailman-nntp-trace'] + xlstid = mlist.internal_name() + '@' + mlist.host_name + del msg['x-mailman-nntp-trace'] + if xtrace: + msg['X-Mailman-NNTP-Trace'] = xtrace + ', ' + xlstid + else: + msg['X-Mailman-NNTP-Trace'] = xlstid + # Lines: is useful if msg['Lines'] is None: # BAW: is there a better way? Index: mailman-2.1.9/Mailman/Defaults.py.in =================================================================== --- mailman-2.1.9.orig/Mailman/Defaults.py.in 2009-04-19 11:42:00.000000000 +0200 +++ mailman-2.1.9/Mailman/Defaults.py.in 2009-04-19 11:45:42.000000000 +0200 -459,6 +459,14 @@ ('mime-version', 'X-MIME-Version'), ] +# The following parameter specifies whether NNTP message ids are mangled +# when received from the newsgroup and pushed to the list. If mangling is +# enabled, mailman will exchange the original id with a mailman-id. This +# usually leads to broken threading in newsgroups. If mangling is disabled, +# Mailman will keep the original id but add a X-Mailman-NNTP-Trace header +# to keep track of duplicates. +NNTP_MANGLE_MSGID = Yes + # All `normal' messages which are delivered to the entire list membership go # through this pipeline of handler modules. Lists themselves can override the # global pipeline by defining a `pipeline' attribute.