espressif / esp-protocols

Collection of ESP-IDF components related to networking protocols
181 stars 126 forks source link

EPPP Reverse link to provide Access Point (IDFGH-12759) #565

Closed DynamicLoader closed 3 months ago

DynamicLoader commented 5 months ago

Is your feature request related to a problem?

Actually, the idea is come up with the requirement for me that,

I have a Openwrt router (RPi3B+), and I'd like to add a wifi access point via ESP32, for my IoT devices. I had noticed ESP-HOSTED, but it can only be used on normal linux system (i.e. Raspbian), not openwrt such that environment is not satisified.

Hence I get the EPPP-Link, It can act as a PPP Server and NAPT a network to client. So I think it's nice to do some little trick, to get a reverse router.

Describe the solution you'd like.

The EPPP-Link Slace (PPP Server) can be used as normal. There are some points to change:

On the router I'd just add a static route to get it forward to the WAN.

So the data link would look like:

\|/  +--------+    Serial/USB   +--------+       Ethernet   +----------+
 |__ |  ESP32 | ------------->- | Router | ------------->-- |  WAN Dev |
     +--------+       PPP       +--------+                  +----------+

Futhermore, USB-CDC-based serial could be used to provide a higher baudrate for a stable connection, with or without flow control.

Describe alternatives you've considered.

I;d considered ESP-modem to connect to PPP Server on Openwrt, but it's somewhat hard to work, since openwrt only provided PPP client configure on LuCI.

Additional context.

No response

david-cermak commented 4 months ago

If I understand the use-case then it's already supported in the current version of the eppp component (without the USB option), correct? The solution is just like this example https://github.com/espressif/esp-protocols/tree/master/components/esp_modem/examples/ap_to_pppos but instead of esp_modem, you'd setup the eppp in server mode.

About the USB-CDC transport, it's very easy to add actually. (you can check a similar implementation in this IDF example: https://github.com/espressif/esp-idf/blob/master/examples/common_components/protocol_examples_common/ppp_connect.c if you like to contribute). I'll be adding SDIO transport soon, so adding USB to the list.

DynamicLoader commented 4 months ago

Yes, It is. I'd like to see what can I do, but I use Arduino more, so the implement of IDF is not so familiar.

I'd try to work on this in a few days. Before that, what version of IDF should I use to test it? Thanks.

david-cermak commented 4 months ago

eppp needs PPP server support (specifically these: 18ff62017a24939ff7d3b6cac696dc7af4f49fd3, 63e8e01646046536af7173e26d3ad419d1936348, 73102c60efddcf0290f9fb7186fd380dca66bee8) which are only available from IDF v5.3

DynamicLoader commented 4 months ago

