Profiter de la fibre Orange pour les geeks

Il y a quelques semaines, j'ai emménagé dans une résidence qui a été fibrée par Orange.

Au début je pensais que cela signifiait que je pouvais continuer à utiliser Free, mais manifestement, l'accord multi-opérateurs qui est nécessaire pour cela n'a pas encore été signé. Malheureusement, cela signifie donc que pour le moment, je serai obligé de passer par le FAI qui a fait le raccordement à la fibre.

C'est pourquoi j'ai décidé de vendre mon âme à Orange (en tant que client mobile et d'ancien stagiaire chez FT R&D c'est déjà chose faite mais bon) pour profiter d'une connexion fibre à 200 Mbps en download et 50 Mbps en upload, une sacrée claque par rapport à l'ADSL2+ dont je profitais avant. Du moins, c'est ce que les différents tests de débit confirment.

Néanmoins, j'ai vu que certains ont mis en place un tunnel GRE entre Orange et un point d'accès chez OVH, ce qui pourrait également se révéler intéressant si ce FAI fait des trucs pas très nets.

L'architecture réseau prévisionnelle

Pour le moment, j'ai mon propre routeur OpenWRT, mais que je laisserai derrière la Livebox. Je sais qu'il y a la possibilité de se passer de la Livebox, mais faute de temps pour faire joujou avec des cartes FXO/FXS et faute de temps pour faire marcher la téléphonie dans ces cas-là, je ne le fais pas encore.

Réseau prévisionnel

En effet, ceux qui n'envisagent pas d'utiliser la télévision ni le téléphone Orange peuvent très simplement utiliser leur propre routeur OpenWRT en lieu et place de la Livebox. L'avantage étant que celui-ci fournit une interface de configuration par SSH et qu'on en garde le contrôle total.

Merci à ack et slash sur IRC pour leurs renseignements, en particulier à propos de l'utilisation de ses propres équipements :

11:31:22 < slash> x0r: j'ai un pfSense à la place de la livebox fibre, 
              ça marche bien, il faut juste que ça gére les VLAN et PPPoE
11:35:22 < slash> x0r: c'est le VLAN 835 pour info :)

Cependant, il est tout à fait possible d'obtenir également la télévision et le téléphone avec cette méthode, mais ce sera un peu plus compliqué et je verrai ça plus tard.

Prérequis

Avant de commencer quoi que ce soit, allez dans l'interface de configuration de la Livebox et donnez une IP fixe à votre routeur OpenWRT. Ajoutez-le également dans la DMZ pour que la Livebox forwarde tous les ports TCP/UDP de la box vers lui.

Connectivité IPv4

Contrairement à leur connectivité IPv6, l'IPv4 passe bien. Seul problème, quelque chose de particulièrement nuisible à tout projet d'auto-hébergement est le fait que les adresses IP sont dynamiques et donc susceptibles de changer d'une minute à l'autre !

Heureusement, il y a des parades tels que le DNS dynamique qui permettent de mettre à jour une entrée DNS ou deux dès qu'une adresse IP change.

Je me suis néanmoins rendu compte de quelque chose d'assez frustrant : lorsqu'on fait pointer une entrée DNS vers l'IP extérieure de la box (par exemple un chezmoi.example.com qui est ensuite DNATé vers un serveur sur lequel on autohéberge un site Web) et qu'on essaye d'accéder à ce chezmoi.example.com depuis l'intérieur via un navigateur, eh bien on obtient... le panneau d'administration de la Livebox. Autrement dit : la Livebox est infoutue de faire du NAT loopback correctement.

La seule mesure palliative à peu près propre à ce "bug" constitue alors à maintenir un DNS "split-horizon", c'est-à-dire maintenir deux examplaires de son domaine example.com. L'une est servie à l'extérieur et fait pointer chezmoi.example.com sur l'IP publique de la box. L'autre n'est accessible que de l'intérieur de son propre LAN et fait pointer chezmoi.example.com sur l'IP du (vrai) serveur à l'intérieur du LAN.

Dans mon cas, j'ai la version publique du domaine x0r.fr chez OVH, et la version privée (avec mes IP privées) du même domaine sur mon serveur sous BIND9.

Connectivité IPv6

Lorsque j'ai eu l'idée saugrenue d'appeler le support technique pour « une question d'ordre technique à propos de [leur] offre Livebox », la conversation téléphonique qui s'en est suivie se résume à cela :

