Aller au contenu

Transport WireGuard

WireGuard fournit un tunnel UDP crypté entre l'implant et le relais. À l'intérieur du tunnel, le protocole HTTP C2 standard fonctionne inchangé, vous offrant une connectivité complète au niveau du réseau avec un cryptage puissant et des capacités de traversée NAT.

graph LR
    subgraph Target Network
        Implant["Implant<br/>10.99.0.2"]
    end
    subgraph Relay
        WG["WireGuard Endpoint<br/>UDP :51820"]
        HTTP["HTTP C2 Server<br/>10.99.0.1:8080"]
    end

    Implant <-->|"WireGuard UDP Tunnel<br/>(Curve25519 + ChaCha20-Poly1305)"| WG
    WG --- HTTP

Cas d'utilisation :

  • Accès complet au niveau du réseau via un tunnel crypté
  • Traversée NAT où les transports basés sur TCP ne sont pas fiables
  • Connectivité IP directe sans surcharge HTTP sur le fil
  • Environnements dans lesquels le trafic UDP se mélange mieux que HTTP/HTTPS

Gestion des clés

WireGuard utilise les paires de clés Curve25519. Le relais et l'implant ont besoin de leur propre paire de clés. L'API fournit un point de terminaison pratique pour générer les deux paires à la fois.

Générer des paires de clés

curl -s -X POST https://stentor.app/api/v1/listeners/wireguard/keygen \
  -H "Authorization: Bearer $TOKEN"

Réponse :

{
  "relay_private_key": "WEhNb3V...<base64>...",
  "relay_public_key": "aGVsbG8...<base64>...",
  "implant_private_key": "c2VjcmV...<base64>...",
  "implant_public_key": "d29ybGQ...<base64>..."
}

Toutes les clés sont des clés Curve25519 codées en base64 (32 octets décodés).

Stockage des clés

Les clés privées sont des informations d'identification sensibles. Stockez-les avec le même soin que les mots de passe ou les clés privées TLS. Le relay_private_key est stocké dans la configuration du listener. Le implant_private_key est intégré à la construction de l'implant.


Création d'un listener WireGuard

# 1. Generate keys
KEYS=$(curl -s -X POST https://stentor.app/api/v1/listeners/wireguard/keygen \
  -H "Authorization: Bearer $TOKEN")

RELAY_PRIV=$(echo "$KEYS" | jq -r '.relay_private_key')
IMPLANT_PUB=$(echo "$KEYS" | jq -r '.implant_public_key')

# 2. Create listener
LISTENER_ID=$(curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"name\": \"WireGuard Tunnel\",
    \"type\": \"wireguard\",
    \"relay_id\": \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",
    \"port\": 51820,
    \"wg_private_key\": \"$RELAY_PRIV\",
    \"wg_peer_public_key\": \"$IMPLANT_PUB\",
    \"wg_tunnel_ip\": \"10.99.0.1/24\",
    \"wg_peer_tunnel_ip\": \"10.99.0.2/32\",
    \"wg_c2_port\": 8080
  }" | jq -r '.id')

# 3. Start listener
curl -s -X POST "https://stentor.app/api/v1/listeners/$LISTENER_ID/start" \
  -H "Authorization: Bearer $TOKEN"

Options de configuration

Champ Type Par défaut Description
name chaîne requis Nom d'affichage pour le listener
type chaîne "wireguard" Doit être wireguard pour les listeners WireGuard
relay_id UUID requis Relais qui hébergera le point de terminaison WireGuard
port int requis Port UDP externe pour tunnel WireGuard
wg_private_key chaîne requis Clé privée Curve25519 de Relay (base64)
wg_public_key chaîne dérivé Clé publique du relais (auto-dérivée de la clé privée, pour affichage uniquement)
wg_peer_public_key chaîne requis Clé publique Curve25519 de l'implant (base64)
wg_tunnel_ip chaîne "10.99.0.1/24" Adresse IP du relais dans le tunnel WireGuard
wg_peer_tunnel_ip chaîne "10.99.0.2/32" Adresse IP de l'implant à l'intérieur du tunnel WireGuard
wg_c2_port int 8080 Port HTTP à l'intérieur du tunnel où le gestionnaire C2 écoute
guardrails JSON null Règles de filtrage des beacons. null signifie accepter toutes les beacons.

Traversée NAT

WireGuard utilise la perforation UDP pour la traversée NAT, ce qui le rend efficace dans la plupart des configurations réseau :

  • PersistentKeepalive : l'implant envoie des paquets keepalive toutes les 25 secondes (par défaut) pour maintenir les mappages NAT.
  • Types de NAT pris en charge : le cône complet, le cône restreint et le NAT restreint au port fonctionnent tous de manière fiable.
  • NAT symétrique : peut nécessiter un point de terminaison de relais routable publiquement.

Considérations MTU

La MTU par défaut est de 1 420 octets. Sur les réseaux double NAT ou les réseaux avec encapsulation supplémentaire (PPPoE, VPN-in-VPN), vous devrez peut-être réduire davantage la MTU (par exemple, 1 280) pour éviter la fragmentation.

Comment ça marche

  1. Le relais écoute sur un port UDP public (par exemple, 51820)
  2. L'implant initie la poignée de main WireGuard vers le point final du relais
  3. Après la poignée de main, les deux parties disposent d'un tunnel avec des adresses IP attribuées (10.99.0.1 et 10.99.0.2).
  4. Les paquets Keepalive maintiennent le mappage NAT en vie
  5. Le trafic HTTP C2 circule à l'intérieur du tunnel, invisible à l'inspection du réseau

Configuration de la connectivité directe

Configuration étape par étape pour un tunnel WireGuard direct implant-relais :

Étape 1 : Générer des paires de clés

