ESP Wifi network packet receive callback

Hey,

for a small project i am looking for a way of intercepting all the received packets at the WiFi module of an esp32 or esp8266 to analyze it and pass it on, dropping or rejecting it. Kind of like a firewall.

Is this possible? I was doing some digging and found the promiscuous mode on the esp32. (https://github.com/ESP-EOS/ESP32-WiFi-Sniffer/blob/master/WIFI_SNIFFER_ESP32.ino)

esp_wifi_set_promiscuous(true);
esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler);

After setting up the WiFi, it shows all the packages but i am only interested in the packages for the esp mac address. So how would i create my own implementation of a wifi_rx_cb?

Thanks in Advance

This may be what you are looking for.

http://www.nongnu.org/lwip/2_0_x/group__lwip__opts__hooks.html#ga9124237c28e2f18f3b28d5be09e9ccb6

1 Like

Thank you for that reply. Let's say i connect to the wifi like this:

Serial.begin(115200);
Serial.println();
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, psk);
while (!WiFi.isConnected())
{
  delay(200);
}
Serial.print("IP: ");
Serial.println(WiFi.localIP());

How and where do i have access to the IwIP Hooks? I am totally lost on how i can register the callback. Do i have to change the wifi class to give me access?

It looks like you have to recompile the lwIP library.

This is where it seems to be happening, but this file is not part of the ESP core. Instead liblwip.a is shipped in binary form.

1 Like

That looks good. I am now working with ESP-IDF Framework, changes to that file are compiled and included. Looking at opt.h (lwIP: Hooks) if i want to register that hook do i have to define LWIP_HOOK_IP4_INPUT like this?

#define LWIP_HOOK_IP4_INPUT(pbuf, input_netif) \
    ({                                         \
        0;                                     \
    })

or this

int my_hook(struct pbuf *pbuf, struct netif *input_netif)
{
    ESP_LOGI(TAG, "TESTING!");
    return ESP_OK;
}

#define LWIP_HOOK_IP4_INPUT(pbuf, input_netif) my_hook(pbuf, input_netif)

This looks like a promising attempt.

And here is a discussion on the same topic.

It looks like the key to get the custom hooks imported is to define ESP_IDF_LWIP_HOOK_FILENAME (or LWIP_HOOK_FILENAME depending on which version of the library is used) before the lwIP library is included.

1 Like

Yeah, this is what i found as well. Looks like there is no final/working example around to show how it's done. I will try and get it to work.

Thank you so much for your help!

Good luck.

Once you have it figured out, perhaps you can write a short tutorial for future reference? There is a section for tutorials #using-arduino:introductory-tutorials (although this is a bit of an advanced topic, but still).

1 Like

So far i got it to work with esp-idf and platformIO.
I will look into getting it to work with arduino framework tomorrow. But as you said, i would need to recompile the LwIP library with my custom hook.

Here the files working so far:

// file: <include/lwip_hooks.h>
#ifndef _LWIP_HOOKS_H_
#define _LWIP_HOOKS_H_

#include "lwip/netif.h"
#include "lwip/pbuf.h"
#include "lwip/ip4.h"

#include "esp_log.h"
#include "esp_err.h"

#ifdef __cplusplus
extern "C"
{
#endif

    int lwip_hook_ip4_input(struct pbuf *pbuf, struct netif *input_netif);
#define LWIP_HOOK_IP4_INPUT lwip_hook_ip4_input

#ifdef __cplusplus
}
#endif

#endif /* _LWIP_HOOKS_H_ */
// file: <src/lwip_hooks.c>
#include "lwip_hooks.h"

const char *get_protocol(u16_t type)
{
    switch (type)
    {
    case 1:
        return "ICMP";
    case 6:
        return "TCP";
    case 17:
        return "UDP";
    default:
        return "-";
    }
}

int lwip_hook_ip4_input(struct pbuf *pbuf, struct netif *input_netif)
{
    const struct ip_hdr *iphdr;
    char ip_address[IP_HLEN];

    iphdr = (struct ip_hdr *)pbuf->payload;
    sprintf(ip_address, "%d.%d.%d.%d", ip4_addr1_16_val(iphdr->src), ip4_addr2_16_val(iphdr->src), ip4_addr3_16_val(iphdr->src), ip4_addr4_16_val(iphdr->src));
    ESP_LOGI("HOOK", "%s: %s",
             get_protocol((u16_t)IPH_PROTO(iphdr)), ip_address);
    return ESP_OK;
}
; file: <platformio.ini>

[env:az-delivery-devkit-v4]
platform = espressif32
board = az-delivery-devkit-v4
framework = espidf
monitor_speed = 115200
build_flags = 
    '-Iinclude'
    '-DESP_IDF_LWIP_HOOK_FILENAME="lwip_hooks.h"'

This gives me following output when sending packets:

I (692811) HOOK: UDP: 10.93.0.1
I (693021) HOOK: UDP: 10.93.0.211
I (693431) HOOK: UDP: 10.93.0.51
I (693631) HOOK: UDP: 10.93.0.1
I (694251) HOOK: TCP: 10.93.0.211
I (695781) HOOK: UDP: 10.93.0.51
I (697321) HOOK: TCP: 10.93.0.211
I (697521) HOOK: UDP: 10.93.0.51
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.