— Bonjour monsieur, est-ce que vous fournissez un préfixe IPv6 à vos clients ?
— Ipévéquoi ?
— IPv6.
(bruits de clavier) Ah oui, pour des connexions à usage professionnel.
— Proposez-vous cela à des particuliers ?
— Non.
— D'accord. (clac)

Conclusion : c'est pas encore pour tout de suite, même si des rumeurs disent que ce sera pour 2014 ou 2015. J'espère juste qu'on ne me mette pas derrière un Carrier-Grade NAT d'ici là. Ceci dit, le carton de la Livebox indique qu'elle est compatible IPv6, donc ils ont au moins prévu une stack IPv6 dans le firmware.

En tout cas, il faudra donc utiliser un tunnel broker, celui de SixXS ou de Hurricane Electric.

Administration de son propre domaine DNS

Nous verrons ici tout ce qu'il reste à faire niveau DNS afin de pouvoir faire de l'auto-hébergement correctement sur sa ligne.

Mise à jour dynamique avec nsupdate

Ce qui est probablement le plus frustrant avec le fait d'avoir une adresse IP dynamique est l'impossibilité de gérer (simplement) une zone DNS ayant des entrées qui pointent vers des machines chez soi.

Heureusement, le paquet ddns-scripts fourni par OpenWRT permet d'utiliser simplement son routeur OpenWRT comme client DynDNS.

Comme le registrar de ma zone DNS est OVH, il me suffisait simplement d'ajouter un champ DYNHOST dans ma zone. Il a fallu que je désactive le "mode avancé" pour ce faire, cependant. Dans le champ "Adresse IP", j'ai saisi l'IP de mon ancienne Freebox pour forcer la première mise à jour.

Ensuite, sur le routeur OpenWRT, rien de très compliqué :

# opkg install ddns-scripts
# vi /etc/config/ddns

Le fichier de config que j'ai utilisé pour OVH est le suivant :

config service "myddns"
        option enabled          "1"
        option interface        "eth0.2"

        option service_name     "ovh.com"
        option domain           "dyn.example.com"
        option username         "example.com-monusername"
        option password         "monpassword"

        option force_interval   "24"
        option force_unit       "hours"
        option check_interval   "10"
        option check_unit       "minutes"
        option retry_interval   "60"
        option retry_unit       "seconds"

        option ip_source        "web"
        option ip_url           "http://checkip.dyndns.com/"

Cette config permet de mettre à jour un domaine dyn.example.com. Comme ça, tous les noms qui devraient pointer vers l'adresse IP de la Livebox suffisent d'être modifiés pour qu'ils deviennent des CNAME ("alias") vers ce dyn.example.com et on n'aura pas besoin de refaire cette configuration cinquante mille fois.

Il y a néanmoins un cas où il m'a fallu rajouter une entrée quasiment identique à ce que j'ai montré : lorsqu'on héberge un serveur mail derrière sa box. Du coup j'ai aussi une autre section config service dans /etc/config/ddns qui sert à mettre à jour un mx.example.com. En effet, Les entrées DNS des serveurs mail devant impérativement être de type A ou AAAA et n'ont donc pas le droit d'être des CNAME.

Ensuite, deux solutions pour démarrer le service. Comme cela ne se fait pas via un initscript mais que ce service démarre automatiquement lors du démarrage de l'interface associée, on a le choix entre rebooter (mais ça, c'est pour les faibles) ou démarrer manuellement à l'aide de la commande :

# ACTION=ifup INTERFACE=eth0.2 /sbin/hotplug-call iface

Pour que les champs DynHost fonctionnent correctement, il m'a néanmoins fallu désactiver de manière permanente le mode avancé (celui où on modifie la zone DNS dans un éditeur de texte, comme un vrai). Un léger inconvénient mais un mal nécessaire pour que les mises à jour fonctionnent.

E-mails sortants : le relais d'Orange à moitié caché

Comme j'avais configuré mon Postfix pour qu'il envoie des mails via le relais mail de Free, je ne peux désormais plus envoyer de mails vers l'extérieur sans un brin de configuration.

Avant de commencer, comme mon serveur mail est un MX principal et que son IP va changer, j'ai viré la clause proxy_interfaces (qui ne servait à rien de toute façon parce que mon serveur n'est pas un MX secondaire).

Ensuite, il suffit d'utiliser le relais SMTP d'Orange. En gros, voici ce que j'ai désormais dans le main.cf de Postfix:

relayhost                       = [193.252.22.72]:587

