VirtualHost : proxy

Eléphant du PHP | 386 Messages

11 janv. 2017, 23:03

Bonjour,

j'aimerai savoir si le code ci-dessous est bien codé ?
Il fonctionne, et redirige mon serveur nodejs https://io.monsite.fr:3016 vers le fichier js de socket.io ;)
(C'est juste pour éviter de montrer le port de mon serveur au visiteur, et plus facile dans le code)

Code : Tout sélectionner

<VirtualHost *:80 *:443> ServerAdmin admin@monsite.fr ServerName io.monsite.fr # io.monsite.fr est redirigé vers io.monsite.fr:3016 (le serveur nodejs en question) SSLEngine on SSLProxyEngine on SSLProxyVerify none SSLProxyCheckPeerCN off SSLProxyCheckPeerName off SSLProxyCheckPeerExpire off SSLCertificateFile /etc/ssl/certs/cert.crt SSLCertificateKeyFile /etc/ssl/private/key.key SSLCertificateChainFile /etc/ssl/certs/cert_int.crt RewriteEngine On RewriteCond %{REQUEST_URI} ^/socket.io [NC] RewriteCond %{QUERY_STRING} transport=websocket [NC] RewriteRule /(.*) wss://io.monsite.fr:3016/$1 [P,L] ProxyRequests off <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass /socket.io/1/websocket wss://io.monsite.fr:3016/socket.io/1/websocket ProxyPassReverse /socket.io/1/websocket wss://io.monsite.fr:3016/socket.io/1/websocket ProxyPass /socket.io/ https://io.monsite.fr:3016/socket.io/ ProxyPassReverse /socket.io/ https://io.monsite.fr:3016/socket.io/ ProxyPass / https://io.monsite.fr:3016/ ProxyPassReverse / https://io.monsite.fr:3016/ </VirtualHost>

ViPHP
ViPHP | 5882 Messages

12 janv. 2017, 00:00

Bonjour,

L'idée est bonne mais souffre de quelques petits problèmes de mise en oeuvre.

C'est effectivement une bonne pratique de placer un serveur HTTP (apache, nginx, etc) devant un serveur applicatif. Le serveur HTTP est théoriquement mieux protégé, et tu peux lui faire faire pas mal d'opérations de traitement de la requête (gestion de la connexion TLS, mise en cache, etc).

Par contre, ton VirtualHost reçoit les connexions http (port 80) et https (port 443) mais, si je ne me trompe, va essayer de traiter la connexion comme https dans les deux cas étant donné que tu actives le SSLEngine. Ce n'est donc pas correct.
D'autre part, cela veut dire que tu souhaites proxyfier tout le trafic vers le serveur applicatif, ce qui n'est pas une bonne pratique. En général, on propose la connexion https, et on redirige toutes les requêtes http vers l'url https correspondante, cette pratique permet d'assurer que toutes les requêtes et réponses seront sécurisées (on force l'utilisateur à utiliser https).

Il est donc préférable d'utiliser une configuration telle que celle ci :

Code : Tout sélectionner

<VirtualHost *:80> ServerName www.example.net RedirectMatch "^/(.*)" "https://www.example.com/$1" </VirtualHost> <VirtualHost *:443> ServerName www.example.net (... - le reste de la configuration - ...) </VirtualHost>
Un autre soucis est que tu places Apache en frontal, qui va assurer la connexion https, et donc en principe soulager le serveur NodeJS, mais tu utilises ensuite des connexions wss et https (donc sécurisées) de Apache vers le serveur NodeJS. Ce que cela veut dire, c'est que après avoir traité la requête sécurisée provenant du client, Apache devra ré-établir une nouvelle requête sécurisée vers le serveur NodeJS, impliquant le double de travail.

La bonne pratique est, lorsqu'on place un serveur en frontal, de réaliser la communication entre le frontal et le serveur applicatif en non sécurisé, afin de ne pas consommer des ressources et engendrer un délai inutilement.

Il est donc préférable de supprimer les lignes suivantes :

Code : Tout sélectionner

SSLProxyEngine on SSLProxyVerify none SSLProxyCheckPeerCN off SSLProxyCheckPeerName off SSLProxyCheckPeerExpire off
Et remplacer les adresses wss:// et https:// dans les directives ProxyPass et ProxyPassReverse par leurs équivalents ws:// et http://.

Dernier point, si tu utilises un serveur pour proxyfier tes requêtes, alors il n'est plus utile de laisser le port 3016 du serveur NodeJS accessible. Je te suggère donc de t'assurer que ton parefeu est configuré en conséquence. Plus généralement, c'est une bonne idée de vérifier que ton parefeu est actif et d'interdire tout port qui ne correspond pas à un service utile.

Cordialement

Eléphant du PHP | 386 Messages

12 janv. 2017, 01:52

Merci beaucoup de votre réponse
J'ai un message d'erreur si j'enlève ce que vous m'avez dit :


Proxy Error

The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request GET /socket.io/socket.io.js.

Reason: Error reading from remote server


Quand il fonctionne, dès qu'on va sur io.monsite.fr, le serveur tourne en boucle, il y a le message en bas : En attente de io.monsite.fr qui tourne sans cesse.
Pouvez-vous me dire comment faire pour que dès qu'un visiteur va sur io.monsite.fr, le serveur affiche une erreur 403 ?

Merci

ViPHP
ViPHP | 5882 Messages

12 janv. 2017, 11:19

Bonjour,
As tu bien désactivé le support TLS sur le serveur NodeJS ?
Plus généralement, pour savoir ce qu'il se passe, il faut aller lire les logs (aussi bien du serveur Apache que du serveur NodeJS), en augmentant le niveau de debug si besoin.
Cordialement

Eléphant du PHP | 386 Messages

12 janv. 2017, 15:13

Voici mon serveur node :

Si j'enlève la partie sécurisé, je met http au lieu d'https et j'enlève les options, j'ai toujours l'erreur 502 Proxy Error

Code : Tout sélectionner

var fs = require('fs'); var path = require('path'); var options = { key: fs.readFileSync(path.join(__dirname,'/../../var/ssl/webastro.key')), cert: fs.readFileSync(path.join(__dirname,'/../../var/ssl/webastro.crt')), ca: fs.readFileSync(path.join(__dirname,'/../../var/ssl/webastro_int.crt')) }; var https = require('https'); var server = https.createServer(options,function(req,res){ res.writeHead(200,{"Content-Type":"text/plain"}); console.log("one client connect"); res.write("Hello World from node"); res.end(); }); server.listen(1812); var io = require('socket.io').listen(server); io.sockets.on('connection', function(socket){ socket.on('disconnect', function(){ }); });
Et voici mon virtualHost actuel :

Code : Tout sélectionner

<VirtualHost *:80> ServerAdmin admin@monsite.fr ServerName io.monsite.fr RewriteEngine On RewriteCond %{REQUEST_URI} ^/socket.io [NC] RewriteCond %{QUERY_STRING} transport=websocket [NC] RewriteRule /(.*) ws://io.monsite.fr:1812/$1 [P,L] ProxyPass / http://io.monsite.fr:1812/ ProxyPassReverse / http://io.monsite.fr:1812/ </VirtualHost>
Voila ce que j'ai dans mon log :

[Thu Jan 12 14:18:13.252052 2017] [proxy_http:error] [pid 6545] (20014)Internal error: [client 2.8.192.65:49811] AH01102: error reading status line from remote server io.monsite.fr:1812, referer: http://io.monsite.fr/

Je vais repartir à zéro sur ce code et ce virtualhost
Je t'explique ce que je veux :

J'aimerai que mon serveur nodejs avec lequel je travaillerai avec socket.io pointe sur io.monsite.fr
Et que io.monsite.fr soit redirigé en proxy sur le port 1812
Mais vu que mon site est en https, comment trouver le fichier socket.io.js en http sur mon site il va trouver l'erreur :

The page at 'https://www.monsite.fr/login' was loaded over HTTPS, but requested an insecure script 'http://io.monsite.fr/socket.io/socket.io.js'. This request has been blocked; the content must be served over HTTPS.

ViPHP
ViPHP | 5882 Messages

12 janv. 2017, 16:04

Voici mon serveur node :

Si j'enlève la partie sécurisé, je met http au lieu d'https et j'enlève les options, j'ai toujours l'erreur 502 Proxy Error
(...)
Si c'est un problème de NodeJS, on ne pourra probablement pas t'aider.

Le mieux est de réaliser tes tests de manière unitaire. Avant d'essayer de voir si tu peux proxyfier, tu dois valider le fait que ton application NodeJS se comporte il faut. C'est à dire, si on veut que le serveur NodeJS serve ses pages en http ou ws, alors tu dois vérifier qu'il sert bien ses pages en http ou ws directement sur le port 1812. Une fois que tu es sûr de ça, tu as éliminé une source d'erreur et tu peux passer à la suite (Apache).
Et voici mon virtualHost actuel :

Code : Tout sélectionner

<VirtualHost *:80> ServerAdmin admin@monsite.fr ServerName io.monsite.fr RewriteEngine On RewriteCond %{REQUEST_URI} ^/socket.io [NC] RewriteCond %{QUERY_STRING} transport=websocket [NC] RewriteRule /(.*) ws://io.monsite.fr:1812/$1 [P,L] ProxyPass / http://io.monsite.fr:1812/ ProxyPassReverse / http://io.monsite.fr:1812/ </VirtualHost>
Sur le principe, c'est une bonne chose dans le cadre d'un test. C'est à dire que ça te permet de vérifier que Apache peut proxyfier en http des requêtes qui lui viennent en http. Donc un cas assez simple.
Ensuite, une fois validé, tu peux passer à proxyfier HTTPS vers HTTP.
Voila ce que j'ai dans mon log :

[Thu Jan 12 14:18:13.252052 2017] [proxy_http:error] [pid 6545] (20014)Internal error: [client 2.8.192.65:49811] AH01102: error reading status line from remote server io.monsite.fr:1812, referer: http://io.monsite.fr/

Je vais repartir à zéro sur ce code et ce virtualhost
Pas forcément besoin de repartir à zéro, il faut surtout que tu investigues pourquoi est-ce que Apache reçoit une information qui n'est pas formattée comme il s'y attend. Un bonne outil peut-être wireshark (ou tshark en ligne de commande). Cela peut te mettre de voir le contenu des paquets échangés entre les deux serveurs et d'identifier une anomalie.
Je t'explique ce que je veux :

J'aimerai que mon serveur nodejs avec lequel je travaillerai avec socket.io pointe sur io.monsite.fr
Et que io.monsite.fr soit redirigé en proxy sur le port 1812
Mais vu que mon site est en https, comment trouver le fichier socket.io.js en http sur mon site il va trouver l'erreur :

The page at 'https://www.monsite.fr/login' was loaded over HTTPS, but requested an insecure script 'http://io.monsite.fr/socket.io/socket.io.js'. This request has been blocked; the content must be served over HTTPS.
Oui, c'est en réalité assez logique. Effectivement les contenus d'une page HTTPS doivent être HTTPS également. Mais ça me parait être un problème mineur, que tu dois pouvoir régler assez facilement dans le code qui génère tes pages web. Je te suggère de regarder le code html et js de tes pages générées pour trouver l'origine de cette erreur.
Tu as peut-être des options dans tes modules NodeJS pour définir le format des urls générées.

Cordialement

Eléphant du PHP | 386 Messages

12 janv. 2017, 21:55

Je me suis penché vers node-http-proxy, je vais essayer de voir ça au lieu de passer par apache pour faire les proxy.
J'ai vu sur internet qu'on peut faire ça avec node ;)
Ça éviterai à apache de faire le travail.

Tu en pense quoi de ce module ?
Merci ;)

ViPHP
ViPHP | 5882 Messages

13 janv. 2017, 01:23

Je me suis penché vers node-http-proxy, je vais essayer de voir ça au lieu de passer par apache pour faire les proxy.
J'ai vu sur internet qu'on peut faire ça avec node ;)
Ça éviterai à apache de faire le travail.

Tu en pense quoi de ce module ?
Merci ;)
Je ne sais pas, je n'ai jamais touché à NodeJS.
Par contre si c'est pour proxyfier vers ton site (donc vers un serveur NodeJS), je ne vois pas l'utilité par rapport à simplement faire écouter ton site sur le port 443.

Cordialement