OpenVPN: Routen aus LDAP

I had an OpenVPN-Server which authenticates users with the help of a slapd / OpenLDAP-Server. But I wanted to have more: Depending on the groups the authenticated user is a member of, firewall and routing rules should be pushed to the client and installed on the server.

OpenVPN has two configuration variables: client-connect and client-disconnect which can be set to scripts.

The connect-script itself searches for groups with ip-ranges and addresses (here, they are parameters of a user defined scheme), sets up the regarding iptables-rules for the Masquerading and pushes the route to the client (with the help of a connection specific configuration file).

Please keep in mind: This is a dirty hack. No exceptions are caught, I even mixed different programming languages. But I didn’t found any other solution – so please use this scripts as a inspiration, implement it how it should be and send me the link ­čśë

First, we need two wrapper-scripts that are called by openvpn:

From openvpn.conf:


client-connect /usr/local/bin/sudo_connect.sh
client-disconnect /usr/local/bin/sudo_disconnect.sh

These scripts are just calling the *real* scripts and are sorting enviromental and command line arguments.

/usr/local/bin/sudo_connect.sh

#!/bin/bash
exec sudo /usr/local/bin/python-ldap-connect.py $username $ifconfig_pool_remote_ip $1

/usr/local/bin/sudo_disconnect.sh

#!/bin/bash
exec sudo /usr/local/bin/clean_ruleset.sh $ifconfig_pool_remote_ip

(The openvpn-user, in my case nobody, has to be allowed to run this commands using sudo. Please allow it in /etc/sudoers )

The clean_ruleset.sh does one simple thing: Delete every iptables-rule created for a given source address in the chain FORWARD:

#!/bin/bash

IP=$1

for line_num in $(iptables -n --line-numbers --list FORWARD | awk '$5=="'$IP'" {print $1}')
do
# You can't just delete lines here because the line numbers get reordered
# after deletion, which would mean after the first one you're deleting the
# wrong line. Instead put them in a reverse ordered list.
LINES="$line_num $LINES"
done

# Delete the lines, last to first.
for line in $LINES
do
sudo iptables -D FORWARD $line
done

unset LINES

It is called by openvpn after a clients disconnects – and by the connect script, just to be sure.

The connect script does the real work:

#!/usr/bin/python

import sys
import ldap
from subprocess import call

def main(username, remote_ip, configfile):
# First: Delete all existing rules:
call(["/usr/local/bin/clean_ruleset.sh", remote_ip])

#Initialize LDAP Connection
ldapServer = "ldap://[ldap-server]"
ldapBindDN = ""
ldapBindPassword = ""
userDn = "uid=" + username + ",ou=[usual User-DN-Suffix for your users]"

try:
ldapCon = ldap.initialize(ldapServer)
ldapCon.simple_bind_s(ldapBindDN, ldapBindPassword)
except ldap.LDAPError, error_message:
print "Couldn't connect to LDAP. Error: %s" % error_message

#Now: Get list of groups the user is in
ldapFilter = "(&(objectClass=[name of your scheme - alternatively groupOfNames])(member=" + userDn + "))"
ldapBase = "[searchBase for your iptables-Groups]"
scope = ldap.SCOPE_SUBTREE
retrieveAttributes = ["[name of the attribute the IP-Adresses are saved]"]

resultSet = []
timeout = 1

try:
resultId = ldapCon.search(ldapBase, scope, ldapFilter, retrieveAttributes)
while 1:
resultType, resultData = ldapCon.result(resultId,0,1)
if (resultData == []):
break
else:
if resultType == ldap.RES_SEARCH_ENTRY:
for address in resultData[0][1]['[name of the attribute the IP-Adresses are saved]']:
resultSet.append(address)

except ldap.LDAPError, error_message:
print error_message

#Open Connection-specific configure file
configFileHandler = open (configfile, 'w')

#Remove duplicates from address-list
resultSet = list(set(resultSet))