smtp_sasl_auth_enable           = yes
smtp_sasl_password_maps         = hash:/etc/postfix/sasl_passwd

smtp_tls_CAfile                 = /etc/ssl/postfix/gmail_cert.pem
smtp_tls_cert_file              = /etc/ssl/postfix/server.crt
smtp_tls_key_file               = /etc/ssl/postfix/server.pem
smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_tls_session_cache
smtp_use_tls                    = yes
smtp_sasl_security_options      = noanonymous
smtp_sasl_tls_security_options  = noanonymous
smtp_tls_note_starttls_offer    = yes
tls_random_source               = dev:/dev/urandom
smtp_tls_scert_verifydepth      = 5
smtp_tls_enforce_peername       = no
smtp_tls_CApath                 = /etc/ssl/certs

Pas mal de trucs datent encore d'une vieille config où j'utilisais Gmail comme relais, et je n'ai pas eu le temps de tester si ces éléments-là sont encore pertinents. (surtout que bon, comme ils refilent tout à la NSA, je ne devrais plus leur faire confiance... mais je suis peut-être mauvaise langue.)

Ne pas oublier de créer le fichier /etc/postfix/sasl_passwd qui contient les identifiants messagerie. Le login est la partie avant @orange.com. Donc si Orange vous a donné une adresse e-mail truc.bidule@orange.com et que le password est supersecret, le fichier contiendra donc :

[193.252.22.72]:587     truc.bidule:supersecret

Enfin, ne pas oublier non plus d'exécuter la commande

# postmap /etc/postfix/sasl_passwd

pour que Postfix tienne compte du password. Un chmod 600 sur ce fichier, ainsi que le sasl_passwd.db produit par la commande postmap(1), n'est probablement pas une mauvaise idée non plus. Rechargez la configuration de Postfix puis testez l'envoi d'un petit mail vers une adresse "extérieure" à votre domaine, genre une adresse Gmail ou Yahoo!.

Remarquez aussi qu'on n'a pas donné de noms DNS pour le relais SMTP d'Orange. Son petit nom est en réalité smtp-msa.orange.fr mais ne peut être résolu qu'en utilisant les DNS d'Orange. Je n'ai pas encore regardé ce que valent les DNS d'Orange, mais comme je ne les utilise pas (encore), je suis obligé de mettre son adresse IPv4 à la place.

Adieu le reverse DNS customisé

Probablement la feature qui me manque le plus depuis que je n'ai plus Free. Hélas, ce reverse DNS n'est pas paramétrable. Sur IRC, il vous faudra donc clamer haut et fort malgré vous le fait d'être sur une connexion Orange. Au lieu d'avoir

--> Poiral (Poiral@mon.super.rever.se) has joined #truc

vous aurez donc :

--> Poiral (Poiral@AMontsouris-puis-plein-de-chiffres.abo.wanadoo.fr) has joined #truc

Au moins, si vous faites tourner un oidentd sur votre bécane, vous n'aurez pas le ~ devant le hostmask.

Conclusion

Après quelques semaines d'utilisation, je trouve que la fibre optique est une sacrée bouffée d'air frais, en particulier pour YouTube où j'ai limite l'impression d'être en réseau local. Avoir 50 Mbps de débit en upload ouvre énormément de possibilités d'auto-hébergement également. C'est juste un peu dommage qu'Orange ne soit pas le fournisseur d'accès le plus "geek-friendly", mais pour le moment il fait largement l'affaire. Pour le reste, on verra bien.

Posté par x0r à 5 commentaires • Tags : orange demenagement free fibre ftth cablage

monrer.fr : autocomplétion et reverse-engineering

Il y a environ deux semaines, j'ai décidé de bouger le site monrer.fr sur un jail FreeBSD (merci KissCool pour ce jail, d'ailleurs). En effet, comme ce site tournait sur le même serveur que x0r.fr et qu'il s'agit d'une machine hébergée derrière une Freebox, un déménagement imminent signifierait au moins 72 heures de downtime, et étant donné la (modeste) fréquentation du site, je ne pouvais plus me permettre cela.

Je vais parler un peu des principales évolutions que j'ai faites ou qui sont en cours de développement.

Balbutiements de mécanisme d'autocomplétion

J'en ai aussi profité pour mettre en place un système d'autocomplétion pour remplacer le menu déroulant de sélection de gare. Il permet de taper aussi bien les premières lettres d'un nom de gare qu'un code TR3 :

Autocomplétion sur monrer.fr

