GuiguiAbloc

OpenBSD

Authentification par mot de passe jetable avec RADIUS et MOTP

par guiguiabloc le 21 avr., 2009, sous OpenBSD, linux, sécurité

En juillet de l’année dernière, j’avais écrit un billet sur l’authentification système par jeton tournant.

Je vous propose aujourd’hui de mettre en place une autre technique, l’authentification sur un serveur RADIUS par mot de passe unique, mot de passe généré sur votre téléphone portable.

Le principe reste assez simple. Pour vous identifier sur votre site web/équipement réseau/connexion wifi (etc, etc, la liste n’est pas exhaustive, du moment que l’authentification se base sur un serveur RADIUS), vous devrez saisir un code PIN sur votre téléphone, qui en retour vous générera un mot de passe, valable 1 seule fois et durant quelques minutes seulement.

Sympa comme moyen d’authentification (qui a dit “la frime” ?) :-)

Pour mettre en œuvre cette solution, nous allons nous utiliser deux produits :

Pour le serveur RADIUS

Pour le système d’authentification unique

RADIUS est un protocole client/serveur permettant de centraliser des données d’authentification.

Je vous invite à lire cette page :

http://fr.wikipedia.org/wiki/RADIUS_(informatique)

Vous l’utilisez tous les jours sans vous en rendre compte, tout simplement par votre accès au Nain Ternet de votre Fournisseur d’accès qui vous authentifie sur ses serveurs RADIUS avant de vous donner accès (ou pas) au réseau informatique mondial.

Bien sûr, tout cela est transparent pour vous, la plupart du temps, c’est votre box adsl qui négocie avec le RADIUS votre authentification.

(Pour les puristes, oui je résume énormément :-D :-D , si en plus on rajoute des proxy radius sur les BAS, on va y passer la nuit :-p )

Bref, pour résumer simplement, un serveur RADIUS sert à 3 choses :

  1. L’authentification

Qui es-tu ?

  1. L’autorisation

A quoi tu as le droit ?

  1. L’accounting (ou traçabilité)

Combien tu consommes et qu’est ce que tu utilises ?

C’est le fameux AAA que vous avez déjà peut-être croisé au fil de vos pérégrinations informatiques.

Maintenant que nous avons survolé le but de ce billet, mettons-nous à la tâche :

  • Installation et configuration de FreeRadius

Que vous soyez sous Linux ou *BSD, FreeRadius est disponible.

L’installation reste des plus triviales, a coup de pkg_add, apt-get install, yum install ou compilation directe depuis les sources sur le site web :

http://freeradius.org/download.html

Je me baserais sur la version 2.x de Freeradius, si vous êtes encore en version 1.x, il serait peut être temps de migrer…

Je ne m’attarderais pas sur son installation, il existe un excellent tutoriel de Thuso, ici :

http://www.pervasive-network.org/SPIP/Installation-de-freeradius-2-4

Passons à la phase MOTP proprement dite :

Téléchargement et installation du script et du dictionnaire MOTP :

serveur:# cd /etc/raddb
serveur:/etc/raddb# wget http://motp.sourceforge.net/otpverify.sh
serveur:/etc/raddb# chmod +x otpverify.sh
 
serveur:/etc/raddb# wget http://motp.sourceforge.net/dictionary.motp
 
Modification du fichier /etc/raddb/dictionary
 
serveur:/etc/raddb#  cat /etc/raddb/dictionary
#
#       This is the master dictionary file, which references the
#       pre-defined dictionary files included with the server.
#
#       Any new/changed attributes MUST be placed in this file, as
#       the pre-defined dictionaries SHOULD NOT be edited.
#
#       $Id: dictionary.in,v 1.4 2004/04/14 15:26:20 aland Exp $
#
#
$INCLUDE        /usr/local/share/freeradius/dictionary
$INCLUDE        dictionary.motp

Dans /var, créer un répertoire motp et lui donner les droits au user “freeradius”

serveur:# mkdir /var/motp
serveur:# mkdir /var/motp/cache
serveur:# mkdir /var/motp/users
serveur:# chown -R _freeradius:_freeradius /var/motp

On va ajouter un module exec à la configuration (/etc/raddb/radiusd.conf)