for address in resultSet :
call("iptables" + " -A FORWARD" + " -s " + remote_ip + " -d " + address + " -o eth0" + " -j ACCEPT", shell=True)
configFileHandler.write('push route ' + address + '\n')

configFileHandler.close()

if __name__ == "__main__":
main(sys.argv[1], sys.argv[2], sys.argv[3])

Advertisements

Leave a comment

Filed under Administration

Ungenutzte Ubuntu-Kernel entfernen

Mir sind bei einigen Servern gerade die /boot-Partitionen vollgelaufen.

Der Grund ist, dass wohl bei ubuntu-server alte Kernel normalerweise nicht beim Upgrade entfernt werden – na toll.

Von Zeit zu Zeit sollte man das selber machen, es gibt aber einen Befehl der das mit Regexpt und uname automatisch hinbekommt.

Zuerst einmal ├╝berpr├╝fen mit

dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get purge

Und wenn dort der aktuelle Kernel nicht mitentfernt werden soll:

dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge

2 Comments

Filed under Uncategorized

Rechner mit zwei IPs und damit auch zwei Standardrouten einrichten

Ich hatte ein Problem: Ein Server von mir sollte zwei IP-Adressen bekommen, beide in verschiedenen Netzen.

Allerdings auch beide mit einem “Default-GW”, und der Rechner sollte ├╝ber beide voll ansprechbar sein.

Das Problem: Das Interface mit der kleinsten Metrik geiwnnt das Rennen, sprich: Obwohl jemand eine Verbindung an IP B initiieren m├Âchte, werden Antworten darauf ├╝ber NIC A versandt.

Nach der Lekt├╝re von http://kindlund.wordpress.com/2007/11/19/configuring-multiple-default-routes-in-linux/ und http://www.thomas-krenn.com/de/wiki/Zwei_Default_Gateways_in_einem_System ging mir aber ein Licht auf und nun l├Ąuft es.

Folgende Schritte f├╝hren zum Erfolg:

Zuerst eine Policy Routing table anlegen (bzw. benamsen):
# echo "1 admin" >> /etc/iproute2/rt_tables

Nun die /etc/network/interfaces anpassen:

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
	address 10.34.41.26
	netmask 255.255.255.192
        post-up ip route add 10.34.41.0/26 dev eth0 src 10.34.41.26 table admin
        post-up ip route add default via 10.34.41.1 dev eth1 table admin
        post-up ip rule add from 10.34.41.26/32 table admin
        post-up ip rule add to 10.34.41.26/32 table admin

auto eth1
iface eth1 inet static
	address 192.168.3.236
	netmask 255.255.255.224
	gateway 192.168.3.224
	dns-nameserver 192.168.3.224

Die Logik dahinter ist ganz einfach: “Nimm per Default das GW 192.168.3.224, wenn aber ein Paket von oder an die 10-er IP geht, nimmst du bitte das andere GW”.

Leave a comment

Filed under Administration, Server

TOTP nun auch auf Arduino

Vor einiger Zeit habe ich mal einen Artikel im Linux-Magazin ├╝ber TOTP und HOTP-Authentifizierung geschrieben.

Nun habe ich gerade ein Projekt von Leuten gefunden, die TOTP auf Arduino portiert haben.

Das Device ist zu gro├č f├╝r den mobilen Transport, aber darauf kommt es schlie├člich nicht an. Man k├Ânnte das sicher mit wenig Aufwand so umschreiben, dass das entstehende OTP auch f├╝r Webserviceaufrufe genutzt werden kann. So w├Ąre ein (halbwegs) sicherer Aufruf auch ├╝ber HTTP machbar, solange die Daten selber unwichtig sind…

 

Leave a comment

Filed under Uncategorized

Eigenes Apt-Repository f├╝r Debian und Ubuntu einrichten

Ich wollte ein eigenes Repository einrichten, um die Verwaltung unserer Server insgesamt zu vereinfachen. Unter anderem soll z.B. die authorized_keys des Users root automatisch auf allen neuen Rechnern eingerichtet werden.