Je suis assez mitigé là-dessus cependant. Je pensais pouvoir faire en sorte de conserver le menu déroulant sur des appareils mobiles et utiliser le champ de texte avec autocomplétion sur les navigateurs « desktop », mais je n'ai pas eu le temps de faire quelque chose de propre qui ne fasse pas déconner certains moteurs JavaScript mobiles (bonjour Opera Mini !).

Néanmoins, le tutoriel autocomplétion en AJAX de Denis Cabasson que j'ai suivi pour en ajouter une sur le site m'a été très utile et est très bien fait. Je trouve que c'est beaucoup plus éducatif d'essayer de le faire soi-même, plutôt que de prendre une random bibliothèque qui le fait déjà.

Une nouvelle source de données

La source de données trafic dont je parlais dans mon premier article à propos de monrer.fr est de moins en moins fiable, et je souhaitais pouvoir le remplacer avec autre chose pour plusieurs raisons :

  • les horaires du RER A et B sont les horaires théoriques et reflètent donc mal la réalité ;
  • il manquait les gares de certaines branches du RER A ;
  • il n'y a pas la possibilité de récupérer les messages qui défilent dans le bandeau en bas des écrans Infogare (donc pas d'infos trafic étendues ni d'infos travaux) ;
  • enfin, le serveur me balance une erreur 500 trois fois sur quatre lorsque je l'interroge.

C'est pourquoi je me suis mis en tête de reverse engineerer l'application Android officielle de Transilien afin de voir comment il fonctionne, et voir si celui-ci utiliserait une autre API en ligne non documentée.

Le temps que la SNCF mette en place une API accessible à tous, qui permette d'obtenir les horaires de toutes les lignes à raison de plus de dix fois par minute et sans authentification HTTP, j'ai constaté la chose suivante :

% dig api.transilien.com

; (snip)

;; ANSWER SECTION:
api.transilien.com.     600     IN      CNAME   api.ode.tn.ocito.com.
api.ode.tn.ocito.com.   86400   IN      A       85.233.209.218

Manifestement, le développement de l'API proposée par la SNCF a été déléguée par un sous-traitant, OCITO, ce qu'on retrouve assez facilement dans le nom des classes Java une fois le .apk de l'application Android officielle téléchargé, dézippé et décompilé avec dexdump. Assez étrange, dans le sens où l'entreprise se présente plus comme une entreprise de marketing mobile plutôt qu'une boîte qui aurait tout plein de datacenters capables de gérer tous les appels d'API d'usagers qui se demanderaient où diable se trouve leur RER, mais là n'est pas la question.

Passage supprimé à la demande de la SNCF.

Dissection de l'API OCITO

Passage supprimé à la demande de la SNCF.

Obtenir les prochains trains

Passage supprimé à la demande de la SNCF.

Le serveur renvoie [...], en JSON, la liste des prochains trains avec leur code mission, leur numéro, le terminus et l'heure de passage. Il ne donne cependant pas la liste des gares desservies, que je dois obtenir séparément et individuellement pour chaque train. Cependant, l'API fournit également cette information. Dans la même réponse figure une liste de chaînes de caractères correspondant aux informations affichées en bas des écrans Infogare.

Obtenir la desserte d'un seul train

Passage supprimé à la demande de la SNCF.

Le serveur renvoie alors la liste des gares ainsi que l'heure de passage, ce qui me permet d'obtenir à nouveau les informations de trafic "live" que j'obtenais jadis de sncf.mobi.

Conclusion

Avant monrer.fr, j'avais codé un plug-in pour un bot IRC qui récupérait le même genre d'informations que ce que je fais maintenant. Ma toute première approche consistait à parser le code HTML du site Transilien à l'aide de la page qui affichait toutes ces informations. Il s'agit donc maintenant de la troisième fois que je recherche une méthode pour obtenir ces horaires en temps réel, et le temps que la SNCF mette au point une API pour les obtenir qui me soit accessible, j'espère que ma méthode fera l'affaire.

En tout cas, des mises à jour sont à prévoir sur monrer.fr, même si je risque d'être assez occupé avec un déménagement imminent.

J'en profite aussi pour remercier tous ceux qui ont utilisé ce site et qui le trouvent utile, et plus particulièrement ceux qui envoient des bugreports.

Révéler les secrets de sa voiture avec le port OBD-II

