Expérimenter Nebula Mesh - Partie 1

samedi 16 juillet 2022 · 4 minutes · 819 mots

Simulons un réseau maillé (mesh en anglais) avec Nebula en configurant 2 machines virtuelles à l’aide de Vagrant.

Le tout sera fait sur ma distribution Linux (Ubuntu 20.04) où j’ai déjà installé Virtualbox.

Vagrant

Vagrant est un outil de gestion de machines virtuelles de la société Hashicorp.

sudo apt install -y vagrant

Je configure vagrant de telle façon à avoir 2 machines virtuelles sous debian 11, nommées boxA et boxB.

Leur interface réseau est directement branchée au réseau de ma machine, soit eth0 (à adapter selon sa propre configuration), pour avoir une IP sur mon réseau local via DHCP.

cat <<EOF > Vagrantfile
Vagrant.configure("2") do |config|
    config.vm.define "boxA" do |boxA|
        boxA.vm.box = "generic/debian11"
        boxA.vm.network "public_network", bridge: "eth0"
    end
    config.vm.define "boxB" do |boxB|
        boxB.vm.box = "generic/debian11"
        boxB.vm.network "public_network", bridge: "eth0"
    end
end
EOF

Je lance les machines virtuelles avec la commande :

vagrant up

Nebula

Pour nebula, je récupère les binaires depuis github selon ma configuration, en l’occurrence nebula-linux-amd64.tar.gz.

wget https://github.com/slackhq/nebula/releases/download/v1.6.0/nebula-linux-amd64.tar.gz

Ensuite, je décompresse l’archive :

tar xf nebula-linux-amd64.tar.gz

J’obtiens 2 binaires : nebula et nebula-cert.

Le binaire nebula sera à recopier et exécuter dans les machines virtuelles (voir plus bas). C’est lui qui établiera le pont entre les machines.

Le binaire nebula-cert sert à générer tous les certificats nécessaires :

./nebula-cert ca -name "ACME, Inc"
./nebula-cert sign -name "boxA" -ip "192.168.168.100/24"
./nebula-cert sign -name "boxB" -ip "192.168.168.200/24"

J’indique les IP que j’utiliserai pour le réseau maillé : 192.168.168.100 pour boxA et 192.168.168.200 pour boxB.

J’obtiens les fichiers suivants :

ca.crt
ca.key
boxA.crt
boxA.key
boxB.crt
boxB.key

Pour faciliter la gestion des configurations, je vais créer un dossier par machine virtuelle et j’y déplacerai les fichiers respectifs :

mkdir boxA boxB
mv boxA.* boxA && mv boxB.* boxB

Je génère un fichier de configuration nebula qui sera commun pour les deux machines.

Pour cela, je dois d’abord récupèrer leur IP publique (pas l’IP interne vagrant mais bien celle de mon réseau local) qui doit être sur l’eth1 de la VM:

D’abord sur boxA :

boxAip=$(vagrant ssh boxA --no-tty -c "ip address show eth1| grep 'inet ' | sed -e 's/^.*inet //' -e 's/\/.*$//'" | tr -d '\r')

Ensuite sur boxB :

boxBip=$(vagrant ssh boxB --no-tty -c "ip address show eth1| grep 'inet ' | sed -e 's/^.*inet //' -e 's/\/.*$//'" | tr -d '\r')

Les 2 adresses IP seront rangées dans les variables d’environnement $boxAip et $boxBip.

Ces 2 variables sont utilisées dans la configuration de Nebula ci-dessous, dans la section static_host_map : les IP obtenues plus haut sont injectées pour faire la correspondance avec l’IP maillée (192.168.168.xxx)

cat <<EOF > config.yml
pki:
  ca: /etc/nebula/ca.crt
  cert: /etc/nebula/host.crt
  key: /etc/nebula/host.key
static_host_map:
    "192.168.168.100": ["$boxAip:4242"]
    "192.168.168.200": ["$boxBip:4242"]
lighthouse:
  am_lighthouse: false
listen:
  host: 0.0.0.0
  port: 4242
punchy:
  punch: true
tun:
  disabled: false
  dev: nebula1
  drop_local_broadcast: false
  drop_multicast: false
  tx_queue: 500
  mtu: 1300
  routes:
  unsafe_routes:
logging:
  level: info
  format: text
firewall:
  conntrack:
    tcp_timeout: 12m
    udp_timeout: 3m
    default_timeout: 10m
    max_connections: 100000
  outbound:
    - port: any
      proto: any
      host: any
  inbound:
    - port: any
      proto: any
      host: any
EOF

Configurons les machines virtuelles

On doit envoyer tous les fichiers nécessaires sur chacune des machines :

# pour uploader depuis le host vers les vms
vagrant upload ./boxA /tmp/ boxA
vagrant upload ./boxB /tmp/ boxB

# il faut aussi uploader le ca.crt
vagrant upload ca.crt /tmp/ boxA
vagrant upload ca.crt /tmp/ boxB

# la config nebula
vagrant upload config.yml /tmp/ boxA
vagrant upload config.yml /tmp/ boxB

# et le binaire nebula
vagrant upload nebula /tmp/ boxA
vagrant upload nebula /tmp/ boxB

Puis on se connecte sur chaque box pour finaliser la configuration. Commençons par nous connecter sur la machine a :

vagrant ssh boxA

Une fois à l’intérieure de la machine A, on déplace et renomme les fichiers :

sudo mkdir /etc/nebula
sudo mv /tmp/config.yml /etc/nebula/config.yml
sudo mv /tmp/ca.crt /etc/nebula/ca.crt
sudo mv /tmp/boxA.crt /etc/nebula/host.crt
sudo mv /tmp/boxA.key /etc/nebula/host.key
sudo mkdir /opt/nebula 
sudo mv /tmp/nebula /opt/nebula/
chmod +x /opt/nebula/nebula

Enfin, on lance nebula en arrière plan sur cette machine :

cd /opt/nebula
sudo ./nebula -config /etc/nebula/config.yml &

On se déconnecte de la machine A avec la commande exit et on recommence avec la machine B. D’abord on s’y connecte :

vagrant ssh boxB

Puis, on déplace les fichiers de configurations et on lance nebula :

sudo mkdir /etc/nebula
sudo mv /tmp/config.yml /etc/nebula/config.yml
sudo mv /tmp/ca.crt /etc/nebula/ca.crt
sudo mv /tmp/boxB.crt /etc/nebula/host.crt
sudo mv /tmp/boxB.key /etc/nebula/host.key
sudo mkdir /opt/nebula 
sudo mv /tmp/nebula /opt/nebula/
chmod +x /opt/nebula/nebula
cd /opt/nebula
sudo ./nebula -config /etc/nebula/config.yml &
exit

Maintenant, nous avons 2 machines virtuelles reliées par Nebula. Cool, mais comment vérifier que le réseau fonctionne ?

On se connecte sur la machine A et on tente de pinguer la machine B avec son IP Nebula, c’est-à-dire 192.168.168.200 :

vagrant ssh boxA

ping 192.168.168.200

Si tout fonctionne, le ping répond normalement. On peut faire l’exercice inverse, c’est-à-dire pinguer boxA depuis boxB.

Et enfin, pour arrêter toutes les machines virtuelles :

vagrant halt

C’est tout pour aujourd’hui !

technique linux