Open-source project
martin-ger/esp_wifi_repeater avatar
martin-ger/esp_wifi_repeater

esp_wifi_repeater: putting a NAT router and an L2 bridge on an ESP8266

A full functional WiFi NAT Router (and now also a WiFi Repeater)

5,267 stars982 forksCMIT

At a glance

What is it?
Ten years of firmware that turns a four-dollar microcontroller into a WiFi access point with firewall ACLs, MQTT control and, since 2026, a true layer two bridge. What the README documents, what the build files reveal, and where the two editions split.
Who is it for?
esp_wifi_repeater is unusual because the hard part is not the code but the ten years of edge cases behind it, and the repository is candid about both halves. Pick the NAT router edition if you want per-device ACLs, port mapping and traffic shaping; pick the layer two bridge edition if you only want coverage and want clients to keep their own IP addresses.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 126 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 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two editions of the same firmware, one tree

The repository leads with an announcement rather than a feature list, and the announcement is about a mode that did not exist for most of the project's life. After ten years, the README says, the project has become what it always pretended to be: a true WiFi repeater. Then it immediately walks that back, because breaking ten years of documentation and links would cost more than the feature gained. The standard edition stays the NAT router everyone already has configured; the new layer two bridge is a separate, stripped down edition you opt into.

The file tree shows how cleanly that split is implemented. There is a `firmware/` directory and a `firmware-repeater/` directory, a `manifest.json` and a `manifest_repeater.json` for the web installer to pick between, and two separate documents, `Bridging.md` and `Layer2Bridging.md`, dedicated to the bridge side. The build files carry the same fork: the Makefile defaults a variable to `default` and switches compiler flags when it is set to `bridge`, adding an include of the bridge configuration header.

make
VARIANT ?= default
ifeq ($(VARIANT),bridge)
    CFLAGS += -include user/user_config_bridge.h
endif

That single variable is the entire difference between the editions at build time, which is worth knowing before you start reading source. GitHub reports the repository description as "A full functional WiFi NAT Router (and now also a WiFi Repeater)" with 5,259 stars, 980 forks and 266 open issues, written in C under the MIT license on the `master` branch. The most recent push was 2026-06-08.

NAT is what makes the router edition work without routing tables

The default mode is a NAT router, and the choice of NAT over bridging is what lets the firmware stay simple. The README is explicit about the consequence: because traffic is translated rather than routed, no routing entries are needed on either the uplink network or on the connected stations. A client joins the ESP's own access point, gets a DHCP lease in the ESP's subnet, and the ESP rewrites the addresses on the way out. That is why a station can be configured with nothing but a WiFi password.

The default addressing is 192.168.4.0/24, and the ESP itself is always x.x.x.1 in whatever subnet you configure, which is the address you use to reach the configuration page. DNS is not run locally: connected stations receive their DNS responder address from the existing uplink network, so name resolution follows whatever your main router already provides.

On first boot, or after a factory reset, the device does something that trips up most people. It offers an open access point named `MyAP` with the password `none`, and it does not attempt to connect to any uplink network, because it has no idea what your SSID and password are. Configuration happens over that open network, and until you change it the device is genuinely open.

bash
set ssid your_home_router's_SSID
set password your_home_router's_password
set ap_ssid ESP's_ssid
set ap_password ESP's_password

Those five commands are the whole minimum setup, entered on the console. The README's own performance claim gives you a realistic expectation of the result: roughly 5 Mbps in both directions, which the author notes is enough for streaming. On hardware that is a 4 MB flash part with a single radio shared between uplink and downlink, that number is the design constraint that explains most of the choices in the rest of the firmware.

The web installer versus the serial console

There are two ways to get firmware onto the chip, and the choice between them is less obvious than it looks. The web installer at `martin-ger.github.io/esp_wifi_repeater` flashes directly onto the device from a browser, which means you never install a cross-compiler at all. That is the fast path, and for most people it is the only path they need.

