VirtualisationService » Historique » Version 12
Version 11 (Raphaël Durand, 25/09/2013 13:33) → Version 12/39 (yannick deroche, 25/09/2013 15:55)
{{>toc}}
h1. VirtualisationService
h2. Objet
Dans l'environnement tetaneutral.net un adhérent a le choix d'utiliser plusieurs IPv4 publiques et un bridge avec son interface pour virtualiser mais ceci consomme plusieurs IPv4 publiques.
Une alternative est de n'utiliser qu'une IPv4 publique et de creer des VMs sur un bridge interne (qui n'a pas l'interface de sortie comme port) avec des IPv4 privées et de se servir de l'hote pour router les requetes de service suivant les ports. Par exemple
- tcp/2222 => ssh host
- tcp/2223 => ssh VM1
- tcp/2224 => ssh VM2
- tcp/2225 => ssh VM3
- tcp/80 => reverse proxy (nginx, apache, varnish, ...) sur host pour redispatch par domaine sur VM1+VM2
- tcp/443 => idem (ouais mais faut gérer le SSL alors !?)
- udp/1194 => serveur openvpn sur VM3
En IPv6 il n'y a pas de probleme car l'adhérent a un /56 donc pas de limite aux IPs de service, il suffit de demander l'activation du routage IPv6 coté tetaneutral.net
h2. Solutions
Solarus : - Pour mutualiser une IPv4 sur HTTP on peut mettre en place un proxy nginx. J'en ai déjà un en place sur mon serveur. Je peux le prêter ou en faire un tuto pour en monter un.
- Pour le reste des flux, je conseille de monter un NAT/PAT et configurer les redirections de port entrants. On peut faire ça avec IPtables sous Linux ou BSD. On peut utiliser une machine virtuelle ou un OpenWRT si on veut le faire sur une machine séparée.
Fab :
- En cas de reverse proxy HTTP, faut gérer le SSL pour le HTTPS...galère, galère
- On peut déjà migrer tous les services internes à TTNN sur des IP RFC 1918, quitte à superviser les VM/machines via un rebond SSH (possible dans cmk) ou qu'en IPv6 (possible aussi)
- Pour tout ce qui est serveur de mail, on peut proposer un (ou même plusieurs) MTA qui accepte tous les domaines des MTA hébergés sur les VMs et qui redispatche (une sorte de reverse proxy mail, en fait) (remarque de Solarus : Attention à la mutualisation des MTA sur un proxy SMTP, notamment la gestion des spams entrants et sortants et le risque de blacklistage des adresses)
- Pour certaines VMs/machines qui n'hébergent pas de services ouverts ont peut sensibiliser les adhérents à l'IPv6 only (c'est ce que je fait sur ma VM)
Yannick:
* utilisation d'un firewall logiciel en VM (pfSense, IPcop, Zentyal ...) qui porte l'adresse IP publique et avec utilisation de règle de NAT/PAT (translation d'adresse et de port)
+ simple d'utilisation, interface graphique disponible pour les allergiques de la CLI
+ Existe en "virtual appliance" pré-packagés pour les environnement virtuels
+ il esxiste même des version virtualisées de Firewall physique de grands constructeurs (Fortinet, Juniper...)
* utilisation d'un reverse proxy pour porter l'@IP publique et rediriger le trafic en fonction du protocole et ce qui est appelé.
+- la conf est un peu plus complexe mais au moins tu peux tout maitriser de la couche 3 Ã la couche 7 (www.exemple.com/toto --> vers le serveur_1:80 ; www.exemple.com/tata --> serveur_2:80 ...)
- par contre, pas de fonction firewall avancée
+ il en existe pas mal: Apache avec module RP, NGINX avec module RP, F5 BigIP VE (version limité à 90j) ...
--> mon conseil: un pfSense en machine virtuelle qui porte l'@IP publique (en cas de plusieurs services HTTP à écouter sur le port 80 -> reverse-proxy NGINX)
h2. Liens
TODO
h2. Configuration d'un reverse proxy nginx
Ci-dessous voici une conf typique pour mettre en place un reverse-proxy nginx afin de partager une IP publique pour plusieurs serveurs.
Le systeme fonctionne par Virtual Host (comme sous Apache)
Pour chaque Virtual Host, il faut créer un fichier de ce type dans /etc/nginx/sites-enabled
<pre>
server {
listen 80;
server_name *.exemple.tld;
location / {
proxy_pass http://10.255.254.1;
}
}
server {
listen 443;
server_name *.exemple.tld;
ssl on;
ssl_certificate certificat_ssl.crt;
ssl_certificate_key certificat_ssl.crt;
location / {
proxy_pass https://10.255.254.1;
}
}
</pre>
Les champs à remplir sont 'server_name' avec le domaine du virtual host et 'proxy_pass' avec l'IP privée du serveur.
Le deuxième bloc servira uniquement si vous voulez faire du HTTPS, il vous restera alors à renseigner les emplacements des certificats.
Cette méthode présente un inconvénient c'est que l'IP des visiteurs n'est pas directement visible,ce qui peut être gênant pour les blogs et les système de commentaires.
h2. Redirection de port(s) via iptables.
Cette solution est loin d'être la panacée. Elle permet de multiplexer un service d'une @IP publique vers n @IP privées.
Voici un exemple de règles pour ouvrir l'accès SSH sur le port 22 d'une centaine de VMs adressées de 172.16.0.1 à 172.16.0.100 à partir d'une @IP publique unique.
h3. 1/ Régles à copier dans la section de la table NAT
<pre>for ((i = 1; i <= 100; i++)); do
echo "-A PREROUTING -i [Nom-interface-réseau-public] -d [@IP-publique] -p tcp --dport $((2200 + $i)) -j DNAT --to-destination 172.16.0.$i:22";
done >> /etc/iptables/rules-to-add</pre>
h3. 2/ Régle à copier dans la section de la table netfilter
<pre>-A FORWARD -i [Nom-interface-réseau-public] -m iprange --dst-range 172.16.0.1-172.16.0.100 -p tcp --syn --dport 22 -m conntrack --ctstate NEW -j ACCEPT</pre>
h3. 3/ Fichier de règles «résumé» utilisable avec le paquet Debian iptables-persistent
<pre>#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# NAT
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# P O S T R O U T I N G
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-A POSTROUTING -o [Nom-interface-réseau-public] -p tcp --syn -m tcpmss --mss 1400:1536 -j TCPMSS --clamp-mss-to-pmtu
-A POSTROUTING -o [Nom-interface-réseau-public] -m iprange --src-range 172.16.0.1-172.16.0.100 -j SNAT --to-source [@IP-publique]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# P R E R O U T I N G
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-A PREROUTING -i [Nom-interface-réseau-public] -d [@IP-publique] -p tcp --dport 2201 -j DNAT --to-destination 172.16.0.1:22
-A PREROUTING -i [Nom-interface-réseau-public] -d [@IP-publique] -p tcp --dport 2202 -j DNAT --to-destination 172.16.0.2:22
<snip/>
#
COMMIT
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# N e t f i l t e r
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# I N P U T
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Suivi de communication chaîne INPUT
-A INPUT -p icmp -m conntrack --ctstate ESTABLISHED -j ACCEPT
-A INPUT -p icmp --icmp-type destination-unreachable -m conntrack --ctstate RELATED -j ACCEPT
-A INPUT -p icmp --icmp-type time-exceeded -m conntrack --ctstate RELATED -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp ! --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT
-A INPUT -p tcp --syn -m conntrack --ctstate RELATED -j ACCEPT
# Boucle locale
-A INPUT -i lo -j ACCEPT
# ICMP
-A INPUT -i bond+ -p icmp --icmp-type echo-request -m limit --limit 5/sec -m conntrack --ctstate NEW -j ACCEPT
# SSH
-A INPUT -m recent --update --seconds 60 --hitcount 4 --name SSH -m limit --limit 5/min -j LOG --log-prefix "SSH_brute_force "
-A INPUT -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP
-A INPUT -i [Nom-interface-réseau-public] -p tcp --dport 22 --syn -m recent --set --name SSH -j ACCEPT
# POUBELLE
-A INPUT -m conntrack --ctstate INVALID -m limit --limit 1/min -j LOG --log-prefix "INPUT/rejected.iptables: "
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p tcp -j REJECT --reject-with tcp-reset -m limit --limit 5/s
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable -m limit --limit 5/s
-A INPUT -m limit --limit 1/min -j LOG --log-prefix "INPUT/poubelle: "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# F O R W A R D
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Suivi de communication chaîne FORWARD
-A FORWARD -p icmp -m conntrack --ctstate ESTABLISHED -j ACCEPT
-A FORWARD -p icmp -m conntrack --ctstate RELATED --icmp-type destination-unreachable -j ACCEPT
-A FORWARD -p icmp -m conntrack --ctstate RELATED --icmp-type time-exceeded -j ACCEPT
-A FORWARD -p udp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -p tcp -m conntrack --ctstate ESTABLISHED ! --syn -j ACCEPT
-A FORWARD -p tcp -m conntrack --ctstate RELATED --syn -j ACCEPT
# Boucle locale
-A FORWARD -i lo -j ACCEPT
# Accès SSH VMs
-A FORWARD -i [Nom-interface-réseau-public] -m iprange --dst-range 172.16.0.1-172.16.0.100 -p tcp --syn --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# Poubelle
-A FORWARD -m conntrack --ctstate INVALID -m limit --limit 5/min -j LOG --log-prefix "FORWARD/rejected: "
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -p tcp -m limit --limit 5/min -j LOG --log-prefix "FORWARD/TCP.rejected: "
-A FORWARD -p tcp -m limit --limit 5/sec -j REJECT --reject-with tcp-reset
-A FORWARD -p tcp -m limit --limit 5/min -j LOG --log-prefix "FORWARD/UDP.rejected: "
-A FORWARD -p udp -m limit --limit 5/sec -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -m limit --limit 5/min -j LOG --log-prefix "FORWARD/poubelle: "
#
COMMIT</pre>
h2. Documentation
TODO
nginx
apache
varnish
iptables
shorewall
netcat
h2. Bénévoles
TODO toulibre ou capitole du libre
h1. VirtualisationService
h2. Objet
Dans l'environnement tetaneutral.net un adhérent a le choix d'utiliser plusieurs IPv4 publiques et un bridge avec son interface pour virtualiser mais ceci consomme plusieurs IPv4 publiques.
Une alternative est de n'utiliser qu'une IPv4 publique et de creer des VMs sur un bridge interne (qui n'a pas l'interface de sortie comme port) avec des IPv4 privées et de se servir de l'hote pour router les requetes de service suivant les ports. Par exemple
- tcp/2222 => ssh host
- tcp/2223 => ssh VM1
- tcp/2224 => ssh VM2
- tcp/2225 => ssh VM3
- tcp/80 => reverse proxy (nginx, apache, varnish, ...) sur host pour redispatch par domaine sur VM1+VM2
- tcp/443 => idem (ouais mais faut gérer le SSL alors !?)
- udp/1194 => serveur openvpn sur VM3
En IPv6 il n'y a pas de probleme car l'adhérent a un /56 donc pas de limite aux IPs de service, il suffit de demander l'activation du routage IPv6 coté tetaneutral.net
h2. Solutions
Solarus : - Pour mutualiser une IPv4 sur HTTP on peut mettre en place un proxy nginx. J'en ai déjà un en place sur mon serveur. Je peux le prêter ou en faire un tuto pour en monter un.
- Pour le reste des flux, je conseille de monter un NAT/PAT et configurer les redirections de port entrants. On peut faire ça avec IPtables sous Linux ou BSD. On peut utiliser une machine virtuelle ou un OpenWRT si on veut le faire sur une machine séparée.
Fab :
- En cas de reverse proxy HTTP, faut gérer le SSL pour le HTTPS...galère, galère
- On peut déjà migrer tous les services internes à TTNN sur des IP RFC 1918, quitte à superviser les VM/machines via un rebond SSH (possible dans cmk) ou qu'en IPv6 (possible aussi)
- Pour tout ce qui est serveur de mail, on peut proposer un (ou même plusieurs) MTA qui accepte tous les domaines des MTA hébergés sur les VMs et qui redispatche (une sorte de reverse proxy mail, en fait) (remarque de Solarus : Attention à la mutualisation des MTA sur un proxy SMTP, notamment la gestion des spams entrants et sortants et le risque de blacklistage des adresses)
- Pour certaines VMs/machines qui n'hébergent pas de services ouverts ont peut sensibiliser les adhérents à l'IPv6 only (c'est ce que je fait sur ma VM)
Yannick:
* utilisation d'un firewall logiciel en VM (pfSense, IPcop, Zentyal ...) qui porte l'adresse IP publique et avec utilisation de règle de NAT/PAT (translation d'adresse et de port)
+ simple d'utilisation, interface graphique disponible pour les allergiques de la CLI
+ Existe en "virtual appliance" pré-packagés pour les environnement virtuels
+ il esxiste même des version virtualisées de Firewall physique de grands constructeurs (Fortinet, Juniper...)
* utilisation d'un reverse proxy pour porter l'@IP publique et rediriger le trafic en fonction du protocole et ce qui est appelé.
+- la conf est un peu plus complexe mais au moins tu peux tout maitriser de la couche 3 Ã la couche 7 (www.exemple.com/toto --> vers le serveur_1:80 ; www.exemple.com/tata --> serveur_2:80 ...)
- par contre, pas de fonction firewall avancée
+ il en existe pas mal: Apache avec module RP, NGINX avec module RP, F5 BigIP VE (version limité à 90j) ...
--> mon conseil: un pfSense en machine virtuelle qui porte l'@IP publique (en cas de plusieurs services HTTP à écouter sur le port 80 -> reverse-proxy NGINX)
h2. Liens
TODO
h2. Configuration d'un reverse proxy nginx
Ci-dessous voici une conf typique pour mettre en place un reverse-proxy nginx afin de partager une IP publique pour plusieurs serveurs.
Le systeme fonctionne par Virtual Host (comme sous Apache)
Pour chaque Virtual Host, il faut créer un fichier de ce type dans /etc/nginx/sites-enabled
<pre>
server {
listen 80;
server_name *.exemple.tld;
location / {
proxy_pass http://10.255.254.1;
}
}
server {
listen 443;
server_name *.exemple.tld;
ssl on;
ssl_certificate certificat_ssl.crt;
ssl_certificate_key certificat_ssl.crt;
location / {
proxy_pass https://10.255.254.1;
}
}
</pre>
Les champs à remplir sont 'server_name' avec le domaine du virtual host et 'proxy_pass' avec l'IP privée du serveur.
Le deuxième bloc servira uniquement si vous voulez faire du HTTPS, il vous restera alors à renseigner les emplacements des certificats.
Cette méthode présente un inconvénient c'est que l'IP des visiteurs n'est pas directement visible,ce qui peut être gênant pour les blogs et les système de commentaires.
h2. Redirection de port(s) via iptables.
Cette solution est loin d'être la panacée. Elle permet de multiplexer un service d'une @IP publique vers n @IP privées.
Voici un exemple de règles pour ouvrir l'accès SSH sur le port 22 d'une centaine de VMs adressées de 172.16.0.1 à 172.16.0.100 à partir d'une @IP publique unique.
h3. 1/ Régles à copier dans la section de la table NAT
<pre>for ((i = 1; i <= 100; i++)); do
echo "-A PREROUTING -i [Nom-interface-réseau-public] -d [@IP-publique] -p tcp --dport $((2200 + $i)) -j DNAT --to-destination 172.16.0.$i:22";
done >> /etc/iptables/rules-to-add</pre>
h3. 2/ Régle à copier dans la section de la table netfilter
<pre>-A FORWARD -i [Nom-interface-réseau-public] -m iprange --dst-range 172.16.0.1-172.16.0.100 -p tcp --syn --dport 22 -m conntrack --ctstate NEW -j ACCEPT</pre>
h3. 3/ Fichier de règles «résumé» utilisable avec le paquet Debian iptables-persistent
<pre>#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# NAT
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# P O S T R O U T I N G
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-A POSTROUTING -o [Nom-interface-réseau-public] -p tcp --syn -m tcpmss --mss 1400:1536 -j TCPMSS --clamp-mss-to-pmtu
-A POSTROUTING -o [Nom-interface-réseau-public] -m iprange --src-range 172.16.0.1-172.16.0.100 -j SNAT --to-source [@IP-publique]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# P R E R O U T I N G
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-A PREROUTING -i [Nom-interface-réseau-public] -d [@IP-publique] -p tcp --dport 2201 -j DNAT --to-destination 172.16.0.1:22
-A PREROUTING -i [Nom-interface-réseau-public] -d [@IP-publique] -p tcp --dport 2202 -j DNAT --to-destination 172.16.0.2:22
<snip/>
#
COMMIT
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# N e t f i l t e r
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# I N P U T
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Suivi de communication chaîne INPUT
-A INPUT -p icmp -m conntrack --ctstate ESTABLISHED -j ACCEPT
-A INPUT -p icmp --icmp-type destination-unreachable -m conntrack --ctstate RELATED -j ACCEPT
-A INPUT -p icmp --icmp-type time-exceeded -m conntrack --ctstate RELATED -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp ! --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT
-A INPUT -p tcp --syn -m conntrack --ctstate RELATED -j ACCEPT
# Boucle locale
-A INPUT -i lo -j ACCEPT
# ICMP
-A INPUT -i bond+ -p icmp --icmp-type echo-request -m limit --limit 5/sec -m conntrack --ctstate NEW -j ACCEPT
# SSH
-A INPUT -m recent --update --seconds 60 --hitcount 4 --name SSH -m limit --limit 5/min -j LOG --log-prefix "SSH_brute_force "
-A INPUT -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP
-A INPUT -i [Nom-interface-réseau-public] -p tcp --dport 22 --syn -m recent --set --name SSH -j ACCEPT
# POUBELLE
-A INPUT -m conntrack --ctstate INVALID -m limit --limit 1/min -j LOG --log-prefix "INPUT/rejected.iptables: "
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p tcp -j REJECT --reject-with tcp-reset -m limit --limit 5/s
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable -m limit --limit 5/s
-A INPUT -m limit --limit 1/min -j LOG --log-prefix "INPUT/poubelle: "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# F O R W A R D
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Suivi de communication chaîne FORWARD
-A FORWARD -p icmp -m conntrack --ctstate ESTABLISHED -j ACCEPT
-A FORWARD -p icmp -m conntrack --ctstate RELATED --icmp-type destination-unreachable -j ACCEPT
-A FORWARD -p icmp -m conntrack --ctstate RELATED --icmp-type time-exceeded -j ACCEPT
-A FORWARD -p udp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -p tcp -m conntrack --ctstate ESTABLISHED ! --syn -j ACCEPT
-A FORWARD -p tcp -m conntrack --ctstate RELATED --syn -j ACCEPT
# Boucle locale
-A FORWARD -i lo -j ACCEPT
# Accès SSH VMs
-A FORWARD -i [Nom-interface-réseau-public] -m iprange --dst-range 172.16.0.1-172.16.0.100 -p tcp --syn --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# Poubelle
-A FORWARD -m conntrack --ctstate INVALID -m limit --limit 5/min -j LOG --log-prefix "FORWARD/rejected: "
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -p tcp -m limit --limit 5/min -j LOG --log-prefix "FORWARD/TCP.rejected: "
-A FORWARD -p tcp -m limit --limit 5/sec -j REJECT --reject-with tcp-reset
-A FORWARD -p tcp -m limit --limit 5/min -j LOG --log-prefix "FORWARD/UDP.rejected: "
-A FORWARD -p udp -m limit --limit 5/sec -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -m limit --limit 5/min -j LOG --log-prefix "FORWARD/poubelle: "
#
COMMIT</pre>
h2. Documentation
TODO
nginx
apache
varnish
iptables
shorewall
netcat
h2. Bénévoles
TODO toulibre ou capitole du libre