modules {
          ...
 
        exec MOTP {
                wait = yes
                program = "/etc/raddb/otpverify.sh %{User-Name} %{User-Password} %{reply:Secret
} %{reply:Pin} %{reply:Offset}"
                input_pairs = request
                output_pairs = reply
 
               ....
 
(vérifier bien que vous avez "exec" dans la partie Instantiate :)
 
instantiate {
        exec
        expr
        expiration
        logintime
 
}

Depuis la version 2, Freeradius utilise des hôtes virtuels (comme Apache), modifier votre fichier vhost comme suit (la partie importante étant l’auth-type external)

serveur:/etc/raddb/sites-enabled# more radius.guiguiabloc.fr
#####################################
authorize {
        preprocess
        chap
        suffix
        sql
        files
        expiration
        logintime
        pap
}
 
#  Authentication.
#
authenticate {
        Auth-Type PAP {
                pap
        }
 
        Auth-Type CHAP {
                chap
        }
        Auth-Type External {
                 MOTP
        }
        unix
}
 
preacct {
        preprocess
        acct_unique
        suffix
        files
}
accounting {
        detail
        unix
        radutmp
        sql
        attr_filter.accounting_response
}
session {
        radutmp
        sql
}
post-auth {
        Post-Auth-Type REJECT {
                attr_filter.access_reject
        }
}
pre-proxy {
}
post-proxy {
}

On va s’arrêter la pour la partie Freeradius et nous occuper de notre téléphone portable.

  • Installation de MOTP

MOTP (Mobile One Time Password), est le projet source de Freeauth dont j’avais parlé dans mon précédent billet.

Le principe est simple, comme dans toute base d’authentification forte à deux facteurs.

- 1 code secret connu également du serveur Radius (ce que JE connais)

- 1 objet unique capable de générer mon code (ce que JE détiens)

Le téléphone ET le serveur RADIUS se partageant ensemble une clé hexadécimale unique.

  • Avoir le téléphone ne sert à rien (j’ignore le code PIN qui n’est pas enregistré dedans)
  • Avoir le code PIN et un autre téléphone avec le même programme ne sert à rien (je ne peux régénérer la même clé hexadécimale)

Une fois tout cela en main, quand vous tapez votre code PIN (pas celui du téléphone hein ;-) celui choisi pour l’authentification), le programme génère 1 mot de passe unique en utilisant un hash MD5 qui cumule le code pin, la clé hexadécimale et l’heure EPOCH (avec une granularité de 10 secondes) et vous donne les 6 premiers caractères qui sont votre mot de passe pour vous connecter.

Ce mot de passe est vérifié par le serveur qui connait le code PIN, l’init-key (la clé hexadécimale) et l’heure actuelle.

Pour pallier les variations de temps entre le téléphone et le serveur, celui accepte le mot de passe 3 minutes dans le passé et dans le futur par rapport à son heure actuelle.

C’est bien pour cela que je vous conseille fortement de synchroniser votre téléphone portable et votre serveur à intervalles réguliers sur un serveur de temps NTP (cf. précédent billet)

Le mot de passe n’est accepté qu’UNE seule fois et en cas de 8 échecs consécutifs, l’utilisateur est verrouillé et ne peux plus se connecter.

Le JAR que vous devez installer sur votre téléphone compatible JAVA est disponible ici :

http://motp.sourceforge.net/MobileOTP.jar

Vous trouverez d’autres formes du client MOTP sur le site du projet (BlackBerry par exemple) :

http://motp.sourceforge.net/#2

Bien sûr, les sources sont également disponibles.

L’installation faite, un nouvel icône fait son apparition

MOTP

MOTP

Dans le menu Options, Time Zone, vérifier votre temps UTC (+0 pour moi) qui doit être identique sur le serveur.

(voir le précédent billet pour plus d’infos sur cette partie)

Commençons par initialiser le programme pour générer la clé Hexadécimale unique

Lancer le programme et en code PIN tapez : #**#

MOTP

MOTP

Appuyez aléatoirement sur 20 touches

MOTP

MOTP

Le programme vous affiche votre clé Hexadécimale unique (l’init Secret), NOTEZ LA BIEN !!!

MOTP

MOTP