The other path is the Makefile, and it is worth reading even if you use the installer, because it documents what the firmware actually links against. The toolchain root points at `esp-open-sdk/xtensa-lx106-elf/bin`, which is the ESP8266's Xtensa LX106 cross-compiler. The flash options are hardcoded to 40 MHz flash, DIO mode and a 32 megabit flash size, and the module list pulls in four directories: `driver`, `user`, `mqtt` and `easygpio`.

make
ESPTOOLOPTS	= -ff 40m -fm dio -fs 32m
MODULES		= driver user mqtt easygpio

The library list is the interesting part, because it includes `lwip_open_napt` next to the SDK's own networking stack. That is the patched lwIP with a NAT table in it, which is the whole mechanism behind the router edition. The `rboot.bin`, `rom0.ld` and `rom1.ld` files in the tree are bootloader pieces, and `liblwip_open_napt.a` is a prebuilt archive checked into the repository, so you are not assembling lwIP from source.

For recovery, the README keeps a good escape hatch: `reset factory` works from the serial console even on a locked device, which means a lost configuration password is never a brick. The console is reachable either over the serial port at 115200 baud or over TCP on port 7777 from any connected station.

Locking the configuration and the hex encoding trap

An access point that reopens with the default SSID after a reboot is a security problem, so the firmware has a lock command. It saves the current configuration and refuses further changes until unlocked, and the default unlock password is the uplink network's password, which you can define even when that network is open. The README points out that you can mark the lock box in the web interface too, which is the setting most people will actually use.

The second thing worth understanding before you type anything is the character encoding. Both the web interface and the console expect HTTP-style percent encoding for anything non-ASCII or special, so a space in an SSID becomes `My%20AccessPoint` and decodes back to `My AccessPoint`. On the console only, there is a shortcut using C-style backslash escapes, so `My\ AccessPoint` does the same job.

The reason for the strictness is stated plainly in the README: the encoding path lets you enter any byte value except zero, and zero is excluded for reasons internal to the C implementation. That is a small but telling detail about where the constraints in this firmware come from. The WiFi stack underneath is written in C and expects fixed buffers.

Once you have configured both the uplink and the soft AP, changing the soft AP settings also moves the configuration interface, because the page is served from the access point you just renamed. The README is explicit that after the change you have to reconnect through one of the new networks to keep configuring, and to reach the interface later you need to remember the subnet, since the device is always x.x.x.1 within it.

What the firewall, MQTT and mesh features are actually for

The README's feature sentence is dense, so it is worth unpacking. Beyond forwarding, the firmware includes a packet filtering firewall with ACLs, port mapping, traffic shaping, hooks for remote monitoring or packet sniffing, an MQTT management interface, simple GPIO interaction and power management. The repository topics back this up: `acls`, `firewall`, `nat`, `sniffer` and `wireshark` all appear there, which is a fair signal about what people actually use it for.

The ACL and port mapping features are the reason to choose this project over a generic extender. Those let you build a separate network for untrusted devices, which the README lists as a target scenario alongside guest networks and battery powered outdoor mesh nodes. Traffic shaping is the third piece, and it is the least common of the three in consumer firmware.

Automesh is the other mode worth understanding, because it changes the configuration flow. If you tick the automesh box during setup, the soft AP settings are not configured separately at all; they are identical to the station settings, and every connected repeater offers the same SSID. The README frames this as the configuration for several routers meshed together to cover a larger area. If you do not tick it, the standard split between uplink and soft AP applies.

The remote monitoring hooks are the feature with the clearest niche. The topic list includes packet sniffing and the README mentions a monitor probe for WiFi traffic analysis, which is a different use of the same hardware than range extension. The `mqtt/` module in the tree is what makes the management interface possible, and `easygpio/` is a separate small library for the GPIO interaction, both of which are compiled in by the module list rather than being optional.

