/ OpenBSD

Déploiement d'un serveur httpd(8) sous OpenBSD 6.0 avec PHP/MYSQL/SSL et sécurisation via PacketFilter

This article is available in english here


Depuis la version 5.7, OpenBSD intègre sa propre solution de serveur http nommée httpd(8). Cette version est actuellement assez mature afin d’héberger de façon pérenne ses applications Web.

Nous détaillerons ici la mise en place des briques logicielles courantes associées à un serveur http ainsi que leur sécurisation.

Configuration basique et lancement d’httpd(8) :

On commence par créer le fichier de configuration :

# touch /etc/httpd.conf

On édite le fichier afin d’y intégrer notre configuration de base :

# vi /etc/httpd.conf

Voici la configuration de base que nous allons détailler. J’ai mis en place des variables assez explicites afin de comprendre l’étendue des possibilités en terme de configuration.

domaine_de_lina="lina.cagedmonster.net" 
bind_adress="egress" 

server "domaine_de_lina" { 
                          listen on $bind_adress port 80 
                          }

Dans le cas présent, egress correspond tout simplement au groupe des interfaces réseau gérant les routes par défaut. N’ayant pas spécifié d’emplacement dédié aux pages à servir, l’emplacement par défaut est situé dans : /var/www/htdocs/

On crée une page de test rapide :

# echo "Page de test" > /var/www/htdocs/index.html

On teste notre configuration :

# httpd -n configuration OK

On active httpd au lancement du serveur :

# rcctl enable httpd

On lance httpd et on va consulter sa page http://IP/ ou http://URL/

# rcctl start httpd

Installation et configuration d’un environnement PHP et MySQL associés à httpd :

Nous allons passer par le système de packages d’OpenBSD, vérifiez que les informations contenues dans /etc/pkg.conf soient exactes.

# pkg_add php-mysql mariadb-server
# ln -sf /etc/php-5.6.sample/mysql.ini /etc/php-5.6/mysql.ini

On active le service PHP au démarrage :

# rcctl enable php56_fpm

On lance le service PHP :

# rcctl start php56_fpm 
php56_fpm(ok)

Configuration de MySQL :

# /usr/local/bin/mysql_install_db

Activation de MySQL au démarrage :

# rcctl enable mysqld

Lancement de MySQL :

# rcctl start mysqld

Fin de la configuration de MySQL :

# /usr/local/bin/mysql_secure_installation 

Enter current password for root (enter for none): [ENTRER] 
Set root password? [Y/n] Y 
New password: PASS 
Re-enter new password: PASS 
Remove anonymous users? [Y/n] Y 
Disallow root login remotely? [Y/n] Y 
Remove test database and access to it? [Y/n] Y 
Reload privilege tables now? [Y/n] Y

Il est temps de configurer httpd afin d’y intégrer la gestion de PHP :

domaine_de_lina="lina.cagedmonster.net" 
bind_adress="egress" 
server "domaine_de_lina" { 
                         listen on $bind_adress port 80 
                         directory {index "index.php" } 
                         location "/*.php" { fastcgi socket "/run/php-fpm.sock" }
                         }

On teste notre configuration :

# httpd -n 
configuration OK

On crée notre page PHP de test :

# echo "<?php phpinfo(); ?>" > /var/www/htdocs/index.php

On relance httpd et on teste à l’emplacement http://IP/ ou http://URL/

# rcctl restart httpd

Vous devriez obtenir quelque chose d’équivalent :

PHP

Il est temps à présent de mettre en place du SSL :

Il y deux méthodes visant à obtenir un certificat SSL.

  1. Auto-générer son certificat (qui ne sera pas validé par une autorité reconnue).
  2. Passer par une autorité telle que LetsEncrypt utilisant Certbot pour générer votre certificat. Auquel cas je vous laisserai le soin de consulter cette page.

Nous allons nous concentrer sur la première.

Génération du certificat :

# openssl genrsa -out /etc/ssl/private/server.key 
Generating RSA private key, 2048 bit long modulus ...............................................................+++ ..........+++ e is 65537 (0x10001) 