Vous pouvez déjà vérifier que cela fonctionne en lançant le script otpverify.sh sur votre serveur RADIUS, suivi de 5 variables :
- le user
- le mot de passe unique généré par votre téléphone
- la clé hexadécimale
- le code PIN
- l’offset (0 pour un UTC +0)

serveur:/etc/raddb# ./otpverify.sh guiguiabloc b662de e37629f6d057dcc5 1234 0
ACCEPT

Maintenant, avec cette clé, retournons à la configuration du serveur RADIUS.

Paramétrage du fichier “users” de RADIUS :

serveur:/etc/raddb# cat /etc/raddb/users
DEFAULT Auth-Type = External
        Exec-Program-Wait = "/etc/raddb/otpverify.sh '%{User-Name}' '%{User-Password}' '%{reply:Secret}' '%{reply:Pin}' '%{reply:Offset}'",
        Fall-Through = Yes
guiguiabloc
        Secret = e37629f6d057dcc5,
        PIN = 1234,
        Offset = 0

Explication :
On ajoute un utilisateur, guiguiabloc
Secret = la clé hexadécimale générée sur le téléphone
PIN = le code secret a 4 chiffres choisi par l’utilisateur
Offset = variation de temps UTC (voir le site pour une explication détaillée)

Ne reste qu’à démarrer votre serveur RADIUS (en mode debug pour l’instant) et tenter une authentification via l’utilitaire RADTEST

serveur:/etc/raddb# /usr/local/sbin/radiusd -X
FreeRADIUS Version 2.0.5, for host i386-unknown-openbsd4.4, built on Aug 13 2008 at 01:30:16
Copyright (C) 1999-2008 The FreeRADIUS server project and contributors.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
You may redistribute copies of FreeRADIUS under the terms of the
GNU General Public License v2.
Starting - reading configuration files ...
....
Listening on authentication address 192.168.18.100 port 1812
Listening on accounting address 192.168.18.100 port 1813
Ready to process requests.

Demande du mot de passe unique sur le téléphone :

MOTP

MOTP

serveur:/etc/raddb# radtest guiguiabloc 356c18  192.168.18.100 0 secret_radius_client
Sending Access-Request of id 41 to 192.168.18.100 port 1812
        User-Name = "guiguiabloc"
        User-Password = "356c18"
        NAS-IP-Address = 192.168.18.70
        NAS-Port = 0
rad_recv: Access-Accept packet from host 192.168.18.100 port 1812, id=41, length=20
 
Côté serveur RADIUS on voit l'authentification se dérouler :
 
auth: type "External"
+- entering group External
        expand: %{User-Name} -> guiguiabloc
        expand: %{User-Password} -> 356c18
        expand: %{reply:Secret} -> e37629f6d057dcc5
        expand: %{reply:Pin} -> 1234
        expand: %{reply:Offset} -> 0
Exec-Program output: ACCEPT
Exec-Program-Wait: plaintext: ACCEPT
Exec-Program: returned: 0
++[MOTP] returns ok
Sending Access-Accept of id 41 to 192.168.18.100 port 29470
Finished request 2.
Going to the next request
Waking up in 4.9 seconds.
Cleaning up request 2 ID 41 with timestamp +215
Ready to process requests.

Un succès :-D :-D :-D

Désormais vous pouvez demander à vos équipements d’interroger le serveur RADIUS pour valider l’authentification et utiliser votre téléphone pour générer votre mot de passe unique et jetable.

Ca fait “classe” quand même :-)

Bonus, il existe un module mod_auth_radius pour Apache ;-)

Un petit .htaccess bien placé :

    AuthType Basic
    AuthName "RADIUS Authentication"
    AuthUserFile /dev/null
    AuthRadiusAuthoritative on
    AuthBasicAuthoritative off
    AuthRadiusCookieValid 5
    AuthRadiusActive On
    require valid-user

Et hop, authentification sur votre site web via RADIUS et MOTP…

Amusez-vous bien ;-)

3 Commentaires :, , , suite...

VLAN et Trunk 802.1q

par guiguiabloc le 03 fév., 2009, sous OpenBSD, architecture, cisco, linux, réseau

En relisant quelques anciens billets, je me suis rendu compte que je n’avais pas abordé précisément la notion de vlan et de trunk dans une architecture réseau.

