ESP8266 Developer Zone The Official ESP8266 Forum 2015-08-03T13:48:22+08:00 https://bbs.espressif.com:443/feed.php?f=7&t=869 2015-08-03T13:48:22+08:00 2015-08-03T13:48:22+08:00 https://bbs.espressif.com:443/viewtopic.php?t=869&p=3025#p3025 <![CDATA[Re: lwip TCP ephemeral source port is not random.]]>
We updated tcp_new_port in esp_iot_rtos_sdk

Could it solve your problem ?

Statistics: Posted by ESP_Faye — Mon Aug 03, 2015 1:48 pm


]]>
2015-08-01T01:11:14+08:00 2015-08-01T01:11:14+08:00 https://bbs.espressif.com:443/viewtopic.php?t=869&p=2984#p2984 <![CDATA[Re: lwip TCP ephemeral source port is not random.]]>
In the SDK used by the ESP8266/Arduino port, the underlying LWIP library implements a function tcp_new_port as part of the tcp_client library portion of the LWIP library.

This library is provided as a binary library by Espressif rather than as open source.

As such, I have to count on you guys to fix it.

Currently that function works by sequential port allocation starting from a fixed value that is reset on every reset. Thus, the first tcp_connect() call from every reboot will always use source port 4096, the second will use 4097, etc.

This is not best practice and can lead to problems as I have already documented.

Yes, there are workarounds, but if you modify the code as I have suggested, the problem is eliminated without negative consequence.

This is a relatively simple library update to resolve a bug in the current implementation.

Statistics: Posted by owendelong — Sat Aug 01, 2015 1:11 am


]]>
2015-07-31T19:15:38+08:00 2015-07-31T19:15:38+08:00 https://bbs.espressif.com:443/viewtopic.php?t=869&p=2979#p2979 <![CDATA[Re: lwip TCP ephemeral source port is not random.]]>
In non-OS SDK, there is an API : espconn_port to return an available port.

Thanks for your interest in ESP8266 !

Statistics: Posted by ESP_Faye — Fri Jul 31, 2015 7:15 pm


]]>
2015-07-31T00:01:48+08:00 2015-07-31T00:01:48+08:00 https://bbs.espressif.com:443/viewtopic.php?t=869&p=2944#p2944 <![CDATA[lwip TCP ephemeral source port is not random.]]> https://github.com/esp8266/Arduino/issues/632

However, once I started actually looking at code, I found that the problem is inside the LWIP library, speciffically here:

Code:

/**
 * Allocate a new local TCP port.
 *
 * @return a new (free) local TCP port number
 */
static u16_t
tcp_new_port(void)
{
  u8_t i;
  u16_t n = 0;
  struct tcp_pcb *pcb;

again:
  if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) {
    tcp_port = TCP_LOCAL_PORT_RANGE_START;
  }
  /* Check all PCB lists. */
  for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
    for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
      if (pcb->local_port == tcp_port) {
        if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) {
          return 0;
        }
        goto again;
      }
    }
  }
  return tcp_port;
}


I suggest modifying as follows:

replace:

Code:

again:
  if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) {
    tcp_port = TCP_LOCAL_PORT_RANGE_START;
  }


with

Code:

tcp_port = random_port_number();

again:
  if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) {
    tcp_port = TCP_LOCAL_PORT_RANGE_START;
  }


And create a function like

Code:

uint16_t random_port_number()
{
  static bool seeded;
  if (! seeded)
  {
    randomSeed(analogReed(A0));
    seeded=true;
  }
  return(random(TCP_LOCAL_PORT_RANGE_START, TCP_LOCAL_PORT_RANGE_END));
}


In this way, the starting point for the sequential port search is randomized so that different source ports will get assigned across reboots.

This will prevent deadly embraces that can occur when the source port is consistent across reboots and the server is holding an old connection one of the wait states related to the TCP termination process (previous transaction did not complete cleanly and ESP8266 reboots).

I ran into this with an application that posts sensor data to a web site every 60 seconds. The application collects the data, connects to the WiFi network, connects to the server, uses a query string to submit the data, and then sleeps (Deep Sleep) until the next sampling period.

Sometimes, the system would fail to finish the connection close process cleanly and thereafter, it would continuously fail to connect to the web server because the SYN packet being sent to open the connection matched an existing connection in a closing wait state and so the server would retry closing the connection (and reset the timers). Thus, the old (dead) session would never die on the server side and the new session could never be created by the client. Randomizing the ephemeral source port will prevent this from occurring and is BCP for TCP libraries in general.

This should be a relatively simple change to the library. Since I don't have the Espressif source code, I cannot test this mechanism in place, but I have tested similar code manipulating the tcp_port starting point from an external library by changing the scb and it is operational and has resolved my issue.

Statistics: Posted by owendelong — Fri Jul 31, 2015 12:01 am


]]>