PAB's blog - Tag - apache2022-11-19T07:02:34+00:00urn:md5:5926f7e05a689ea9af53f3d15057feb6DotclearNode et socket.io derrière Apache en Reverse Proxyurn:md5:9461de25f9ec6dea0b08f4d04e6568fa2018-06-18T12:03:00+02:002018-06-18T12:03:00+02:00Pierre-Alain Bapachelinuxnodejsproxysocket.iowebsocket <p>Je viens de déployer une application NodeJS basée sur Angular et utilisant socket.io pour communiquer entre le "front-end" et le "back-end". Dans Firefox, je voyais toutefois ce message d'erreur :</p>
<pre>
Firefox can’t establish a connection to the server at wss://my.app/socket.io/?token=verylongtoken&EIO=3&transport=websocket&sid=verylongsid
</pre>
<p>et pourtant l'application fonctionnait parfaitement.</p>
<p>Après enquête, il semble que socket.io avait le bon goût de faire un "fallback" sur une méthode AJAX et s'accomodait donc du non établissement du WebSocket.</p>
<p>Pour régler proprement le problème, il fallait :</p>
<ul>
<li>activer le module proxy_wstunnel d'Apache</li>
</ul>
<pre>
a2enmod proxy_wstunnel
service apache2 restart
</pre>
<ul>
<li>puis ajouter ces lignes dans la configuration (attention, le module rewrite d'Apache doit aussi être chargé !)</li>
</ul>
<pre>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) ws://localhost:3000/$1 [P,L]
</pre>
<p>Et hop, tout était fonctionnel désormais !</p>LemonLDAP::NG et Let's Encrypturn:md5:510cc644bc44f514854a367253bbe87c2016-03-28T06:16:00+02:002016-06-04T11:34:01+02:00Pierre-Alain Badminsysapachelemonldapletsencryptplanet-libreréseausécurité <p>Nous allons voir dans ce court article comment obtenir des certificats Let's Encrypt pour des services LemonLDAP::NG. Les chemins d'accès évoqués dans la suite correspondent à une installation de LemonLDAP::NG sur Debian Jessie à partir du paquet officiel fourni <a href="http://lemonldap-ng.org/documentation/1.0/installdeb">sur les dépôts de LemonLDAP::NG</a>.</p>
<h3>Étape 1 : obtenir un certificat pour le Manager</h3>
<p>Nous allons commencer par autoriser l'accès au dossier .well-known dans lequel Let's Encrypt travaille (pour mémoire, il y place une clé qu'un serveur externe vient interroger, permettant ainsi d'affirmer que le demandeur gère le domaine). D'abord dans la configuration d'Apache, dans le fichier <em>/etc/apache2/sites-available/manager-apache2.conf</em>, nous allons remplacer la ligne</p>
<pre>
RewriteCond "%{REQUEST_FILENAME}" "!^/(?:static|doc|fr-doc|lib).*"
</pre>
<p>par</p>
<pre>
RewriteCond "%{REQUEST_FILENAME}" "!^/(?:static|\.well-known|doc|fr-doc|lib).*"
</pre>
<p>Puis, dans le manager lui-même, il faut demander à LemonLDAP::NG de ne pas bloquer l'accès au même dossier .well-known aux utilisateurs non authentifiés. Ainsi, il faut se rendre dans <em>Virtual Hosts -> manager.mondomaine.fr -> Access rule</em>, et ajouter une nouvelle règle :</p>
<ul>
<li>Regular expression: ^/\.well-known</li>
<li>Rule: skip</li>
</ul>
<p><a href="https://blog.bandinelli.net/public/Screenshot_2016-03-28_06-02-19.png" title="Screenshot_2016-03-28_06-02-19.png"><img src="https://blog.bandinelli.net/public/.Screenshot_2016-03-28_06-02-19_m.png" alt="Screenshot_2016-03-28_06-02-19.png" style="display:table; margin:0 auto;" title="Screenshot_2016-03-28_06-02-19.png, mar. 2016" /></a></p>
<p>Dès lors, Let's Encrypt devrait être capable d'accéder à la clé placée dans <em>.well-known</em>. Nous pouvons donc démarrer le processus avec le client Let's Encrypt :</p>
<pre>
certbot certonly --renew-by-default -a webroot --webroot-path /usr/share/lemonldap-ng/manager/ -d manager.mondomaine.fr
</pre>
<h3>Étape 2 : obtenir un certificat pour le portail d'authentification</h3>
<p>Facile :</p>
<pre>
certbot certonly --renew-by-default -a webroot --webroot-path /var/lib/lemonldap-ng/portal/ -d auth.mondomaine.fr
</pre>
<h3>Étape 3 : obtenir un certificat pour une application placée derrière LemonLDAP::NG</h3>
<p>Si l'application est protégée derrière LemonLDAP::NG, il faut commencer par indiquer à LemonLDAP::NG de laisser transiter les requêtes vers le dossier <em>.well-known</em>. A l'image de ce qui a été fait pour le manager, il faut se rendre dans <em>Virtual Hosts -> manager.mondomaine.fr -> Access rule</em>, et ajouter une nouvelle règle :</p>
<ul>
<li>Regular expression: ^/\.well-known</li>
<li>Rule: skip</li>
</ul>
<p>Puis tout simplement (si l'application sous-jacente ne filtre pas les accès à <em>.well-known</em>) :</p>
<pre>
certbot certonly --renew-by-default -a webroot --webroot-path /var/www/mon-app -d mon-app.mondomaine.fr
</pre>Apache 2 : SetEnvIf et variables d'environnement, e.g. n'autoriser que certaines IP ou UserAgent à se connecterurn:md5:365104c86620945c88ec27de4c39a9522015-12-18T06:53:00+01:002015-12-18T06:54:53+01:00Pierre-Alain Badminsysapachelinuxplanet-libre <p>Le serveur web Apache est extrêmement modulable quand il s'agit de filtrer des requêtes. Si tout le monde connaît les habituelles commandes <em>Require all denied</em>, <em>Require all granted</em>, <em>Require Host example.org</em>, nous allons voir ici comment utiliser une variable interne d'environnement et l'utiliser comme contrôle d'accès à un hôte virtuel.</p>
<p>Imaginons par exemple le cas suivant : nous souhaitons n'autoriser que certaines IP à se connecter, sauf pour les navigateurs dotés d'un User-Agent très spécifique.</p>
<p>Avant toute chose, il est nécessaire d'activer le module SetEnvIf (<a href="https://httpd.apache.org/docs/2.4/mod/mod_setenvif.html">https://httpd.apache.org/docs/2.4/mod/mod_setenvif.html</a>) qui permet de paramétrer une variable d'environnement d'Apache. Sous Debian (ou dérivé), cela se fera par :</p>
<pre>
a2enmod setenvif
</pre>
<p>Commençons par placer une condition sur l'IP :</p>
<pre>
SetEnvIf Remote_Addr 1.2.3.4 variable
</pre>
<p>ou alors si le serveur se trouve derrière un proxy qui fournit l'adresse d'origine dans le champ X-Forwarded-For :</p>
<pre>
SetEnvIf X-Forwarded-For 1.2.3.4 variable
</pre>
<p>La valeur fixe 1.2.3.4 peut-être remplacée par toute expression régulière de son choix.</p>
<p>Puis filtrons sur le User-Agent :</p>
<pre>
SetEnvIf User-Agent ^MaValeurPerso variable
</pre>
<p>Et finalement, expliquons à Apache qu'il faut interdire l'accès si aucune des conditions n'a été atteinte :</p>
<pre>
Require env variable
</pre>
<p>Dès lors, une fois la configuration rechargée, Apache n'autorisera l'accès qu'aux requêtes provenant de <em>1.2.3.4</em> ou émises par un navigateur au User-Agent correspondant à l'expression régulière <em>^MaValeurPerso</em>. Ces éléments de configuration offrent beaucoup de richesse !</p>Apache, protéger par mot de passe tout un hôte virtuel sauf certaines adresses : utilisation de LocationMatchurn:md5:4d6d0dc3a39c8cb6e4e6f79095d1c3652014-05-11T08:45:00+02:002014-05-11T10:28:20+02:00Pierre-Alain Bapachedéveloppement weblinuxplanet-libreréseau <p>Il est assez classique d'utiliser les fonctions d'authentification d'Apache, par exemple <a href="http://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html">auth_digest</a>, pour sécuriser l'accès à un répertoire ou une application web propulsée par Apache.</p>
<p>Toutefois, il est parfois souhaitable de laisser en accès sans mot de passe une adresse spécifique, correspondant par exemple à une page publique ou à une fonctionnalité de l'application qu'un utilisateur lambda doit pouvoir déclencher.</p>
<p>Apache permet cela grâce à la direction "LocationMatch" et à des expressions régulières.</p>
<p>Par exemple, avec l'exemple ci-dessous placé dans un hôte virtuel correspondant à <em>mon-app.domaine.tld</em> :</p>
<pre>
<LocationMatch "^(?!/zone-publique)">
AuthType Digest
AuthName "mon-app"
AuthDigestProvider file
AuthUserFile /path/to/digest-password-file
Require valid-user
</LocationMatch>
</pre>
<p>tout accès à l'hôte virtuel sera protégé par mot de passe sauf l'adresse <em>http://mon-app.domaine.tld/zone-publique</em> qui sera accessible à tous sans mot de passe.</p>
<p>Bons paramétrages !</p>Forcer la bascule vers HTTPS derrière un 'reverse proxy'urn:md5:b576fb1b0dff98f17f1743e7d4b39c012013-10-18T20:56:00+02:002013-10-18T19:57:12+02:00Pierre-Alain Bapachelinuxplanet-libreréseausécuritéweb <p>Pound (déjà évoqué à de nombreuses reprises dans ces lignes) est un 'reverse proxy' (et aussi un 'load balancer' si on souhaite utiliser ces fonctionnalités) très efficace... Il peut notamment gérer toutes les connexions en HTTPS vers vos serveurs web, les décrypter et ensuite les distribuer (bien sûr ce n'est à faire que sur un réseau local hermétique aux oreilles indiscrètes !) en HTTP à vos différents serveurs.</p>
<p>Selon les configurations, on acceptera les connexions en HTTP ou HTTPS ou seulement l'une ou l'autre. Parfois, on souhaite récupérer les utilisateurs qui se connectent en HTTP et les renvoyer automatiquement vers HTTPS.</p>
<p>Il faut alors demander au serveur web sous-jacent de réécrire les adresses, ce qui, sous Apache, se fait de la façon suivante :</p>
<pre>
RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</pre>
<p>On notera que la réécriture ne s'applique que dans les cas où le drapeau 'X-Forwarded-Proto' n'est pas déjà HTTPS.</p>
<p>On peut bien sûr restreindre ce paramétrage à certains dossiers seulement (même si généraliser le HTTPS aujourd'hui serait une bonne pratique).</p>
<p>Pour restreindre cette ré-écrire (et donc ne forcer la connexion en HTTPS) que sur certains dossiers, on pourra inclure ces instructions dans un champ Directory :</p>
<pre>
<Directory /var/www/appli/admin>
RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</Directory>
</pre>
<p>Ne laissez plus vos mots de passe transités en clair sur le net ! Forcez HTTPS <em>a minima</em> sur les zones sensibles !</p>Apache derrière un 'reverse proxy' : la magie du X-Forwarded-Forurn:md5:1355dbe9058f4207c8881daacfbbe06f2013-10-16T21:50:00+02:002013-10-20T10:53:08+02:00Pierre-Alain Bapachelinuxlogplanet-libreréseau <p>Si votre serveur Web se trouve "caché" derrière un "reverse proxy" ou toute forme de "load balancer", alors vous serez peut-être embêté en constatant que les logs d'accès d'Apache ne mentionnent par défaut que l'adresse du proxy comme adresse d'origine... Ennuyeux !</p>
<p>Heureusement, les esprits ingénieux qui ont conçu les "reverse proxies" ont pensé à ajouter aux paquets transmis le drapeau "X-Forwarded-For". Il suffit alors de demander à votre serveur web de prendre en compte l'IP spécifiée dans ce champ comme origine de la communication !</p>
<p>Dans le cas d'Apache2, la configuration intiale qui était :</p>
<pre>
LogFormat "%v:%p %h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" vhost_combined
LogFormat "%h%l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" combined
LogFormat "%h %l %u %t "%r" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
</pre>
<p>devient (on remplace %h par %{X-Forwarded-For}i) :</p>
<pre>
LogFormat "%v:%p %{X-Forwarded-For}i %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" vhost_combined
LogFormat "%{X-Forwarded-For}i %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" combined
LogFormat "%{X-Forwarded-For}i %l %u %t "%r" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
</pre>
<p>Pour les logs d'erreur (importants par exemple pour permettre à fail2ban, ou un autre démon du genre, d'agir), la version 2.2 d'Apache ne permet malheureusement pas de prendre en compte un format spécifique pour les logs. Il semble que cela soit corrigé dans la version 2.4 d'Apache (<a href="http://httpd.apache.org/docs/current/mod/core.html#errorlogformat">cf. ici</a>). Si vous utilisez la version 2.2, alors il faudra installer le module rpaf :</p>
<pre>
aptitude install libapache2-mod-rpaf
a2enmod rpaf
</pre>
<p>puis dans /etc/apache2/conf.d/mod_rpaf :</p>
<pre>
RPAFenable On
RPAFsethostname On
RPAFproxy_ips a.b.c.d e.f.g.h
RPAFheader X-Forwarded-For
</pre>
<p>en remplaçant a.b.c.d et e.f.g.h par les adresses du reverse proxy. RPAF va veiller, dans les logs d'erreur, à remplacer l'adresse du 'reverse proxy' par l'adresse du client telle que signalée dans "X-Forwarded-For".</p>
<p>Et le tour est joué !</p>Faire du ruby sur le web sans Rails : Sinatraurn:md5:30523e9d922948f1da39153ac34fbb8a2011-06-12T17:17:00+02:002011-06-12T16:28:19+02:00Pierre-Alain Bapacheinformatiquerubyréseau <p>Sinatra peut être considéré comme une boîte à outil web pour Ruby très légère. Si Rails est bourré de fonctionnalités qui rendent la vie facile, il est parfois un peu démesuré d'utiliser Rails quand on veut juste exécuter un script Ruby et en afficher le résultat en ligne.</p>
<p>Une solution plus légère que Rails est Sinatra.
[|http://www.sinatrarb.com/||http://www.sinatrarb.com/</p>
<p>Sinatra est un gem à ajouter à l'installation courante de Ruby :</p>
<pre>
gem install sinatra
</pre>
<p>On écrit alors le script en spécifiant les routes dans le code, par exemple :</p>
<pre>
#monApp.rb
require 'sinatra'
get '/hi' do
"Hello World!"
end
get '/generate/:arg'
generate(params[:arg])
end
def generate (arg)
str=""
5.times {
str=str+","+arg
}
str
end
</pre>
<p>Ce code contient 2 routes : la première qui est appelée sur http://$host/hi et la seconde sur http://$host/generate/text.</p>
<p>On peut exécuter le script de manière locale en exécutant :</p>
<pre>
ruby -rubygems monApp.rb
</pre>
<p>(par défaut, le serveur de test est lancé sur http://localhost:4567)</p>
<p>Pour exécuter l'application via Passenger dans Apache, on ajoute dans le répertoire courant :
- un dossier public (mkdir public)
- un dossier tmp (mkdir tmp)
- un fichier config.ru</p>
<p>qui contient par exemple le code suivant :</p>
<pre>
require 'rubygems'
require 'sinatra'
require '/path/to/myApp.rb'
root_dir = File.dirname(__FILE__)
set :environment, ENV['RACK_ENV'].to_sym
set :root, root_dir
set :app_file, File.join(root_dir, 'myApp.rb')
disable :run
run Sinatra::Application
</pre>
<p>On ajoute alors un VirtualHost convenable dans la configuration d'Apache et Passenger sert l'application Sinatra !</p>