Corrigeons donc cela rapidement.

Un VLAN est un réseau Virtuel. Dans un réseau local physique, vous pouvez donc mettre en place des réseaux logiques, séparés les uns de autres, on parle alors de “segmentation”.

Pour pouvoir mettre cela en place, il vous faut donc un switch qui supporte cette fonctionnalité.

Si maintenant vous désirez propager plusieurs VLANs sur un même lien physique, il faut configurer un “trunk” et la norme établie est la 802.1q aussi appelé couramment : dot1q.

Pour cela, il faudra que vos paquets soit “taggués”, c’est à dire qu’ils contiennent dans leurs en-têtes le numéro du vlan (VLAN ID) pour lequel ils sont destinés.

(Cisco supporte bien évidemment cette norme sur ses équipements, mais également sa propre norme propriétaire, ISL “Inter Swtich Link”, dont je ne parlerais pas ici).

En situation, nous aurons quelque chose de ressemblant a ceci :

Outre un switch supportant les VLANs, il vous faudra bien évidemment un routeur pour les routages inter-vlan (ou un pc faisant office de routeur).

Bref, a la fin, vous risquez de vous retrouvez avec cela (vous avez de la chance, je vous ouvre les arcanes de mon installation personnelle :-) )

Réseau Perso Guiguiabloc

Réseau Perso Guiguiabloc

(Vous trouverez un billet sur la naissance de cette baie ICI )

Les exemples suivants se basent sur un Switch Catalyst 2924 XL et un Routeur 2611-XM, mais ils restent standard pour tout IOS récent (comprendre qui n’a pas 10 ans…)

La création d’un VLAN sur le switch est très simple :

catalyst#vlan database
catalyst(vlan)#vlan 2 name vlan_base_de_donnees
VLAN 2 added:
Name: vlan_base_de_donnees

Sur l’interface du switch où est branché votre pc/serveur, vous définissez alors sur quel VLAN il est relié :

catalyst#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
catalyst(config)#int fastEthernet 0/1
catalyst(config-if)# switchport mode access
catalyst(config-if)# switchport access vlan 2
 
Ce qui donne :
 
interface FastEthernet0/1
 description serveur Mysql
 port block multicast
 switchport access vlan 2
 spanning-tree portfast
 no cdp enable

La variable “switchport access” définit le droit d’accès au VLAN.

Attention : Il existe un VLAN un peu particulier, le VLAN 1, qui est le VLAN de Management des équipements Cisco. Eviter donc d’y mettre des machines accessibles par tous.

Certains recommandent de déplacer le VLAN 1 sur un autre VLAN, personnellement, ça ne m’a pas porté chance de jouer à cela, donc un peu de rigueur suffit en changeant les vlans natifs sur les interfaces.

Sachez que sur le Catalyst 2924, il existe une petite commande sympa et peu documentée :

switchport mode multi
swichport multi vlan 1,2,3

Cela permet a une machine d’accéder à plusieurs VLANs sans avoir à tagguer ses trames.

Dans ce mode de configuration, les machines connectées aux interfaces du switch n’ont pas besoin de tagguer leurs paquets, donc une configuration réseau toute basique (avec en passerelle l’interface définit dans votre routeur par exemple).

La connectivité entre notre routeur et notre switch par contre sera différente.

Nous avons 1 (voire 2) interfaces physiques sur le Cisco 2600 et c’est sur cette interface que nous allons faire passer l’ensemble des VLANs afin de permettre au routeur de… router ;-)

Coté Switch :

interface FastEthernet0/2
description Trunk fastEthernet 0/0 rt-2611
duplex full
speed 100
switchport trunk encapsulation dot1q
switchport mode trunk
spanning-tree portfast
no cdp enable

Ici, le mode du switch est “trunk” et l’encapsulation, 802.1q.
Sans spécifications particulières, nous passons l’intégralité des VLANs définis sur le switch sur cette interface.

Vous pouvez bien sur être plus restrictif sur cette configuration :

switchport trunk allowed vlan 2,3   # autorise que l'accès aux VLANS 2 et 3

Attention : Dans ce genre de configuration, un paquet non taggué partira dans le vlan par défaut qui est le VLAN 1.

