ESP32 Ethernet-WiFi Bridge

May 31, 2026 · View on GitHub

Firmware that creates a plain transparent Layer 2 bridge between an Ethernet port and a WiFi access point. Devices on both sides appear on the same network — no NAT, no routing, no separate subnet.

Derived from esp32_nat_router. The original project is a WiFi NAT router with lot of additional features. This variant operates as a pure L2 bridge: the Ethernet port and WiFi AP share a single broadcast domain, and all frames are forwarded transparently at the MAC layer.

By default, all clients receive their IP addresses from the upstream network's DHCP server. Optionally, the bridge can run its own DHCP server and hand out leases to devices on both sides — Ethernet and WiFi — from a single pool. The bridge itself can obtain a management IP (static or DHCP) for web access and remote administration.

All settings are managed through a browser-based web interface or via the serial console at 115200 bps.


Supported Hardware

Two compile-time variants are provided. Both expose the same feature set and CLI.

WT32-ETH01 (default)

ESP32 module with an integrated LAN8720 Ethernet PHY.

ParameterValue
SoCESP32 (dual-core 240 MHz)
Flash4 MB
Ethernet PHYLAN8720 (internal EMAC)
Ethernet MDCGPIO 23
Ethernet MDIOGPIO 18
PHY address1
PHY powerGPIO 16
Status LEDGPIO 2 (configurable)
Serial115200 bps (UART0)

ESP32-C3 SuperMini + W5500

ESP32-C3 module with a W5500 SPI Ethernet chip. Default wiring (all pins configurable via menuconfig):

W5500 pinGPIO
MISO5
MOSI6
SCLK4
CS7
INT3
RST2
ParameterValue
SoCESP32-C3 (single-core 160 MHz)
Flash4 MB
EthernetW5500 via SPI (~26.67 MHz)
Serial115200 bps (USB Serial/JTAG, /dev/ttyACM0)

More details this setup can be found in this repo.


Use Cases

  • Wireless extension for a wired network — add WiFi access to a switch or router that has no wireless capability (classic WiFi AP)
  • Transparent monitoring tap — capture and inspect all bridged traffic in Wireshark without any client changes
  • Stand-alone Ethernet/WiFi network — set up a self-contained combined Ethernet/WiFi network segment (using the build-in DHCP server)

Features

  • Transparent Layer 2 bridging between Ethernet and WiFi AP
  • WiFi AP with configurable SSID, password, channel, and authentication (WPA2/WPA3)
  • Optional management IP (static or DHCP) for web and remote access
  • Optional built-in DHCP server — serves Ethernet and WiFi clients from a single configurable pool
  • Packet capture to Wireshark over TCP (PCAP streaming, promiscuous mode)
  • Remote console — password-protected TCP CLI on a configurable port
  • Syslog forwarding — ship ESP log output to a remote syslog server via UDP
  • OTA firmware update through the web interface
  • Configurable WiFi TX power, status LED, and timezone
  • AP interface can be enabled/disabled at runtime
  • All settings persisted in NVS flash; survive firmware updates

LED Behavior

  • Solid on: Ethernet link up (idle)
  • Solid off: Ethernet link down
  • Flickering: network traffic activity

Web Interface

Access the web interface from any device connected to the WiFi AP or the Ethernet network. The default address is http://<management-ip> or if the client supports mDNS http://esp32-bridge.local (if you use the default hostname for the device).

Pages

/ — Status

Shows current connection state: Ethernet link status, management IP, connected WiFi clients, byte counters, and uptime. When a web password is set, the login form appears here.

Configuration

Grouped into sections. Changes trigger a reboot to apply.

  • AP Settings — SSID, password, channel, authentication mode (WPA2/WPA3), hidden SSID, enable/disable
  • Management IP — static IP, subnet mask, gateway; leave empty to use DHCP
  • DHCP Server — enable/disable, pool start/end, lease time, DNS override
  • DNS Server — override DNS for AP clients
  • Remote Console — enable/disable, port, interface binding (AP/ETH), idle timeout
  • PCAP Packet Capture — on/off toggle, snaplen
  • Device Management — OTA firmware upload, factory reset

Password Protection

Set a password with set_router_password <password> or through the web interface. When set, the Configuration page requires authentication. Sessions last 30 minutes. Clear the password by setting an empty string.


DHCP Server

The bridge can serve IP addresses to devices on both the Ethernet and WiFi AP sides from a single address pool. This is useful when there is no upstream DHCP server, or when you want the bridge to control the IP range.

Requirements:

  • A static management IP must be configured (set_mgmt_ip) before enabling — the DHCP server needs a fixed address to operate from.
  • The upstream DHCP server (e.g., on your router) should be disabled or have its scope restricted to avoid address conflicts. The bridge cannot block upstream DHCP offers.
  • Changes require a reboot to take effect.

Setup

set_mgmt_ip 192.168.10.1 255.255.255.0 192.168.10.1
dhcps range 192.168.10.50 192.168.10.200
dhcps lease_time 120
dhcps enable
restart

After reboot, devices connecting to the WiFi AP or Ethernet port will receive addresses from the configured pool. The bridge IP (192.168.10.1 in the example above) is used as the default gateway and DNS server unless overridden:

dhcps dns 8.8.8.8

Commands

dhcps                           Show status and active leases
dhcps enable                    Enable DHCP server (requires static IP, reboot to apply)
dhcps disable                   Disable DHCP server (reboot to apply)
dhcps range <start_ip> <end_ip> Set pool address range (max 100 addresses)
dhcps lease_time <minutes>      Set lease duration (1–14400 min, default 120)
dhcps dns <ip>                  Set DNS server to advertise (empty = bridge IP)

To revert to using the upstream DHCP server, run set_mgmt_ip dhcp (this also disables the built-in DHCP server) and reboot.


Packet Capture

Traffic on the bridge can be streamed live to Wireshark over a TCP connection on port 19000. No client software other than netcat and Wireshark is required.

Usage

pcap start
pcap stop
pcap snaplen [<bytes>]
pcap status

Connect from a workstation on the network:

nc <bridge-ip> 19000 | wireshark -k -i -

The connection command is also shown in the PCAP section of the Configuration page. Snaplen limits the captured bytes per packet (64-1600, default 1600).


Remote Console

A TCP server provides a password-authenticated CLI session accessible over the network. It reuses the web interface password. Output from CLI commands is captured and forwarded to the remote session.

remote_console enable
remote_console disable
remote_console port <port>
remote_console bind <ap,eth>
remote_console timeout <seconds>
remote_console kick
remote_console status

Default port is 2323. Connect with any TCP client:

nc <bridge-ip> 2323

The service is disabled by default. A web password must be set before enabling it. Idle sessions are disconnected after the configured timeout (default 300 seconds; 0 disables the timeout). Only one session is active at a time.

The bind option controls which network interfaces the server listens on (AP = WiFi access point, ETH = Ethernet uplink).


Syslog

ESP log output can be forwarded to a remote syslog server over UDP.

syslog enable <server> [<port>]
syslog disable
syslog status

The default port is 514. Configuration is persisted in NVS.


CLI Reference

Connect via serial at 115200 bps, or via the remote console.

Network

CommandDescription
show configAP and Ethernet configuration
set_ap <ssid> <password>Set WiFi AP credentials
set_ap_dns <dns>Set DNS server for AP clients
set_ap_mac <mac>Override AP MAC address
set_ap_hidden <on|off>Hide or show AP SSID
set_ap_auth <wpa2|wpa3|wpa2wpa3>Set AP authentication mode
set_ap_channel <0-13>Set AP WiFi channel (0=auto)
set_wifi_country <CC>Set WiFi regulatory country code (2-char ISO 3166, e.g. US, DE; use 01 for world-safe)
ap <enable|disable>Enable or disable AP interface
set_mgmt_ip <ip> <mask> <gw>Set static management IP
set_mgmt_ip dhcpRevert management IP to DHCP
dhcpsShow DHCP server status and active leases
dhcps enableEnable built-in DHCP server (requires static IP, reboot to apply)
dhcps disableDisable built-in DHCP server (reboot to apply)
dhcps range <start> <end>Set address pool (max 100 addresses)
dhcps lease_time <minutes>Set lease duration (1–14400, default 120)
dhcps dns <ip>DNS server to advertise (empty = bridge IP)
set_hostname <name>Set DHCP hostname
set_tx_power <dBm>Set WiFi transmit power (2-20, 0=max)
set_tz <TZ string>Set POSIX timezone
bytesShow Ethernet byte counters
bytes resetReset byte counters
ping <host> [-c <n>] [-i <ms>] [-W <ms>] [-s <bytes>]Send ICMP echo requests

Packet Capture

CommandDescription
pcap startStart promiscuous capture
pcap stopStop capture
pcap snaplen [<bytes>]Get or set max bytes per packet
pcap statusShow capture statistics

Remote Console and Syslog