Where this project stops and its neighbours begin

The README is unusually clear about scope, which makes it easy to avoid the wrong repository. If you want the NAT feature inside an Arduino sketch, the author points you at a separate project, `lwip_nat_arduino`. If you want more capable hardware, the advanced ESP32 router lives at `esp32_nat_router`, and the README frames this project as the ESP8266 and ESP8285 implementation. Those are three distinct codebases with three sets of issues.

Inside this repository, the README covers first boot, the basic web interface, the command line and its basic and advanced commands, and then stops. The bridge documentation is separate: `Bridging.md` and `Layer2Bridging.md` sit in the tree as their own files rather than as README sections, which suggests the repeater mode is documented at a different depth than the router mode. If you are evaluating the bridge edition specifically, those two files are the ones to read, and the Makefile variable tells you which configuration header your build actually pulled in.

One more practical note for anyone evaluating this seriously. The repository publishes no GitHub releases at all, and it has no homepage field. Version tracking happens through the web installer rather than through tags, so the push date of 2026-06-08 is the only freshness signal available, and a 266-issue backlog is large enough that searching it before you post is worth the minute it costs.

For the underlying engineering, the honest summary is that the NAT router edition has had a decade to accumulate the workarounds that real uplink networks demand, and the bridge edition trades almost all of that away for simplicity. Both are built from the same tree with a single compiler flag, which makes the tradeoff unusually easy to defer until you know which problem you have.

Editorial conclusion

esp_wifi_repeater is unusual because the hard part is not the code but the ten years of edge cases behind it, and the repository is candid about both halves. Pick the NAT router edition if you want per-device ACLs, port mapping and traffic shaping; pick the layer two bridge edition if you only want coverage and want clients to keep their own IP addresses. The build system makes that a one-variable choice, the web installer avoids the toolchain entirely, and the console at 115200 baud or port 7777 is where you will actually spend your time if anything goes wrong. Start with the web installer and the basic web config page, keep the serial console cable within reach for the first hour, and read Layer2Bridging.md before you assume the bridge mode is interchangeable with the router.

Frequently asked questions

Is esp_wifi_repeater still worth using on a modern router?

It depends on what you are solving. As a cheap second access point for a dead zone, hardware with mesh or extenders already built in will do the same thing with less configuration. The cases this firmware covers are the ones a consumer router does not: a separate ACL-restricted network for untrusted devices, traffic shaping, port mapping, an MQTT interface for remote control, or a mesh of battery powered outdoor nodes. The project also runs on ESP8285, so old hardware is not wasted.

What is the difference between the NAT router mode and the L2 bridge mode?

NAT translates addresses, so connected clients get addresses from the ESP's own 192.168.4.0/24 subnet by default and no routing entries are needed anywhere. A layer two bridge forwards frames instead, so clients keep the addresses their own router hands them and see the real network. The README keeps the NAT router as the default edition and ships the bridge as a separate, stripped down build.

How do I recover the ESP if I lose the configuration password?

Run `reset factory` from the serial console. The README states that this works on a locked device when issued from the serial port, which is the one path that bypasses the lock. You will need the console over the serial port at 115200 baud rather than the TCP console on port 7777, because the lock applies to remote configuration changes.

Do I need to install a cross-compiler to build this firmware?

Not if you use the web installer, which flashes the device straight from a browser. Building from source does require the ESP8266 Xtensa LX106 toolchain from esp-open-sdk, and the Makefile hardcodes flash options for 40 MHz, DIO mode and a 32 megabit flash. It also expects a prebuilt lwIP NAT archive checked into the repository rather than assembling lwIP itself.

Official sources

  1. Issues
  2. License: MIT
  3. martin-ger/esp_wifi_repeater on GitHub
  4. README
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/martin-ger-esp-wifi-repeater.svg)](https://hysenlabs.com/projects/martin-ger-esp-wifi-repeater)