Open-source project
spacemeowx2/ldn_mitm avatar
spacemeowx2/ldn_mitm

ldn_mitm and the case for local Switch LAN play without the wireless scan

Play local wireless supported games online

947 stars136 forksC++GPL-2.0

At a glance

What is it?
ldn_mitm is a sysmodule that replaces the Switch's ldn service and emulates console discovery over LAN UDP instead of the WiFi scan, so locally supported games can find each other. It is GPLv2 with named exemptions, version-locked to Atmosphère releases, and last pushed on 2026-08-24.
Who is it for?
ldn_mitm fits owners of a hacked Switch who want locally supported games to find each other on a wired network or a router that blocks the wireless discovery path, and who are comfortable matching an Atmosphère version to a module version. It does not fit anyone relying on official online play, and it does not fit a build that must run on a console with no custom firmware, since the module is a replacement for a system service rather than a standalone application.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 59 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

It replaces the ldn service instead of joining the wireless scan

ldn_mitm is a sysmodule, a small piece of code loaded by the console's custom firmware, and its job is to make local wireless games find each other when the normal route does not work.

The mechanism is described in two sentences in the README. ldn_mitm implements LAN connectivity by replacing the system's ldn service. The original ldn service is only responsible for calling the WiFi service to scan and connect to nearby Switch consoles, and ldn_mitm uses the LAN UDP to emulate this scanning process.

That is the whole design. The stock service looks for peers over the wireless radio. This module stands in for it and answers the same role over LAN UDP instead. The consequence is that two consoles on the same wired network, or on a router that blocks or degrades the local wireless discovery, can still see each other for a game that supports local wireless play.

Because the module replaces a system service rather than running as an application, it is not a standalone tool. It is loaded by Atmosphère, the custom firmware loader, which is why every ldn_mitm release is pinned to a specific Atmosphère version in the README's version table. The companion tool named in the README is switch-lan-play, and the configuration tutorial is at lan-play.com/install.

The primary language is C++, the licence field on the repository says GPL-2.0, and the repository is not archived. The last push was on 2026-08-24.

Version pairs, and the nightly builds for the unsupported ones

The version table is the part of this project that most affects whether an install works, and it is long. ldn_mitm 1.25.1 pairs with Atmosphère 1.11.1, 1.25.0 with 1.11.0, 1.24.0 with 1.10.2, 1.23.0 with 1.10.1, and so on back through 1.3.3 with 0.10.

The pattern is not always one to one. ldn_mitm 1.11.0 lists two Atmosphère versions, 1.2.1 and 1.2.2, and ldn_mitm 1.7.0 lists five, from 0.16.1 up to 0.18.1. So the table is a compatibility map, not a mirror of release numbers, and the module version does not follow the firmware version.

The release history in the repository is short. The tagged releases are v1.25.1 on 2026-04-08, v1.25.0 on 2026-04-05 and v1.24.0 on 2026-02-10, and those three fall inside the version table's most recent entries. The last push came later than all of them, on 2026-08-24, so work is continuing on the branch after the latest tag.

The README gives a specific instruction for anyone ahead of the table: try the GHA nightlies, the GitHub Actions builds, if you have updated beyond the supported Atmosphère versions. That is the escape hatch for a console whose firmware is newer than the newest tagged combination, and it is also the reason to read the version table before, not after, choosing a build.

Building with Docker or devkitPro, and the submodule that has to be initialised

Building ldn_mitm needs a Nintendo Switch toolchain, and the project offers two routes to it. Both start with the same first step, because the repository contains submodules that must be present.

bash
git submodule update --init --recursive

The top level of the repository shows what those submodules are. There is an Atmosphère-libs directory, which the Makefile refers to as libstratosphere, a libtesla directory, the ldn_mitm source directory, an ldnmitm_config directory, and an overlay directory. The Makefile builds those as a set of subfolders, and ldn_mitm depends on Atmosphère-libs/libstratosphere being built first.

The Docker route is the shorter one, and the compose file in the repository shows exactly what it does.

yaml
version: "2"

services:
  devkit:
    image: devkitpro/devkita64:latest
    volumes:
      - ".:/code"
    command: bash -c "dkp-pacman -Syu --noconfirm && cd /code && make -j8"

The image is the aarch64 devkitPro image, the repository is mounted at /code, and the command updates the package set with dkp-pacman before running make -j8. The README's own instructions are to install Docker and docker-compose and then run the compose command.

bash
docker-compose up --build

The devkitPro route is the manual one: install devkitPro, install switch-dev, libnx and switch-libjpeg-turbo using dkp-pacman, and then run make.

bash
make

The difference in approach is who owns the toolchain. Docker pins the environment to an image and updates its packages on every run, so a build is reproducible without installing anything on the host beyond Docker itself. The devkitPro route installs a toolchain into your system and leaves version drift to you, which is faster to iterate against but is where build failures on a newer package set come from.

What the build actually produces on the SD card

The Makefile describes the packaging precisely, and the output layout tells you how the module is actually installed on a console.

Two targets are defined at the top, KIPS as ldn_mitm and NROS as ldnmitm_config, and the subfolders built are Atmosphère-libs/libstratosphere, ldn_mitm, ldnmitm_config and overlay. Everything lands under an out directory, with an sd tree inside it.

