1 <?php
declare(strict_types
=1);
4 * This file is part of the Rapsys BlogBundle package.
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Rapsys\BlogBundle\Fixture
;
14 use Doctrine\Bundle\FixturesBundle\Fixture
;
15 use Doctrine\Persistence\ObjectManager
;
17 use Rapsys\PackBundle\Util\SluggerUtil
;
19 use Rapsys\BlogBundle\Entity\Civility
;
20 use Rapsys\BlogBundle\Entity\Group
;
21 use Rapsys\BlogBundle\Entity\User
;
22 use Rapsys\BlogBundle\Entity\UserTranslation
;
23 use Rapsys\BlogBundle\Entity\Keyword
;
24 use Rapsys\BlogBundle\Entity\KeywordTranslation
;
25 use Rapsys\BlogBundle\Entity\Article
;
26 use Rapsys\BlogBundle\Entity\ArticleTranslation
;
31 class BlogFixture
extends Fixture
{
33 * @var Rapsys\PackBundle\Util\SluggerUtil
35 private SluggerUtil
$slugger;
40 public function __construct(SluggerUtil
$slugger) {
42 $this->slugger
= $slugger;
48 public function load(ObjectManager
$manager) {
58 foreach($civilityTree as $civilityData) {
59 $civility = new Civility($civilityData);
60 $manager->persist($civility);
61 $civilitys[$civilityData] = $civility;
66 //XXX: ROLE_XXX is required by
74 foreach($groupTree as $groupData) {
75 $group = new Group($groupData);
76 $manager->persist($group);
77 $groups[$groupData] = $group;
81 //Flush to get the ids
87 'civility' => 'Mister',
89 'mail' => 'blog@rapsys.eu',
91 'forename' => 'Raphaël',
95 'pseudonym' => 'Rapsys',
96 'slug' => $this->slugger
->slug('Raphaël Gertz (rapsys)'),
98 'en_gb' => 'Raphaël Gertz, born in 1984, is a web developper since 2007. Interested in free software, since 2004, when he begin contributing to a linux distribution, known now as Mageia, some path has been traveled since then.',
99 'fr_fr' => 'Raphaël Gertz, né en 1984, est développeur web depuis 2007. Passionné par le monde du logiciel libre, depuis 2004, où il commence à contribuer à une distribution linux, connue maintenant sous le nom Mageia, un certain chemin a été parcouru dès lors.'
106 foreach($userTree as $userData) {
107 $user = new User($userData['mail'], $userData['password'], $civilitys[$userData['civility']], $userData['forename'], $userData['surname'], $userData['active'], $userData['enable'], $userData['pseudonym'], $userData['slug']);
108 $user->addGroup($groups[$userData['group']]);
109 $manager->persist($user);
110 //Flush to get the id
112 $users[$userData['mail']] = $user;
113 foreach($userData['translations'] as $locale => $description) {
114 $userTranslation = new UserTranslation($users[$userData['mail']], $locale, $description);
115 $manager->persist($userTranslation);
116 unset($userTranslation);
121 //Flush to get the ids
129 'description' => 'Portable Network Graphics (PNG) is an raster graphics file open format that supports lossless data compression'
133 'description' => 'Le Portable Network Graphics (PNG) est un format ouvert d’images numériques, qui a été créé pour remplacer le format GIF, à l’époque propriétaire et dont la compression était soumise à un brevet'
138 'title' => 'Imagick',
139 'description' => 'ImageMagick is a free and open-source software suite for displaying, converting, and editing raster image and vector image files'
142 'title' => 'Imagick',
143 'description' => 'Image Magick est une collection de logiciels libres pour afficher, convertir et modifier des images numériques matricielles ou vectorielles dans de nombreux formats'
149 'description' => 'An image is an artifact that depicts visual perception, for example, a photo or a two-dimensional picture, that has a similar appearance to some subject'
153 'description' => 'Une image est une représentation visuelle, voire mentale, de quelque chose'
158 'title' => 'Varnish',
159 'description' => 'Varnish is an HTTP cache server deployed as a reverse proxy between applications servers and clients'
162 'title' => 'Varnish',
163 'description' => 'Varnish est un serveur de cache HTTP déployé en tant que proxy inverse entre les serveurs d\'application et les clients'
168 'title' => 'Web service',
169 'description' => 'A web service is a service offered by an electronic device to another electronic device, communicating with each other via the World Wide Web'
172 'title' => 'Service web',
173 'description' => 'Un service web, ou service de la toile, est un protocole d\'interface informatique de la famille des technologies web permettant la communication et l\'échange de données entre applications et systèmes hétérogènes'
179 'description' => 'Representational state transfer (REST) or RESTful web services are a way of providing interoperability between computer systems on the Internet'
183 'description' => 'Representational state transfer (REST) ou services web RESTful est une manière de fournir de l\'intéropérabilité entre systèmes d\'information sur Internet'
188 'title' => 'HATEOAS',
189 'description' => 'HATEOAS, abbreviation of Hypermedia As The Engine Of Application State, is a constraint of the REST application architecture that distinguishes it from other network application architectures'
192 'title' => 'HATEOAS',
193 'description' => 'HATEOAS, abréviation de Hypermedia As Engine of Application State, Hypermédia en tant que moteur de l\'état d\'application, constitue une contrainte de l\'architecture d\'application REST qui la distingue de la plupart des autres architectures d\'applications réseau'
199 'description' => 'In information technology, a Uniform Resource Identifier (URI) is a string of characters used to identify a resource'
203 'description' => 'En technologie de l\'information, une URI, abréviation d\'Uniform Resource Identifier, Identifiant uniforme de ressource, est une chaine de caractères utilisée pour identifier une ressource'
209 'description' => 'Classless Inter-Domain Routing, CIDR, is a method for aggregating IP addresses and route them'
213 'description' => 'Routage inter-domaine sans classe, de l\'anglais Classless Inter-Domain Routing, CIDR, est une méthode pour agréger des adresses IP et les router'
219 'description' => 'Amazon Elastic Compute Cloud or EC2 is an Amazon server renting service allowing third party to run their own web application'
223 'description' => 'Amazon Elastic Compute Cloud ou EC2 est un service proposé par Amazon permettant à des tiers de louer des serveurs sur lesquels exécuter leurs propres applications web'
229 'description' => 'PHP: Hypertext Preprocessor, better known as PHP, is an open programming language, used mostly to produce dynamic web pages through an HTTP server'
233 'description' => 'PHP : Hypertext Preprocessor, plus connu sous son sigle PHP, est un langage de programmation libre, principalement utilisé pour produire des pages Web dynamiques via un serveur HTTP'
239 'description' => 'MySQL is a free and open-source relational database management system'
243 'description' => 'MySQL est un logiciel libre de gestion de bases de données relationnelles'
249 'description' => 'Microsoft Azure, formerly Windows Azure, is a cloud computing service created by Microsoft for building, testing, deploying, and managing applications and services through a global network of Microsoft-managed data centers'
253 'description' => 'Microsoft Azure, anciennement Windows Azure, est une plateforme applicative en nuage crée par Microsoft pour construire, tester, déployer et gérer des applications et services sur un réseau global de centres de données opéré par Microsoft'
258 'title' => 'Microsoft',
259 'description' => 'Microsoft Corporation is an american multinational technology company, founded in 1975 by Bill Gates and Paul Allen'
262 'title' => 'Microsoft',
263 'description' => 'Microsoft Corporation est une multinationale informatique et micro-informatique américaine, fondée en 1975 par Bill Gates et Paul Allen'
269 'description' => 'Apache is a free and open-source HTTP server for modern operating systems'
273 'description' => 'Apache est un logiciel libre serveur HTTP pour les systèmes d\'exploitation modernes'
278 'title' => 'HAProxy',
279 'description' => 'HAProxy is a reliable high performance TCP/HTTP free and open-source load balancer'
282 'title' => 'HAProxy',
283 'description' => 'HAProxy est un logiciel libre équilibreur de charge TCP/HTTP fiable et haute performance'
289 'description' => 'HTTP, abbreviation of HyperText Transfer Protocol, is a network client-server communications protocol developed for the World Wide Web'
293 'description' => 'HTTP, abréviation de HyperText Transfer Protocol, est un protocole de communication client-serveur réseau développé pour le World Wide Web'
299 'description' => 'Intermediate server application between two hosts to improve privacy, security and performance'
302 'title' => 'Serveur mandataire',
303 'description' => 'Application serveur intermédiaire entre deux hôtes pour améliorer la confidentialité, la sécurité et les performances'
309 'description' => 'QUIC, abbreviation of Quick UDP Internet Connections, is a fast network client-server communications protocol over UDP developed for Google'
313 'description' => 'QUIC, abréviation de Quick UDP Internet Connections, est un protocole de communication client-serveur réseau rapide sur UDP développé pour Google'
319 'description' => 'Mageia is a free operating system community project, based on GNU/Linux, supported by a French 1901 law association made up of elected contributors'
323 'description' => 'Mageia est un projet communautaire de système d\'exploitation libre, basé sur GNU/Linux, soutenu par une association loi 1901 française constituée de contributeurs élus'
329 'description' => 'Google organize the world\'s information and make it universally accessible and useful'
333 'description' => 'Google organise les informations à l\'échelle mondiale pour les rendre accessibles et utiles à tous'
340 foreach($keywordTree as $name => $data) {
341 $keyword = new Keyword();
342 $manager->persist($keyword);
343 //Flush to get the id
345 $keywords[$name] = $keyword;
346 foreach($data as $locale => $translation) {
347 $keywordTranslation = new KeywordTranslation($keywords[$name], $locale, $translation['description'], $this->slugger
->slug($translation['title']), $translation['title']);
348 $manager->persist($keywordTranslation);
349 unset($keywordTranslation);
354 //Flush to get the ids
360 'mail' => 'blog@rapsys.eu',
361 'keywords' => ['image', 'imagick', 'png'],
364 'title' => 'How to reliably detect transparency in PNG image with PHP',
365 'description' => 'Reliable PHP function to detect PNG images with transparency supporting all the variants to process.',
366 'body' => 'The primary need is to find out if a PNG has transparency using PHP.
368 All the code I found didn\'t seemed to work correctly for the collection of PNG I had to convert.
370 I finished using the following function:
372 function png_has_transparency($im) {
373 //Retrieve content from imagick object
374 $content = $im->getImageBlob();
376 //Detect 32-bit png (each pixel has tranparency level)
377 if (ord(substr($content, 25, 1)) & 4) {
379 $p = $im->getPixelIterator();
383 //Loop on each row pixel
384 foreach($r as $pix) {
385 //Check if pixel has partial transparency
386 if ($pix->getColorValue(Imagick::COLOR_ALPHA) != 1) {
391 //Check 8-bit png transparency
392 } elseif (stripos($content, \'PLTE\') !== false || stripos($content, \'tRNS\') !== false) {
396 //Didn\'t found clue of transparency
401 This function works with the only two transparency possibilities: 8 and 32-bit PNG.
403 The first case is a 32-bit PNG with transparency enabled, we have then to check every pixel to detect if it has transparent part or not.
405 The second case is a 8-bit PNG, then we only have to look the file content for transparency markers.
407 In this function configuration, we only read part of the file in 32-bit PNG until we detect one transparent pixel or parse content until transparency marker is detected in 8-bit PNG.
409 The worst case scenario will be 32-bit PNG with transparency flag without transparency or 8-bit PNG without transparency flag.
411 Depending on how likely you are to have transparency in each cases you might want to reverse the flow of this function.
413 Big thanks to these articles which expains how these parts work in a bit more detail:
414 - <https://www.jonefox.com/blog/2011/04/15/how-to-detect-transparency-in-png-images>
415 - <http://camendesign.com/code/uth1_is-png-32bit>
416 - <https://stackoverflow.com/questions/5495275/how-to-check-if-an-image-has-transparency-using-gd>
418 Hope this helps someone else out there.'
421 'title' => 'Comment détecter la tranparence dans des images PNG en PHP de manière fiable',
422 'description' => 'Fonction PHP fiable pour détecter les images PNG avec transparence prenant en charge toutes les variantes à traiter.',
423 'body' => 'Le besoin principal est de savoir si un PNG a de la transparence en utilisant PHP.
425 Les codes trouvés ne semblaient pas fonctionner de manière satisfaisante pour les différents types de PNG à contrôler.
427 J\'ai fini par utiliser la fonction suivante:
429 function png_has_transparency($im) {
430 //Retrieve content from imagick object
431 $content = $im->getImageBlob();
433 //Detect 32bit png (each pixel has tranparency level)
434 if (ord(substr($content, 25, 1)) & 4) {
436 $p = $im->getPixelIterator();
440 //Loop on each row pixel
441 foreach($r as $pix) {
442 //Check if pixel has partial transparency
443 if ($pix->getColorValue(Imagick::COLOR_ALPHA) != 1) {
448 //Check 8bit png transparency
449 } elseif (stripos($content, \'PLTE\') !== false || stripos($content, \'tRNS\') !== false) {
453 //Didn\'t found clue of transparency
458 Cette fonction fonctionne avec les deux seules possibilités : PNG 8 et 32 bits.
460 Le premier cas est un PNG 32 bits avec transparence activée, on doit alors vérifier l\'opacité de chaque pixel savoir si l\'image a de la transparence ou non.
462 Le second cas est un PNG 8 bits, on a simplement à détecter un marqueur de transparence dans le contenu du fichier.
464 Dans cette configuration de fonction, on lit seulement une partie du PNG 32 bits jusqu\'à détection d\'un pixel transparent où on analyse le contenu jusqu\'à trouver un marqueur de transparence dans un PNG 8 bits.
466 Les pires cas seront un PNG 32 bits avec marqueur de transparence sans pixel transparent ou PNG 8 bits sans marqueur de transparence.
468 Selon les probabilités de rencontrer les différents cas de transparence vous pouvez être intéressé pour renverser l\'ordre des tests de cette fonction.
470 Un grand merci à ces articles qui expliquent plus en détail comment fonctionnent les différentes parties de ce code:
471 - <https://www.jonefox.com/blog/2011/04/15/how-to-detect-transparency-in-png-images>
472 - <http://camendesign.com/code/uth1_is-png-32bit>
473 - <https://stackoverflow.com/questions/5495275/how-to-check-if-an-image-has-transparency-using-gd>
475 En espérant que cela puisse aider quelques personnes.'
480 'mail' => 'blog@rapsys.eu',
481 'keywords' => ['hateoas', 'http', 'rest', 'uri', 'varnish', 'webservice'],
484 'title' => 'Caching webservice with Varnish',
485 'description' => 'Cache a webservice responses by ignoring the Authorization header using Varnish.',
486 'body' => 'The primary goal is to find a way to reduce the load of a webservice by caching its responses.
488 The webservice is a RESTfull API serving as a gateway between a private HATEOAS API and a client generating more than 500 000 requests a day.
490 The first surprise is that if your well educated client, sending you a header Authorization: Bearer, will not be cached by default by Varnish !
492 Let\'s force back the standard behaviour with this header for our webservice uri prefix:
496 # Force cache response even with req.http.Authorization set
497 if (req.http.Authorization) {
498 if (req.url ~ "^/webservice/uri/prefix/") {
505 This has security implication, because anyone allowed to request varnish will be able to retrieve a cached result without authentification.
507 It is important to validate the Authorization header value before serving the result from cache.
509 Now, our webservice has three possibles answers :
510 - 200: the data in JSON
511 - 404: data was not found
512 - 410: data is not available anymore
514 Let\'s cache our results depending on the reponse code:
518 if (req.url ~ "^/webservice/uri/prefix/") {
519 if (beresp.status == 404) {
522 if (beresp.status == 410) {
525 if (beresp.status == 200) {
526 set beresp.ttl = 24h;
532 With this configuration, we divided by 5 the quantity of request on our gateway from the client who was not able to cache our result himself.'
535 'title' => 'Mise en cache de webservice avec Varnish',
536 'description' => 'Mettre en cache les réponses d\'un service web en ignorant l’en-tête Authorization à l’aide de Varnish.',
537 'body' => 'Le but premier est de trouver une solution pour réduire la charge d\'un service web en mettant en cache ses réponses.
539 L\'API RESTfull du webservice sert de passerelle entre un API privé HATEOAS et un client générant plus de 500 000 requêtes par jour.
541 La première surprise est qu\'un client bien élevé, envoyant un en-tête Authorization: Bearer, ne sera pas mis en cache par Varnish par défaut !
543 Forçons le fonctionnement standard avec l\'en-tête pour le préfixe de l\'uri de notre webservice:
547 # Force la mise en cache de la réponse même avec req.http.Authorization présent
548 if (req.http.Authorization) {
549 if (req.url ~ "^/webservice/uri/prefix/") {
556 Ce changement a des conséquences sur la sécurité, puisque n\'importe quelle personne autorisée à interroger Varnish sera en mesure de récupérer un résultat en cache sans s\'identifier.
558 Il est important de valider la valeur de l\'en-tête Authorization avant de fournir le résultat depuis le cache.
560 Notre webservice a trois réponses possibles :
561 - 200: les données en JSON
562 - 404: données non trouvées
563 - 410: données plus jamais disponibles
565 Mettons en cache les résultats selon le code de retour :
569 if (req.url ~ "^/webservice/uri/prefix/") {
570 if (beresp.status == 404) {
573 if (beresp.status == 410) {
576 if (beresp.status == 200) {
577 set beresp.ttl = 24h;
583 Avec cette configuration, on a divisé par 5 la quantité de demandes sur notre passerelle pour le client qui n\'était pas en mesure de mettre en cache lui-même nos résultats.'
588 'mail' => 'blog@rapsys.eu',
589 'keywords' => ['amazon', 'azure', 'cidr', 'http', 'microsoft', 'mysql', 'php', 'webservice', 'google'],
592 'title' => 'Dealing with IP range in PHP/MySQL',
593 'description' => 'Secure a webservice by granting access only to remote IP address included in a CIDR blocks set.',
594 'body' => 'The goal is to process some CIDR blocks to tighten a webservice security.
596 First let\'s see how to compute the first and last address of an IP range with just the block base IP and mask:
599 $range = [\'127.0.0.1\', 8];
600 function rangeBegin($range) {
603 function rangeEnd($range) {
604 return long2ip(ip2long($range[0]) | ((1 << (32 - $range[1])) - 1));
608 How to detect if an IP is present in a CIDR block:
612 $range = [\'127.0.0.1\', 8];
613 function ipInRange($ip, $range) {
614 if (ip2long($range[0]) <= ip2long($ip) && ip2long($ip) <= (ip2long($range[0]) | ((1 << (32 - $range[1])) - 1))) {
621 As a first bonus, how to retrieve amazon IP ranges:
624 function fetchAmazonRange() {
628 $ctx = stream_context_create(
631 \'method\' => \'GET\',
632 \'max_redirects\' => 0,
634 \'ignore_errors\' => false,
636 \'Connection: close\',
637 \'Accept: application/json\'
644 if (($json = file_get_contents(\'https://ip-ranges.amazonaws.com/ip-ranges.json\', false, $ctx)) === false) {
649 if (($json = json_decode($json)) === null || empty($json->prefixes)) {
654 foreach($json->prefixes as $range) {
655 //Skip ipv6 and invalid ranges
656 if (empty($range->ip_prefix)||!preg_match(\'/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/([0-9]+)$/\', $range->ip_prefix, $matche
661 array_shift($matches);
663 $amazonRanges[] = $matches;
667 return $amazonRanges;
671 Microsoft Azure IP ranges urls:
672 - <https://www.microsoft.com/en-us/download/details.aspx?id=41653>
673 - <https://msdn.microsoft.com/library/mt757330.aspx>
675 Google IP ranges urls:
676 - <https://support.google.com/a/answer/10026322?hl=en>'
679 'title' => 'Gestion des plages d\'IP en PHP/MySQL',
680 'description' => 'Sécuriser un service web en accordant l\'accès uniquement à l\'adresse IP distante incluse dans un jeu de blocs CIDR.',
681 'body' => 'L\'objectif est de traiter des blocs CIDR pour renforcer la sécurité d’un service web.
683 Premièrement, voyons comment calculer la première et la dernière adresse IP d\'une plage (bloc CIDR) avec sa base et son masque :
686 $range = [\'127.0.0.1\', 8];
687 function rangeBegin($range) {
690 function rangeEnd($range) {
691 return long2ip(ip2long($range[0]) | ((1 << (32 - $range[1])) - 1));
695 Maintenant comment vérifier si une IP est présente dans une plage (bloc CIDR) :
699 $range = [\'127.0.0.1\', 8];
700 function ipInRange($ip, $range) {
701 if (ip2long($range[0]) <= ip2long($ip) && ip2long($ip) <= (ip2long($range[0]) | ((1 << (32 - $range[1])) - 1))) {
708 En premier bonus, comment récupérer les plages d\'IP d\'amazon :
711 function fetchAmazonRange() {
715 $ctx = stream_context_create(
718 \'method\' => \'GET\',
719 \'max_redirects\' => 0,
721 \'ignore_errors\' => false,
723 \'Connection: close\',
724 \'Accept: application/json\'
731 if (($json = file_get_contents(\'https://ip-ranges.amazonaws.com/ip-ranges.json\', false, $ctx)) === false) {
736 if (($json = json_decode($json)) === null || empty($json->prefixes)) {
741 foreach($json->prefixes as $range) {
742 //Skip ipv6 and invalid ranges
743 if (empty($range->ip_prefix)||!preg_match(\'/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/([0-9]+)$/\', $range->ip_prefix, $matche
748 array_shift($matches);
750 $amazonRanges[] = $matches;
754 return $amazonRanges;
758 Urls pour les plages d\'IP de Microsoft Azure :
759 - <https://www.microsoft.com/en-us/download/details.aspx?id=41653>
760 - <https://msdn.microsoft.com/library/mt757330.aspx>
762 Urls pour les plages d\'IP de Google :
763 - <https://support.google.com/a/answer/10026322?hl=en>'
768 'mail' => 'blog@rapsys.eu',
769 'keywords' => ['apache', 'haproxy', 'http', 'mageia', 'proxy', 'quic'],
772 'title' => 'A load balancer to standardize access to heterogeneous web services',
773 'description' => 'Setup a single entry point for various web services including Apache and a few others available on exotic ports.',
774 'body' => 'The primary need is to set up a single entry point for different web services including Apache and a few others on exotic ports.
776 Like any new project, implementation, as usual, took longer than initially expected.
778 To this end, I packaged the HAProxy service in the Mageia Linux distribution with a transparent proxy configuration by default.
780 HAProxy does not support the certificate path layout used on Red Hat-derived distributions, where public and private keys are separated into two separate files in two different directories.
782 HAProxy suffers from a critical bug when using standard output for logging which resumes at the beginning of the file after a restart.
784 HAProxy is penalized by disabling the buffer on its standard output when used for logging.
786 Three fixes were made by me for this purpose to resolve these problems:
787 - support for certificate path layout for Red Hat distribution
788 - no longer starts at the beginning of the log file after a restart
789 - no longer deactivate the standard output buffer
791 New features are being developed for the next version of HAProxy that could make my choices and developments on logging obsolete.
793 To make support of the HTTP/3 protocol possible by HAProxy, it was necessary to integrate the quictls library, a branch of OpenSSL with support for the QUIC protocol.
795 To install the server:
797 # urpmi haproxy haproxy-quic
800 Activate the service:
802 # systemctl enable haproxy.service
807 # systemctl start haproxy.service
810 In order to avoid a waltz of ports when integrating into an existing architecture, port indirection in Shorewall is proposed:
812 # Redirect tcp traffic from net on port 80 to 8000
813 REDIRECT net 8000 tcp 80
814 # Redirect tcp traffic from net on port 443 to 8000
815 REDIRECT net 8000 tcp 443
816 # Redirect udp traffic from net on port 443 to 8443
817 REDIRECT net 8443 udp 443
820 This allows HAProxy to capture HTTP and HTTPS traffic on port 8000/TCP and QUIC on port 8443/UDP.
822 The default configuration captures HTTP and HTTPS traffic on the tcp_default front end, then switches it to the tcp_http and tcp_https back ends, the latter will send the flows to the http_default and https_default front ends, taking care to add a proxy header to transmit the original IP address and port. This configuration allows other TCP services (SSH, VPN, etc.) to be captured and redistributed as needed.
824 The traffic is then received by the http_default and https_default front-ends respectively, the original IP address and port is preserved via the proxy header received from the TCP back-ends.
826 They can advertise HTTP/3 support, clean up some headers, deny access to bots, forward original IP addresses and ports via a Forwarded header, and distribute to different backends based on hosts and requested paths.
828 Configuring Apache to receive the proxy header is problematic, it\'s simpler to pass the Forwarded header than to configure the freshly released mod_remoteip.
830 Support for the HTTP/3 protocol is announced by sending an alt-svc: h3="<host>:<port>"; ma=<timeout> where host can be empty, port=443 and timeout=3600 for example. The certificate served must match the initial host name and not the offload server for security reasons.
832 Configuring the different http backends will come down to declaring the offload servers, the additional headers to add, the compression according to the content types and the method to test their health.
834 Without further ado, the configuration to adapt to your needs:
836 # HAProxy configuration file
841 log stdout format short daemon
845 pidfile /run/haproxy/haproxy.pid
848 stats socket /run/haproxy/haproxy.sock mode 0660 level admin
854 # Certificate base dir
855 crt-base /etc/pki/tls/certs
856 # Private key base dir
857 key-base /etc/pki/tls/private
858 # Don\'t load extra files
859 ssl-load-extra-files none
860 # Disable SSL-v3 TLSv1.0 TLSv1.1 and TLS tickets
861 ssl-default-server-options ssl-min-ver TLSv1.2 no-tls-tickets
862 # Do not verify certificate
863 ssl-server-verify none
864 # Supported bind ciphers
865 #XXX: https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended-configurations
866 ssl-default-bind-ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
868 # SSL/TLS session cache size
869 tune.ssl.cachesize 20000
870 # SSL/TLS session life time in cache
871 tune.ssl.lifetime 300
872 # SSL/TLS layer maximum passed bytes at a time
874 # Diffie-Hellman ephemeral keys max size
875 tune.ssl.default-dh-param 2048
878 # Reserved buffer size
880 # Max number of headers
893 # Set http keep alive mode
894 #XXX: https://cbonte.github.io/haproxy-dconv/2.3/configuration.html#4
895 option http-keep-alive
896 # Dont log empty line
898 # Dissociate client from dead server
901 # Number of retries on connection failure
903 # Max concurrent connections
905 # Max pending connections
908 # Max time for a connection attempt
910 # Max inactivitiy time on client side
912 # Max inactivitiy time on server side
914 # Max inactivitiy time on client and server for tunnels
916 # Max time for new request
917 timeout http-keep-alive 1s
918 # Max time for a complete http request
919 timeout http-request 15s
920 # Max time for a free slot
922 # Duration for tarpitted connections
926 errorfile 400 /usr/share/doc/haproxy/error/400.http
927 errorfile 403 /usr/share/doc/haproxy/error/403.http
928 errorfile 408 /usr/share/doc/haproxy/error/408.http
929 errorfile 500 /usr/share/doc/haproxy/error/500.http
930 errorfile 502 /usr/share/doc/haproxy/error/502.http
931 errorfile 503 /usr/share/doc/haproxy/error/503.http
932 errorfile 504 /usr/share/doc/haproxy/error/504.http
935 # Default tcp frontend
946 tcp-request inspect-delay 5s
947 # Wait for extension detection
948 #tcp-request content accept if { req.proto_http } or { req.ssl_hello_type 1 } or { req.ssl_ec_ext 1 }
949 tcp-request content accept if { req.proto_http } or { req.ssl_hello_type 1 }
951 # Send to https tcp backend
952 use_backend tcp_https if { req.ssl_hello_type 1 }
954 # Send to ec tcp backend
955 #use_backend tcp_ec if { req.ssl_ec_ext 1 }
957 # Send to OpenVPN backend
958 #acl openvpn payload(0,2) -m bin 003c
959 #tcp-request content accept if openvpn
960 #use_backend tcp_openvpn if openvpn
962 # Send to OpenSSH backend
963 #XXX: https://jonnyzzz.com/blog/2017/05/24/ssh-haproxy/
964 #XXX: https://issues.apache.org/jira/browse/SSHD-656
965 #acl ssh payload(0,7) -m str SSH-2.0
966 #tcp-request content accept if ssh
967 #use_backend tcp_ssh if ssh
969 # Send to http tcp backend (if { req.proto_http })
970 default_backend tcp_http
977 # Send to localhost without ssl with v2 proxy header
978 server haproxy 127.0.0.1:8080 no-ssl verify none send-proxy-v2
985 # Send to localhost without ssl with v2 proxy header
986 server haproxy 127.0.0.1:8443 no-ssl verify none send-proxy-v2-ssl
989 # Default http frontend
990 frontend http_default
992 bind :::8080 accept-proxy
993 # Insert X-Forwarded-For header
995 # Set http log format
1000 # Check if acme challenge
1001 acl acme_challenge path_beg /.well-known/acme-challenge/
1003 # Add X-Backend header
1004 #http-response add-header X-Backend %[haproxy.backend_name]
1007 #http-response add-header alt-svc \'h3=":443"; ma=3600\'
1008 #http-after-response add-header alt-svc \'h3=":443"; ma=3600\'
1010 # Remove server and x-powered-by headers
1011 #http-after-response del-header server
1012 #http-after-response del-header x-powered-by
1014 # Redirect to https scheme when unsecure and not acme challenge
1015 http-request redirect scheme https code 302 unless { ssl_fc } || acme_challenge
1017 # Check if denied path
1018 #XXX: use ,url_dec like in https://serverfault.com/questions/754752/block-specific-url-in-haproxy-url-encoding
1019 #acl denied_path path_reg ^/(\.env|login|admin/|wp-login\.php|\.git/config)$
1020 # Deny access on denied path
1021 #http-request deny if denied_path
1023 # Check if protected path
1024 #acl protected_path path_reg ^/(contact|register)$
1025 # Deny access on protected path
1026 #http-request deny deny_status 503 if protected_path { method \'POST\' } { req.ver \'1.0\' }
1028 # Store origin variable as txn
1029 http-request set-var(txn.origin) req.hdr(Origin)
1030 # Store host variable as txn
1031 http-request set-var(txn.host) req.hdr(Host),field(1,:),lower
1032 # Store proto variable as txn
1033 http-request set-var(txn.proto) ssl_fc,iif(https,http)
1035 # Set forwarded proto
1036 http-request set-header X-Forwarded-Proto %[var(txn.proto)]
1037 # Set forwarded port
1038 http-request set-header X-Forwarded-Port %[dst_port]
1040 #http-request set-header X-Forwarded-For %[src]
1042 http-request set-header X-Forwarded-By %[dst]
1045 #http-request set-header Forwarded by=%[dst]:%[dst_port];for=%[src]:%[src_port];host=%[var(txn.host)];proto=%[var(txn.proto)]
1046 http-request set-header Forwarded by=%[dst]:%[dst_port];for=%[src]:%[src_port];proto=%[var(txn.proto)]
1048 # Check if host is cdn.example.com
1049 acl cdn var(txn.host) -m str cdn.example.com
1050 # Check if cdn css path
1051 acl cdn_css path_beg /css
1052 # Check if cdn js path
1053 acl cdn_js path_beg /js
1054 # Check if haproxy status path
1055 acl haproxy_status path_beg /haproxy-status
1056 # Check if debug path
1057 acl debug path_beg /debug
1059 # Send to css backend if path start with /css
1060 use_backend http_css if cdn cdn_css
1061 # Send to js backend if path start with /js
1062 use_backend http_js if cdn cdn_js
1063 # Send to status backend if path start with /haproxy-status
1064 use_backend http_status if haproxy_status
1065 # Send to debug backend if path start with /debug
1066 use_backend http_debug if debug
1068 # Send to https backend
1069 use_backend https_default if { ssl_fc }
1071 # Send to default backend
1072 default_backend http_default
1074 # Default https frontend
1075 #XXX: copy of upper one, just done to skip logs here
1076 frontend https_default
1077 # Bind to 8443 tcp port as ssl
1078 bind :::8443 ssl crt haproxy.pem alpn h2,http/1.1,http/1.0 accept-proxy
1079 # Bind to 8443 udp port as ssl
1080 #bind quic6@:::8443 ssl crt haproxy.pem alpn h3
1081 # Insert X-Forwarded-For header
1083 # Set http log format
1088 # Check if acme challenge
1089 acl acme_challenge path_beg /.well-known/acme-challenge/
1091 # Add X-Backend header
1092 #http-response add-header X-Backend %[haproxy.backend_name]
1095 #http-response add-header alt-svc \'h3=":443"; ma=3600\'
1096 #http-after-response add-header alt-svc \'h3=":443"; ma=3600\'
1098 # Remove server and x-powered-by headers
1099 #http-after-response del-header server
1100 #http-after-response del-header x-powered-by
1102 # Redirect to https scheme when unsecure and not acme challenge
1103 http-request redirect scheme https code 302 unless { ssl_fc } || acme_challenge
1105 # Check if denied path
1106 #XXX: use ,url_dec like in https://serverfault.com/questions/754752/block-specific-url-in-haproxy-url-encoding
1107 #acl denied_path path_reg ^/(\.env|login|admin/|wp-login\.php|\.git/config)$
1108 # Deny access on denied path
1109 #http-request deny if denied_path
1111 # Check if protected path
1112 #acl protected_path path_reg ^/(contact|register)$
1113 # Deny access on protected path
1114 #http-request deny deny_status 503 if protected_path { method \'POST\' } { req.ver \'1.0\' }
1116 # Store origin variable as txn
1117 http-request set-var(txn.origin) req.hdr(Origin)
1118 # Store host variable as txn
1119 http-request set-var(txn.host) req.hdr(Host),field(1,:),lower
1120 # Store proto variable as txn
1121 http-request set-var(txn.proto) ssl_fc,iif(https,http)
1123 # Set forwarded proto
1124 http-request set-header X-Forwarded-Proto %[var(txn.proto)]
1125 # Set forwarded port
1126 http-request set-header X-Forwarded-Port %[dst_port]
1128 #http-request set-header X-Forwarded-For %[src]
1130 http-request set-header X-Forwarded-By %[dst]
1133 #http-request set-header Forwarded by=%[dst]:%[dst_port];for=%[src]:%[src_port];host=%[var(txn.host)];proto=%[var(txn.proto)]
1134 http-request set-header Forwarded by=%[dst]:%[dst_port];for=%[src]:%[src_port];proto=%[var(txn.proto)]
1136 # Check if host is cdn.example.com
1137 acl cdn var(txn.host) -m str cdn.example.com
1138 # Check if cdn css path
1139 acl cdn_css path_beg /css
1140 # Check if cdn js path
1141 acl cdn_js path_beg /js
1142 # Check if haproxy status path
1143 acl haproxy_status path_beg /haproxy-status
1144 # Check if debug path
1145 acl debug path_beg /debug
1147 # Send to css backend if path start with /css
1148 use_backend http_css if cdn cdn_css
1149 # Send to js backend if path start with /js
1150 use_backend http_js if cdn cdn_js
1151 # Send to status backend if path start with /haproxy-status
1152 use_backend http_status if haproxy_status
1153 # Send to debug backend if path start with /debug
1154 use_backend http_debug if debug
1156 # Send to https backend
1157 use_backend https_default if { ssl_fc }
1159 # Send to default backend
1160 default_backend http_default
1163 # Debug http backend
1166 acl trusted src 127.0.0.0/8 ::1
1167 # Allow access from trusted only
1168 http-request deny unless trusted
1169 # Server without ssl or check
1170 server debug 127.0.0.1:8090 no-ssl verify none
1173 # Default http backend
1174 backend http_default
1177 # User server default
1178 http-check connect default
1179 # Send HEAD on / with protocol HTTP/1.1 for host example.com
1180 http-check send meth HEAD uri / ver HTTP/1.1 hdr Host example.com
1181 # Expect return code between 200 and 399
1182 http-check expect status 200-399
1184 # Insert header X-Server: apache
1185 #http-response add-header X-Server apache
1187 # Set compression algorithm
1188 #compression algo gzip
1189 # Enable compression for html, plain and css text types
1190 #compression type text/html text/plain text/css
1192 # Server with ssl and check without certificate verification
1193 server apache 127.0.0.1:80 no-ssl verify none check #cookie apache
1196 # Default https backend
1197 backend https_default
1200 # User server default
1201 http-check connect default
1202 # Send HEAD on / with protocol HTTP/1.1 for host example.com
1203 http-check send meth HEAD uri / ver HTTP/1.1 hdr Host example.com
1204 # Expect return code between 200 and 399
1205 http-check expect status 200-399
1207 # Insert header X-Server: apache
1208 #http-response add-header X-Server apache
1210 # Force HSTS for 5 minutes on domain and all subdomains
1211 #http-response set-header Strict-Transport-Security max-age=300#;\ includeSubDomains#;\ preload
1213 # Set compression algorithm
1214 #compression algo gzip
1215 # Enable compression for html, plain and css text types
1216 #compression type text/html text/plain text/css
1218 # Server with ssl and check without certificate verification
1219 server apache 127.0.0.1:443 ssl verify none check #cookie apache
1226 # User server default
1227 http-check connect default
1228 # Send GET on /css/empty.css with protocol HTTP/1.1 for host cdn.example.com
1229 http-check send meth GET uri /css/empty.css ver HTTP/1.1 hdr Host cdn.example.com
1230 # Expect return code between 200 and 399
1231 http-check expect status 200-399
1233 # Server with check without ssl and certificate verification
1234 server css 127.0.0.1:80 no-ssl verify none check
1241 # User server default
1242 http-check connect default
1243 # Send HEAD on /js/missing.js with protocol HTTP/1.1 for host cdn.example.com
1244 http-check send meth HEAD uri /js/missing.js ver HTTP/1.1 hdr Host cdn.example.com
1245 # Expect return code 404
1246 http-check expect status 404
1248 # Check if txn.origin start with https://cdn.example.com
1249 acl cdn_origin var(txn.origin) -m beg https://cdn.example.com
1250 # Send origin as ACAO
1251 http-response set-header Access-Control-Allow-Origin %[var(txn.origin)] if cdn_origin
1252 # Set ACMA for one day
1253 http-response set-header Access-Control-Max-Age 86400 if cdn_origin
1255 # Server with check without ssl and certificate verification
1256 server js 127.0.0.1:80 no-ssl verify none check
1262 user admin insecure-password ADMINPASSWORD
1264 user operator insecure-password OPERATORPASSWORD
1265 # Assign admin in admin group
1266 group admin users admin
1267 # Assign operator and admin in operator group
1268 group operator users operator,admin
1271 # Status http backend
1274 acl is_operator http_auth(status)
1276 acl is_admin http_auth_group(status) admin
1278 acl trusted src 127.0.0.0/8 ::1
1281 # Set stats hook on /haproxy-status
1282 stats uri /haproxy-status
1289 # Allow access from trusted or authentified operator only
1290 #stats http-request auth unless trusted or is_operator
1291 stats http-request auth unless trusted
1292 # Activate admin interface from trusted or authentified admin only
1293 #stats admin if is_admin
1296 Hope this article was helpful to you.'
1299 'title' => 'Un équilibreur de charge pour standardiser l\'accès aux services web hétérogènes',
1300 'description' => 'Configurer un point d\'entrée unique pour différents services web dont Apache et quelques autres disponibles sur des ports exotiques.',
1301 'body' => 'Le besoin principal est de mettre en place un point d\'entrée unique pour différents services web dont Apache et quelques autres sur des ports exotiques.
1303 Comme tout nouveau projet, la mise en œuvre, comme d\'habitude, a nécessité plus de temps que prévu initialement.
1305 À cet effet, j\'ai réalisé la mise en paquet du service HAProxy dans la distribution linux Mageia avec une configuration de proxy transparent par défaut.
1307 HAProxy ne prend pas en charge la disposition de chemin des certificats utilisée sur les distributions dérivées de Red Hat, où clef publique et privée sont séparées en deux fichiers distincts dans deux répertoires différents.
1309 HAProxy souffre d\'un bug critique lors de l\'usage de la sortie standard pour la journalisation qui reprend en début de fichier après un redémarage.
1311 HAProxy est pénalisé par la désactivation du tampon sur sa sortie standard lorsqu\'elle est utilisée pour la journalisation.
1313 Trois correctifs ont été réalisé par mes soins à cet effet pour résoudre ces problèmes sur le chemin de mes besoins :
1314 - prise en charge de la disposition de chemin des certificats pour distribution Red Hat
1315 - ne recommence plus au début du fichier journal après un redémarage
1316 - ne plus désactiver le tampon de la sortie standard
1318 De nouvelles fonctionnalités sont en cours de développement pour la prochaine version d\'HAProxy qui pourraient rendre obsolètes mes choix et développements sur la journalisation.
1320 Pour rendre possible la prise en charge du protocole HTTP/3 par HAProxy, il a été nécessaire d\'intégrer la librairie quictls, une branche d\'OpenSSL avec support du protocole QUIC.
1322 Pour installer le serveur :
1324 # urpmi haproxy haproxy-quic
1327 Activer le service :
1329 # systemctl enable haproxy.service
1332 Démarrer le service :
1334 # systemctl start haproxy.service
1337 Afin d\'éviter une valse de ports lors de l\'intégration dans une architecture existante, l\'indirection de ports dans Shorewall est proposée :
1339 # Redirect tcp traffic from net on port 80 to 8000
1340 REDIRECT net 8000 tcp 80
1341 # Redirect tcp traffic from net on port 443 to 8000
1342 REDIRECT net 8000 tcp 443
1343 # Redirect udp traffic from net on port 443 to 8443
1344 REDIRECT net 8443 udp 443
1347 Cela permet à HAProxy de capturer le trafic HTTP et HTTPS sur le port 8000/TCP et QUIC sur le port 8443/UDP.
1349 La configuration par défaut capture le trafic HTTP et HTTPS sur le frontal tcp_default, puis le bascule sur les dorsaux tcp_http et tcp_https, ces derniers enverront les flux sur les frontaux http_default et https_default, en prenant soin d\'ajouter un en-tête proxy pour transmettre l\'adresse IP et le port d\'origine. Cette configuration permet à d\'autre services TCP (SSH, VPN, etc) d\'être capturés et redistribués au besoin.
1351 Le trafic est ensuite reçu respectivement par les frontaux http_default et https_default, l\'adresse IP et le port d\'origine est conservée via l\'en-tête proxy reçu des dorsaux TCP.
1353 Ils peuvent annoncer la prise en charge de HTTP/3, nettoyer certains en-têtes, refuser l\'accès aux robots, transférer les adresses IP et ports d\'origine via un en-tête Forwarded et distribuer à différents dorsaux en fonction des hôtes et chemins demandés.
1355 Configurer Apache pour recevoir l\'en-tête proxy est problématique, il est plus simple de transmettre l\'en-tête Forwarded que de configurer le fraîchement publié mod_remoteip.
1357 La prise en charge du protocole HTTP/3 est annoncée par l\'envoi d\'un en-tête alt-svc: h3="<host>:<port>"; ma=<timeout> où host peut être vide, port=443 et timeout=3600 par exemple. Le certificat servi doit correspondre au nom d\'hôte initial et non à celui du serveur de déchargement pour des raisons de sécurité.
1359 Configurer les différents backends http se résumera à déclarer les serveurs de déchargement, les en-têtes supplémentaires à ajouter, la compression selon les types de contenus et la méthode pour tester leur santé.
1361 Sans plus attendre la configuration à adapter à vos besoins :
1363 # HAProxy configuration file
1368 log stdout format short daemon
1372 pidfile /run/haproxy/haproxy.pid
1375 stats socket /run/haproxy/haproxy.sock mode 0660 level admin
1381 # Certificate base dir
1382 crt-base /etc/pki/tls/certs
1383 # Private key base dir
1384 key-base /etc/pki/tls/private
1385 # Don\'t load extra files
1386 ssl-load-extra-files none
1387 # Disable SSL-v3 TLSv1.0 TLSv1.1 and TLS tickets
1388 ssl-default-server-options ssl-min-ver TLSv1.2 no-tls-tickets
1389 # Do not verify certificate
1390 ssl-server-verify none
1391 # Supported bind ciphers
1392 #XXX: https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended-configurations
1393 ssl-default-bind-ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
1395 # SSL/TLS session cache size
1396 tune.ssl.cachesize 20000
1397 # SSL/TLS session life time in cache
1398 tune.ssl.lifetime 300
1399 # SSL/TLS layer maximum passed bytes at a time
1400 tune.ssl.maxrecord 0
1401 # Diffie-Hellman ephemeral keys max size
1402 tune.ssl.default-dh-param 2048
1405 # Reserved buffer size
1406 tune.maxrewrite 1024
1407 # Max number of headers
1408 tune.http.maxhdr 101
1420 # Set http keep alive mode
1421 #XXX: https://cbonte.github.io/haproxy-dconv/2.3/configuration.html#4
1422 option http-keep-alive
1423 # Dont log empty line
1425 # Dissociate client from dead server
1428 # Number of retries on connection failure
1430 # Max concurrent connections
1432 # Max pending connections
1435 # Max time for a connection attempt
1437 # Max inactivitiy time on client side
1439 # Max inactivitiy time on server side
1441 # Max inactivitiy time on client and server for tunnels
1442 timeout tunnel 3600s
1443 # Max time for new request
1444 timeout http-keep-alive 1s
1445 # Max time for a complete http request
1446 timeout http-request 15s
1447 # Max time for a free slot
1449 # Duration for tarpitted connections
1453 errorfile 400 /usr/share/doc/haproxy/error/400.http
1454 errorfile 403 /usr/share/doc/haproxy/error/403.http
1455 errorfile 408 /usr/share/doc/haproxy/error/408.http
1456 errorfile 500 /usr/share/doc/haproxy/error/500.http
1457 errorfile 502 /usr/share/doc/haproxy/error/502.http
1458 errorfile 503 /usr/share/doc/haproxy/error/503.http
1459 errorfile 504 /usr/share/doc/haproxy/error/504.http
1462 # Default tcp frontend
1463 frontend tcp_default
1473 tcp-request inspect-delay 5s
1474 # Wait for extension detection
1475 #tcp-request content accept if { req.proto_http } or { req.ssl_hello_type 1 } or { req.ssl_ec_ext 1 }
1476 tcp-request content accept if { req.proto_http } or { req.ssl_hello_type 1 }
1478 # Send to https tcp backend
1479 use_backend tcp_https if { req.ssl_hello_type 1 }
1481 # Send to ec tcp backend
1482 #use_backend tcp_ec if { req.ssl_ec_ext 1 }
1484 # Send to OpenVPN backend
1485 #acl openvpn payload(0,2) -m bin 003c
1486 #tcp-request content accept if openvpn
1487 #use_backend tcp_openvpn if openvpn
1489 # Send to OpenSSH backend
1490 #XXX: https://jonnyzzz.com/blog/2017/05/24/ssh-haproxy/
1491 #XXX: https://issues.apache.org/jira/browse/SSHD-656
1492 #acl ssh payload(0,7) -m str SSH-2.0
1493 #tcp-request content accept if ssh
1494 #use_backend tcp_ssh if ssh
1496 # Send to http tcp backend (if { req.proto_http })
1497 default_backend tcp_http
1504 # Send to localhost without ssl with v2 proxy header
1505 server haproxy 127.0.0.1:8080 no-ssl verify none send-proxy-v2
1512 # Send to localhost without ssl with v2 proxy header
1513 server haproxy 127.0.0.1:8443 no-ssl verify none send-proxy-v2-ssl
1516 # Default http frontend
1517 frontend http_default
1519 bind :::8080 accept-proxy
1520 # Insert X-Forwarded-For header
1522 # Set http log format
1527 # Check if acme challenge
1528 acl acme_challenge path_beg /.well-known/acme-challenge/
1530 # Add X-Backend header
1531 #http-response add-header X-Backend %[haproxy.backend_name]
1534 #http-response add-header alt-svc \'h3=":443"; ma=3600\'
1535 #http-after-response add-header alt-svc \'h3=":443"; ma=3600\'
1537 # Remove server and x-powered-by headers
1538 #http-after-response del-header server
1539 #http-after-response del-header x-powered-by
1541 # Redirect to https scheme when unsecure and not acme challenge
1542 http-request redirect scheme https code 302 unless { ssl_fc } || acme_challenge
1544 # Check if denied path
1545 #XXX: use ,url_dec like in https://serverfault.com/questions/754752/block-specific-url-in-haproxy-url-encoding
1546 #acl denied_path path_reg ^/(\.env|login|admin/|wp-login\.php|\.git/config)$
1547 # Deny access on denied path
1548 #http-request deny if denied_path
1550 # Check if protected path
1551 #acl protected_path path_reg ^/(contact|register)$
1552 # Deny access on protected path
1553 #http-request deny deny_status 503 if protected_path { method \'POST\' } { req.ver \'1.0\' }
1555 # Store origin variable as txn
1556 http-request set-var(txn.origin) req.hdr(Origin)
1557 # Store host variable as txn
1558 http-request set-var(txn.host) req.hdr(Host),field(1,:),lower
1559 # Store proto variable as txn
1560 http-request set-var(txn.proto) ssl_fc,iif(https,http)
1562 # Set forwarded proto
1563 http-request set-header X-Forwarded-Proto %[var(txn.proto)]
1564 # Set forwarded port
1565 http-request set-header X-Forwarded-Port %[dst_port]
1567 #http-request set-header X-Forwarded-For %[src]
1569 http-request set-header X-Forwarded-By %[dst]
1572 #http-request set-header Forwarded by=%[dst]:%[dst_port];for=%[src]:%[src_port];host=%[var(txn.host)];proto=%[var(txn.proto)]
1573 http-request set-header Forwarded by=%[dst]:%[dst_port];for=%[src]:%[src_port];proto=%[var(txn.proto)]
1575 # Check if host is cdn.example.com
1576 acl cdn var(txn.host) -m str cdn.example.com
1577 # Check if cdn css path
1578 acl cdn_css path_beg /css
1579 # Check if cdn js path
1580 acl cdn_js path_beg /js
1581 # Check if haproxy status path
1582 acl haproxy_status path_beg /haproxy-status
1583 # Check if debug path
1584 acl debug path_beg /debug
1586 # Send to css backend if path start with /css
1587 use_backend http_css if cdn cdn_css
1588 # Send to js backend if path start with /js
1589 use_backend http_js if cdn cdn_js
1590 # Send to status backend if path start with /haproxy-status
1591 use_backend http_status if haproxy_status
1592 # Send to debug backend if path start with /debug
1593 use_backend http_debug if debug
1595 # Send to https backend
1596 use_backend https_default if { ssl_fc }
1598 # Send to default backend
1599 default_backend http_default
1601 # Default https frontend
1602 #XXX: copy of upper one, just done to skip logs here
1603 frontend https_default
1604 # Bind to 8443 tcp port as ssl
1605 bind :::8443 ssl crt haproxy.pem alpn h2,http/1.1,http/1.0 accept-proxy
1606 # Bind to 8443 udp port as ssl
1607 #bind quic6@:::8443 ssl crt haproxy.pem alpn h3
1608 # Insert X-Forwarded-For header
1610 # Set http log format
1615 # Check if acme challenge
1616 acl acme_challenge path_beg /.well-known/acme-challenge/
1618 # Add X-Backend header
1619 #http-response add-header X-Backend %[haproxy.backend_name]
1622 #http-response add-header alt-svc \'h3=":443"; ma=3600\'
1623 #http-after-response add-header alt-svc \'h3=":443"; ma=3600\'
1625 # Remove server and x-powered-by headers
1626 #http-after-response del-header server
1627 #http-after-response del-header x-powered-by
1629 # Redirect to https scheme when unsecure and not acme challenge
1630 http-request redirect scheme https code 302 unless { ssl_fc } || acme_challenge
1632 # Check if denied path
1633 #XXX: use ,url_dec like in https://serverfault.com/questions/754752/block-specific-url-in-haproxy-url-encoding
1634 #acl denied_path path_reg ^/(\.env|login|admin/|wp-login\.php|\.git/config)$
1635 # Deny access on denied path
1636 #http-request deny if denied_path
1638 # Check if protected path
1639 #acl protected_path path_reg ^/(contact|register)$
1640 # Deny access on protected path
1641 #http-request deny deny_status 503 if protected_path { method \'POST\' } { req.ver \'1.0\' }
1643 # Store origin variable as txn
1644 http-request set-var(txn.origin) req.hdr(Origin)
1645 # Store host variable as txn
1646 http-request set-var(txn.host) req.hdr(Host),field(1,:),lower
1647 # Store proto variable as txn
1648 http-request set-var(txn.proto) ssl_fc,iif(https,http)
1650 # Set forwarded proto
1651 http-request set-header X-Forwarded-Proto %[var(txn.proto)]
1652 # Set forwarded port
1653 http-request set-header X-Forwarded-Port %[dst_port]
1655 #http-request set-header X-Forwarded-For %[src]
1657 http-request set-header X-Forwarded-By %[dst]
1660 #http-request set-header Forwarded by=%[dst]:%[dst_port];for=%[src]:%[src_port];host=%[var(txn.host)];proto=%[var(txn.proto)]
1661 http-request set-header Forwarded by=%[dst]:%[dst_port];for=%[src]:%[src_port];proto=%[var(txn.proto)]
1663 # Check if host is cdn.example.com
1664 acl cdn var(txn.host) -m str cdn.example.com
1665 # Check if cdn css path
1666 acl cdn_css path_beg /css
1667 # Check if cdn js path
1668 acl cdn_js path_beg /js
1669 # Check if haproxy status path
1670 acl haproxy_status path_beg /haproxy-status
1671 # Check if debug path
1672 acl debug path_beg /debug
1674 # Send to css backend if path start with /css
1675 use_backend http_css if cdn cdn_css
1676 # Send to js backend if path start with /js
1677 use_backend http_js if cdn cdn_js
1678 # Send to status backend if path start with /haproxy-status
1679 use_backend http_status if haproxy_status
1680 # Send to debug backend if path start with /debug
1681 use_backend http_debug if debug
1683 # Send to https backend
1684 use_backend https_default if { ssl_fc }
1686 # Send to default backend
1687 default_backend http_default
1690 # Debug http backend
1693 acl trusted src 127.0.0.0/8 ::1
1694 # Allow access from trusted only
1695 http-request deny unless trusted
1696 # Server without ssl or check
1697 server debug 127.0.0.1:8090 no-ssl verify none
1700 # Default http backend
1701 backend http_default
1704 # User server default
1705 http-check connect default
1706 # Send HEAD on / with protocol HTTP/1.1 for host example.com
1707 http-check send meth HEAD uri / ver HTTP/1.1 hdr Host example.com
1708 # Expect return code between 200 and 399
1709 http-check expect status 200-399
1711 # Insert header X-Server: apache
1712 #http-response add-header X-Server apache
1714 # Set compression algorithm
1715 #compression algo gzip
1716 # Enable compression for html, plain and css text types
1717 #compression type text/html text/plain text/css
1719 # Server with ssl and check without certificate verification
1720 server apache 127.0.0.1:80 no-ssl verify none check #cookie apache
1723 # Default https backend
1724 backend https_default
1727 # User server default
1728 http-check connect default
1729 # Send HEAD on / with protocol HTTP/1.1 for host example.com
1730 http-check send meth HEAD uri / ver HTTP/1.1 hdr Host example.com
1731 # Expect return code between 200 and 399
1732 http-check expect status 200-399
1734 # Insert header X-Server: apache
1735 #http-response add-header X-Server apache
1737 # Force HSTS for 5 minutes on domain and all subdomains
1738 #http-response set-header Strict-Transport-Security max-age=300#;\ includeSubDomains#;\ preload
1740 # Set compression algorithm
1741 #compression algo gzip
1742 # Enable compression for html, plain and css text types
1743 #compression type text/html text/plain text/css
1745 # Server with ssl and check without certificate verification
1746 server apache 127.0.0.1:443 ssl verify none check #cookie apache
1753 # User server default
1754 http-check connect default
1755 # Send GET on /css/empty.css with protocol HTTP/1.1 for host cdn.example.com
1756 http-check send meth GET uri /css/empty.css ver HTTP/1.1 hdr Host cdn.example.com
1757 # Expect return code between 200 and 399
1758 http-check expect status 200-399
1760 # Server with check without ssl and certificate verification
1761 server css 127.0.0.1:80 no-ssl verify none check
1768 # User server default
1769 http-check connect default
1770 # Send HEAD on /js/missing.js with protocol HTTP/1.1 for host cdn.example.com
1771 http-check send meth HEAD uri /js/missing.js ver HTTP/1.1 hdr Host cdn.example.com
1772 # Expect return code 404
1773 http-check expect status 404
1775 # Check if txn.origin start with https://cdn.example.com
1776 acl cdn_origin var(txn.origin) -m beg https://cdn.example.com
1777 # Send origin as ACAO
1778 http-response set-header Access-Control-Allow-Origin %[var(txn.origin)] if cdn_origin
1779 # Set ACMA for one day
1780 http-response set-header Access-Control-Max-Age 86400 if cdn_origin
1782 # Server with check without ssl and certificate verification
1783 server js 127.0.0.1:80 no-ssl verify none check
1789 user admin insecure-password ADMINPASSWORD
1791 user operator insecure-password OPERATORPASSWORD
1792 # Assign admin in admin group
1793 group admin users admin
1794 # Assign operator and admin in operator group
1795 group operator users operator,admin
1798 # Status http backend
1801 acl is_operator http_auth(status)
1803 acl is_admin http_auth_group(status) admin
1805 acl trusted src 127.0.0.0/8 ::1
1808 # Set stats hook on /haproxy-status
1809 stats uri /haproxy-status
1816 # Allow access from trusted or authentified operator only
1817 #stats http-request auth unless trusted or is_operator
1818 stats http-request auth unless trusted
1819 # Activate admin interface from trusted or authentified admin only
1820 #stats admin if is_admin
1823 Espérons que cet article vous a été utile.'
1830 foreach($articleTree as $i => $data) {
1831 $article = new Article($users[$data['mail']]);
1832 foreach($data['keywords'] as $keyword) {
1833 $article->addKeyword($keywords[$keyword]);
1835 $manager->persist($article);
1836 //Flush to get the id
1838 $articles[$i] = $article;
1839 foreach($data['translations'] as $locale => $translation) {
1840 $articleTranslation = new ArticleTranslation($articles[$i], $locale, $translation['body'], $translation['description'], $this->slugger
->slug($translation['title']), $translation['title']);
1841 $manager->persist($articleTranslation);
1846 //Flush to get the ids