2 Agent Network
GnomeZworc edited this page 2025-11-19 21:30:26 +01:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Le reseaux entre les vms

+--------------------------------------------------------------+     +----------------------------------------------------+
|                          HOST A                              |     |                  HOST B                            |
|                                                              |     |                                                    |
|  [ netns-1 (VPC 1) ]                                         |     |                                                    |
|                                                              |     |                                                    |
|    br-subnet-1 (10.0.1.1/32)  ---- veth1 <----------------+  |     |                                                    |
|                                    (dans netns)              |     |                                                    |
|                                                              |     |                                                    |
|    br-subnet-2 (10.0.2.1/32)  ---- veth2 <----------------+  |     |                                                    |
|                                    (dans netns)              |     |                                                    |
|                                                              |     |                                                    |
|                                                              |     |                                                    |
|  [ netns-2 (VPC 2) ]                                         |     |  [ netns-2 (VPC 2) ]                               |
|                                                              |     |                                                    |
|    br-subnet-3 (10.0.3.1/32)  ---- veth3 <------+            |     |    br-subnet-3 (10.0.3.1/32)  ---- veth4 <------+  |
|                                    (dans netns) |            |     |                                    (dans netns) |  |
|                                                 |            |     |                                                 |  |
+-------------------------------------------------+------------+     +-------------------+--------------------------------+
                                                  |                                                                    |
                                                  |                                                                    |
                                       +----------v-----------+                                            +-----------v----------+
                                       |   br-vx-1 (host)     |                                            |    br-vx-1 (host)    |
                                       |   (infra bridge)     |                                            |    (infra bridge)    |
                                       +----------------------+                                            +----------------------+
                                                  |                                                                    |
                                      +-----------v-----------+                                             +----------v------------+
                                      |     vxlan1001         |                                             |     vxlan1001         |
                                      | (Tunnel inter-host)   |                                             | (Tunnel inter-host)   |
                                      +-----------------------+                                             +-----------------------+

package netutils

import (
	"fmt"
	"net"

	"github.com/vishvananda/netlink"
	"github.com/vishvananda/netns"
	"golang.org/x/sys/unix"
)

// CreateNetns crée un nouveau namespace nommé
func CreateNetns(name string) error {
	path := fmt.Sprintf("/var/run/netns/%s", name)
	return unix.Mount("/proc/self/ns/net", path, "none", unix.MS_BIND, "")
}

// CreateBridge crée un bridge dans le namespace donné (ou root si nsPath == "")
func CreateBridge(name, nsPath string) error {
	link := &netlink.Bridge{
		LinkAttrs: netlink.LinkAttrs{Name: name},
	}
	if nsPath != "" {
		newNs, err := netns.GetFromPath(nsPath)
		if err != nil {
			return err
		}
		defer newNs.Close()

		return netns.Do(newNs, func(_ netns.NsHandle) error {
			return netlink.LinkAdd(link)
		})
	}
	return netlink.LinkAdd(link)
}

// LinkBridgeNetns connecte deux bridges via un veth pair (br1 dans root, br2 dans netns)
func LinkBridgeNetns(vethName, peerName, netnsPath, bridgeRoot, bridgeInNs string) error {
	peer := netlink.Veth{
		LinkAttrs: netlink.LinkAttrs{Name: vethName},
		PeerName:  peerName,
	}

	if err := netlink.LinkAdd(&peer); err != nil {
		return err
	}

	// Set peer into target netns
	ns, err := netns.GetFromPath(netnsPath)
	if err != nil {
		return err
	}
	defer ns.Close()

	linkPeer, err := netlink.LinkByName(peerName)
	if err != nil {
		return err
	}
	if err := netlink.LinkSetNsFd(linkPeer, int(ns)); err != nil {
		return err
	}

	// Attach veth to host bridge
	br, err := netlink.LinkByName(bridgeRoot)
	if err != nil {
		return err
	}
	veth, _ := netlink.LinkByName(vethName)
	if err := netlink.LinkSetMaster(veth, br); err != nil {
		return err
	}
	if err := netlink.LinkSetUp(veth); err != nil {
		return err
	}

	// Attach peer to bridge in netns
	return netns.Do(ns, func(_ netns.NsHandle) error {
		peerLink, err := netlink.LinkByName(peerName)
		if err != nil {
			return err
		}
		brInNs, err := netlink.LinkByName(bridgeInNs)
		if err != nil {
			return err
		}
		if err := netlink.LinkSetMaster(peerLink, brInNs); err != nil {
			return err
		}
		return netlink.LinkSetUp(peerLink)
	})
}