The config program is a separate NRO placed at switch/ldnmitm_config/ldnmitm_config.nro. The module itself is packaged as an NSP and copied as exefs.nsp into a title directory under atmosphere/contents/4200000000000010, which is where a sysmodule of this kind is expected to live. The overlay file overlay.ovl is copied into switch/.overlays with the name ldnmitm_config.ovl, so the config program is patched in at load time rather than replaced outright. A toolbox.json is copied to the title directory for the on-console toolbox, and a flags/boot2.flag file is touched, which is what makes the module take effect at boot rather than only on demand.

Two things follow from that layout. The module and the config program are not interchangeable parts: the module is the persistent sysmodule, and the config NRO is the user-facing tool that configures it. And because the overlay mechanism is used, a mismatch between the module and the config tool is likely to produce a broken configuration rather than a clean error, which is another reason the version table matters.

The build also has clean and all targets at the top level, and a PACK target that does the copying, so a rebuild after a source change does not need manual steps.

Where this is the wrong tool

The clearest case for putting ldn_mitm aside is a console that runs official software. The module is a replacement for a system service, so it only exists on a console running custom firmware, and on a stock console the local wireless scan works as designed. Nothing about the problem ldn_mitm solves applies there.

The second case is a network where discovery already works. If two consoles can see each other over the console's own wireless radio, the original ldn service does its job and this module adds a moving part for no benefit. The module earns its place when the wireless path is blocked, degraded, or simply unavailable, which is the case the README describes it for.

The third is a firm need for online play rather than local play. This project emulates the local discovery process over LAN UDP, and the games it targets are the ones that support local wireless play. It is not a substitute for an online service, and it is not a general purpose network proxy, despite the name.

There is also a maintenance edge to consider. The module is version-locked to a firmware loader, and the escape hatch when the table runs out is a nightly build rather than a tagged release. A console owner who updates their firmware regularly and expects stable tagged builds will find that the two schedules are not aligned.

And the licence deserves a direct look before use. The software is licensed under the terms of the GPLv2, with exemptions for specific projects, and the exemptions are unusually explicit: the yuzu Nintendo Switch emulator and the Ryujinx Team and Contributors are exempt and may at their individual discretion license any source code authored for the ldn_mitm project as GPLv2 or later or the MIT licence, altering, supplementing or entirely removing the copyright notice for each file they relicense, and neither the ldn_mitm project nor its individual contributors shall assert their moral rights against those projects. Nintendo is exempt as well and may at its option license source code authored for the project under the Zero-Clause BSD licence.

Against the stock service, and the sibling project it was derived from

The natural alternative to ldn_mitm is doing nothing and letting the console's own ldn service run. The difference in approach is where the peer discovery traffic goes. The stock service calls the WiFi service and scans for nearby consoles over the radio, and the module emulates that same scanning process over LAN UDP instead. Same role, different transport, which is why the module is a drop-in replacement rather than a companion that has to be configured to coexist.

The second comparison is with fs_mitm, from which ldn_mitm is described as a mitm kip modified from fs_mitm. Both take the same shape: a sysmodule that intercepts a system communication path. The difference is in which path each one takes over, and the README is not explicit about fs_mitm's role beyond naming it as the source of the modification, so the useful conclusion is limited to this: ldn_mitm is a derived work, not a from-scratch implementation, and the version table only documents compatibility with Atmosphère, not with fs_mitm's own release cadence.

The third alternative is the official route: play online with the publisher's own service. That gives you the same game without any custom firmware, and it is the correct answer for anyone whose goal is playing with distant players rather than with the console down the hall. ldn_mitm exists for the narrow case where you want local play to work on a network where the console's own discovery does not, and the switch-lan-play tool plus the configuration tutorial at lan-play.com/install are the documented path to getting there.

Editorial conclusion

ldn_mitm fits owners of a hacked Switch who want locally supported games to find each other on a wired network or a router that blocks the wireless discovery path, and who are comfortable matching an Atmosphère version to a module version. It does not fit anyone relying on official online play, and it does not fit a build that must run on a console with no custom firmware, since the module is a replacement for a system service rather than a standalone application. Verify three things before you install it: that your Atmosphère version has a matching ldn_mitm release in the version table, that the companion switch-lan-play tool is the configuration path you intend to use, and that the GPLv2 terms and the stated exemptions are acceptable for your situation.

Frequently asked questions

Which Atmosphère version matches my ldn_mitm version?

The README carries a version table mapping each ldn_mitm release to the Atmosphère versions it supports, from ldn_mitm 1.25.1 with Atmosphère 1.11.1 down to 1.3.3 with 0.10. If your firmware is newer than every listed combination, the README points to the GHA nightlies.

How do I build ldn_mitm?

Initialise the submodules with `git submodule update --init --recursive`, then either run `docker-compose up --build` with Docker and docker-compose installed, or install devkitPro with switch-dev, libnx and switch-libjpeg-turbo through dkp-pacman and run `make`.

What does ldn_mitm actually change on the console?

It replaces the system's ldn service, which normally calls the WiFi service to scan for nearby consoles, and emulates that scanning over LAN UDP instead. The README describes it as a mitm kip modified from fs_mitm, and it is normally used together with switch-lan-play.

What licence is ldn_mitm under?

GPLv2, with exemptions listed in the README. The yuzu emulator and the Ryujinx Team and Contributors are exempt and may license code authored for the project as GPLv2 or later or the MIT licence, and Nintendo is exempt and may license it under the Zero-Clause BSD licence.

Official sources

  1. Issues
  2. License: GPL-2.0
  3. README
  4. Releases
  5. spacemeowx2/ldn_mitm on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/spacemeowx2-ldn-mitm.svg)](https://hysenlabs.com/projects/spacemeowx2-ldn-mitm)

Was this useful?