Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ephemeral source port not random #31

Closed
mcspr opened this issue Mar 22, 2019 · 1 comment
Closed

Ephemeral source port not random #31

mcspr opened this issue Mar 22, 2019 · 1 comment
Assignees

Comments

@mcspr
Copy link
Collaborator

mcspr commented Mar 22, 2019

I happened to stumble upon another difference between lwip1.4 and lwip2 used by the Arduino Core - source port randomization. After reset, lwip1 always selects a random port when doing outgoing connections, while lwip2 increments port values starting from the same number. Which causes weird issues from time to time.

Some sources:
esp8266/Arduino#632
me-no-dev/ESPAsyncTCP#108
https://blog.voneicken.com/2018/lp-wifi-esp8266-2/

Core's WiFiClient has an option to select source port, but current versions of AsyncTCP does not expose such method. IDK whether this is a issue for async lib or lwip but! current versions of ESP32 and ESP8266_RTOS modify lwip to randomize it by default:

idf: espressif/esp-lwip@4cc89a0
https://github.com/espressif/esp-idf/blob/1aa8e8d38ebe688c391359b5962707c1d135d07e/components/lwip/port/esp32/include/lwipopts.h#L749

esp8266: espressif/ESP8266_RTOS_SDK@a66d130#diff-d4ffea296f65048ca90617f4680cf389

@d-a-v d-a-v self-assigned this Mar 22, 2019
@d-a-v
Copy link
Owner

d-a-v commented Mar 22, 2019

while lwip2 increments port values starting from the same number

This number is uninitialized, and is checked and increased by upstream lwIP (ref)
(I just confirmed this to myself with +=2 instead)

I understand the issue, thanks for the links, and we can in this repository apply the same patch as in lwIP-2.0.3 used by rtos-sdk.

@d-a-v d-a-v closed this as completed in 25d5e81 Mar 22, 2019
d-a-v added a commit to d-a-v/Arduino that referenced this issue Mar 22, 2019
d-a-v added a commit to esp8266/Arduino that referenced this issue Apr 5, 2019
ref: d-a-v/esp82xx-nonos-linklayer#31
origin: #5902
me-no-dev/ESPAsyncTCP#108

Following the links above is instructive.
To summarize:

    * currently and from a long time lwIP tcp client connections always uses the same tcp source port number right after boot
    * this port number is increased everytime a new one is needed (= new tcp client connection)
      (to be noted, linux has the same increasing behavior)
    * when connecting to the same server (right after boot), the triplet (esp-ip-address, source port, destination port) are the same, and may hit remote server list of sockets in time-wait-state (previous connection unproperly closed from the same esp). Consequently the new connection fails when it happens.
    * this is happening only when debugging (esp reboots often, in less time than time-wait expiration), so the nasty effect is amplified especially when bugs are being chased
    * efforts had been done when espressif's lwIP implementation wasn't open source, with WiFiClient::setLocalPortStart() #632 but it must be explicitely called with a different random number at every reboot. Efficient but not ideal.

This PR uses espressif firmware's r_rand() everytime a new local source port is needed. A different source port number is now showed by tcpdump right after boot. Source port range and duplication is verified everytime in lwIP's src/core/tcp.c:tcp_new_port(). It is implemented as a local patch for upstream lwIP so it is valid not only with WiFiClient but also with @me-no-dev's Async libraries (they don't use WiFiClient).

WiFiClient::setLocalPortStart() is still usable with the same effects as before.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants