This project consists of an ESP32 firmware and a Linux application that transform an ESP32 board into a wireless (WiFi) dongle for a Linux PC, acting either as a wireless client (STA) or an access point (AP).
The esp32-tuntap.py
python script initializes the ESP32's network module and
then tunnels its packets to/from a Linux system, connected over the ESP32
board's built-in USB serial.
The pyserial and
python-pytun modules are required. They
can be installed with pip
as usual; for instance, the following shell commands
create a python virtual environment and install them:
python3 -m venv esp32-tuntap-venv
esp32-tuntap-venv/bin/pip install -r requirements.txt
The esp32-tuntap.py
script can then be launched as follows:
esp32-tuntap-venv/bin/python esp32-tuntap.py --help
Note: root privileges are needed to use serial ports and create TUN/TAP interfaces!
To connect to an existing network with static IP 192.168.1.123
(DHCP client is
not supported yet), assuming your router's IP address is 192.168.1.1
:
# Run the following commands as root (with either "sudo -s" or "su")
# Configure DNS server (8.8.8.8 is Google's DNS server)
echo nameserver 8.8.8.8 > /etc/resolv.conf
# Run esp32-tuntap agent
esp32-tuntap-venv/bin/python esp32-tuntap.py sta \
--ssid YourNetworkName \
--password YourNetworkPassword \
--local-address 192.168.1.123/24 \
--gateway-address 192.168.1.1 \
--up
To create a NAT wireless network sharing your existing eth0
connection:
# Run the following commands as root (with either "sudo -s" or "su")
# Configure NAT
iptables -t nat -A POSTROUTING -s 192.168.199.0/24 -o eth0 -j MASQUERADE
sysctl -w net.ipv4.ip_forward=1
# Run esp32-tuntap agent
esp32-tuntap-venv/bin/python esp32-tuntap.py ap \
--ssid ANewNetworkName \
--password ANewNetworkPassword \
--local-address 192.168.199.1/24 \
--up
Then, open another shell and run the following commands to run a DHCP+DNS server on your new wireless network:
# Run the following commands as root (with either "sudo -s" or "su")
# Ensure dnsmasq is installed
apt install dnsmasq
# Launch it ("tap0" is the network interface created by esp32-tuntap.py)
dnsmasq --interface=tap0 --no-daemon --dhcp-range=192.168.199.2,192.168.199.254,255.255.255.0
Alternatively, if you do not need a DHCP server, clients can be configured with static IP addresses and the following parameters:
- IP address: any address in range
192.168.199.2
-192.168.199.254
- Default gateway:
192.168.199.1
- DNS server:
8.8.8.8
(to use Google's) or your own
To create a wireless network attached to an existing bridge:
# Run the following commands as root (with either "sudo -s" or "su")
# Run esp32-tuntap agent
esp32-tuntap-venv/bin/python esp32-tuntap.py ap \
--ssid ANewNetworkName \
--password ANewNetworkPassword \
--add-to-bridge br0 \
--up
The esp32-tuntap
firmware is just a regular ESP32 IDF-based application.
This section summarizes the steps needed to build and flash it. Further details can be found in the ESP-IDF documentation.
By default, IDF will download the ESP32 toolchain into the .espressif
folder
in your home directory. You can optionally set a different path with the
IDF_TOOLS_PATH
environment variable. For instance:
export IDF_TOOLS_PATH=/home/fabio/esp32-tuntap/.espressif
Clone the git repository and its submodules with:
git submodule init
git submodule update --recursive
Then, initialize the ESP-IDF environment with:
modules/esp-idf/install.sh
If a custom IDF_TOOLS_PATH
value was set when preparing the environment, it
must be set while building too:
export IDF_TOOLS_PATH=/home/fabio/esp32-tuntap/.espressif
We also need to source a script provided by IDF that will set further environment variables:
. modules/esp-idf/export.sh
Then, build the firmware with:
cd firmware
idf.py build
Lastly, it can be flashed to the connected board with:
idf.py flash
DOIT ESP32 DEVKIT V1 (link)
This is this project's main development board. Everything works out of the box.
ESP32-CAM (link)
Modify firmware/main/main.cpp
before building the firmware, to select the
proper LED pin and polarity (by commenting the default values and
uncommenting those for ESP32-CAM):
// ESP32-CAM
static constexpr gpio_num_t ledPin = GPIO_NUM_33;
static constexpr int ledOffValue = 1;
Also, in this board the UART cannot reset the ESP32. Therefore, it will be
necessary to reset it manually every time esp32-tuntap.py
is started (by
pressing the reset button on the back of the board).
Other ESP32 boards are likely to work too, either out of the box or with minimal modifications to pin mappings.