# Création d'un serveur web sur FreeBSD avec des jails

description : Article sur comment créer un serveur web (nginx, php, sql) sur FreeBSD en utilisant des jails
categories : Sysadmin;
tags : Freebsd; Bsd;

création d'un serveur web sur FreeBSD en utilisant des jails

Dans cet article je vais détailler comment créer un serveur web comprenant nginx, php et mariadb. Pour plus de sécurité je vais utiliser des prisons, une pour emprisonner php et nginx, une autre pour mariadb.

création du réseau pour les jails

Pour plus de sécurité, je crée un réseau spécial pour les jails avec 2 IPv4 : 192.168.1.101 pour webjail et 192.168.1.102 pour sqljail :

1
2
3
doas sysrc cloned_interfaces="lo1"
doas sysrc ipv4_addrs_lo1="192.168.1.101-102/31"
doas service netif restart

le firewall

Je vais utiliser PF avec ces règles écrites dans /etc/pf.conf :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
tcp_services_in = "{ ssh, http, https }" # mes services TCP en entrée
tcp_services_out = "{ http, https }" # mes services TCP en sortie

udp_services_out = "{ domain }" # mes services UDP en sortie

table <bruteforce> persist # la table contenant les floodeurs / bruteforceurs bloqués

# pas de restrictions sur lo0
set skip on lo0

# normalisation des paquets
scrub in all
scrub in all fragment reassemble no-df max-mss 1440

nat on em0 from lo1:network to any -> (em0) # nat pour les jails

rdr on em0 proto tcp from any to any port http -> 192.168.1.101 port http # redirection http sur webjail
rdr on em0 proto tcp from any to any port https -> 192.168.1.101 port https # redirection https sur webjail

# anti spoofing
antispoof for { em0, lo1 }

block in all # bloque tout en entrée par défaut
block out all # bloque tout en sortie par défaut

# bloque les floodeurs bruteforceurs / qui sont dans la table bruteforce
block quick from <bruteforce>

# accepte en sortie tcp_services_out et enregistre l'état
pass out quick on em0 proto tcp from em0:network to any port $tcp_services_out flags S/SA keep state

# accepte en sortie udp_services_out et enregistre l'état
pass out quick on em0 proto udp from em0:network to any port $udp_services_out keep state

# accepte en entrée tcp_services_in ou bloque les floodeurs / bruteforceurs
pass in quick on em0 proto tcp from any to em0:network port $tcp_services_in flags S/SA synproxy state \
    (max-src-conn 100, max-src-conn-rate 15/5, overload <bruteforce> flush global)

pass out quick on lo1 proto tcp from lo1:network to any port mysql keep state
pass in quick on lo1 proto tcp from any to lo1:network port mysql flags S/SA synproxy state

# accepte tout ICMP en entrée et en sortie
pass inet proto icmp from em0:network to any keep state
pass inet proto icmp from any to em0 keep state
1
doas sysrc pf_enable="YES" && doas sysrc pflog_enable="YES"

Je reboot pour appliquer ces règles :

1
doas reboot

création des prisons

Pour créer les prisons je vais utiliser l'outil ezjail :

1
doas pkg install ezjail

ezjail utilise le protocol FTP par défaut. Le protocole FTP est relou à protéger avec un firewall. Je paramètre donc ezjail pour qu'il utilise le protocole HTTPS à la place et ainsi me faciliter la vie :

1
doas nano /usr/local/etc/ezjail.conf

Je modidie la variable ezjail_ftphost pour avoir :

1
ezjail_ftphost=https://ftp.freebsd.org

Pour séparer le réseau du serveur web avec le reste je vais créer une nouvelle interface et je lui donne 2 ipv4 :

Je démarre ezjail et précise qu'il doit démarrer au boot :

1
2
doas sysrc ezjail_enable="YES"
doas service ezjail start

J'installe l'environnement ezjail, la "basejail" :

1
doas ezjail-admin install

prison pour nginx et php

Je crée la prison qui va accueillir les services nginx et php, cette jail a comme IP 192.168.1.101 :

1
doas ezjail-admin create webjail 'lo1|192.168.1.101'

Pour pouvoir communiquer sur internet depuis la prison webjail je copie le fichier resolv.conf de l'hôte dans la prison :

1
doas cp /etc/resolv.conf /usr/jails/webjail/etc/

Je démarre webjail :

1
doas ezjail-admin start webjail

prison pour mariadb

Je crée la prison qui va accueillir le service mariadb, cette jail a comme IP 192.168.1.102 :

1
doas ezjail-admin create sqljail 'lo1|192.168.1.102'

Pour pouvoir communiquer sur internet depuis la prison sqljail je copie le fichier resolv.conf de l'hôte dans la prison :

1
doas cp /etc/resolv.conf /usr/jails/sqljail/etc/

Je démarre sqljail :

1
doas ezjail-admin start sqljail

installation de nginx && php dans webjail

Je me connece à la console de webjail :

1
doas ezjail-admin console webjail

J'installe la dernière version des services nginx et php :

1
pkg install nginx php83 php83-mysqli mariadb106-client

Je démarre nginx et le fait démarrer au boot :

1
2
sysrc nginx_enable="YES"
service nginx start

installation de mariadb dans sqljail

Je me connece à la console de sqljail depuis l'hôte :

1
doas ezjail-admin console sqljail

J'installe la dernière version du service sql mariadb :

1
pkg install mariadb106-server

Je démarre mariadb et le fait démarrer au boot :

1
2
sysrc mysql_enable=YES
service mysql-server start

Je run le script d'installation :

1
mysql_secure_installation

Pour pouvoir tester la connexion, je crée une base de données avec son user :

1
mysql -u root -p
1
2
3
4
CREATE DATABASE testdb;
GRANT ALL ON testdb.* TO test@'%' IDENTIFIED BY 'testpass';
FLUSH PRIVILEGES;
EXIT;

test des services

Pour commencer je reboot le serveur :

1
doas reboot

Ensuite, depuis un navigateur internet, je me connecte sur le serveur qui chez moi a pour IPv4 : 192.168.1.32

Après, pour tester le service sql, je me connecte à la console de webjail :

1
doas ezjail-admin console webjail

Et depuis webjail je me connecte au service sql sur sqljail :

1
mysql -u test -h 192.168.1.102 -p

Pour finir, je test le firewall. Depuis mon poste de travail j'utilise nmap pour tester la config du firewall sur le serveur :

1
nmap -p- 192.168.1.32

w00t !