esp_wifi_repeater

全功能WiFi中继器(正确:WiFi NAT路由器)。【 A full functional WiFi Repeater (correctly: a WiFi NAT Router) 】

Github stars Tracking Chart

esp_wifi_repeater

全功能WiFi中继器(正确:WiFi NAT路由器)

这是esp8266和esp8285上WiFi WiFi路由器的实现。它还包括带有ACL的基本防火墙,端口映射,流量整形,用于远程监控(或数据包嗅探)的钩子,MQTT管理接口和电源管理。对于具有网格中多个路由器以覆盖更大区域的设置,已包括新模式“Automesh”( https://github.com/martin-ger/esp_wifi_repeater#automesh-mode

典型的使用场景包括:

  • 现有WiFi网络的简单范围扩展器
  • 为来宾或物联网设备设置具有不同SSID /密码的其他WiFi网络
  • 电池供电的室外(网状)网络
  • 监控WiFi流量分析探针

ESP充当STA和软AP,并通过它透明地转发任何IP流量。由于它使用NAT,在网络侧和连接的站点上都不需要路由条目。在192.168.4.0/24网络中,站点默认通过DHCP进行配置,并从现有WiFi网络接收DNS响应者地址。

测量显示,它可以在两个方向上实现大约5 Mbps的速度,因此即使是流式传输也是如此。

以下视频介绍了一些详情: https://www.youtube.com/watch?v=OM2FqnMFCLw

关于WPA2企业(PEAP)的说明

如果您需要一个将带有PEAP认证的WPA2企业网络转换为WPA2-PSK网络的“转换器”,请查看 https://github.com/martin-ger/esp_peap_psk 。正在尝试将此功能集成到此项目中 - 但这很难,因为WPA2企业在认证过程中需要非常多的免费堆,几乎没有任何其他内存可用。所以我决定把它留在一个单独的项目中。

关于WPA2 KRACK安全问题的提示

最新的固件(2017年10月17日之后)已经使用Espressif SDK 2.1.x的补丁版本构建,可以减轻KRACK( https://www.krackattacks.com/)攻击。

第一次启动

esp_wifi_repeater从以下默认配置开始:

  • ap_ssid:MyAP,ap_password:none,ap_on:1,ap_open:1
  • 网络:192.168.4.0/24

首次启动(或出厂重置)后,它将提供一个带有开放式AP和ssid“MyAP”的WiFi网络。它尚未尝试自动重新连接到上行链路AP(因为它不知道有效的ssid或密码)。

连接到这个WiFi网络,通过简单的网络界面进行基本配置,或通过控制台进行所有配置的完整配置。

基本Web配置界面

Web界面允许配置基本转发功能所需的所有参数。感谢rubfi在这方面的主要工作: https://github.com/rubfi/esp_wifi_repeater/。将浏览器指向 http://192.168.4.1。此页面应该显示:

首先输入上行WiFi网络的适当值,“STA设置”,然后点击“连接”。开放网络使用密码“无”。 ESP重新启动并将连接到您的WiFi路由器。状态指示灯应该在几秒钟后闪烁。

现在您可以重新加载页面并更改“Soft AP Settings”。点击“设置”,ESP再次重启。现在可以通过新配置的软AP转发流量了。请注意,这些更改也会影响配置界面,即进行进一步配置,通过新配置的WiFi网络之一连接到ESP。对于通过软AP访问,请记住软AP网络的地址(如果您已更改该地址)(ESP在此网络中始终具有地址x.x.x.1)。

如果你愿意,你可以标记“锁定”复选框并点击“锁定”。现在如果没有使用上行WiFi网络的密码进行解锁,配置就无法再进行更改(即使网络已打开,也要定义一个密码)。

如果你犯了一个错误,并且你失去了与ESP的任何联系,你仍然可以使用串行控制台来恢复它(“reset facory”,见下文)。

命令行界面

高级配置必须通过控制台界面上的命令行完成。该控制台可以通过115200波特的串行端口或通过TCP端口7777(例如,来自连接的STA的“telnet 192.168.4.1 7777”)获得。

使用以下命令进行初始设置:

  • 设置ssid your_home_router's_SSID
  • 设定密码your_home_router's_password
  • 设置ap_ssid ESP's_ssid
  • 设置ap_password ESP's_password
  • show(检查参数)
  • 保存
  • 重置

如果您想在命令行中输入非ASCII或特殊字符,可以使用引号:或者使用带有反斜杠的C形引号,如“My \ AccessPoint”或使用HTTP风格的十六进制编码,如“My%20AccessPoint ”。这两种方法都会产生一个字符串“My AccessPoint”。使用十六进制编码,您可以输入任何您喜欢的字节值,除了0(由于C内部原因)。

命令行了解更多命令:

基本命令

足以让它在几乎所有环境中都能正常工作。

  • help:打印简短的帮助信息
  • set [ssid | password] value :更改上行链路AP(家庭路由器的WiFi配置)的设置,开放网络使用密码“none”。
  • 设置[ap_ssid | ap_password] :更改ESP(针对您的电台)的软AP的设置
  • show [config | stats]:打印当前配置或某些状态信息和统计信息
  • save [dhcp]:将当前配置参数[+当前的DHCP租约]保存为
  • 锁定[_password_]:保存并锁定当前配置,不允许更改。如果之前已设置密码,则密码可以保持打开状态(默认为上行WiFi密码)
  • 解锁密码:解锁配置,需要锁定命令中的密码
  • 重置[factory]:重置esp,'factory'可选地将WiFi参数重置为默认值(仅在串行控制台上锁定的设备上工作)
  • quit:终止远程会话

高级命令

大多数设置命令只有在保存和重置后才有效。

Automesh config

  • 设置automesh [0 | 1]:选择自动关闭模式是打开还是关闭(默认),详情请看 https://github.com/martin-ger/esp_wifi_repeater#automesh-mode
  • set am_scan_time secs :设置ESP在automesh模式下尝试在休眠前查找上行链路AP的时间间隔(以秒为单位)(禁用0,默认值)
  • 设置am_sleep_time <秒>秒:设置ESP在没有找到上行链路AP时以automesh模式休眠的时间间隔(0禁用,默认)

WiFi配置

  • set ap_on [0 | 1]:选择是否禁用软AP(ap_on = 0)或启用(ap_on = 1,默认)
  • set ap_open [0 | 1]:选择软AP是否使用WPA2安全性(ap_open = 0,自动,如果设置了ap_password)或打开(ap_open = 1)
  • 设置auto_connect [0 | 1]:选择STA是否应该继续重试连接到AP。 auto_connect在第一次闪烁或“重置工厂”之后关闭(0)。当您输入新的SSID时,它将自动设置为(1)。
  • set ssid_hidden [0 | 1]:选择是否隐藏软件AP的SSID(ssid_hidden = 1)或可见(ssid_hidden = 0,默认值)
  • 设置phy_mode [1 | 2 | 3]:设置WiFi的PHY_MODE(1 = b,2 = g,3 = n(默认))
  • set bssid xx:xx:xx:xx:xx:xx :设置要连接的上行链路IP的特定BSSID(默认00:00:00:00:00:00表示任何)
  • set [ap_mac | sta_mac] xx:xx:xx:xx:xx:xx :将STA和SOFTAP的MAC地址设置为用户定义的值(第一个字节MAC地址不能是1)
  • 设置sta_hostname 名称:设置STA的名称(对上行链路AP可见)
  • 扫描:扫描AP
  • connect:尝试使用当前配置的 ssid 密码连接到AP
  • 断开连接:断开与任何上行链路

TCP/IP配置

  • ping ip-addr :使用ICMP回应请求/回复检查IP连接
  • set network ip-addr :设置内部网络的IP地址,网络始终为/24,路由器始终为x.x.x.1
  • set dns dns-addr :设置通过DHCP分发给客户端的静态DNS地址
  • set dns dhcp:配置使用来自DHCP的动态DNS地址,默认
  • set ip ip-addr :为上行网络中的ESP设置一个静态IP地址
  • set ip dhcp:配置上行网络中ESP的动态IP地址,默认为
  • set netmask netmask :为上行网络设置静态网络掩码
  • set gw gw-addr :在上行网络中设置静态网关地址
  • portmap add [TCP | UDP] _external port _internal ip _internal port :添加端口转发
  • portmap删除[TCP | UDP] _external 端口:删除端口转发

Firewall/Monitor 配置

  • acl [from_sta | to_sta] [TCP | UDP | IP] src-ip [_src_port_] desr-ip [_dest_port_] [allow | deny | allow_monitor | deny_monitor ]:为ACL添加新规则
  • acl [from_sta | to_sta] clear:清除整个ACL
  • show acl:显示定义的ACLs和一些统计信息
  • set acl_debug [0 | 1]:打开/关闭ACL调试输出 - 拒绝的数据包将被记录到终端中
  • set [upstream_kbps | downstream_kbps] bitrate :设置最大上行/下行比特率(0 =无限制)
  • monitor [on | off | acl] port :启动和停止给定端口上的监视服务器

Interface config

  • 设置config_port portno :设置控制台登录的端口号(默认为7777,禁用远程控制台配置)
  • set web_port portno :设置Web配置服务器的端口号(默认为80,0禁用Web配置)
  • 设置config_access 模式:控制允许配置访问控制台和网络的网络(0:无访问,1:只有内部,2:只有外部,3:都是(默认))

芯片配置

  • 设置速度[80 | 160]:设置CPU时钟频率(默认80 Mhz)
  • 睡眠:将ESP进入深度睡眠状态达指定的秒数。有效值介于1和4294之间(约71分钟)
  • set status_led GPIOno :为状态指示灯选择一个GPIO引脚(默认值为2,禁用&gt; 16)
  • set hw_reset GPIOno:选择GPIO引脚进行硬件恢复出厂设置(>16禁用,默认)
  • set ap_watchdog secs:设置AP看门狗超时 - 如果没有收到来自上行链路AP的秒数,则转发器重置(“none”= no timeout,default)
  • set client_watchdog secs:设置客户端看门狗超时 - 如果从任何连接的客户端收到的秒没有收到数据包,则转发器将重置(“none”= no timeout,default)
  • 设置vmin 电压:设置mV中的最小电池电压。如果Vdd下降,ESP进入深度睡眠。如果为0,则没有任何反应
  • 设置vmin_sleep <秒>秒:设置ESP在低电压时睡眠的时间间隔(秒)

状态LED

在默认配置中,GPIO2配置为驱动状态LED(连接到GND),并带有以下指示:

  • 永久开启:已启动,但未成功连接到AP(无效的外部IP)
  • 闪烁(每秒1次):正在工作,连接到AP
  • 不定期闪烁:正在工作,内部网络中的流量

使用“set status_led GPIOno”可以改变GPIO引脚(任何值> 16,例如“set status_led 255”将完全禁用状态指示灯)。配置为GPIO1时,它可与ESP-01板上的buildin蓝色LED配合使用。但是,由于GPIO1也是UART-TX引脚,这意味着串行控制台不工作。配置仅限于网络访问。

端口映射

为了允许来自外部网络的客户端连接到内部网络上的服务器端口,端口必须被映射。外部端口映射到特定内部IP地址的内部端口。使用“portmap add”命令。端口映射可以使用“show”命令列出,并以当前配置保存。

但是,为了确保预期的设备正在侦听某个IP地址,必须确保这些设备具有相同的IP地址,一旦它或ESP重新启动。为此,可以在设备中配置固定IP地址,或者ESP必须记住其DHCP租约。这可以通过“save dhcp”命令来实现。它保存当前状态和所有DHCP租约,以便重新启动后恢复它们。 DHCP租约可以通过“show stats”命令列出。

自动混合模式

有时您可能想要在一排或一个网格中使用多个esp_wifi_repeaters来覆盖更大的距离或面积。通常,这可以在NAT路由器没有任何问题的情况下完成,实际上你会有几层NAT。但是,这意味着连接是有限的:所有节点都可以与互联网通话,但通常节点之间没有直接的IP连接。而且,当然,可用带宽越多,就越需要更多的跳跃。但用户报告说,连续5个esp_wifi_repeaters工作得很好。

在这样的设置中,配置是相当耗时且易出错的活动。为了简化,esp_wifi_repeater现在有一个新的模式:“Automesh”。只需配置SSID和密码并打开“automesh”即可。 (在CLI中用“set automesh 1”或在Web界面上选中复选框)。这将执行以下操作:

以这种方式配置的每个esp_wifi_repeater将自动在AP上提供与其连接的SSID /密码相同的WiFi网络。客户可以对原始网络或重复的网络使用相同的WiFi设置。每个配置了“automesh”的esp_wifi_repeater将首先搜索要连接的最佳其他AP。这是最接近原始WiFi网络,并具有最好的信号强度(RSSI)。

信号强度很容易通过扫描来测量,但是当您看到多个具有相同SSID的接入点时,它最接近原始WiFi网络?因此,该协议使用了一个有点肮脏的技巧:“automesh”模式下的esp_wifi_repeaters操纵其BSSID(实际上,根据IEEE 802.11标准,这是“ESSID”,因为它是一个AP,但SDK称它为“BSSID”),即它们AP接口的MAC地址,每个信标帧10每秒发送一次时间。它使用格式:24:24:mm:rr:rr:rr。 “24:24”就是这样中继器的唯一标识符(与真实的AP MAC发生冲突的概率很小,但我们可以忽略这一点,因为如果真的需要,我们可以更改该前缀)。 “mm”表示“网格级别”,这是跳至原始WiFi网络的距离。最后三个“rr:rr:rr”只是用来区分各种ESP的随机数字。原始AP保留其BSSID,即没有前缀“24:24”的那个被识别为根,称为网格级别0。

现在每个esp_wifi_repeater都可以了解哪个esp_wifi_repeater距离原始WiFi网络最近,可以连接到该网络,并相应地选择自己的BSSID。此外,内部网络的IP地址也会调整为网格级别:10.24.m.0。这将创建一个以原始WiFi AP为根的树(一个非常特殊的网格),并在几个网格层次上重复节点(实际上,它与链路层上的生成树协议(STP)或网络层上的路由有点相似距离矢量协议)。一旦检测到上行链路链路丢失,重新启动配置。这应该避免循环,因为在(重新)配置期间也不会发送带有BSSID的信标。

为方便起见,“automesh”配置后的esp_wifi_repeater首先尝试检查它是否可以连接到上行链路AP。如果失败,即使找到了正确SSID的AP,它也会假设用户对密码进行了错误操作并重置为出厂默认设置。连接成功一次后,它将假定配置正确,并且只要需要连接丢失或重置就可以继续尝试(避免配置错误的AP进行DOS攻击)。

如果已将GPIO16连接到RST,则可以在automesh模式下使用_am_scan time 和_am_sleep time 两个参数进行电源管理。启动后,esp_wifi_repeater会扫描_am_scan time 时间秒的avilable上行链路AP。如果找不到,则进入深度睡眠状态_am_sleep time 秒,并在重新启动后再次尝试(默认为0 =禁用这两个参数)。

监控

通过控制台可以启动显示器服务(“monitor on [portno]”)。此服务将pcap格式的内部网络流量镜像到TCP流。例如。从外部网络中的计算机使用“netcat [external_ip_of_the_repeater] [portno] | sudo wireshark -k -S -i - ”,您现在可以实时观察内部网络中的流量。使用此例如观察您的内部客户与哪些互联网站进行通信。请注意,这至少会将esp和WiFi网络的负载加倍。在负载较重的情况下,这可能会导致一些数据包在监视器会话中被缩短甚至丢失。小心:将此端口打开是潜在的安全问题。任何来自本地网络的人都可以连接并观察您的流量。

防火墙

ESP路由器有一个集成的基本防火墙。 ACL(访问控制列表)可以应用于SoftAP接口。这是物联网安全的基石,当路由器用于将其他物联网设备带入互联网时。它可以用来防止例如第三方物联网设备从“打电话到家里”,被滥用为恶意软件,并保护家庭网络中的PC,平板电脑和手机不被家庭自动化设备看到。

这两个接口上的四个ACL列表分别命名为“from_sta”,“to_sta”,“from_ap”和“to_ap”(“sta”表示到连接器客户端的接口,“ap”上行链路AP)。 ACL在“CISCO IOS风格”中定义。以下示例将允许向本地代理传出本地广播(用于DHCP),UDP 53(DNS)和TCP 1883(MQTT),任何其他数据包将被阻止:

  • acl from_sta清除
  • acl from_sta IP any 255.255.255.255 allow
  • acl from_sta UDP任何任何53都允许
  • acl from_sta TCP任何192.168.0.0/16 1883都允许
  • acl from_sta IP any any deny

也可以定义“to_sta”方向的ACL,但这通常不是必需的,因为通过NAT转换,反向方向可以很好地防止未经请求的流量。

ACL包含为每个数据包处理的过滤规则。每个规则由协议(IP,TCP或UDP),源地址/端口,目标地址/端口以及“允许”或“拒绝”操作组成。在普通IP无端口的情况下,只给出地址。 IP规则包括TCP和UDP数据包。地址可以以“/”符号的子网地址给出,例如, 192.168.178.0/24。另外,“any”可以用作通配符,它匹配任何地址或端口号。规则由“acl”命令定义:

  • acl [from_sta | to_sta | from_ap | to_ap] [TCP | UDP | IP] src-ip [_src_port_] desr-ip [_dest_port_] [允许|拒绝| allow_monitor | deny_monit或

这些规则按照它们在列表中出现的顺序从上到下进行处理。匹配数据包的第一条规则被应用并确定数据包是被允许(并被转发)还是被拒绝(并被丢弃)。这意味着,首先是特殊情况,最后是一般规则。如果ACL中有规则,则所有不符合任何规则的数据包都会被默认拒绝。因此,上述示例中的最后一条规则“from_sta IP any any deny”并不是真的需要,因为它是默认值。如果ACL为空,则允许所有数据包。

ACL规则的定义也是自上而下的:总是在列表的末尾添加新规则。要更改ACL,首先必须清除它(acl from_sta clear),然后重建它。 ACL与配置一起保存。 “show acl”将打印出ACL以及每个规则的点击次数以及允许和拒绝的数据包总数的统计信息。

使用命令“set acl_debug 1”,将所有被拒绝的数据包摘要打印到控制台。此外,MQTT主题可以发布此摘要。这可以用于防火墙配置,以确定要使连接的设备工作所需的规则。如果发生意外的流量(并且被拒绝),它也会给出提示。

为了进行更深入的分析,可以使用监控服务(即使被拒绝的数据包在丢弃之前也会向监视器报告)。当监视器使用“monitor acl port ”命令启动时,ACL可以用作联机筛选器。所有被定义为的规则 像往常一样处理“allow_monitor”而不是“allow”和“deny_monitor”而不是“deny”,从而允许转发分组,但是它们也将分组发送到监视器。因此,基本上“允许”或“允许监听”所有数据包的规则列表仍然有意义,因为它可用于在catpure时间内已经选择哪个数据包应该被记录。例如。一个列表:

  • acl from_sta清除
  • acl from_sta IP 192.168.0.0/16 any allow_monitor
  • acl from_sta IP any any allow
  • acl to_sta清除
  • acl to_sta IP any 192.168.0.0/16 allow_monitor
  • acl to_sta IP any any allow

将允许所有数据包,并选择所有数据包进行从站到192.168.0.0/16(本地)子网和从192.168.0.0/16到站的监控。当然,这样的过滤器也可以在捕获到完整的监控跟踪之后应用,但是如果您已经知道,您在寻找什么,这些在线过滤器将有助于大幅降低监控开销。它也可以用来调试所有拒绝防火墙规则,只需使用“deny_monitor”而不是拒绝。

比特率限制

通过将upstream_kbps和downstream_kbps设置为值!= 0(默认值为0),您可以限制ESP的AP的最大比特率。该值是适用于所有连接客户端的流量的限制。将放弃定义比特率的数据包。流量整形器使用“令牌桶”算法,桶的大小为当前每秒四倍的比特率,允许在之前没有流量时发生突发。

MQTT支持

从版本1.3开始,路由器有一个内置MQTT客户端(感谢Tuan PM为他的图书馆 https://github.com/tuanpmt/esp_mqtt )。这可以帮助将路由器/中继器集成到物联网中。家庭自动化系统可以例如基于关于当前相关站的信息作出决定,它可以打开和中继器(例如基于时间表),或者它可以简单地用于监视负载。路由器可以连接到本地MQTT代理或连接到云中的公共代理。但是,目前它不支持TLS加密。

默认情况下,MQTT客户端被禁用。可以通过将config参数“mqtt_host”设置为不同于“none”的主机名来启用它。要配置MQTT,您可以设置以下参数:

  • 设置mqtt_host _IP_或<主机名> :MQTT代理的IP或主机名(“none”禁用MQTT客户端)
  • set mqtt_port port :用于连接的MQTT代理的端口(默认值:1883)
  • 设置mqtt_user 用户名:用于身份验证的用户名(如果代理无需身份验证,则为“none”)
  • 设置mqtt_user 密码:用于身份验证的密码
  • 设置mqtt_id clientId :代理处客户端的ID(默认值:源自MAC地址的“ESPRouter_xxxxxx”)
  • 设置mqtt_prefix _prefix 路径:所有已发布主题的前缀(默认值:“/WiFi/ESPRouter_xxxxxx/system”,同样源自MAC地址)
  • 设置mqtt_command_topic _command topic :订阅接收命令的主题,与控制台相同。 (默认:“/WiFi/ESPRouter_xxxxxx/command”,“none”通过MQTT禁用命令)
  • set mqtt_interval secs :设置路由器publis的时间间隔hs状态主题(默认:15s,0禁用状态发布)
  • 设置mqtt_mask _mask_in 十六进制:选择发布哪些主题(默认:“ffff”表示全部)

可以使用“show mqtt”命令显示MQTT参数。

路由器可以定期发布以下状态主题(每个mqtt_interval):

  • _prefix 路径/Uptime:自s上次重置后的系统正常运行时间(掩码:0x0020)
  • _prefix 路径/Vdd:电源电压,单位为mV(掩码:0x0040)
  • _prefix 路径/Bpsin:来自工作站的Bytes/s到AP(掩码:0x0800)
  • _prefix 路径/Bpsout:从AP到工作站的字节数(掩码:0x1000)
  • _prefix 路径/Ppsin:从工作站到AP的包/s(掩码:0x0200)
  • _prefix 路径/Ppsout:从AP到工作站的数据包(掩码:0x0400)
  • _prefix 路径/Bin:从站到AP的总字节数(掩码:0x0100)
  • _prefix 路径/Bout:从AP到工作站的总字节数(掩码:0x0100)
  • _prefix 路径/NoStations:当前连接到AP的站数(掩码:0x2000)

另外它可以在事件的基础上发布:

  • _prefix 路径/join:加入AP的站点的MAC地址(掩码:0x0008)
  • _prefix 路径/leave:离开AP的站点的MAC地址(掩码:0x0010)
  • _prefix 路径/IP:通过DHCP接收路由器时的IP地址(掩码:0x0002)
  •  <em> path </em>/ScanResult:“扫描”命令的结果的单独主题(每个找到的AP有一条消息)(掩码:0x0004)
    <li> _prefix <em>路径</em>/ACLDeny:数据包已被ACL规则拒绝并被丢弃(掩码:0x0080)</li>
        

路由器可以使用以下主题进行配置:

  • _command topic :路由器订阅此主题并将所有消息解释为命令行
  • _prefix path /response:路由器在此主题上发布命令行输出(掩码:0x0001)

如果您现在希望路由器发布例如只有Vdd,其IP和命令行输出,将mqtt_mask设置为0x0001 | 0x0002 | 0x0040(=“set mqtt_mask 0043”)。

电源管理

中继器监视其当前电源电压(显示在“show stats”命令中)。如果 vmin (以mV为单位,默认值为0)被设置为值&gt; 0并且电源电压降至此值以下时,它将进入深度睡眠模式以进行_vmin 睡眠秒。如果您已将GPIO16连接到RST(在ESP-01上很难焊接),它将在此间隔后重新启动,尝试重新连接并继续其测量。如果 vmin 与配置保存在一起,它会一遍又一遍地休眠,直到电源电压升高到阈值以上。如果您使用(锂)电池为ESP供电而没有充电保护,则这些设置特别有用(仅适用于)。然后,2900mV-3000mV的值可能会有所帮助,因为它将ESP的功耗降至最低,并且在损坏之前您有更多时间对电池进行充电或更换。这只有有意义,如果你有ESP直接连接到电池。如果你有额外的逻辑,这仍然会耗尽电池。

您可以使用“睡眠”命令手动发送ESP进入睡眠状态。

小心:如果您将 vmin 值保存为高于最大电源电压以闪烁,则每次重新启动后,中继器都会立即关闭。然后,您必须通过将blank.bin(或任何其他文件)闪烁到0x0c000来清除整个配置。

构建和闪烁

要构建这个二进制文件,你需要下载并安装esp-open-sdk( https://github.com/pfalcon/ESP-开放式的SDK )。请确保,您可以编译并下载包含的“闪烁”示例。

然后将该源代码树下载到一个单独的目录中,并调整Makefile中的BUILD_AREA变量以及user/user_config.h中的所需选项。使用“make”构建esp_wifi_repeater固件。 “make flash”将其闪烁到esp8266上。

源代码树包含liblwip_open的二进制版本以及来自我的esp-open-lwip分支的所需附加内容。 不需要额外的安装操作。仅当您不想使用预编译库时,请检查 https://github.com/martin-ger/esp-open-lwip 。用它来替换esp-open-sdk树中的目录“esp-open-lwip”。 esp_open_lwip目录中的“make clean”,并再次在esp_open_sdk目录中的“make”。这将编译一个包含NAT特性的liblwip_open.a。将liblwip_open_napt.a替换为该二进制文件。

如果要使用完整的预编译固件二进制文件,可以使用“esptool.py --port/dev/ttyUSB0 write_flash -fs 4MB -ff 80m -fm dio 0x00000 firmware/0x00000.bin 0x10000 firmware/0x10000.bin“(对于ESP-01,使用-fs 1MB)对于esp8285,您必须使用-fs 1MB和-fm dout。

在Windows上,您可以使用 https://espressif.com/上提供的“ESP8266下载工具”将其刷新。恩/支持/下载/其它工具的。从固件目录下载两个文件0x00000.bin和0x10000.bin。对于通用ESP12,NodeMCU或Wemos D1使用以下设置(对于ESP-01将FLASH SIZE更改为“8Mbit”):

如果设备上的“QIO”模式失败,请尝试使用“DIO”。还可以查看“检测到的信息”来检查闪存芯片的大小和模式。

有时,特别是在旧的ESP-01上,闪存中存在错误或不匹配的“esp_init_data_default.bin”版本。如果上面的固件文件正确闪烁,但在重新启动后,您只能看到串口上的垃圾和/或GPIO2上的LED正在快速闪烁,请尝试重新初始化此扇区:download https://github.com/martin-ger/esp_wifi_repeater/raw/master/firmware/esp_init_data_default_v08_vdd33.bin 并将其闪烁为0x7c000对于512 MB模块(某些ESP-01,Sonoff Switch),对于1 MB模块(大多数ESP-01)为0xfc000,对于4 MB模块(大多数ESP-12,Wemos D1)为0x3fc000。

如果下载的固件仍然无法正常启动,请检查所附的校验和是否可能损坏二进制文件。

已知问题

  • 由于ESP的SoftAP实施的限制,最多有8个同时连接的站点。
  • 通过TCP配置(write_flash)需要良好的电源。试着检查一下,如果你ESP运行不稳定。如果您遇到问题,Vdd和Gnd之间的大电容可以提供帮助。

Overview

Name With Ownermartin-ger/esp_wifi_repeater
Primary LanguageC
Program languageMakefile (Language Count: 3)
Platform
License:MIT License
Release Count0
Created At2016-12-16 11:41:52
Pushed At2023-12-24 00:44:14
Last Commit At2021-04-08 20:52:24
Stargazers Count4.7k
Watchers Count238
Fork Count891
Commits Count356
Has Issues Enabled
Issues Count486
Issue Open Count229
Pull Requests Count35
Pull Requests Open Count4
Pull Requests Close Count9
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private

esp_wifi_repeater

A full functional WiFi repeater (correctly: a WiFi NAT router)

This is an implementation of a WiFi NAT router on the esp8266 and esp8285. It also includes support for 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. For a setup with multiple routers in a mesh to cover a larger area a new mode "Automesh" has been included https://github.com/martin-ger/esp_wifi_repeater#automesh-mode .

If you are looking for a way to integrate the NAT feature into your Arduino project - see https://github.com/martin-ger/lwip_nat_arduino .

A similar NAT feature for the ESP32 can be found at: https://github.com/jonask1337/esp-lwip .

Typical usage scenarios include:

  • Simple range extender for an existing WiFi network
  • Battery powered outdoor (mesh) networks
  • Setting up an additional WiFi network with different SSID/password for guests
  • Setting up a secure and restricted network for IoT devices
  • Translating WPA2 Enterprise networks to WPA-PSK
  • Monitor probe for WiFi traffic analysis
  • Network experiments with routes, ACLs and traffic shaping
  • Meshed IoT device with basic I/O capabilities and MQTT control

By default, the ESP acts as STA and as soft-AP and transparently forwards any IP traffic through it. As it uses NAT no routing entries are required neither on the network side nor on the connected stations. Stations are configured via DHCP by default in the 192.168.4.0/24 net and receive their DNS responder address from the existing WiFi network.

Measurements show, that it can achieve about 5 Mbps in both directions, so even streaming is possible.

Some details are explained in this video: https://www.youtube.com/watch?v=OM2FqnMFCLw

First Boot

The esp_wifi_repeater starts with the following default configuration:

  • ap_ssid: MyAP, ap_password: none, ap_on: 1, ap_open: 1
  • network: 192.168.4.0/24

After first boot (or factory reset) it will offer a WiFi network with an open AP and the ssid "MyAP". It does not yet try to automatically re-connect to an uplink AP (as it does not know a valid ssid or password).

Connect to this WiFi network and do the basic configuration either via a simple web interface or the full config with all options via the console.

Basic Web Config Interface

The web interface allows for the configuration of all parameters required for the basic forwarding functionality. Thanks to rubfi for the major work on that: https://github.com/rubfi/esp_wifi_repeater/ . Point your browser to "http://192.168.4.1". This page should appear:

First enter the appropriate values for the uplink WiFi network, the "STA Settings". Use password "none" for open networks. Check the "Automesh" box if and only if you really want to use the automesh mode. Click "Connect". The ESP reboots and will connect to your WiFi router. The status LED should be blinking after some seconds.

If you have selected automesh, you are done with config. Configuring the "Soft AP Settings" is not required as in automesh mode these settings are identical to the "STA Settings". The same ssid will be offered by all connected ESP repeaters.

If you are not using automesh, you can now reload the page and change the "Soft AP Settings". Click "Set" and again the ESP reboots. Now it is ready for forwarding traffic over the newly configured Soft AP. Be aware that these changes also affect the config interface, i.e. to do further configuration, connect to the ESP through one of the newly configured WiFi networks. For access through the Soft AP remember the address of the Soft APs network if you have changed that (the ESP has always the address x.x.x.1 in this network).

If you like, you can mark the "lock" checkbox and click "Lock". Now the config cannot be changed anymore without first unlocking it with the uplink WiFi network's password (define one even if the network is open).

If you want to enter non-ASCII or special characters in the web interface you have to use HTTP-style hex encoding like "My%20AccessPoint". This will result in a string "My AccessPoint". With this hex encoding you can enter any byte value you like, except for 0 (for C-internal reasons).

If you made a mistake and have lost all contact with the ESP you can still use the serial console to recover it ("reset factory", see below).

Command Line Interface

Advanced configuration has to be done via the command line on the console interface. This console is available either via the serial port at 115200 baud or via tcp port 7777 (e.g. "telnet 192.168.4.1 7777" from a connected STA).

Use the following commands for an initial setup:

  • 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
  • show (to check the parameters)
  • save
  • reset

Again, if you want to enter non-ASCII or special characters you can use HTTP-style hex encoding (e.g. "My%20AccessPoint") or, only on the CLI, as shortcut C-style quotes with backslash (e.g. "My\ AccessPoint"). Both methods will result in a string "My AccessPoint".

The command line understands a lot more commands:

Basic Commands

Enough to get it working in nearly all environments.

  • help: prints a short help message
  • set [ssid, password] value: changes the settings for the uplink AP (WiFi config of your home-router), use password "none" for open networks.
  • set [ap_ssid, ap_password] value: changes the settings for the soft-AP of the ESP (for your stations)
  • show [config, stats]: prints the current config or some status information and statistics
  • save [dhcp]: saves the current config parameters, ACLs, and routing entires [+ the current DHCP leases] to flash
  • lock [password]: saves and locks the current config, changes are not allowed. Password can be left open if already set before (Default is the password of the uplink WiFi)
  • unlock password: unlocks the config, requires password from the lock command
  • reset [factory]: resets the esp, 'factory' optionally resets WiFi params to default values (works on a locked device only from serial console)
  • quit: terminates a remote session

Advanced Commands

Most of the set-commands are effective only after save and reset.

Automesh Config

  • set automesh [0, 1]: selects, whether the automesh mode is on or off (default), see details here https://github.com/martin-ger/esp_wifi_repeater#automesh-mode
  • set am_threshold dB: sets the threshold for a "bad" connection (in negative dB, default 85, i.e. -85 dB)
  • set am_scan_time secs: sets the time interval in seconds the ESP tries in automesh mode to find an uplink AP before going to sleep (0 disabled, default)
  • set am_sleep_time secs: sets the time interval in seconds the ESP sleeps in automesh mode if no uplink AP is found (0 disabled, default)

WiFi Config

  • set ap_on [0, 1]: selects, whether the soft-AP is disabled (ap_on=0) or enabled (ap_on=1, default)
  • set ap_open [0, 1]: selects, whether the soft-AP uses WPA2-PSK security (ap_open=0, automatic, if an ap_password is set) or open (ap_open=1)
  • set auto_connect [0, 1]: selects, whether the STA should keep retrying to reconnect to the AP. auto_connect is off (0) after first flashing or after "reset factory". When you enter a new SSID it will be automatically set on (1).
  • set ssid_hidden [0, 1]: selects, whether the SSID of the soft-AP is hidden (ssid_hidden=1) or visible (ssid_hidden=0, default)
  • set phy_mode [1, 2, 3]: sets the PHY_MODE of the WiFi (1=b, 2=g, 3=n(default))
  • set bssid xx:xx:xx:xx:xx:xx: sets the specific BSSID of the uplink AP to connect to (default 00:00:00:00:00:00 which means any)
  • set [ap_mac, sta_mac] xx:xx:xx:xx:xx:xx: sets the MAC address of the STA and SOFTAP to a user defined value (bit 0 of the first byte of the MAC address can not be 1)
  • set sta_mac random: set a new random STA MAC after each reboot
  • set sta_hostname name: sets the name of the STA (visible to the uplink AP)
  • set max_clients [1-8]: sets the number of STAs that can connct to the SoftAP (limit of the ESP's SoftAP implementation is 8, default)
  • scan: does a scan for APs
  • connect: tries to connect to an AP with the currently configured ssid and password
  • disconnect: disconnects from any uplink AP

WPA2 Enterprise Config

  • set use_peap[0, 1]: selects, whether the STA should connect via simple WPA-PSK (use_peap=0, default) or usinf WPA2 Enterprise (PEAP)
  • set peap_identity value: sets the PEAP 'outer' identity (the string that is first presented to the RADIUS server, maybe anonymous@yourorg.org)
  • peap_username value: sets the PEAP username
  • peap_password value: sets the PEAP password

TCP/IP Config

  • set network ip-addr: sets the IP address of the internal network, network is always /24, router is always x.x.x.1
  • set dns dns-addr: sets a static DNS address that is distributed to clients via DHCP
  • set dns dhcp: configures use of the dynamic DNS address from DHCP, default
  • set ip ip-addr: sets a static IP address for the STA interface
  • set ip dhcp: configures dynamic IP address for the STA interface, default
  • set netmask netmask: sets a static netmask for the STA interface
  • set gw gw-addr: sets a static gateway address for the STA interface
  • set max_nat no_of_entries: sets the size of the NAPT table (default 512)
  • set max_portmap no_of_entries: sets the size of the portmap table (default 32)
  • set tcp_timeout secs: sets the NAPT timeout for TCP connections (0=default (1800 secs))
  • set udp_timeout secs: sets the NAPT timeout for UDP connections (0=default (2 secs))
  • show dhcp: prints the current status of the dhcp lease table

Routing

  • show route: displays the current routing table
  • route clear: clears all static routes
  • route add network gw: adds a static route to a network (network given CIDR notation ('x.x.x.x/n')) via gateway gw
  • route delete network: removes a static route to a network
  • interface inX [up, down]: sets the interface state up or down (no IP routing/traffic through down interfaces, default: up)
  • set nat [0, 1]: selects, whether the soft-AP interface is NATed (nat=1, default) or not (nat=0). Without NAT transparent forwarding of traffic from the internal STAs doesn't work! Useful mainly in combination with static routing.
  • portmap add [TCP, UDP] external_port internal_ip internal_port: adds a port forwarding
  • portmap remove [TCP, UDP] external_port: deletes a port forwarding
  • nslookup name: starts a DNS lookup for the given name and displays the result
  • ping host: checks IP connectivity with ICMP echo request/reply (host as IP address or DNS name)

Firewall/Monitor Config

  • acl [from_sta, to_sta, from_ap, to_ap] [TCP, UDP, IP] src-ip [src_port] desr-ip [dest_port] [allow, deny, allow_monitor, deny_monitor]: adds a new rule to the ACL
  • acl [from_sta, to_sta, from_ap, to_ap] clear: clears the whole ACL
  • show acl: shows the defined ACLs and some stats
  • set acl_debug [0, 1]: switches ACL debug output on/off - all denied packets will be logged to the terminal
  • set [upstream_kbps, downstream_kbps] bitrate: sets a maximum upstream/downstream bitrate (0 = no limit, default)
  • set daily_limit limit_in_KB: defined a max. amount of kilobytes that can be transferred by STAs per day (0 = no limit, default)
  • set timezone hours_offset: defines the local timezone (required to know, when a day is over at 00:00)
  • monitor [on, off, acl] port: starts and stops monitor server on a given port

User Interface Config

  • set config_port portno: sets the port number of the console login (default is 7777, 0 disables remote console config)
  • set web_port portno: sets the port number of the web config server (default is 80, 0 disables web config)
  • set config_access mode: controls the networks that allow config access for console and web (0: no access, 1: only internal, 2: only external, 3: both (default))

GPIO Config

  • show gpio: displays the gpio configuration
  • gpio [0-16] mode [in, in_pullup, out]: configures a GPIO port of the ESP (saved to flash)
  • gpio [0-16] set [high, low]: writes to an output port
  • gpio [0-16] set [high, low] for seconds: writes to an output port and reverts after a certain duration
  • gpio [0-16] get: reads from an input port
  • gpio [0-16] trigger [0-16] [monostable_NO, monostable_NC, bistable_NO, bistable_NC]: links an input port to an output port, either as a monostable normally open (pushbutton triggering when state changes to low), a monostable normally closed (pushbutton triggering when state changes to high), a bistable normally open (switch replicating the input), or a bistable normally closed (switch which state is the opposite of the input)
  • gpio [0-16] trigger none: clears the link

Chip Config

  • set speed [80, 160]: sets the CPU clock frequency (default 80 Mhz)
  • sleep seconds: Put ESP into deep sleep for the specified amount of seconds. Valid values between 1 and 4294 (aprox. 71 minutes)
  • set status_led GPIOno: selects a GPIO pin for the status LED (default 2, >16 disabled)
  • set hw_reset GPIOno: selects a GPIO pin for a hardware factory reset (>16 disabled, default)
  • set ap_watchdog secs: sets the AP watchdog timeout - if there are no packets received for secs from the uplink AP the repeater resets ("none" = no timeout, default)
  • set client_watchdog secs: sets the client watchdog timeout - if there are no packets received for secs from any connected client the repeater resets ("none" = no timeout, default)
  • set vmin voltage: sets the minimum battery voltage in mV. If Vdd drops below, the ESP goes into deep sleep. If 0, nothing happens
  • set vmin_sleep secs: sets the time interval in seconds the ESP sleeps on low voltage

Status LED

In default config GPIO2 is configured to drive a status LED (connected to GND) with the following indications:

  • permanently on: started, but not successfully connected to the AP (no valid external IP)
  • flashing (1 per second): working, connected to the AP
  • unperiodically flashing: working, traffic in the internal network

With "set status_led GPIOno" the GPIO pin can be changed (any value > 16, e.g. "set status_led 255" will disable the status LED completely). When configured to GPIO1, it works with the built-in blue LED on the ESP-01 boards. However, as GPIO1 is also the UART-TX-pin this means, that the serial console is not working. Configuration is then limited to network access.

HW Factory Reset

If you pull low a selected GPIO for more than 3 seconds, the repeater will do a factory reset and restart with default config. With "set hw_reset GPIOno" the GPIO pin can be changed (any value > 16, e.g. "set hw_reset 255" will disable the hw factory reset feature).

For many modules, incl. ESP-01s and NodeMCUs, it is probably a good idea to use GPIO 0 for that, as it is used anyway. However, it is not the default pin, as it might interfere with pulling it down during flashing. Thus, if you want to use an existing push button on GPIO 0 for HW factory reset, configure it with "set hw_reset 0" and "save" after flashing. A factory reset triggered by the HW pin will NOT reset the configured hw_reset GPIO number ("reset factory" from console will do).

Port Mapping

In order to allow clients from the external network to connect to server port on the internal network, ports have to be mapped. An external port is mapped to an internal port of a specific internal IP address. Use the "portmap add" command for that. Port mappings can be listed with the "show" command and are saved with the current config.

However, to make sure that the expected device is listening at a certain IP address, it has to be ensured the this devices has the same IP address once it or the ESP is rebooted. To achieve this, either fixed IP addresses can be configured in the devices or the ESP has to remember its DHCP leases. This can be achieved with the "save dhcp" command. It saves the current state and all DHCP leases, so that they will be restored after reboot. DHCP leases can be listed with the "show stats" command.

WPA2 Enterprise (PEAP)

WPA2 Enterprise (PEAP) support has now been included into the project. It allows for a "converter" that translates a WPA2 enterprise network with PEAP authentication into a WPA2-PSK network. This solves a common problem especially in university environments: the local WiFi network is a WPA2 Enterprise network with PEAP-MSCHAPv2 authentication. A very prominent example is the "eduroam"-network that is available at many universities around the world. The problem is, that many IoT devices cannot handle WPA2 Enterprise authentication. So development and demos are difficult. What is very helpful is a "converter" that logs into the WPA2 Enterprise network and offers a simpler WPA-PSK network to its clients.

To use it set the following config parameters: ssid, use_peap, peap_identity, peap_username, and peap_password (you don't need the usual password parameter). This configuration has to be done (and saved) via the CLI and is not available in the web interface.

The code currently does not check the certificate of the RADIUS-Server. It is vulnerable to MITM-attacks, when somebody sets up a rogue AP and RADIUS server. While the password is not send in plaintext, the used MSCHAPv2 is known to be broken. Also, be aware of the fact that the ESP8266 now contains your enterprise network password. All traffic that is forwarded by it can now be related by the network admin to your account. Do not missuse it and offer it to untrusted others, eg. by configuring an open network. And even when the device is locked, your enterprise network password can be extracted via serial port from the ESP's flash in plain text.

Automesh Mode

Sometimes you might want to use several esp_wifi_repeaters in a row or a mesh to cover a larger distance or area. Generally, this can be done without any problems with NAT routers, actually you will have several layers of NAT. However, this means connectivity is limited: all nodes can talk to the internet, but generally there's no direct IP connectivity between the nodes. And, of course, the available bandwidth goes down the more hops you need. But users have reported that even 5 esp_wifi_repeaters in a row work quite well.

In such a setup configuration is quite a time consuming and error-prone activity. To simplify that, the esp_wifi_repeater now has a new mode: "Automesh". Just configure the SSID and the password and switch "automesh" on. (either on the CLI with "set automesh 1" or on the Web interface with just select the checkbox). This will do the following:

Each esp_wifi_repeater configured in that way will automatically offer a WiFi network on the AP with the same SSID/password as it is connected to. Clients can use the same WiFi settings for the original network or the repeated ones. Each esp_wifi_repeater configured with "automesh" will first search for the best other AP to connect to. This is the one which is closest to the original WiFi network and has the best signal strength (RSSI).

The signal strength is easy to measure with a scan, but which is the one closest to the original WiFi network when you see several APs with the same SSID? Therefore the protocol use a somewhat dirty trick: the esp_wifi_repeaters in "automesh" mode manipulate their BSSID (actually, according to the IEEE 802.11 standard this is the "ESSID" as it is an AP, but the SDK calls it "BSSID"), i.e. the MAC address of their AP interface, which is send out with every beacon frame 10 about time times per second. It uses the format: 24:24:mm:rr:rr:rr. "24:24" is just the unique identifier of a repeater (there is a minimal probability that this collides with the real APs MAC, but we can neglect this, as we can change that prefix if really required). "mm" means the "mesh level", this is the distance in hops to the original WiFi network. The last three "rr:rr:rr" are just random numbers to distinguish the various ESPs. The original AP keeps its BSSID, i.e. the one without the prefix "24:24" is recognized as root, called mesh level 0.

Now each esp_wifi_repeater can learn which other esp_wifi_repeater is the closest to the the original WiFi network, can connect to that, and chose its own BSSID accordingly. Also the IP address of the internal network is adjusted to the mesh level: 10.24.m.0. This creates a tree (a very special mesh) with the original WiFi AP as root and repeating nodes on several mesh levels (actually, it works somewhat similar as the Spanning Tree Protocol (STP) on the link layer or routing on the network layer using a Distance Vector protocol). As soon as an uplink link loss is detected, configuration is restarted. This should avoid loops, as during (re-)configuration also no beacons with an BSSID are sent.

For convenience, the esp_wifi_repeater after "automesh" configuration first tries to check, whether it can connect to an uplink AP. If this fails, even when an AP with the correct SSID has been found, it assumes, the user did a mistake with the password and resets to factory defaults. After it had connected successfully once, it will assume config is correct and keep on trying after connection loss or reset as long as it takes (to avoid a DOS attack with a misconfigured AP).

Tuning Automesh

If there are more than one ESP in range, there might be a trade-off between a shorter "bad" path and a longer "good" path (good and bad in terms of link quality). The parameter am_threshold determines what a bad connection is: if the RSSI in a scan is less than this threshold, a connection is bad and path with one more hop is preferred. I.e. given am_threshold is 85 and there are two automesh nodes detected in the scan: A with level 1 and RSSI -88 dB and B with level 2 and RSSI -60 dB, then a link to A is considered as too bad (-88 dB < -am_threshold) and B is preferred. The new node will become a level 3 node with uplink via B. am_threshold is given as a positive value but means a negative dB. A smaller value is better.

If you want to get more insight into the topology of an automesh network, you might consider to connect all nodes to an MQTT broker and let them publish the "Topology" topic (see below). If you now subscribe on "/WiFi/+/system/Topology" you will get all the node and link infos including the RSSI (of connected ESPs) you need to reconstruct the complete graph and detect weak links in the mesh. The TopologyInfo topic contains the following JSON structure, that can be used to reconstruct a complete graph of an automesh network:

{
"nodeinfo" {
	"id":"ESP_07e37e",
	"ap_mac":"24:24:01:72:c7:f9",
	"sta_mac":"60:01:bc:07:e3:7e",
	"uplink_bssid":"00:1a:54:93:23:0a",
	"ap_ip":"10.24.1.1",
	"sta_ip":"192.168.178.33",
	"rssi":"-66",
	"mesh_level":"1",
	"no_stas":"2"
},
"stas":[
	{"mac":"5c:cf:45:11:7f:13","ip":"10.24.1.2"},
	{"mac":"00:14:22:76:99:c5","ip":"10.24.1.3"}
]
}

Using the two parameters am_scan_time and am_sleep_time power management can be implemented in automesh mode, if you have connected GPIO16 to RST. After booting the esp_wifi_repeater scans for available uplink APs for am_scan_time seconds. If none is found, it goes to deepsleep for am_sleep_time seconds and tries again after reboot (default is 0 = disabled for both parameters).

Monitoring

From the console a monitor service can be started ("monitor on [portno]"). This service mirrors the traffic of the internal network in pcap format to a TCP stream. E.g. with a "netcat [external_ip_of_the_repeater] [portno], sudo wireshark -k -S -i -" from an computer in the external network you can now observe the traffic in the internal network in real time. Use this e.g. to observe with which internet sites your internals clients are communicating. Be aware that this at least doubles the load on the esp and the WiFi network. Under heavy load this might result in some packets being cut short or even dropped in the monitor session. CAUTION: leaving this port open is a potential security issue. Anybody from the local networks can connect and observe your traffic.

Firewall

The ESP router has a integrated basic firewall. ACLs (Access Control Lists) can be applied to the SoftAP interface. This is a cornerstone in IoT security, when the router is used to bring other IoT devices into the internet. It can be used to prevent e.g. third-party IoT devices from "calling home", being misused as malware bots, and to protect your home network with PCs, tablets and phones from being visible to home automation devices.

The four ACL lists are named "from_sta", "to_sta", "from_ap" and "to_ap" for incoming and outgoing packets on both interfaces ("sta" means the interfaces to the connectes clients, "ap" the interface to the uplink AP). ACLs are defined in "CISCO IOS style". The following example will allow for outgoing local broadcasts (for DHCP), UDP 53 (DNS), and TCP 1883 (MQTT) to a local broker, any other packets will be blocked:

  • acl from_sta clear
  • acl from_sta IP any 255.255.255.255 allow
  • acl from_sta UDP any any any 53 allow
  • acl from_sta TCP any any 192.168.0.0/16 1883 allow
  • acl from_sta IP any any deny

ACLs for the "to_sta" direction may be defined as well, but this is usually not required, as the reverse direction is quite well protected against unsolicited traffic by the NAT transation.

ACLs consist of filtering rules that are processed for each packet. Each rule consists of a protocol (IP, TCP, or UDP), source address/port, destination address/port, as well as an action "allow" or "deny". In case of plain IP no ports, only addresses are given. IP rules include TCP and UDP packets. Addresses can be given as subnet addresses in the "/" notation, e.g. 192.168.178.0/24. Also "any" can be used as wildcard, it matches on any address or portnumber. A rule is defined by the "acl" command:

  • acl [from_sta, to_sta, from_ap, to_ap] [TCP, UDP, IP] src-ip [src_port] desr-ip [dest_port] [allow, deny, allow_monitor, deny_monitor]

The rules are processed top-down in the order of their appearance in the list. The first rule that matches a packet is applied and determies whether a packet is allowed (and forwarded) or denied (and dropped). This means, special cases first, general rules at the end. If there are rules in an ACL all packets that don't match any rule are denied by default. Thus, the last rule "from_sta IP any any deny" in the example above is not really needed, as it is the default anyway. If an ACL is empty, all packets are allowed.

Definition of ACL rules works also top-down: a new rule is always added at the end of a list. To change an ACL you first have to clear it completely (acl from_sta clear) and then rebuild it. ACLs are saved with the config. "show acl" will print out the ACLs plus statistics on the number of hits for each rule and the overall number of allowed and denied packets.

With the command "set acl_debug 1" a summary of all denied packets is printed to the console. Also, an MQTT topic can publishe this summary. This can be used for firewall configuration to determine which rules are required to get the connected devices working. It also gives a hint if, if unexpected traffic happens (and is denied).

For deeper analysis the monitoring service can be used (even denied packets are reported to the monitor before they are dropped). When the monitor is started with the "monitor acl port" command, ACLs can be used as online filters. All rules that are defined as
"allow_monitor" instead of "allow" and "deny_monitor" instead of "deny" are processed as usual, resulting in allowing of forwarding a packet, but they also send the packet to the monitor. Thus a list of rules that basically "allow" or "allow_monitor" all packets still makes sense, as it can be used to select already during catpure time which packet should be recorded. E.g. a lists:

  • acl from_sta clear

  • acl from_sta IP 192.168.0.0/16 any allow_monitor

  • acl from_sta IP any any allow

  • acl to_sta clear

  • acl to_sta IP any 192.168.0.0/16 allow_monitor

  • acl to_sta IP any any allow

will allow all packets and also select all packets for monitoring that go from a station to the 192.168.0.0/16 (local)subnet and from the 192.168.0.0/16 to a station. Of course such a filter can be applied also after the capture to a full monitoring trace, but if you already know, what you are looking for, these online filters will help to reduce monitoring overhead drastically. It can also be used to debug all deny firewall rules by simply using "deny_monitor" instead of deny.

Static Routes

By default the AP interface is NATed, so that any node connected to the AP will be able to access the outside world transparently via the ESP's STA interface. So no further action is required, if you are not a real network nerd.

For those of you that are really interested in further network config: the ESP's lwip IPv4 stack has been enhanced for this project with support for static routes: "show route" displays the routing table with all known routes, including the links to the connected network interfaces (the AP and the STA interface). Routing between these two interfaces works without further configuration. Additional routes to other networks can be set via the "route add network gateway" command, known from Linux boxes or routers. A "save" command writes the current state of the routing table to flash configuration.

Here is a simple example of what can be done with static routes. Given the following network setup with two ESPs connected with the STA interfaces via a central home router:
, 10.0.1.1 AP-ESP1-STA 192.168.1.10, <->, Home Router, <->, 192.168.1.20 STA-ESP2-AP 10.0.2.1,
Each ESP has a second network behind its AP with different network addresses: 10.0.1.0/24 and 10.0.2.0/24. ESP1 can ping to ESP2 to the 192.168.1.20 but not to the 10.0.2.1, as it doesn't know that it can reach it via the 192.168.1.20. This changes if you add two static routes. On ESP1:

route add 10.0.2.0/24 192.168.1.20

and on ESP2:

route add 10.0.1.0/24 192.168.1.10

Now a "ping 10.0.2.1" on ESP1 will be successful. It is send to 192.168.1.20 and then answered by ESP2.

Now in each network an additional client connects (with addresses 10.0.1.2 and 10.0.2.2):
, STA1 10.0.1.2, <->, 10.0.1.1 ESP1 192.168.1.10, <->, Home Router, <->, 192.168.1.20 ESP2 10.0.2.1, <->, STA2 10.0.2.2,
Now even client STA1 with the local address 10.0.1.2 can ping to STA2 with 10.0.2.2 as it send its request first to its default router ESP1 and this knows, that all packets to a 10.0.2.0/24 address have to be forwarded to 192.168.1.20. There the ESP2 knows how to send it to STA2. Tthe same applies for the reply in the other direction.

This allows you to configure a multi-star topology of ESPs, where each ESP and its STA clients can direcly reach each other (without any need for portmaps). Configuration of the required routes maybe somewhat painful - but a nice exercise in networking. Next step would be to port a dynamic routing protocol like RIP on the ESP...

Bitrate Limits

By setting upstream_kbps and downstream_kbps to a value other than 0 (0 is the default), you can limit the maximum bitrate of the ESP's AP. This value is a limit that applies to the traffic of all connected clients. Packets that would exeed the defined bitrate are dropped. The traffic shaper uses the "Token Bucket" algorithm with a bucket size of currently four times the bitrate per seconds, allowing for bursts, when there was no traffic before.

MQTT Support

Since version 1.3 the router has a built-in MQTT client (thanks to Tuan PM for his library https://github.com/tuanpmt/esp_mqtt). This can help to integrate the router/repeater into the IoT. A home automation system can e.g. make decisions based on infos about the currently associated stations, it can switch the repeaters on and off (e.g. based on a time schedule), or it can simply be used to monitor the load. The router can be connected either to a local MQTT broker or to a publicly available broker in the cloud. However it does not currently support TLS encryption.

By default the MQTT client is disabled. It can be enabled by setting the config parameter "mqtt_host" to a hostname different to "none". To configure MQTT you can set the following parameters:

  • set mqtt_host IP_or_hostname: IP or hostname of the MQTT broker ("none" disables the MQTT client)
  • set mqtt_port port: Port of the MQTT broker used for connection (default: 1883)
  • set mqtt_qos QoS: MQTT QoS value for publications and subscriptions (0-2, default: 0)
  • set mqtt_user username: Username for authentication ("none" if no authentication is required at the broker)
  • set mqtt_password password: Password for authentication
  • set mqtt_id clientId: Id of the client at the broker (default: "ESPRouter_xxxxxx" derived from the MAC address)
  • set mqtt_prefix prefix_path: Prefix for all published topics (default: "/WiFi/ESPRouter_xxxxxx/system", again derived from the MAC address)
  • set mqtt_command_topic command_topic: Topic subscribed to receive commands, same as from the console. (default: "/WiFi/ESPRouter_xxxxxx/command", "none" disables commands via MQTT)
  • set mqtt_interval secs: Set the interval in which the router publishs status topics (default: 15s, 0 disables status publication)
  • set mqtt_mask mask_in_hex: Selects which topics are published (default: "ffff" means all)

The MQTT parameters can be displayed with the "show mqtt" command.

The router can publish the following status topics periodically (every mqtt_interval):

  • prefix_path/Uptime: System uptime since last reset in s (mask: 0x0020)
  • prefix_path/Vdd: Voltage of the power supply in mV (mask: 0x0040)
  • prefix_path/Bpsin: KBytes/s from stations into the AP (mask: 0x0800)
  • prefix_path/Bpsout: KBytes/s from the AP to stations (mask: 0x0800)
  • prefix_path/Bpd: KBytes per day from and to stations (mask: 0x0400)
  • prefix_path/Ppsin: Packets/s from stations into the AP (mask: 0x0200)
  • prefix_path/Ppsout: Packets/s from the AP to stations (mask: 0x0200)
  • prefix_path/Bin: Total bytes from stations into the AP (mask: 0x0100)
  • prefix_path/Bout: Total bytes from the AP to stations (mask: 0x0100)
  • prefix_path/NoStations: Number of stations currently connected to the AP (mask: 0x2000)
  • prefix_path/TopologyInfo: JSON struct with the current topology info of the node (mask: 0x1000)

In addition the repeater can publish on an event basis:

  • prefix_path/join: MAC address of a station joining the AP (mask: 0x0008)
  • prefix_path/leave: MAC address of a station leaving the AP (mask: 0x0010)
  • prefix_path/IP: IP address of the router when received via DHCP (mask: 0x0002)
  • prefix_path/ScanResult: Separate topic for the results of a "scan" command (one message per found AP) (mask: 0x0004)
  • prefix_path/ACLDeny: A packet has been denied by an ACL rule and has been dropped (mask: 0x0080)

As LWT and status report the repeater publishes:

  • prefix_path/status: A retained topic either "online" (as soon as the repeater connects) or "offline" (after connection loss as LWT)

The router can be configured using the following topics:

  • command_topic: The router subscribes on this topic and interprets all messages as command lines
  • prefix_path/response: The router publishes on this topic the command line output (mask: 0x0001)

If you now want the router to publish e.g. only Vdd, its IP, and the command line output, set the mqtt_mask to 0x0001, 0x0002, 0x0040 (= "set mqtt_mask 0043").

ENC28J60 Ethernet Support

The esp_wifi_repeater now includes support for an ENC28J60 Ethernet NIC connected via SPI (Thanks to Andrew Kroll https://github.com/xxxajk for his great work on getting right), if you switch on the HAVE_ENC28J60 compile option in "user_config.h". The Ethernet interface will support about 1 Mbps when the ESP is running an 160 MHz. Switching the AP interface on and using the Ethernet as uplink will turn the esp_wifi_repeater into a cheap AP for WiFi devices (e.g. other ESPs).

The connection via SPI has to be:

NodeMCU/Wemos  ESP8266      ENC28J60

        D6     GPIO12 <---> MISO
        D7     GPIO13 <---> MOSI
        D5     GPIO14 <---> SCLK
        D8     GPIO15 <---> CS
        D1     GPIO5  <---> INT
	D2     GPIO4  <---> RESET
               Q3/V33 <---> 3.3V
               GND    <---> GND

Short and soldered wires work best. In addition you will need a transistor for decoupling GPIO15, otherwise your ESP will not boot any more, see: https://esp8266hints.wordpress.com/category/ethernet/ . Also, it is important to have a good power supply: the ENC28j60 needs about 160mA when active. For me it fails, if I try to use the 3.3V from the ESP board.

Now you can configure the new Ethernet interface:

  • set eth_enable [0, 1]: enables/disables an ENC28J60 Ethernet NIC on the SPI bus (default: 0 - disabled)
  • set eth_ip ip-addr: sets a static IP address for the ETH interface
  • set eth_netmask netmask: sets a static netmask for the ETH interface
  • set eth_gw gw-addr: sets a static gateway address for the ETH interface
  • set eth_dhcpd [0, 1]: starts a DHCP server for dynamic IP addresses on the ETH interface, (default: 0 - disabled)

Power Management

The repeater monitors its current supply voltage (shown in the "show stats" command). This only works, if the 107th byte in esp_init_data_default.bin, named as vdd33_const, is set to 255(0xFF). The easiest way to achieve that, is to write esp_init_data_default_v08_vdd33.bin to flash (see below).

If vmin (in mV, default 0) is set to a value > 0 and the supply voltage drops below this value, it will go into deep sleep mode for vmin_sleep seconds. If you have connected GPIO16 to RST (which is hard to solder on an ESP-01) it will reboot after this interval, try to reconnect, and will continue its measurements. If vmin is saved with the config, it will sleep over and over again, until the supply voltage raises above the threshold. These settings are especially (only?) useful if you have powered the ESP with a (lithium) battery without undercharge protection. Then a value of 2900mV-3000mV is probably helpful, as it reduces power consumption of the ESP to a minimum and you have much more time to recharge or replace the battery before damage. This only makes sense, if you have the ESP connected directly to the battery. If you have additional logic, this will still drain the battery.

You can send the ESP to sleep manually once by using the "sleep" command.

Caution: If you save a vmin value higher than the max supply voltage to flash, the repeater will immediately shutdown every time after reboot. Then you have to wipe out the whole config by flashing blank.bin (or any other file) to 0x0c000.

Building and Flashing

To build this binary you download and install the esp-open-sdk (I suggest this version with base NONOS SDK 2.2: https://github.com/xxxajk/esp-open-sdk). Make sure, you can compile and download the included "blinky" example.

Then download this source tree in a separate directory and adjust the BUILD_AREA variable in the Makefile and any desired options in user/user_config.h. Changes of the default configuration can be made in user/config_flash.c. Build the esp_wifi_repeater firmware with "make". "make flash" flashes it onto an esp8266.

The source tree includes a binary version of the liblwip_open plus the required additional includes from my fork of esp-open-lwip and a binary of the rboot tool. No additional install action is required for that. Only if you don't want to use the precompiled library, checkout the sources from https://github.com/martin-ger/esp-open-lwip . Use it to replace the directory "esp-open-lwip" in the esp-open-sdk tree. "make clean" in the esp_open_lwip dir and once again a "make" in the upper esp_open_sdk directory. This will compile a liblwip_open.a that contains the NAT-features. Replace liblwip_open_napt.a with that binary. Also you might build the "rboot.bin" binary from https://github.com/raburton/rboot and replace it in the root directory of the project.

Update: if you read somewhere in the web install instructions using "0x10000.bin" - due to OTA this has been changed to "0x02000.bin" now.

If you want to use the complete precompiled firmware binaries you can flash them with "esptool.py --port /dev/ttyUSB0 write_flash -fs 4MB -ff 80m -fm dio 0x00000 firmware/0x00000.bin 0x02000 firmware/0x02000.bin" (use -fs 1MB for an ESP-01). For the esp8285 you must use -fs 1MB and -fm dout.

On Windows you can flash it using the "ESP8266 Download Tool" available at https://espressif.com/en/support/download/other-tools. Download the two files 0x00000.bin and 0x02000.bin from the firmware directory. For a generic ESP12, a NodeMCU or a Wemos D1 use the following settings (for an ESP-01 change FLASH SIZE to "8Mbit"):

If "QIO" mode fails on your device, try "DIO" instead. Also have a look at the "Detected Info" to check size and mode of the flash chip. If your downloaded firmware still doesn't start properly, please check with the enclosed checksums whether the binary files are possibly corrupted. If you are in doubt concerning the firmware binaries being corrupted, download the complete repo as zip and extract the binaries from that zip - this avoids HTTP-download problems (e.g. CR-LF conversions).

OTA (Over the air) update support

Based on using the rboot lib: https://github.com/raburton/rboot and thanks to the contribution of christianchristensen.

The build process creates two copies of the esp_wifi_repeater binary in the firmware directory: 0x02000.bin and 0x82000.bin. For an initial installation it is fine just to flash 0x00000.bin (the rboot boot loader) and 0x02000.bin (one copy of the program). The esp_wifi_repeater will work.

If you have at least 1MB of flash you can do an OTA (Over the air) update with another version. I.e. you can interactively load a new binary from the CLI and switch over to it. The other binary is loaded to the currently non active memory location (either 0x02000 (rom0) or 0x82000 (rom1)) and started on success. You can also interactively switch between two installed binaries. The current config will be used for both binaries (as long as its format hasn't changed).

You can control the OTA features with the following commands:

  • show ota: shows the currently active binary and the URL of the next update
  • set ota_host hostname: sets hostname or IP address of the OTA server (default: "none")
  • set ota_port portno: sets port number of the OTA server (default: 80)
  • ota update: tries to download a new binary (0x02000.bin or 0x82000.bin) via HTTP from ota_host:ota_port and starts it
  • ota switch: switches to the other binary (if installed)

To test the OTA feature, configure your ESP (as STA or AP) to be connected to the network with the update server. There start a simple Web server in the firmware directory, e.g.;

cd firmware
python -m SimpleHTTPServer 8080

Set the parameter hostname to the hostname or IP of your computer, set portno to 8080, and "save". Then type on the CLI:

ota update

If configured correctly, the update will start and the ESP will reboot with the new binary.

Known Issues

  • Due to the limitations of the ESP's SoftAP implementation, there is a maximum of 8 simultaniously connected stations.
  • The ESP8266 requires a good power supply as it produces current spikes of up to 170 mA during transmit (typical average consumption is around 70 mA when WiFi is on). Check the power supply first, if your ESP runs unstable and reboots from time to time. A large capacitor between Vdd and Gnd can help if you experience problems here.
  • All firmware published after 17/Oct/2017 have been built with the patched version of the SDK 2.1.0 from Espressif that mitigates the KRACK (https://www.krackattacks.com/ ) attack.
To the top