Eigentlich habe ich mich ausschlie├člich an Tutorials gehalten, die beschreiben, wie neue deb-Pakete zu erstellen sind und wie man sich sein eigenes Repository einrichtet.

Damit das System nicht ├╝ber fehlende Keys meckert, habe ich ein eigenes Paket erzeugt, dass lediglich das folgende postinst-Skript enth├Ąlt:

#!/bin/bash

echo "
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (GNU/Linux)

(base64-kodierter PGPKEY, zu bekommen mit "gpg -a --export keyid")
-----END PGP PUBLIC KEY BLOCK-----
"  | apt-key add -

Das Paket zur Erzeugung der ssh-authorized enth├Ąlt auch nur ein
postinst-Skript:

#!/bin/bash

mkdir -p -m 0700 /root/.ssh/

touch /etc/default/ssh-authkey

cat /etc/default/ssh-authkey > /root/.ssh/authorized_keys

echo "
#####
# Hier bitte auf keinen Fall eigene Änderungen einbringen
# Bitte eigene Keys in die /etc/default/ssh-authkey eintragen!
# Danach dann: apt-get install --reinstall imi-authkey
#####

# (Hier folgt in der echten Datei der Teil mit den GPG-Keys)

" > /root/.ssh/authorized_keys
	

cat /etc/default/ssh-authkey >> /root/.ssh/authorized_keys


chmod 0600 /root/.ssh/authorized_keys

Das ist eigentlich ein bisschen unsch├Ân, vor allem, da der User jetzt
nicht mehr an der authorized_keys direkt rumfummeln kann. (Auch nicht
mehr, um z.B. den Command des Backuppc-Aufrufs zu ├Ąndern.) Wer wei├č, wie
man das besser machen kann: Ich bin ├╝ber alle Tipps dankbar.

1 Comment

Filed under Administration, Server

Nachtrag: jack speichert Einstellungen

Am Rande noch ein Nachtrag zu Jack:
Mit der Kommandooption “–save” speichert jack alle auch angegebenen Optionen in der “~/.jack3rc”, womit sie zuk├╝nftig standardm├Ą├čig wirken.

Dort kann man dann gleich auch zu ersetzende Zeichen angeben:

unusable_chars:['├Ą','├Â','├╝','├ä','├ľ','├ť','%','/','"']
replacement_chars:['ae','oe','ue','Ae','Oe','Ue',' ',' ',' '] 

Damit vermeidet Jack dann Umlaute in Dateinamen und schreibt sie phonetisch korrekt um.

Leave a comment

Filed under Audio

Jack – CDs rippen mit der Konsole

Lange habe ich nach einem brauchbaren CD-Ripper gesucht, dabei zuletzt rubyripper ausprobiert, was mir sehr gut gefallen hat. Wichtig war vor allem eine FreeDB-Anbindung zur Benamsung der Tracks. Das Problem ist nur, dass rubyripper alle Tracks zweimal auslesen will, und das kostet zeit.

Ich bin oft ├╝ber “Jack” gestolpert, habe es mir aber nie n├Ąher angesehen, da es ein CLI-Interface hat – ein Fehler, wie sich nun rausgestellt hat:

Jack ist zwar ein Konsolenprogramm, bietet aber eine sehr ├╝bersichtliche Curses-Oberfl├Ąche. Die ist zwar nicht wirklich interaktiv; die Aktionen werden weiterhin ├╝ber Konsolenoptionen gesteuert. Diese sind aber recht trivial und vor allem gut in der man-Page erl├Ąutert.

jack --device /dev/sr0 -Q --write-m3u --write-id3v2=true --write-id3v1=true --various=true  --rename-fmt-va "%n - %a - %t" --rename-fmt "%n - %a - %t" --remove-files

Damit rippt jack eine CD, konvertiert die WAVs zu OGG, schl├Ągt die Namen der Tracks in der Freedb nach und speichert alles korrekt ab.

Leave a comment

Filed under Audio