N’oubliez donc pas d’indiquer explicitement le VLAN par défaut en cas de trames non tagguées :

switchport trunk native vlan 2     # on envoie sur le vlan 2 si pas de tag

Côté Routeur 2600 :

interface FastEthernet0/0.1
encapsulation dot1Q 1 native
ip address 192.168.0.254 255.255.255.0
ip virtual-reassembly
no cdp enable

Il ne vous reste plus qu’a définir vos interfaces “virtuelles” sur votre routeur Cisco :

Pour le VLAN 2 par exemple :

interface FastEthernet0/0.2
encapsulation dot1Q 2
ip address 192.168.2.254 255.255.255.0
no cdp enable

NB : Si vous voulez faire sortir vos machines par votre passerelle générale (exemple le pix :-p) n’oubliez pas les nat inside/outside sur vos interfaces, ainsi que des ACL bien placées.

Côté Linux :

Si vous voulez faire du trunk sur Linux, il suffit d’activer le support 802.1q dans le noyau.

Sous Debian, apt-get install vlan
Sous RedHat, le support est natif

Création de l’interface :

Debian :

vconfig add eth0 2 (pourt créer le VLAN 2)

Modification du fichier /etc/network/interfaces :

 auto eth0.2
 iface eth0.2 inet static
 address 192.168.2.254
 netmask 255.255.255.0
 network 192.168.2.0
 broadcast 192.168.2.255
 vlan_raw_device eth0

RedHat :

Création du fichier /etc/sysconfig/network-scripts/ifcfg-eth0.2

DEVICE=eth0.2
BOOTPROTO=static
HWADDR=XX:XX:XX:XX:XX:XX
IPADDR=192.168.2.254
NETMASK=255.255.255.0
NETWORK=192.168.2.0
ONBOOT=yes
TYPE=Ethernet
VLAN=yes

Rédémarrage des services réseaux bien entendu.

Dans les 2 cas, pour supprimer l’interface, il faudra passer un :

vconfig rem eth0.2

(ps: l’écriture d’un alias d’une interface “vlan” se note : eth0.2:1 par exemple)

Côté OpenBSD :

création du fichier /etc/hostname.vlan2 (vlandev étant votre interface réseau physique)

inet 192.168.2.254 255.255.255.0 vlan 2 vlandev sis0

Sous Windows, ce n’est absolument pas natif, tout dépend de la carte réseau et du pilote du fabricant fourni… (en même temps, qui voudrait faire un routeur avec windows ;-) )

Voilà, j’espère que ces explications vous aideront a mettre en oeuvre des VLANs chez vous, et surtout à l’utiliser car en cloisonnement, c’est quand même l’idéal.

17 Commentaires :, , , , suite...

Switch applicatif avec OpenBSD, un Altéon à la maison ?…

par guiguiabloc le 14 jan., 2009, sous OpenBSD, architecture, cisco

Dans une infrastructure informatique sensible, la disponiblité des applicatifs est primordiale.

Pour répondre à cette exigence, les solutions mises en oeuvre se basent donc sur de la haute-disponibilité et de l’équilibrage de charge (communément appelé LoadBalancing).

J’avais déjà évoquer la haute-disponibilité sous Linux dans ce billet et abordé ce type d’architecture dans celui ci.

Je vais donc aller un peu plus loin dans ce concept et tenter de mettre en oeuvre un équivalent “open-source” d’un produit commercial.

Ceux qui d’entre vous travaillent ou ont travaillé dans ce genre d’environnement, doivent avoir de fortes chances d’avoir croiser dans les baies des boitiers “Alteons”.

(merci à Morgan pour les Altéons :-)))

(merci à Morgan pour les Altéons :-)))

Alteon WebSytems est une société américaine spécialisée dans la haute-disponibilité et rachetée par Nortel fin 2000.

Les produits s’appellent désormais AS (pour Application Switch) et vous trouverez un comparatif des boiboites ICI, mais par facilité, le terme “Alteon” est toujours employé.

Sachez que chez CISCO également il existe ce genre de solution (ACE).

Je ne rentrerais pas dans les arcanes d’un altéon mais en voir rapidement le principe et d’en construire un équivalent chez soi.

Globalement, le principe est le suivant :