Utilisez le point de terminaison de l'API keygen pour créer des paires de clés Curve25519 pour le relais et l'implant :

curl -s -X POST https://stentor.app/api/v1/listeners/wireguard/keygen \
  -H "Authorization: Bearer $TOKEN" | jq .

Enregistrez les quatre clés. La clé privée du relais va dans la configuration du listener. La clé privée de l'implant et la clé publique du relais vont dans la configuration de construction de l'implant.

Étape 2 : créer et démarrer le listener

Créez le listener WireGuard sur le relais avec la clé privée du relais et la clé publique de l'implant :

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "WireGuard Tunnel",
    "type": "wireguard",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "port": 51820,
    "wg_private_key": "<relay_private_key>",
    "wg_peer_public_key": "<implant_public_key>"
  }'

Étape 3 : Configurer l'implant

L'implant nécessite la configuration WireGuard suivante :

Champ de configuration de l'implant Valeur Source
PrivateKey <implant_private_key> De la réponse keygen
PeerPublicKey <relay_public_key> De la réponse keygen
Endpoint <relay-ip>:51820 IP publique et port UDP du relais
TunnelIP 10.99.0.2/32 Doit correspondre à wg_peer_tunnel_ip
RelayTunnelIP 10.99.0.1 Doit correspondre à wg_tunnel_ip
C2Port 8080 Doit correspondre à wg_c2_port

Étape 4 : L'implant se connecte

Lorsque l’implant démarre, il lance la poignée de main WireGuard. Une fois le tunnel établi, l'implant envoie des requêtes HTTP C2 standard (enregistrement, obtention de la tâche, soumission du résultat) à http://10.99.0.1:8080 à l'intérieur du tunnel.

Comparaison des architectures

graph TB
    subgraph HTTPS Transport
        I1["Implant"] -->|"HTTPS (TLS)"| R1["Relay :8443"]
        R1 --> H1["C2 Handler"]
    end

    subgraph WireGuard Transport
        I2["Implant"] -->|"UDP (WireGuard)"| R2["Relay :51820"]
        R2 --> T["Tunnel Network<br/>10.99.0.0/24"]
        T --> H2["C2 Handler<br/>10.99.0.1:8080"]
    end
Aspect HTTPS WireGuard
Protocole TCP + TLS UDP + ChaCha20-Poly1305
Calque Demande (HTTP) Réseau (tunnel IP)
Traversée NAT TCP (fiable) Perforation UDP (keepalive nécessaire)
Signature du trafic Cela ressemble à du trafic Web HTTPS Cela ressemble au trafic VPN WireGuard
Latence Supérieur (prise de contact TCP + TLS) Inférieur (UDP, pas de prise de contact par requête)
Frais généraux En-têtes de trame TLS Surcharge du paquet WireGuard (32 octets)

Configuration des implants

Le client WireGuard de l'implant utilise la structure de configuration suivante :

Champ Type Par défaut Description
PrivateKey chaîne requis Clé privée Curve25519 de l'implant (base64)
PeerPublicKey chaîne requis Clé publique Curve25519 de Relay (base64)
Endpoint chaîne requis Point de terminaison WireGuard UDP du relais (host:port)
TunnelIP chaîne "10.99.0.2/32" IP attribuée à l'implant à l'intérieur du tunnel
RelayTunnelIP chaîne "10.99.0.1" IP du relais à l'intérieur du tunnel
C2Port int 8080 Port HTTP à l'intérieur du tunnel pour le trafic C2
PersistentKeepalive int 25 Intervalle Keepalive en secondes pour la traversée NAT
MTU int 1420 MTU du tunnel en octets

Implémentation de l'espace utilisateur

L'implant utilise netstack (pile TCP/IP de l'espace utilisateur) pour faire fonctionner le tunnel WireGuard sans nécessiter de pilotes de noyau ou de privilèges d'administrateur :

  • Aucun module WireGuard du noyau n'est nécessaire
  • Aucune installation d'adaptateur TUN/TAP requise
  • Fonctionne dans l'espace utilisateur -- pas de privilèges spéciaux pour le tunnel lui-même
  • Le client HTTP à l'intérieur du tunnel réutilise les points de terminaison C2 standards (/api/v1/c2/beacon, /api/v1/c2/beacon/{id}/task, /api/v1/c2/beacon/{id}/result)

Le côté relais utilise également netstack, créant un listener TCP à l'intérieur du tunnel qui sert le même multiplexeur HTTP C2 utilisé par les listeners HTTP/HTTPS.


Dépannage

Symptôme Parce que Corriger
Aucun tunnel établi Port UDP bloqué sur le pare-feu relais Ouvrez le port UDP configuré (par exemple, 51820) sur le pare-feu du relais
Tunnel vers le haut mais pas de C2 Incompatibilité des ports C2 Vérifiez que wg_c2_port sur le listener correspond à C2Port sur l'implant
Tunnel vers le haut mais pas de C2 Incompatibilité IP du tunnel Vérifiez la correspondance wg_tunnel_ip et wg_peer_tunnel_ip entre le listener et l'implant.
Gouttes intermittentes Le mappage NAT expire Augmentez l'intervalle PersistentKeepalive (25 s par défaut devraient fonctionner pour la plupart des NAT)
Fragmentation / perte de paquets MTU trop grand Réduisez le MTU de 1 420 à 1 280 sur les réseaux double NAT ou encapsulés
Erreur "décoder la clé privée" Clé base64 mal formée Régénérez les clés à l'aide de l'API keygen. Les clés doivent faire exactement 32 octets une fois décodées.
Inadéquation des clés Mauvais appairage des clés Assurez-vous que le relais utilise relay_private_key et que l'implant utilise implant_private_key. Les clés homologues doivent correspondre.