OK, I tested the current WiFi to PPPoS slave with ESP32-C3, with pppd on openwrt, but something is just wrong -> The pppd did get client ip (192.168.11.2), but it cannot get remote ip (defaults to 10.64.64,64 and refused by ESP32-C3, see the log below)

Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: rcvd [LCP ConfReq id=0x7 <asyncmap 0x0> <magic 0x3847e1fa> <pcomp> <accomp>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: sent [LCP ConfRej id=0x7 <pcomp> <accomp>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: rcvd [LCP ConfReq id=0x8 <asyncmap 0x0> <magic 0x3847e1fa>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: sent [LCP ConfAck id=0x8 <asyncmap 0x0> <magic 0x3847e1fa>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x6473b95c>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: rcvd [LCP ConfAck id=0x1 <asyncmap 0x0> <magic 0x6473b95c>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: sent [LCP EchoReq id=0x0 magic=0x6473b95c]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: sent [IPCP ConfReq id=0x1 <compress VJ 0f 01> <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: sent [IPV6CP ConfReq id=0x1 <addr fe80::5100:82ab:af79:6c55>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: rcvd [LCP EchoRep id=0x0 magic=0x3847e1fa]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: rcvd [IPCP ConfRej id=0x1 <compress VJ 0f 01> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: sent [IPCP ConfReq id=0x2 <addr 0.0.0.0>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: rcvd [IPV6CP ConfAck id=0x1 <addr fe80::5100:82ab:af79:6c55>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: rcvd [IPCP ConfNak id=0x2 <addr 192.168.11.2>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: sent [IPCP ConfReq id=0x3 <addr 192.168.11.2>]
Wed May  8 13:44:18 2024 daemon.debug pppd[30167]: rcvd [IPCP ConfAck id=0x3 <addr 192.168.11.2>]
Wed May  8 13:44:20 2024 daemon.debug pppd[30167]: sent [LCP EchoReq id=0x1 magic=0x6473b95c]
Wed May  8 13:44:20 2024 daemon.debug pppd[30167]: rcvd [LCP EchoRep id=0x1 magic=0x3847e1fa]
Wed May  8 13:44:21 2024 daemon.debug pppd[30167]: sent [LCP EchoReq id=0x2 magic=0x6473b95c]
Wed May  8 13:44:21 2024 daemon.debug pppd[30167]: rcvd [LCP EchoRep id=0x2 magic=0x3847e1fa]
Wed May  8 13:44:21 2024 daemon.debug pppd[30167]: sent [IPV6CP ConfReq id=0x1 <addr fe80::5100:82ab:af79:6c55>]
Wed May  8 13:44:21 2024 daemon.debug pppd[30167]: rcvd [IPV6CP ConfAck id=0x1 <addr fe80::5100:82ab:af79:6c55>]
Wed May  8 13:44:21 2024 daemon.debug pppd[30167]: sent [IPCP ConfReq id=0x3 <addr 192.168.11.2>]
Wed May  8 13:44:21 2024 daemon.debug pppd[30167]: rcvd [IPCP ConfAck id=0x3 <addr 192.168.11.2>]
Wed May  8 13:44:23 2024 daemon.debug pppd[30167]: sent [LCP EchoReq id=0x3 magic=0x6473b95c]
Wed May  8 13:44:23 2024 daemon.debug pppd[30167]: rcvd [LCP EchoRep id=0x3 magic=0x3847e1fa]
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: rcvd [IPCP ConfReq id=0xd <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>]
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: sent [IPCP ConfRej id=0xd <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>]
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: rcvd [IPV6CP ConfReq id=0x4 <addr fe80::cd80:1620:ec05:a960>]
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: sent [IPV6CP ConfAck id=0x4 <addr fe80::cd80:1620:ec05:a960>]
Wed May  8 13:44:24 2024 daemon.notice pppd[30167]: local  LL address fe80::5100:82ab:af79:6c55
Wed May  8 13:44:24 2024 daemon.notice pppd[30167]: remote LL address fe80::cd80:1620:ec05:a960
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Joining mDNS multicast group on interface ppp-123.IPv6 with address fe80::5100:82ab:af79:6c55.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: New relevant interface ppp-123.IPv6 for mDNS.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Registering new address record for fe80::5100:82ab:af79:6c55 on ppp-123.*.
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: rcvd [IPCP ConfReq id=0xe <addrs 0.0.0.0 192.168.11.2>]
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: sent [IPCP ConfRej id=0xe <addrs 0.0.0.0 192.168.11.2>]
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: rcvd [IPCP ConfReq id=0xf]
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: sent [IPCP ConfAck id=0xf]
Wed May  8 13:44:24 2024 daemon.warn pppd[30167]: Could not determine remote IP address: defaulting to 10.64.64.64
Wed May  8 13:44:24 2024 daemon.notice ttyd[6773]: [2024/05/08 13:44:24:2813] N: rops_handle_POLLIN_netlink: DELADDR
Wed May  8 13:44:24 2024 daemon.notice pppd[30167]: local  IP address 192.168.11.2
Wed May  8 13:44:24 2024 daemon.notice pppd[30167]: remote IP address 10.64.64.64
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Joining mDNS multicast group on interface ppp-123.IPv4 with address 192.168.11.2.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: New relevant interface ppp-123.IPv4 for mDNS.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Registering new address record for 192.168.11.2 on ppp-123.IPv4.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Withdrawing address record for 192.168.11.2 on ppp-123.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Leaving mDNS multicast group on interface ppp-123.IPv4 with address 192.168.11.2.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Interface ppp-123.IPv4 no longer relevant for mDNS.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Joining mDNS multicast group on interface ppp-123.IPv4 with address 192.168.11.2.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: New relevant interface ppp-123.IPv4 for mDNS.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Registering new address record for 192.168.11.2 on ppp-123.IPv4.
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: Script /lib/netifd/ppp-up started (pid 30899)
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: rcvd [IPCP TermReq id=0x10 "Refused our IP address"]
Wed May  8 13:44:24 2024 daemon.info pppd[30167]: IPCP terminated by peer (Refused our IP address)
Wed May  8 13:44:24 2024 daemon.info pppd[30167]: Connect time 0.0 minutes.
Wed May  8 13:44:24 2024 daemon.info pppd[30167]: Sent 0 bytes, received 26 bytes.
Wed May  8 13:44:24 2024 daemon.notice ttyd[6773]: [2024/05/08 13:44:24:2876] N: rops_handle_POLLIN_netlink: DELADDR
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Withdrawing address record for 192.168.11.2 on ppp-123.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Leaving mDNS multicast group on interface ppp-123.IPv4 with address 192.168.11.2.
Wed May  8 13:44:24 2024 daemon.info avahi-daemon[5529]: Interface ppp-123.IPv4 no longer relevant for mDNS.
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: sent [IPCP TermAck id=0x10]
Wed May  8 13:44:24 2024 daemon.notice netifd: Network device 'ppp-123' link is up
Wed May  8 13:44:24 2024 daemon.notice netifd: Network alias 'ppp-123' link is up
Wed May  8 13:44:24 2024 daemon.notice netifd: Interface '123' is now up
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: Script /lib/netifd/ppp-up finished (pid 30899), status = 0x1
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: Script /lib/netifd/ppp-down started (pid 30918)
Wed May  8 13:44:24 2024 daemon.notice netifd: Interface '123' has lost the connection
Wed May  8 13:44:24 2024 daemon.notice netifd: Network alias '' link is down
Wed May  8 13:44:24 2024 daemon.debug pppd[30167]: Script /lib/netifd/ppp-down finished (pid 30918), status = 0x1
Wed May  8 13:44:24 2024 user.warn mwan3rtmon[1687]: failed: 'ip -4 route replace table 2 10.64.64.64 dev ppp-123 proto kernel scope link src 192.168.11.2 ' - error: Error: Invalid prefsrc address.
Wed May  8 13:44:24 2024 user.warn mwan3rtmon[1687]: failed: 'ip -4 route replace table 4 10.64.64.64 dev ppp-123 proto kernel scope link src 192.168.11.2 ' - error: Error: Invalid prefsrc address.

The parameter used is: nodetach ipparam 123 ifname ppp-123 lcp-echo-interval 1 lcp-echo-failure 5 lcp-echo-adaptive nodefaultroute usepeerdns maxfail 1, with the options in /etc/ppp/options:

debug
logfile /dev/null
noipdefault
noaccomp
nopcomp
nocrtscts
lock
maxfail 0
local
ipcp-accept-local
ipcp-accept-remote

2000000

Note: I'm using a CH340 USB to TTL Serial, hence there is no flow control, local is required to get pppd ignore the CD signal and establish connection with ESP32-C3.

What's the problem? Thanks.

DynamicLoader commented 4 months ago

I also tested manually set the ip, using pppd -detach 192.168.11.2:192.168.11.1 nocrtscts noipv6 ttyUSB0. It can connect actually, but when I ping 192.168.11.1, there is activity on serial, but lots of packet dorpped. Like this:

PING 192.168.11.1 (192.168.11.1): 56 data bytes
64 bytes from 192.168.11.1: seq=26 ttl=64 time=6.020 ms
64 bytes from 192.168.11.1: seq=27 ttl=64 time=6.109 ms
64 bytes from 192.168.11.1: seq=28 ttl=64 time=6.159 ms
64 bytes from 192.168.11.1: seq=49 ttl=64 time=6.558 ms
64 bytes from 192.168.11.1: seq=148 ttl=64 time=6.374 ms

And the console of ESP32-C3 just reported:

I (1634) uart: queue free spaces: 16
I (1634) eppp_link: Waiting for IP address 0
I (1734) eppp_link: Got IPv4 event: Interface "pppos_server(EPPP0)" address: 192.168.11.1
I (1734) esp-netif_lwip-ppp: Connected
I (1734) eppp_link: Connected! 0
W (1734) esp_netif_lwip: napt disabled on esp_netif:0x3fcaaaa0
I (1744) main_task: Returned from app_main()

Edit: After slow down the serial baudrate to 115200, ping works well. After adding a static route, NAPT works fine.

david-cermak commented 4 months ago

The pppd did get client ip (192.168.11.2), but it cannot get remote ip

Can reproduce it, and the issue seems to be on the ESP32 side (doesn't seem to properly negotiate it's own address), but need to take a deeper look and debug.

there is activity on serial, but lots of packet dorpped. Like this:

This should work reliably on 921600 bauds, in ESP-ESP scenario up to 3Mbauds.

DynamicLoader commented 4 months ago

I guess the baudrate should be the issue of my wire and the oscillator used on the CH340... Never mind, since we could always make a PCB or just use USB-CDC.

DynamicLoader commented 4 months ago

I'd merged some code to create AP and set DNS from esp_modem to the example in the commit of my fork (https://github.com/DynamicLoader/esp-protocols/commit/12eaabc2a7656fbb9f1774e11f87c31d708dbddb)

How can the NAPT work in this case? i.e, we hadn't specify the default route, which would be set by the wifi client I guess?

Thanks.

david-cermak commented 4 months ago

i.e, we hadn't specify the default route, which would be set by the wifi client I guess?

The default netif is determined from the route_prio option of each interface. Esp_netif then chooses the one which is up and has the highest route_prio number.

david-cermak commented 4 months ago

About the IP negotiation issue you pointed out above in https://github.com/espressif/esp-protocols/issues/565#issuecomment-2099797367

Here's the fix:

diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.c b/components/esp_netif/lwip/esp_netif_lwip_ppp.c
index bd2b17086f..3d4b845e7a 100644
--- a/components/esp_netif/lwip/esp_netif_lwip_ppp.c
+++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.c
@@ -255,6 +255,7 @@ esp_err_t esp_netif_start_ppp(esp_netif_t *esp_netif)
         // Set our preferred address, and accept the remote
         ppp_ctx->ppp->ipcp_wantoptions.ouraddr = ppp_ctx->ppp_our_ip4_addr.addr;
         ppp_ctx->ppp->ipcp_wantoptions.accept_remote = 1;
+        ppp_ctx->ppp->ask_for_local = 1;
     }

I think it's actually a long forgotten bug in lwip, as ask_for_local suggests that "we are to ask our peer for our local address":

https://github.com/lwip-tcpip/lwip/blob/1cc1536e6a7117e23ebaf5546405a843a3e558ae/src/include/netif/ppp/ppp.h#L331

but fixing it in lwip might cause more problems...

DynamicLoader commented 4 months ago

One thing I'd mention is IPV6CP is working. There seems no 'ask_for_local' used in ipv6?

Besides, as we are the server, we would know local ip. The problem seems to be that, the server did not send a valid remote ip to the client so the client is to reject. (in the log, we could see 0.0.0.0, instead of 192.168.11.1, for remote ip and dns request from server)

david-cermak commented 4 months ago

The problem seems to be that, the server did not send a valid remote ip to the client so the client is to reject. (in the log, we could see 0.0.0.0, instead of 192.168.11.1, for remote ip and dns request from server)

Yes, this is exactly what's happening here:

https://github.com/lwip-tcpip/lwip/blob/1cc1536e6a7117e23ebaf5546405a843a3e558ae/src/netif/ppp/ipcp.c#L728-L729

so even if we know our preferred address, with the default settings of ask_for_local=0 we just reset it to 0.0.0.0 before the initial advertisement).

I'll fix it in IDF. You can also try to apply the patch from https://github.com/espressif/esp-protocols/issues/565#issuecomment-2104877956 and see if this solves the issue.

(the reason why it worked with the preferred addresses on both sides is that it negotiated 192.168.11.1 from the client side and was accepted on the server side, while without it, the client simply defaulted to 10.64.64.64 which was rejected by the server)