(source image IBM)

(source image IBM)

La configuration se fait sur 4 points principaux donc je vais vous détailler la configuration ci-dessous.

Il s’agit d’une configuration de base pour un loadbalancing en haute-dispo sur 2 serveurs web.

Spécial grand Merci à Steven pour son aide sur l’Alteon :-D

1 - Les serveurs réels

Il s’agit des applications à “load balancer”.

/cfg/slb/real 1
enable
rip aa.bb.cc.dd     #l'ip du serveur réel 1
retry 2     #nombre d'essai avant de considérer le serveur comme down
restr 2     #nombre d'essai avant de considérer le serveur comme up
inter 15     #intervalle entre 2 checks en secondes
name lenom
/cfg/slb/real 2
enable
rip aa.bb.cc.ee
retry 2
restr 2
inter 15
name lenom

2 - Le groupe

On regroupe ensuite les applications à “load balancer” au sein d’un même groupe. Le groupe comprend les Real Servers ainsi que le “jeu” de test permettant de vérifier leur bon état.

cfg/slb/group 1
health http     #service concernée, ici http mais peut être : link|arp|icmp|tcp|http|httphead|dns|pop3|smtp|
nntp|ftp|imap|sslh|radius-auth|radius-acc|radius-aa|script|udpdns|wsp|wtp|wtls|ldap|snmp|tftp|rtsp|sip|wts|dhcp
viphl disable     #désactive le check VIP lié au DSR (Direct Server Return)
content "/status.html"     #la page a checker
add 1     #ajout du serveur réel 1 dans le groupe
add 2     #ajout serveur 2 dans le groupe
name lenomdugroupe

3 - Le virtual server

Un Virtual Server se caractérise par son adresse virtuelle (VIP), son port d’écoute virtuel (service), le groupe de Real server auquel il est associé et les ports d’écoute des Real Servers

/cfg/slb/virt 1
enable
vip 10.1.1.1
 
/cfg/slb/virt 1/service 80
group 1
hname lenom
epip ena     #on force la sélection par egress ou VLAN

4 - le virtual router

Le routeur virtuel qui contient la VIP, le groupe, l’interface physique et la priorité par rapport à son “voisin”.

/cfg/l3/vrrp/vr 1 (avec le chiffre égale au virt associé)
ena
vrid n     # le numero du Virtual Routeur
if 1     # l'interface
prio 99     #la priorité (plus le chiffre est haut plus l'atéon est prioritaire par rapport a l'altéon de backup)
addr 10.1.1.1     #la VIP
share dis     #on désactive l'extension Nortel VRRP

Un dessin valant toujours mieux qu’un long discours ;-) , nous allons imaginer l’architecture suivante :

  • 2 Altéons
  • 1 VLAN dédié aux IP loadbalancées en 10.0.0.0/24
  • 1 VLAN dédié aux serveurs Web en 192.168.1.1/24
  • 2 serveurs Web

C’est forcément simplifié au maximum mais cela donne une idée de ce que nous allons mettre en place.

Avec des “Altéons”, nous aurions donc ce genre de schéma :

Shématisation Alteon

Shématisation Alteon

Le but étant de reproduire a peu près la même chose chez soi, il y a un système d’exploitation qui contient déjà tout ce qu’il faut pour cela : OpenBSD.

Alors, oui, on pourrait faire la même chose avec Linux, en se tapant l’installation d’Ucarp, Balance, LVS et/ou autres joyeusetés, mais personnellement, je préfère laisser cela a OpenBSD qui peut le faire nativement et qui a fait ses preuves en environnement réseau critique.

Après tout, OpenBSD est amour, avec du poil autour, et c’est tout.

Reprenons notre schéma et adaptons le à une solution basée sur 2 serveurs sous OpenBSD pour remplacer les “Altéons” :

Schématisation OpenBSD

Schématisation OpenBSD

Ne reste qu’a configurer tout cela :-D

  • CARP + VLAN (optionnel)

Définir une VIP sur nos OpenBSD (une interface CARP sur interface physique ou sur interface VLAN)

/etc/sysctl.conf
 
net.inet.carp.preempt=1
net.inet.carp.allow=1
 
#ifconfig carp0 create
 