Lorsque j'ai découvert que ma voiture a un port de diagnostic qui permet d'obtenir en temps réel tous les paramètres instantanés comme la vitesse, le régime du moteur ou d'autres choses encore, je me suis immédiatement mis en tête de faire l'acquisition d'un module USB permettant de faire mumuse avec ce port.

Ce port, qu'on appelle OBD-II (pour On Board Diagnostics), serait obligatoire dans toutes les voitures construites à partir du début des années 2000. Il est donc fort possible que votre voiture en ait également un. En général, il est assez bien caché, parfois sous une trappe, mais le plus souvent sous le volant ou un autre endroit atteignable depuis le siège conducteur.

À l'origine, il s'agit d'un port de diagnostic qui permet aux constructeurs automobiles de surveiller l'état et les émissions de gaz ou particules des moteurs qu'ils mettent dans leurs voitures, afin d'être en règle avec les lois sur les émissions de gaz à effet de serre notamment. Bien entendu, nous allons nous servir de ce port pour faire des choses un peu plus ludiques.

En effet, les possibilités sont nombreuses. Certains pourraient utiliser ce port pour faire de la surveillance de parc automobile. D'autres pourraient s'en servir pour fabriquer un panneau d'instruments alternatifs affichant des paramètres du moteur (retards à l'allumage, forces...) que le tableau de bord n'indique pas. Personnellement, je rêve de fabriquer un affichage têtes hautes. Même si je suis assez dubitatif face à la réalisabilité du projet pour plusieurs raisons, je me suis néanmoins procuré les outils pour faire mumuse.

Pour communiquer avec la voiture, il existe plusieurs protocoles (de couches 1 et 2 grosso modo) standardisés, et savoir lequel utiliser relève généralement de la devinette, parce que comme tout protocole industriel, c'est toujours le bordel. Heureusement, des circuits intégrés l'ELM327 font cette autodétection pour nous, et il suffit de balancer les commandes OBD-II dessus (qui, eux, ne varient quasiment pas) pour interagir avec la voiture.

Le matériel

Il vous faut :

  • un PC, smartphone, PDA, console de jeux, Arduino, grille-pain ou je ne sais quoi d'improbable ;
  • un dongle ELM-327 USB (ou un montage comportant ce chip).

Photo d'un dongle ELM-327

Ce dernier est trouvable sur eBay pour une dizaine d'euros. Il permet de communiquer avec le port OBD-II au moyen de son propre protocole série (RS-232). La version USB intègre tout simplement un convertisseur PL2303 et il est possible de dialoguer avec le dongle via minicom ou un outil similaire.

Hackons un petit peu

D'un point de vue utilisateur, le protocole est de la forme « requête-réponse » pour les choses les plus simples. De la même manière qu'en HTTP, on envoie une requête pour obtenir une donnée particulière, et le dongle nous répond. Par exemple, pour demander la valeur actuelle du compte-tours, la session ressemble à ça :

> 01 0D
41 0C 23 6C

Dans la requête, l'octet 01 indique qu'on demande une valeur réelle instantanée, et l'octet 0D (appelé « PID ») indique qu'on souhaite la valeur du compte-tours. La liste des données qu'on peut obtenir est disponible un peu partout sur le Net. La réponse est 23 6C, ce qui, converti en base 10 et après division par 4, donne la valeur réelle, qui est 2 267 tours par minute.

Chaque valeur est renvoyée sous sa forme brute ; pour les exploiter, il faut généralement les traiter bit à bit pour en extraire un chiffre exploitable.

Bien entendu, seule une petite partie des PIDs listés dans la page sus-citée est généralement prise en charge par l'ordinateur de bord, sinon ce ne serait pas drôle. Heureusement, il y a une commande qui permet d'obtenir la liste des PIDs prise en charge :

> 01 00
41 00 BE 3E B8 11

La réponse est renvoyée sous la forme de 32 bits. Converti en base 2, ce nombre donne 1011 1110 0011 1110 1011 1000 0001 0001. En lisant de gauche à droite, on conclut donc que ma voiture prend en charge les PIDs 00, 02 à 06, 0A à 0E, 10, 12 à 14, 1B et 1F.

Exemple d'application : une simple boîte noire

Comme je voulais tester l'acquisition en temps réel de la vitesse v de la voiture et du régime moteur N, j'ai écrit un petit programme qui interroge un dongle OBD environ 16 fois par seconde et formate, pour une date t donnée, un couple (v, N).