# openssl req -new -x509 -key /etc/ssl/private/server.key -out /etc/ssl/server.crt -days 3650 
You are about to be asked to enter information that will be incorporated into your certificate request. 
What you are about to enter is what is called a Distinguished Name or a DN. 
There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. 
----- 
Country Name (2 letter code) []:FR 
State or Province Name (full name) []:SomeWhere 
Locality Name (eg, city) []:Deauville 
Organization Name (eg, company) []:CagedMonster 
Organizational Unit Name (eg, section) []:CGM 
Common Name (eg, fully qualified host name) []:lina.cagedmonster.net 
Email Address []:lina@cagedmonster.net

Modification de la configuration de notre httpd :

domaine_de_lina="lina.cagedmonster.net" 
bind_adress="egress" 

server "domaine_de_lina" { 
                          listen on $bind_adress port 80 
                          listen on $bind_adress tls port 443 
                          directory {index "index.php" } 
                          location "/*.php" { fastcgi socket "/run/php-fpm.sock" } 
                          tls { certificate "/etc/ssl/server.crt" key "/etc/ssl/private/server.key" }
                          }

Comme à l’accoutumée, vérification de la configuration, restart du serveur et consultation à l’adresse **https://**IP/ ou **https://**URL/ :

# httpd -n 
configuration OK 
# rcctl restart httpd 
httpd(ok)

A présent, nous allons configurer httpd afin que toutes les requêtes http soient redirigées en https automatiquement. Voici la configuration associée :

domaine_de_lina="lina.cagedmonster.net" 
bind_adress="egress" 

server $domaine_de_lina { 
                         listen on $bind_adress port 80 block return 301 "https://$SERVER_NAME$REQUEST_URI" 
                         } 

server "domaine_de_lina" { 
                         listen on $bind_adress tls port 443 directory {index "index.php" } 
                         location "/*.php" { fastcgi socket "/run/php-fpm.sock" } 
                         tls { certificate "/etc/ssl/server.crt" key "/etc/ssl/private/server.key" } 
                         }

Même procédure, on teste notre configuration, on relance et cette fois ci nous allons visiter notre adresse en http://IP/ ou http://URL/ afin de tester si la redirection est effectuée automatiquement.

# httpd -n && rcctl restart httpd 
configuration OK 
httpd(ok)

Nous avons à présent un service httpd configuré avec PHP / MySQL / SSL et redirigeant les requêtes http:// vers https://

Dernier point, la sécurisation de votre service httpd avec Packet Filter (pf) :

Dans le cas où vous aimeriez mettre en ligne un CMS (WordPress, Drupal, etc.), il est fort probable que vous subissiez des tentatives de bruteforce sur le système de Login ce qui en plus de remplir vos logs risque de consommer des ressources serveur inutiles.

Voici une configuration adaptée comprenant un maximum de connexions de 100 et un nombre de requêtes maximum de 30 requêtes toutes les 15 secondes :

# vi /etc/pf.conf

pass quick proto tcp from any to any port 80 \ 
flags S/SA keep state \ 
(max-src-conn 100, max-src-conn-rate 30/15, \ 
verload <bruteforce> flush global) 

pass quick proto tcp from any to any port 443 \ 
flags S/SA keep state \ 
(max-src-conn 100, max-src-conn-rate 30/15, \ 
overload <bruteforce> flush global)

Reste à recharger la configuration :

# pfctl -f /etc/pf.conf

Il vous est également possible de consulter les adresses bannies :

# pfctl -t bruteforce -T show

Pour supprimer une adresse :

# pfctl -t bruteforce -T delete <IP>

Pour que les adresses bannies expirent au bout d’un temps donné (une heure dans ce cas précis) :

# pfctl -t bruteforce -T expire 3600

Besoin d’aide ?

CagedMonster

CagedMonster

« I know everyone I've been everywhere I know everything Because I'm everybody » Ether - Nothingface

Read More