CommandDescription
remote_console enableEnable remote console
remote_console disableDisable remote console
remote_console port <port>Set TCP port
remote_console bind <ap,eth>Set interface binding
remote_console timeout <seconds>Set idle timeout
remote_console kickDisconnect active session
remote_console statusShow status
log_level [<level>] [-t <tag>]Get/set log level (none/error/warn/info/debug/verbose)
syslog enable <server> [<port>]Enable syslog forwarding
syslog disableDisable syslog forwarding
syslog statusShow syslog configuration

Web Interface

CommandDescription
web_ui enableEnable web server (after reboot)
web_ui disableDisable web server (after reboot)
web_ui port <port>Set web server port (default 80)
set_router_password <password>Set web/console password

Status and System

CommandDescription
show statusConnection state, clients, heap
show otaOTA partition info
set_led_gpio <gpio|none>Set status LED GPIO
set_led_lowactive <true|false>Set LED to active-low mode
versionShow chip and SDK version
restartSoftware reset of the chip
heapShow current and minimum free heap
tasksList running FreeRTOS tasks
deep_sleep [--time <ms>] [--io <gpio>] [--io_level <0|1>]Enter deep sleep
light_sleep [--time <ms>] [--io <gpio>]...Enter light sleep
factory_resetErase all NVS settings and reboot

W5500 Build Only (ESP32-C3 + W5500)

CommandDescription
set_spi_clock <MHz>Set W5500 SPI clock speed (1–80 MHz). Saved to NVS, applied after restart
w5500 statusShow W5500 register snapshot and SPI error counters
w5500 resetSoft-reset W5500 socket without disturbing lwIP or bridge state

show status also prints the active SPI clock and any SPI error counts when running the W5500 build. The ESP32c3 also reports its CPU temperature.


Building

Requires ESP-IDF v5.x. Source the ESP-IDF environment first:

. $IDF_PATH/export.sh

WT32-ETH01 (default)

./build_firmware.sh

Performs a clean build and copies binaries to firmware/:

firmware/
├── bootloader.bin
├── partition-table.bin
├── ota_data_initial.bin
└── esp32_eth_wifi_bridge.bin

To reconfigure before building:

idf.py -B build_eth_sta menuconfig

ESP32-C3 + W5500

./build_firmware_w5500_c3.sh

Performs a clean build targeting esp32c3 and copies binaries to firmware_w5500_c3/:

firmware_w5500_c3/
├── bootloader.bin
├── partition-table.bin
├── ota_data_initial.bin
└── esp32_eth_wifi_bridge.bin

To reconfigure before building:

idf.py set-target esp32c3 -B build_w5500_c3 \
  -D SDKCONFIG=sdkconfig.w5500_c3 \
  -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.w5500_c3" \
  menuconfig

OTA updates are supported through the web interface (Device Management section) with partition rollback on failed updates.


Installation

WT32-ETH01

esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 \
  write_flash \
  0x1000  firmware/bootloader.bin \
  0x8000  firmware/partition-table.bin \
  0xf000  firmware/ota_data_initial.bin \
  0x20000 firmware/esp32_eth_wifi_bridge.bin

ESP32-C3 + W5500

# SuperMini (USB-JTAG port):
esptool.py --chip esp32c3 --port /dev/ttyACM0 --baud 460800 \
  write_flash \
  0x0000  firmware_w5500_c3/bootloader.bin \
  0x8000  firmware_w5500_c3/partition-table.bin \
  0xf000  firmware_w5500_c3/ota_data_initial.bin \
  0x20000 firmware_w5500_c3/esp32_eth_wifi_bridge.bin

Note: the ESP32-C3 bootloader flashes to 0x0000 (not 0x1000 as on classic ESP32).

First-time setup (both variants)

After flashing, connect via serial at 115200 bps and configure the WiFi AP:

set_ap MyWiFiSSID MyPassword
restart

The bridge will reboot. Connect a WiFi client to the AP — it will receive an IP from the upstream network's DHCP server (or from the bridge's own DHCP server if configured). You can then access the web interface at http://esp32-bridge.local (mDNS) or set a static management IP:

set_mgmt_ip 192.168.1.200 255.255.255.0 192.168.1.1

To erase all settings and return to defaults:

factory_reset

or via esptool (full flash wipe):

# ESP32 (WT32-ETH01)
esptool.py --chip esp32 --port /dev/ttyUSB0 erase_flash

# ESP32-C3 + W5500
esptool.py --chip esp32c3 --port /dev/ttyACM0 erase_flash