Les serveurs Nintendo Wi-Fi Connection sont éteints depuis 2014. Ce dépôt fait tourner
AltWFC (dwc_network_server_emulator) sur le Mac, en Docker, pour rejouer en ligne
sur les jeux DS et Wii — ici Mario Kart Wii — depuis une vraie console et depuis Dolphin,
sans dépendre d'un service tiers et sans ouvrir un seul port sur la box.
Ce README est la synthèse. Le détail, les procédures et les pièges sont dans
SETUP.md ; le raisonnement qui a mené à ces choix est dans
docs/superpowers/specs/2026-08-06-altwfc-selfhost-design.md.
| Serveur | 192.168.1.100 (le Mac), 3 conteneurs sous OrbStack |
| Exposition | LAN uniquement, aucun port ouvert sur la box |
| Clients validés | vraie Wii softmoddée · Dolphin sur Ayn Thor (Android) |
| Jeu validé | Mario Kart Wii, en ligne, à plusieurs |
| État | fonctionnel, vérifié les 2026-08-06 et 2026-08-07 |
cd ~/code/wii/dwc-docker
docker compose up -d # démarrer
docker compose ps # état des 3 conteneurs
docker compose logs -f dwc # suivre les connexions en direct
docker compose down # arrêter — les comptes surviventLes comptes, profils et friend codes vivent dans le volume Docker dwc-docker_data.
Un down ne les détruit pas ; seul un down -v le ferait.
La console croit parler à Nintendo. On ne la modifie pas, on modifie le monde autour :
console ──DNS──▶ dnsmasq « nintendowifi.net ? → 192.168.1.100 »
──HTTP─▶ HAProxy aiguille selon l'en-tête Host
└────────▶ dwc 13 services GameSpy / NAS / Storage
- dnsmasq ment sur
*.nintendowifi.netet relaie le reste vers1.1.1.1, pour que la console garde un accès internet normal. - HAProxy écoute sur le port 80 et route par nom d'hôte (
nas,sake,gamestats,dls1). Une requête arrivant par IP brute est rejetée en 503 : c'est normal, pas une panne. - dwc est l'émulateur lui-même, code de 2014 en Python 2.7, épinglé à un commit précis
dans le
Dockerfilepour que deux builds à deux mois d'écart donnent le même serveur.
Une pièce manque, et elle est dans le jeu. La Wii contacte le NAS en HTTPS, avec un certificat Nintendo qu'on ne peut ni reproduire ni faire accepter. Rediriger le nom ne sert à rien si la poignée de main TLS échoue derrière : chaque jeu doit être converti en HTTP. C'est la grande différence avec la DS, dont le NAS accepte le trafic en clair.
| Client | DNS | Patch HTTPS→HTTP |
|---|---|---|
| Vraie Wii | Réglages Wii → Internet, DNS primaire 192.168.1.100 |
USB Loader GX, Private Server = NoSSL only — à la volée, le disque n'est jamais modifié |
| Dolphin / Android | réglage Wi-Fi + RethinkDNS (voir piège n°2) | ISO patchée d'avance avec les outils Wiimm |
| Dolphin / macOS | une ligne dans /etc/hosts |
idem, ISO patchée |
Deux points qui font gagner du temps :
- Sur console, choisir
NoSSL onlyet surtout pasAltWFCmalgré le nom : cette entrée-là réécrit le domaine enzwei.moe, que ni dnsmasq ni HAProxy ne connaissent. - Dolphin n'a aucun réglage DNS pour la Wii, ni sur Android ni sur desktop. Le « DNS Server » de son interface pilote l'adaptateur Broadband GameCube. C'est le DNS du système hôte qui décide.
Procédures complètes dans SETUP.md : « Client 2 — vraie console Wii softmoddée »,
« Client 1 — Dolphin sur Ayn Thor », « Patcher l'ISO (voie Dolphin) ».
1. L'IP du Mac est distribuée par DHCP. Tout le montage repose sur 192.168.1.100 :
au renouvellement du bail, l'adresse change et tout casse d'un coup, le DNS pointant vers
une machine qui n'existe plus. C'est arrivé le 2026-08-07. Une réservation DHCP est posée
depuis ; si l'IP dérive quand même, il faut la corriger dans dwc-docker/dnsmasq/dnsmasq.conf.
Symptôme : ipconfig getifaddr en0 ne dit plus .100.
2. Sur Android, le réglage DNS du Wi-Fi ne pilote que l'IPv4. La box annonce en plus
son propre résolveur IPv6 par Router Advertisement, qu'aucune case de l'interface
Android ne couvre — et c'est lui qui gagne. Le jeu obtient alors les vraies IP Nintendo,
mortes depuis 2014, et affiche erreur 23301 sans qu'un seul paquet n'atteigne le Mac.
La vraie Wii y échappe parce qu'elle ignore l'IPv6 : la différence n'était pas entre
l'émulateur et la console, mais entre pile simple et double pile. Correctif retenu :
RethinkDNS en mode proxy Do53 vers 192.168.1.100:53, « Empêcher les fuites DNS » sur
ON. Voir SETUP.md, « Le piège IPv6, qui coûte une soirée » et « Le correctif : RethinkDNS ».
Le test le plus concluant tient en une ligne, console Android branchée en USB :
adb shell ping -c 1 zzz-nimportequoi.nintendowifi.netCe nom n'existe pas chez Nintendo. S'il répond 192.168.1.100, c'est le joker de dnsmasq
qui a parlé — aucun autre résolveur au monde ne peut produire cette réponse. C'est une
preuve, pas un indice. Sinon, la console interroge quelqu'un d'autre.
Côté serveur, docker compose logs -f dwc : une connexion réussie laisse gamename: mariokartwii, un authtoken, un profileid et un friend code. La section
« Diagnostiquer quand ça ne marche pas » de SETUP.md détaille le reste, dont deux pièges
de mesure — tcpdump sur en0 ne voit que ce qui est adressé au Mac, et une capture
vide ne prouve donc rien.
SETUP.md le cahier de bord : procédures, pièges, diagnostics
dwc-docker/ submodule → Jobierre/dwc-docker (fork de TheForcer)
docker-compose.yml 3 services : haproxy, dwc, dnsmasq
Dockerfile build de l'émulateur, commit épinglé
haproxy.cfg routage par en-tête Host
dnsmasq/ le résolveur menteur — c'est ici qu'est l'IP du Mac
README.md le README amont, conservé tel quel
upstream-src/ submodule → Jobierre/dwc_network_server_emulator
(fork de barronwaffles, code de l'émulateur, en lecture)
docs/superpowers/ le design et les décisions
Les deux sous-dossiers sont des submodules pointant sur mes forks, donc un clone simple les laisse vides :
git clone --recurse-submodules https://github.com/Jobierre/wii-server-2026.git
# dépôt déjà cloné sans l'option :
git submodule update --initChaque fork garde un remote upstream vers le dépôt d'origine, pour pouvoir récupérer
une correction amont par git fetch upstream && git merge upstream/main.
Note : upstream-src/ n'est utile qu'à la lecture. Le Dockerfile ne s'en sert pas —
il clone lui-même l'émulateur au commit 2c65a9f, épinglé dans son ARG DWC_COMMIT,
qui est exactement celui référencé ici.
Le Dockerfile a dû être repris : python:2.7-slim repose sur une Debian archivée dont
les dépôts renvoient 404, et Twisted ne s'installe plus par pip en Python 2.7. Il vient
donc d'APT. Le détail est dans le design doc.
- LAN uniquement, c'est un choix. Jouer avec des amis distants demanderait d'ouvrir onze ports et un vrai nom de domaine.
- Le serveur vit avec le Mac : il s'arrête quand la machine s'éteint. Le stack se
transplante tel quel sur un LXC Proxmox ou sur Unraid — seules les IP de
dnsmasq.confchangeraient. - Le port 53 est occupé tant que le stack tourne, à savoir si un Pi-hole local arrive un jour.
- Code de 2014, Python 2.7 : la compatibilité varie titre par titre.