#ifconfig carp0 vhid 1 pass motdepasse carpdev em0 advskew 1 10.0.0.1 netmask 255.255.255.0
 
Pour un VLAN (exemple):
cat /etc/hostname.vlan3
inet 10.0.0.3 255.255.255.0 vlan 3 vlandev em0
 
cat /etc/hosname.carp0
inet 10.0.0.1 255.255.255.0 10.0.0.255 vhid 1 carpdev vlan3 advskew 1 pass motdepasse

Je ne m’attarde pas la dessus, en ayant déjà parler sur CE BILLET.

  • PFSYNC
ifconfig pfsync0 syncpeer "ip openbsd en face" syncdev em1
ifconfig pfsync0 up
  • Partie PF / Hoststated
/etc/pf.conf
 
rdr-anchor "hostatetd/*"
 
table  persist { 192.168.1.1, 192.168.1.2 }
 
rdr on $carp0 from any to $ipcarp port 80 ->  round-robin sticky-address
 
# la variable sticky-address signifie que PF maintient la session du client sur le même serveur
 
/etc/hoststated.conf
 
real1="192.168.1.1"
real2="192.168.1.2"
vip="10.0.0.1" # VIP CARP
 
interval 5 #on vérifie l'état des serveurs toutes les 5 secondes
 
table messerveurs {
check http "/status.html" code 200
timeout 300
real port 80
host $real1
host $real2
}
 
service www {
virtuel ip $vip port 80
table messerveurs
}

Petite explication :

On utilise une table “messerveurs” qui contient la liste des serveurs à “loadbalancer”.
PF redirige les requètes entrantes sur la VIP (10.0.0.1) alternativement (round-robin) et maintient la session du client sur le même serveur (sticky-address).
Bien évidemment, tout cela est optionnel et à vous d’adapter selon vos applis (man pf ;-) ).

Le démon Hoststated vérifie que les serveurs réels sont bien vivants en appelant la page status.html sur chacun des serveurs de sa liste.
En cas de non réponse (code retour http différent de 200), il considérera le serveur comme down et le retirera de la table “messerveurs”.

C’est pas beau tout cela ? :-D

La commande # hoststatectl show vous donnera l’état des serveurs et vous pouvez manuellement les sortir ou les remettre dans le pool (# hoststatectl host disable/enable 192.168.1.x).

Et petit bonus, vous pouvez agir directement sur la couche 7 ;-)

Exemple de relais load-balancé HTTPS :

protocol monchteuteupeucrypte {
protocol http
header append "$REMOTE_ADDR" to "X-Forwarder-For"
header append "$SERVER_ADDR:$SERVER_PORT" to "X-Forwarder-By"
header change "Keep-Alive" to "$TIMEOUT"
url hash "sessid"
cookie hash "sessid"
path filter "*command=*" from "/cgi-bin/index.cgi"
 
ssl { sslv2, ciphers "MEDIUM:HIGH" }
tcp { nodelay, sack, socket buffer 65536, backlog 128 }
}
 
relay wwwssl {
listen on $vip port 443 ssl
protocol monchteuteupeucrypte
table messerveurs loadbalance
}

Maintenant que je vous ai titillé avec tout cela, je vous invite, outre à manger les MAN d’OpenBSD, mais aussi à lire cet excellent ouvrage :

The Book of PF
A No-Nonsense Guide to the OpenBSD Firewall
Par Peter N.M. Hansteen

Vous le trouverez chez Amazon par exemple :
http://www.amazon.fr/Book-PF-No-nonsense-Guide-Firewall/dp/1593271654

Conclusion :

Loin de moi l’idée de vous dire qu’une architecture comme celle-ci sera tout aussi efficace qu’un Switch Applicatif hors de prix, il existe des fonctions sur ces boitiers que l’on peut évidemment reproduire mais qui demanderons du temps…

Par contre, ce type d’architecture n’a pas a rougir en Production pour load-balancer des applications se prétant à ce jeu.

Amusez vous bien ;-)

5 Commentaires :, suite...

Mandater ses connexions TCP, tu t’es lavé les mains avant d’entrer ?

par guiguiabloc le 17 nov., 2008, sous OpenBSD, architecture, réseau

Ce billet est un petit exercice de style :-)