// AddIPToBridge ajoute une IP en /32 à un bridge dans un namespace
func AddIPToBridge(nsPath, bridgeName, ipCidr string) error {
	ns, err := netns.GetFromPath(nsPath)
	if err != nil {
		return err
	}
	defer ns.Close()

	return netns.Do(ns, func(_ netns.NsHandle) error {
		br, err := netlink.LinkByName(bridgeName)
		if err != nil {
			return err
		}
		addr, err := netlink.ParseAddr(ipCidr)
		if err != nil {
			return err
		}
		return netlink.AddrAdd(br, addr)
	})
}

// AddLinkLocalRoute ajoute une route link-local dans un netns
func AddLinkLocalRoute(nsPath string) error {
	ns, err := netns.GetFromPath(nsPath)
	if err != nil {
		return err
	}
	defer ns.Close()

	return netns.Do(ns, func(_ netns.NsHandle) error {
		_, dst, _ := net.ParseCIDR("fe80::/64")
		route := &netlink.Route{
			Dst: dst,
			Scope: netlink.SCOPE_LINK,
		}
		return netlink.RouteAdd(route)
	})
}

// CleanupNetns démonte et supprime un netns (utilise iproute2 fs)
func CleanupNetns(name string) error {
	path := fmt.Sprintf("/var/run/netns/%s", name)
	if err := unix.Unmount(path, 0); err != nil {
		return err
	}
	return unix.Unlink(path)
}

// DeleteLink supprime un lien réseau (bridge, veth, etc.)
func DeleteLink(name string) error {
	link, err := netlink.LinkByName(name)
	if err != nil {
		return err
	}
	return netlink.LinkDel(link)
}
CreateNetns("netns-1")
CreateBridge("br-subnet-1", "/var/run/netns/netns-1")
CreateBridge("br-vx-1", "") // root
LinkBridgeNetns("veth1", "veth1-peer", "/var/run/netns/netns-1", "br-vx-1", "br-subnet-1")
AddIPToBridge("/var/run/netns/netns-1", "br-subnet-1", "10.0.1.1/32")
AddLinkLocalRoute("/var/run/netns/netns-1")

systemd pour dnsmasq et metadata

Oui, cest tout à fait possible avec la bibliothèque go-systemd, en particulier via le module dbus, qui permet de démarrer, arrêter et interroger l'état des unités systemd.

Voici un exemple minimal de code Go pour démarrer et arrêter une unité comme dnsmasq@vpc-00003_br-00000.service :


Exemple de code pour start/stop via go-systemd:

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/coreos/go-systemd/v22/dbus"
)

func main() {
	conn, err := dbus.NewSystemdConnectionContext(context.Background())
	if err != nil {
		log.Fatalf("Erreur de connexion à systemd: %v", err)
	}
	defer conn.Close()

	unitName := "dnsmasq@vpc-00003_br-00000.service"

	// Démarrer l'unité
	jobID, err := conn.StartUnitContext(context.Background(), unitName, "replace", nil)
	if err != nil {
		log.Fatalf("Erreur au démarrage de l'unité: %v", err)
	}
	fmt.Printf("Service démarré (job ID: %s)\n", jobID)

	time.Sleep(3 * time.Second) // attendre un peu

	// Arrêter l'unité
	jobID, err = conn.StopUnitContext(context.Background(), unitName, "replace", nil)
	if err != nil {
		log.Fatalf("Erreur à l'arrêt de l'unité: %v", err)
	}
	fmt.Printf("Service arrêté (job ID: %s)\n", jobID)
}

🔐 Privilèges requis :

  • Il faut que votre programme Go soit exécuté avec des droits suffisants (souvent sudo) pour interagir avec systemd au niveau système.

Exemple d'exécution :

sudo ./mon-binaire-go

📦 Dépendance :

Ajoutez ce module dans votre go.mod :

go get github.com/coreos/go-systemd/v22

Souhaitez-vous aussi vérifier létat de lunité (Active, Failed, etc.) ou juste la gestion start/stop ?