Comme je conduis généralement seul, et que je me suis dit que conduire avec un laptop sur les genoux est une très mauvaise idée, j'ai eu l'idée de logguer ces informations pour ensuite les rejouer après coup, comme une sorte de boîte noire.

Des tests stationnaires (point mort, frein à main et quelques petits coups sur l'accélérateur) m'ont permis de voir que 16 échantillonnages par seconde suffisaient largement pour avoir quelque chose de fluide et qui semblait refléter parfaitement ce qu'indiquaient les instruments au tableau de bord, sans pour autant trop surcharger le dongle OBD.

Screenshot de données logguées à l'aide du dongle OBD

Conclusion

Que dire de l'intérêt d'exploiter les possibilités du port OBD-II de sa voiture, à part celui de mieux comprendre comment fonctionne le moteur, faire du diagnostic et du dépannage soi-même, ou tout simplement pour la simple curiosité intellectuelle ? Nous avons vu comment récupérer des paramètres « live » du moteur et les logguer.

Ma prochaine étape sera d'utiliser un Raspberry Pi ou un Arduino pour tenter d'exploiter le plus de données possibles. J'ai d'ores et déjà commandé un écran 7 pouces HDMI sur eBay, dans l'optique de faire quelque chose en ce sens avec mon Raspberry Pi.

Posté par x0r à 5 commentaires • Tags : hack linux voiture obd

Le futur appartient à l'auto-hébergement

Cela fait maintenant au moins un an que j'auto-héberge ce site Web (et beaucoup plus de choses) derrière ma modeste connexion Internet, alors que de plus en plus de décideurs dans des grandes entreprises ont l'air d'avoir la tête dans les nuages en parlant de cloud ceci, cloud cela, à tout va. À croire qu'on pourra un jour faire le café dans le cloud.

Personnellement, je ne fais pas confiance au cloud. Les multiples déboires des hébergeurs de cloud, voire des services en ligne de manière générale (webmails, plateformes de blogs, etc.) font que je ne souhaite plus confier mes données à une entreprise tierce dans la mesure du possible. Sans parler de choses incroyablement complexes comme toute l'affaire autour de PRISM.

Bien entendu, une solution pour réduire à coup sûr les chances qu'une organisation gouvernementale américaine lise mes mails aurait été de se payer un serveur dédié et de faire tourner son service mail depuis cette machine. Mais même si j'avais les accès root sur ce serveur dédié, je ne suis probablement pas le seul ; le fournisseur du service a parfois besoin de mettre la main dessus pour dépanner la machine, par exemple. Et une bonne bécane coûte aussi cher qu'une connexion Internet.

D'où la solution que j'adopte maintenant depuis plus d'un an, qui est d'auto-héberger mes services. Ceci procure d'ailleurs énormément de plaisir et de nuits blanches à la fois : j'apprends en même temps que j'ajoute de nouveaux services. Un serveur Web par ci, un DNS par là, un Postfix ensuite avec un Dovecot et un RoundCube fraîchement installés, voire un serveur DHCP/DHCPv6 pendant un moment.

Auto-héberger ses services apporte de nombreux petits avantages, à savoir :

  • la maîtrise totale de son environnement informatique ; je sais que je suis le seul avec les accès root, je suis donc libre dans mes choix techniques et je peux donc installer tous les applicatifs que je veux sur mon serveur, ne serait-ce que pour les essayer ;

  • l'assurance que les données que l'on gère et qui ne sont pas expressément publiées ne quitteront pas le serveur. Bien entendu, cela sous réserve d'aucune compromission de mots de passe. Enfin, pour mitiger cette menace, le minimum consiste à stocker des mots de passe hashés et salés (donc pas comme LinkedIn) et de mettre en œuvre des mécanismes type fail2ban ;  

  • la possiblité d'apprendre comment fonctionne chaque service, et comment les paramétrer pour qu'ils fassent ce qu'ils veulent ; par exemple, comment configurer son DNS et ses entrées MX et SPF pour pouvoir envoyer et recevoir mes mails, ou apprendre comment est réellement acheminé un e-mail à travers le réseau ;

  • être libre de toute restriction arbitraire sur les contenus que l'on publie, dans les limites de la loi française bien entendu. Je pourrais publier des contenus « NSFW » si ça me chante ;

  • en somme, ce que j'aime par-dessus tout dans la vie : le fait que cela soit un défi intellectuel permanent.

Bien entendu, même si j'ai appris la grande majorité des connaissances nécessaires sur le tas, en fouillant dans les résultats de mon moteur de recherche préféré ou dans le cadre de mon implication dans l'association ARISE, ma modestie me conduira sûrement à ne jamais me considérer comme un administrateur système suffisamment chevronné. Je n'ai par exemple jamais essayé de mettre en place des systèmes redondants (avec « failover »), ni touché à du BGP, entre autres. Mais je pense que les connaissances que j'ai suffisent largement pour continuer à faire vivre mes services autohébergés.

Cependant, on pourrait croire que l'auto-hébergement reste quelque chose d'inaccessible au commun des mortels, mais je crois que cela pourrait changer. Auto-héberger implique en effet de garder un ordinateur allumé 24 heures sur 24, 7 jours sur 7. Or, un périphérique assimilable à un ordinateur et qui est le plus souvent allumé en permanence est présent chez la plupart des internautes en France : la « box » fournie par leur FAI. Or, on voit de plus en plus de FAI proposer de plus en plus de services dans leurs box.

De plus, il existe maintenant des distributions Linux comme YunoHost, qui fournissent des solutions clé en main pour auto-héberger un maximum de services tout en passant par une interface Web pour les configurer. Je serais tenté de regarder juste pour voir ce que ça vaut.

En somme, je pense qu'il suffit qu'un FAI donne un petit coup de pouce en fournissant des services auto-hébergés dans leurs box. Free est déjà sur la bonne voie en proposant, en plus, des noms DNS de la forme machin.hd.free.fr, ce qui encourage déjà beaucoup cette pratique.

La seule chose qui manque pour que l'auto-hébergement soit réellement pratique et viable, c'est le débit en upload. Et pendant ce temps, l'actualité fait que certaines entreprises migrent leurs services "cloud" en Suisse plutôt qu'aux États-Unis...

Posté par x0r à 0 commentaire • Tags : autohebergement linux sysadmin cloud vpn securite prism nsa

Exécuter du Lua dans du PHP à l'aide d'une sandbox

Un projet (personnel) sur lequel je travaille en ce moment consiste à réaliser un jeu de rôle en ligne (autrement dit, un « webgame »). Devant le nombre d'objets, d'armes, de quêtes ou d'autres choses différentes, il est alors évident que le moteur du jeu se doit d'être le plus flexible possible. En effet, certains objets modifient les règles du jeu, de la même manière que les actions des cartes L5R modifient la résolution des batailles.

Cependant, implémenter ces modificateurs de règle de manière statique, c'est-à-dire en PHP, obligerait en réalité de mélanger les règles générales et les règles particulières de chaque objet, ce qui ne serait pas souhaitable.

La solution consiste alors en l'exécution de petits bouts de code particuliers dans un langage de script facile à manier. Un très bon candidat pour cela est le Lua.

L'avantage du Lua réside dans sa simplicité et la présence de « first-class variables » : c'est-à-dire que n'importe quel objet, y compris une fonction, peut être affectée à une variable. Sa simplicité permet également, avec peut-être une page pour résumer l'API, à des gens qui ne sont pas forcément les développeurs d'exercer leur créativité.

Compiler l'extension PECL sur Gentoo

Tout d'abord, avant de pouvoir s'amuser avec ce langage, il nous faut compiler l'extension PECL lua.

Il s'avère que même s'il est disponible tout prêt sur PHP.net, qu'il n'a pas encore été packagé pour Gentoo.

Heureusement, l'ebuild n'est pas très compliqué, et l'installer ne l'est pas non plus :

  • Téléchargez-le ici : pecl-lua-1.0.0.ebuild
  • Placez l'ebuild dans /usr/local/portage/dev-php/pecl-lua ;
  • Tapez les commandes suivantes en tant que root :
# cd /usr/local/portage/dev-php/pecl-lua
# ebuild pecl-lua-1.0.0.ebuild manifest
  • Vérifiez que vous avez un PORTDIR_OVERLAY="/usr/local/portage" dans votre /etc/portage/make.conf ;
  • Enfin, mergez le paquet à l'aide d'un emerge pecl-lua.

Oui, je sais, je devrais publier cet ebuild sur l'overlay Sunrise, mais j'ai pas le temps là.

Il se pourrait que vous devrez ajouter votre architecture aux KEYWORDS avant de pouvoir merger le paquet. N'hésitez pas à me signaler si cet ebuild fonctionne sur d'autres architectures ; je vous en serais reconnaissant !

Le bac à sable

Maintenant que nous avons installé l'environnement, nous pourrons exécuter du code Lua à l'intérieur de l'interpréteur PHP.

Cependant, face à la possibilité d'exécuter du code arbitraire, et vu les risques que cela implique, nous allons exécuter ce code Lua dans un environnement contrôlé, ou « sandbox » (bac à sable) ; en particulier, nous désactiverons les fonctions suivantes :

  • os.setlocale, afin d'empêcher les bugs ou failles exploitées à l'aide d'un changement de locale ;
  • os.execute, afin d'empêcher l'exécution de commandes arbitraires ;
  • os.getenv, afin d'empêcher la fuite d'informations sensibles sur le serveur ;
  • enfin, toutes les fonctions de la famille debug.*, afin d'interdire les bidouilles avec l'interpréteur Lua.

Preuve de concept

En guise de preuve de concept et afin de tester l'intégration de Lua dans PHP, j'ai codé le script PHP suivant. Il affiche les caractéristiques d'un personnage fictif, et permet ensuite de les modifier en exécutant le code Lua adéquat.

<?php

$perso 
= array(
    
'nom'     => 'Herp Derp',
    
'sexe'    => 'M',
    
'race'    => 'Humain',
    
'origine' => 'Détessay',
    
'bru'     => 10,
    
'fin'     => 12,
    
'dis'     => 17,
    
'con'     => 13,
);

$perso_b $perso;

$lua_disabled_funcs = array(
    
'os.setlocale',    /* This potentially breaks things */
    
'os.execute',      /* Potentially very dangerous */
    
'os.getenv',       /* Might leak too much info about server */
    
'debug',           /* Disable debugging stuff */
);


function 
dump_perso($perso) {
    echo 
"<pre>\n";

    echo 
htmlspecialchars($perso['nom']) . "\n\n";
    echo 
htmlspecialchars($perso['race']) . ", ";

    switch(
$perso['sexe']) {
        case 
'M': echo "homme"; break;
        case 
'F': echo "femme"; break;
        default: echo 
"sexe inconnu"; break;
    }
    echo 
", " $perso['origine'] . "\n\n";

    echo 
"Brutalité :    " htmlspecialchars($perso['bru']) . "\n";
    echo 
"Finesse :      " htmlspecialchars($perso['fin']) . "\n";
    echo 
"Discipline :   " htmlspecialchars($perso['dis']) . "\n";
    echo 
"Constitution : " htmlspecialchars($perso['con']) . "\n";

    echo 
"</pre>\n";
}

?>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>test lua</title>
<style type="text/css">
.float {
    float: left;
    width: 40%;
}
</style>
</head>
<body>


<form method="POST" action="<?php print $_SERVER['SCRIPT_NAME'?>">
    <textarea id="lua-code" name="lua-code" style="min-width: 30em; min-height: 20em;">
        <?php if (isset($_POST['lua-code'])) { print $_POST['lua-code']; } ?>
    
</textarea>
    <br />
    <input type="submit" value="Exécuter" />
</form> 

<div class="float">
    <h1>Avant</h1>
    <pre><?php dump_perso($perso_b); ?></pre>
</div>

<?php
if (isset($_POST['lua-code'])) {
    
/* Set up Lua environment */
    
$l = new lua();

    
/* Set some variables from outside */
    
$l->assign("perso"$perso);

    
/* Deactivate dangerous functions */
    
foreach ($lua_disabled_funcs as $function) {
        try {
            
$l->eval("${function} = nil");
        } catch(
LuaException $e) {
            echo 
"$function: " $e->getMessage();
        }
    }

    
/* Run user code */
    
try {
        
$l->eval($_POST['lua-code']);
    } catch (
LuaException $e) {
        echo 
"user code: " $e->getMessage();
    }
?>

<div class="float">
    <h1>Après</h1>
    <pre><?php dump_perso($l->perso); ?></pre>
</div>
<?php
}
?>


</body>
</html>

Le code le plus intéressant se trouve plutôt vers la fin du script, et illustre comment on peut faire passer des données de l'environnement PHP vers l'environnement Lua, et vice-versa.

Et quand on exécute la page, ça marche :

Démo Lua en PHP

En conclusion, ce système est bien sympathique, et je suis content d'avoir pu expérimenter avec ça. Cela dit, pendant que je rédigais l'article, je suis passé à du Perl/Catalyst pour le projet en question (la même techno que ce qui fait tourner ce site), parce que Zend me donnait des boutons.

Posté par x0r à 0 commentaire • Tags : securite lua php web sandbox