Dans le cadre d’une architecture “standard”, vous disposez d’un routeur qui vous donne accès au Nain Ternet, un firewall dédié et vos serveurs.

Les serveurs dédiés à offrir des services aux utilisateurs externes sont normallement en DMZ.

Ca c’est le cas idéal, mais il peut arriver (souvent même), que quelques applications soient hébergées sur des serveurs du LAN et là on joue avec de la NAT dans tout les sens.

Vous avez donc ouvert le port sur votre firewall puis fait une redirection sur la machine dans le LAN.

Ca marche mais bof quoi ;-)

Dans ce genre de concept (très fréquent), on laisse donc la transaction TCP (le fameux 3-way handshake) s’établir entre le client et le serveur dans le LAN.

Moyen hein ?

Après tout, vous obligez bien vos utilisateurs à passer par un proxy Squid pour aller sur le Web, pourquoi ne pas faire pareil avec vos connexions entrantes TCP ?…

Voila ce que nous allons mettre en place :

Schéma

Schéma

Et qui a la plus de compétences pour gérer le 3-way handshake a la place des autres ? Qui a la plus grosse quand on parle de couche réseau ?

Réponse : OpenBSD forcement

Nous allons partir du principe que vous désirez offrir un accès SMTP sur la machine LAN-MAIL depuis le Nain Ternet.

L’adressage utilisée sera le suivant (et comme toujours un dessin valant mieux qu’un grand discours) :

Schéma

Schéma

Coté Firewall, redirection toute simple, tout ce qui entre sur le port 25 SMTP depuis le Net sur l’interface externe est redirigé sur 10.154.1.1 port 25 (ou autre hein, c’est vous qui voyez).

La, c’est du truc habituel, rien de bien sorcier.

Coté OpenBSD, on va se monter un petit socket :

vi /etc/inetd.conf
 
127.0.0.1:5025 stream tcp nowait nobody /usr/bin/nc nc 192.168.0.50 25

On reload le process inetd

Puffy:~# ps aux | grep inetd
root     24243  0.0  0.3   524   780 ??  Is    26Sep08    0:18.06 inetd
root     30919  0.0  0.3   472   764 p0  S+    11:23AM    0:00.02 grep inetd
Puffy:~# kill -HUP 24243

Explication, on utilise netcat pour établir une connexion tcp vers LAN-MAIL sur le port 25 quand une requète TCP arrive sur son port 5025 en localhost.

Maintenant on s’attaque à la couche la plus poilue, Packet Filter :

(wan_if étant l’interface sis0 dans le schéma)

pf.conf
 
rdr pass on $wan_if inet proto tcp from any to $wan_if port 25 --> 127.0.0.1 port 5025
pass in quick inet proto tcp from any to 127.0.0.1 port 5025

Et c’est tout.

Bien évidemment vous avez déjà un beau PF configuré avec toutes les options qui vont bien, antispoof, scrub in all et tout, et tout…

J’ai volontairement simplifié l’architecture et les règles, alors ne me criez pas dessus :-D

Et ca fait quoi donc maintenant ce joli truc ?

Cela fait que désormais, c’est l’OpenBSD qui va traiter la connexion entrante, l’accepter, ouvrir une nouvelle connexion vers LAN-MAIL et véhiculer les paquets vers lui.

Toute la phase d’échange TCP sera traitée par le BSD et c’est avec lui que le client discutera directement.

Bref, l’OpenBSD joue le rôle de Proxy TCP :-)

Voila pour ce petit exercice que je vous laisse peaufiner et qui peut vous dépatouiller d’architectures un peu compliqués ou surtout, de connexions TCP moisies entre le Firewall et le Serveur final.

P.S. : Attention avec le protocole FTP, ce n’est aussi simple que cela y parait. Je vous conseille fortement d’utiliser le programme ftp-proxy d’openBSD (surtout si vous voulez redirigez vos requêtes FTP externes vers le FTP de votre Freebox HD par exemple ;-) )

Laisser un commentaire :, , suite...

Vous cherchez quelque chose ?

Utilisez le formulaire ci-dessous:

Vous ne trouvez pas ce que vous voulez ? Laisser un Commentaire sur un Billet !

Special Copinage!

Quelques sites amis ou recommandés...