Tag: proxy
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 :
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) :
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
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
)
Haute-Disponibilité de fermes Apache et Tomcat
par guiguiabloc le 04 juil, 2008, sous OpenBSD, architecture, linux
Trouver un titre court pour résumer ce billet n’a pas été facile.
Pour détailler un peu plus, je vous propose de mettre un place un Load-balancing croisé entre une ferme de serveurs Apache et une ferme de serveurs Tomcat, le tout bien sûr contrôlé par un système de répartition de charges et d’ip virtuelle.
(nb. Le terme « ferme » désigne un ensemble de serveurs (2 minimum
). Et puis, Apache… Indien, Plumes, Poule, Ferme, la boucle est bouclée
… Bon ok, je –>[] )
Un dessin valant mieux qu’un long discours, voici ce que nous allons mettre en place
![]()
Oui je sais, je suis un grand malade…
Le principe est le suivant : Nous avons une IP Virtuelle, affectée par le protocole CARP sur un ensemble de 2 serveurs OpenBSD. Nous utilisons « Hoststated » qui est un « vérificateur d’état » pour Packet Filter qui nous permettra de load balancer nos frontaux Apache.
Bien évidemment, j’utilise ce moyen car nous n’avons pas tous un ALTEON chez soi…
En dessous nous aurons notre ferme Apache en mode proxy qui fera du load-balancing sur nos tomcats qui eux, ecouteront en http.
(dans cette architecture, on laisse les Tomcats gérér les contenus dynamiques ET statiques).
- Configuration des Tomcats
Que ce soit un tomcat 5 ou 6, la configuration du connecteur Coyote se fait tout simplement dans le fichier server.xml dans le répertoire conf.
Exemple :
<Connector port="60001"
minProcessors="5"
maxProcessors="64"
enableLookups="false"
scheme="http"
proxyName="monappli.blog.guiguiabloc.fr"
proxyPort="80"
acceptCount="100" debug="0" connectionTimeout="1000"
useURIValidationHack="false" disableUploadTimeout="true" />
<Engine name="Catalina" defaultHost="localhost" jvmRoute="guiguiabloc-a">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<Alias>monappli.blog.guiguiabloc.fr</Alias>
<Context path="/guiguiabloc"
docBase="/opt/tomcat-guiguiabloc/webapps/guiguiabloc"
debug="0" privileged="false">
A adapter bien sûr à votre appli tomcat.
Ce qui est important c’est :
- Le « Connector Port » qui est le port http sur lequelle écoute le tomcat (identique sur le deuxième serveur tomcat), ici 60001.
- la JVMRoute qui nous servira pour le balancing (ici « guiguiabloc-a » pour le serveur Tomcat-A et « guiguiabloc-b » pour le serveur Tomcat-B).
Le reste est a peu près classique, il est bon de rajouter un « proxyName » qui nous aidera lorsque l’appli est mal codée… (qui a dit, cela arrive souvent ???)
Il faut créer une page des test dans notre webapp, qui servira au redirecteur principal a vérifier que le Tomcat répond correctement :
Exemple de page test.jsp :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ page session="false" %>
<HTML>
<HEAD>
<%
response.setHeader("Pragma","No-cache");
response.setDateHeader("Expires",0);
response.setHeader("Cache-Control","no-cache");
%>
</HEAD>
<BODY>
Cette page est utilisée par le frontal pour tester si Tomcat est lancé
</BODY>
</HTML>
Vérifier que cela fonctionne avec un navigateur :
lynx http://monappli.blog.guiguiabloc.fr:60001/guiguiabloc/test.jsp
- Configuration des frontaux Apache
Pré-requis, compiler les modules proxy (j’utilise la version 2.2.8 d’Apache).
N’oubliez pas de les inclure dans votre httpd.conf :
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
Etc… (modules mod_rewrite, mod_unique_id, mod_setenvif, mod_logio, mod_log* et d’autres sont nécessaire et dépendent de la façon dont vous travaillez avec Apache).
Un petit peaufinage en fin de fichier :
ProxyReceiveBufferSize 65536
# Capacity configuration
ServerLimit 4096
MaxClients 4096
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
Ne reste qu’a configurer vos vhost :
<VirtualHost 192.168.1.1:80> l’ip du web-a
ServerName monappli.blog.guiguiabloc.fr
<Proxy balancer://lbguigui> Un nom unique pour identifier le loadbalancer
BalancerMember http://l’adresse ip du tomcat-a:60001 route=guiguiabloc-a retry=1
connecttimeout=2000 timeout=30 loadfactor=100
BalancerMember http://l’adresse ip du tomcat-b:60001 route=guiguiabloc-b retry=1
connecttimeout=2000 timeout=30 loadfactor=100
</Proxy>
ProxySet balancer://lbguigui stickysession=JSESSIONID|jsessionid nofailover=on
maxattempts=1
Pour des applis PHP, remplacer « JSESSIONID » par « PHPSESSIONID » (si vous gérez les sessions)
On positionne le « nofailover=on » car on ne fait pas de réplication de session
Si vous voulez plus d’informations, je vous invite à consulter le site d’Apache, surtout LA .
Le Proxy via le module Rewrite :
RewriteEngine On
RewriteRule ^(.*)$ $1 [E=request-uri:$1,C]
RewriteRule ^(/.*)$ balancer://lbguigui$1 [P,L]
RewriteRule ^(.*)$ / [R=permanent,L]
PS: Je vous conseille fortement de vous définir votre propre format de log afin de tracer au mieux vos sessions.
Exemple de création de format de Log et de modification des en-têtes :
LogFormat "%h %l %u %t \"%r\" %>s %B \"
%{Referer}i\" \"%{User-Agent}i\" I=%I O=%O %{X-Guiguiabloc-Diag}o
h=web-a r=%{BALANCER_SESSION_ROUTE}e w=%{BALANCER_WORKER_NAME}e D
D=%D C=%X s=%{REDIRECT_STATUS}e
XFF=\"%{X-Forwarded-For}i\"" GuiguiablocLogFormat
CustomLog logs/monappli.blog.guiguiabloc.fr/access.log GuiguiablocLogFormat
ErrorLog logs/monappli.blog.guiguiabloc.fr/error.log
Header set X-Guiguiabloc-Diag "%t %D"
Header set X-Guiguiabloc-Route "h=web-a
r=%{BALANCER_SESSION_ROUTE}e w=%{BALANCER_WORKER_NAME}e"
Header set X-Guiguiabloc-URI "u=%{request-uri}e"
Header append Vary User-Agent
RequestHeader set Host monappli.blog.guiguiabloc.fr
ProxyPreserveHost On
Header set Server "MA FERME H-A"
Header set Cache-Control no-cache="Set-Cookie,Set-Cookie2" env=cacheable-maxage
Header append Cache-Control private env=cacheable-private
Header append Cache-Control max-age=%{cacheable-maxage}e env=cacheable-maxage
Header set Cache-Control no-store env=!cacheable-maxage
Header append Cache-Control no-cache env=!cacheable-maxage
Header unset Set-Cookie env=cacheable-maxage
Header unset Set-Cookie2 env=cacheable-maxage
Header unset ETag
Lire cette partie chez Apache.
- Configuration de la VIP et du load-balancer
J’avais déjà expliquer dans un billet précédent la configuration d’une VIP avec CARP sous OpenBSD, je ne reviendrais donc pas dessus.
La configuration du Load Balancing avec PacketFilter est on ne peut plus simple (comme toujours avec ce bijou
) :
webA = "192.168.1.1"
webB = "192.168.1.2"
rdr on $ext from any to $VIP port 80 -> {$webA $webB}
table <serveursWeb> persist rdr on $ext from any $VIP port 80 -> <serveursWeb>
Ne reste qu’a ajouter nos serveurs Apache dans la table « serveursWeb » :
pfctl -t serveursWeb -T a 192.168.1.1
pfctl -t serveurWeb -T a 192.168.1.2
Afin de vérifier l’état de nos serveurs Web, nous allons utiliser « Hoststated« . (Sa mise en oeuvre est extrèmement simpliste).
Une petite ancre bien placée dans notre pf.conf :
rdr-anchor "hoststated/*"
Puis on renseigne notre fichier /etc/hoststated.conf :
webA="192.168.1.1"
webB="192.168.1.2"
interval 5 # vérifiation toutes les 5 secondes
table serveursWeb {
check http "/test.jsp" code 200
timeout 300
real port 80
host $webA
host $webB
}
service www {
virtual ip $VIP port 80
table serveursWeb
}
Vous pouvez vérifier l’état de vos serveurs Apache en temps réel :
# hoststatectl show Type Id Name Status service 0 www active table 0 serveursWeb active (2 hosts up) host 1 192.168.1.1 down host 0 192.168.1.2 up
Magique non ?
Le schéma du début avec les IP utilisées pour vous aider à comprendre l’architecture :
J’ai bien évidemment survoler toutes les possibilités que vous offre ce type d’architecture. Je laisse votre esprit désormais en ébullition pour peaufiner le travail et vous plonger dans les MAN et fichiers de configuration des différents outils utilisés ici afin de l’adapter à vos besoins.

