The Ephemeral Port Range

A TCP/IPv4 connection consists of two endpoints, and each endpoint consists of an IP address and a port number.  Therefore, when a client user connects to a server computer, an established connection can be thought of as the 4-tuple of (server IP, server port, client IP, client port).  Usually three of the four are readily known -- client machine uses its own IP address and when connecting to a remote service, the server machine's IP address and service port number are required.  

What is not immediately evident is that when a connection is established that the client side of the connection uses a port number.  Unless a client program explicitly requests a specific port number, the port number used is an ephemeral port number.  Ephemeral ports are temporary ports assigned by a machine's IP stack, and are assigned from a designated range of ports for this purpose.  When the connection terminates, the ephemeral port is available for reuse, although most IP stacks won't reuse that port number until the entire pool of ephemeral ports have been used.  So, if the client program reconnects, it will be assigned a different ephemeral port number for its side of the new connection.

Similarly, for UDP/IP, when a datagram is sent by a client from an unbound port number, an ephemeral port number is assigned automatically so the receiving end can reply to the sender.

Contents

Limits Implied by the Ephemeral Port Range

Another important ramification of the ephemeral port range is that it limits the maximum number of connections from one machine to a specific service on a remote machine!  The TCP/IP protocol uses the connection's 4-tuple to distinguish between connections, so if the ephemeral port range is only 4000 ports wide, that means that there can only be 4000 unique connections from a client machine to a remote service at one time.

A port range of 4000 may seem large, but it is actually small for 21st century computing demands when you consider that a TCP connection must expire through the TIME_WAIT state before it is really completed.  For example, even if both sides of a connection properly close their ends of the connection, due to TCP's error control, each side must wait until the TIME_WAIT state is expired before the connection's resources can really be disposed.  The TIME_WAIT state is twice the MSL (maximum segment lifetime) which, depending on the IP stack, is usually configured to be 240 seconds total.  That means that you could have only 4000 connections per 240 second window, and in practice this can be exhausted.

Problems Exacerbated by the File Transfer Protocol

For example, the File Transfer Protocol (FTP) uses a separate data connection for each data transfer, so this phenomenon can be experienced when FTP'ing hundreds of small files over a fast local network.  When all ephemeral ports are in use, a compatible BSD Sockets TCP/IP stack will return "Address already in use" errors.

The second problem with the FTP is that with the default mode of operation, the separate data transfer connections originate from the server machine back to the client machine to an ephemeral port number requested by the client program.  Since many firewalls restrict incoming connections, when the FTP data connection tries to connect to an ephemeral port number on the client machine, the connection may be denied by the firewall since the port number isn't a well-known service port.

It may be best to illustrate this by showing a sample FTP session:

Client: USER anonymous
Server: 331 Guest login ok, send your e-mail address as password.
Client: PASS NcFTP@
Server: 230 Logged in anonymously.
Client: PORT 192,168,1,2,7,138 The client wants the server to send to port number 1930 on IP address 192.168.1.2.
Server: 200 PORT command successful.
Client: LIST
Server: 150 Opening ASCII mode data connection for /bin/ls. The server now connects out from port 20 to port 1930 on 192.168.1.2.
Server: 226 Listing completed. That succeeded, so the data is now sent over the established data connection.
Client: QUIT
Server: 221 Goodbye.

Now, had there been a restrictive firewall on the client machine, when the connection from the server to port 1930 on the client would have failed.  Note that the client program did not explicitly ask for port 1930 -- it just asked for an unused port number to use for this temporary data connection.

Traditional Configuration of the Ephemeral Port Range

The BSD Sockets TCP/IP stack used ports 1024 through 4999 as ephemeral ports.  Additionally, ports 1 through 1023 were intended for systems services running as the superuser, so those ports are called reserved ports.  

As discussed earlier, BSD's choice of the ephemeral port range is unfortunate because of its relatively small size (3975 ports) and its low numbered position.  We feel that the default range should be 49152 through 65535, which is both much larger (16383 ports) and is at the very top of the full port range.

Firewalling the Ephemeral Port Range

For firewalls, often administrators choose to restrict access to as many port numbers as possible.  For cases where inbound connections to the ephemeral ports is required, an entire range of ports must be opened.  It is imperative that when opening a range of ports on the firewall that no system services are listening on ports in the open range.  Administrators will often want to open a specific range on the firewall, and then for each machine on the internal network, make sure that the ephemeral port range on the machine coincides with the open range on the firewall.

It must be made clear that the ephemeral port range on machines on the internal network often do not coincide with each other since different operating systems may use different ranges.  That is why it can be time consuming to manually configure each machine's ephemeral port range so it coincides with the open range on the firewall.  As a result, administrators often end up changing to a policy of allowing all incoming ports and deny access to specific ports when needed.

Luckily, it may not be necessary to open the ephemeral port range.  It is usually only necessary when FTP is being served to the outside world (Passive "PASV" data connections use inbound ephemeral ports), or when FTP client access must work in non-passive mode ("PORT" connections from the server are inbound to clients using ephemeral ports).

Changing the Ephemeral Port Range

It is desirable to change which port numbers are used for the ephemeral port range for any of the following:

To use a larger range so that more simultaneous connections are possible

To shift the range to the higher numbered ports.  The higher numbered ports should be used as ephemeral ports because they are less likely to be used as port numbers for system services.  Well-known service ports have traditionally been assigned to lower port numbers.

To change the range to coincide with other systems for purposes of firewalling and automatic network address translation. 

When changing the range, we suggest you change it to 49152 through 65535.  If you need a larger range, continue downward from 49152, but leave 65535 as your upper bound.  We will now list how to change the ephemeral port range on various operating systems.  As you'll see below, some systems already use our preferred range and will not need to be changed.  Some operating systems also use two or more ranges, and to use the other ranges an application will have to be explicitly coded to choose the other range.  

This document was written for administrators using NcFTPd Server, so if the only reason you need to worry about ephemeral ports is because you want to run NcFTPd, then depending on the operating system you may not have to do anything since NcFTPd is aware of and alternate high-numbered ephemeral port ranges and will use them automatically.

What follows are operating system-specific instructions on changing the ephemeral port range.


AIX

AIX uses the "no" command to set network options.  AIX uses two separate ephemeral port ranges, one for TCP and UDP, and both default to the values 32768 through 65535:

# /usr/sbin/no -a | fgrep ephemeral
        tcp_ephemeral_low = 32768
       tcp_ephemeral_high = 65535
        udp_ephemeral_low = 32768
       udp_ephemeral_high = 65535

The default range is sufficient, but you can change it using the no command.  Here is an example that sets the TCP ephemeral port range to 49152 through 65535:

# /usr/sbin/no -o tcp_ephemeral_low=49152 -o tcp_ephemeral_high=65535

The options you set with no must be done each time the system starts up.  One way to do that is to edit /etc/rc.tcpip and insert your no commands just before the script starts running the server daemons.

 

BSD/OS

The default range is 49152 through 65535, as defined in /usr/include/netinet/in.h:

/*
* Local port number conventions:
* Ports < IPPORT_RESERVED are reserved for
* privileged processes (e.g. root).
* Ports >= IPPORT_RESERVED && < IPPORT_DYNAMIC
* are reserved for servers, not necessarily privileged.
* Ports >= IPPORT_DYNAMIC are available for
* dynamic port assignment.
*/
#define IPPORT_RESERVED 1024
#define IPPORT_DYNAMIC 49152
#define IPPORT_DYNAMIC_LAST 65535

There doesn't appear to be a runtime kernel setting for this (i.e. no available sysctl parameter to tweak), so to change this you would need to recompile the kernel after changing those definitions.  Since the default range is exactly what we recommend anyway, changing the range is not necessary.

 

FreeBSD

FreeBSD uses three ranges:

  1. The regular ephemeral port range
  2. An alternate ("high") ephemeral port range
  3. An alternate ("low") reserved port range, for use by programs using the rresvport() function.

These ranges are briefly documented in the system header file /usr/include/netinet/in.h:

/*
 * Local port number conventions:
 *
 * When a user does a bind(2) or connect(2) with a port number of zero,
 * a non-conflicting local port address is chosen.
 * The default range is IPPORT_RESERVED through
 * IPPORT_USERRESERVED, although that is settable by sysctl.
 *
 * A user may set the IPPROTO_IP option IP_PORTRANGE to change this
 * default assignment range.
 *
 * The value IP_PORTRANGE_DEFAULT causes the default behavior.
 *
 * The value IP_PORTRANGE_HIGH changes the range of candidate port numbers
 * into the "high" range. These are reserved for client outbound connections
 * which do not want to be filtered by any firewalls.
 *
 * The value IP_PORTRANGE_LOW changes the range to the "low" are
 * that is (by convention) restricted to privileged processes. This
 * convention is based on "vouchsafe" principles only. It is only secure
 * if you trust the remote host to restrict these ports.
 *
 * The default range of ports and the high range can be changed by
 * sysctl(3). (net.inet.ip.port{hi,low}{first,last}_auto)
 *
 * Changing those values has bad security implications if you are
 * using a a stateless firewall that is allowing packets outside of that
 * range in order to allow transparent outgoing connections.
 *
 * Such a firewall configuration will generally depend on the use of these
 * default values. If you change them, you may find your Security
 * Administrator looking for you with a heavy object.
 *
 * For a slightly more orthodox text view on this:
 *
 * ftp://ftp.isi.edu/in-notes/iana/assignments/port-numbers
 *
 * port numbers are divided into three ranges:
 *
 * 0 - 1023 Well Known Ports
 * 1024 - 49151 Registered Ports
 * 49152 - 65535 Dynamic and/or Private Ports
 *
 */

/*
 * Ports < IPPORT_RESERVED are reserved for
 * privileged processes (e.g. root). (IP_PORTRANGE_LOW)
 * Ports > IPPORT_USERRESERVED are reserved
 * for servers, not necessarily privileged. (IP_PORTRANGE_DEFAULT)
 */
#define IPPORT_RESERVED 1024
#define IPPORT_USERRESERVED 5000

/*
 * Default local port range to use by setting IP_PORTRANGE_HIGH
 */
#define IPPORT_HIFIRSTAUTO 49152
#define IPPORT_HILASTAUTO 65535

/*
 * Scanning for a free reserved port return a value below IPPORT_RESERVED,
 * but higher than IPPORT_RESERVEDSTART. Traditionally the start value was
 * 512, but that conflicts with some well-known-services that firewalls may
 * have a fit if we use.
 */
#define IPPORT_RESERVEDSTART 600

Running the sysctl program shows the default values for these ranges:

/sbin/sysctl -a | fgrep net.inet.ip.portrange
net.inet.ip.portrange.lowfirst: 1023
net.inet.ip.portrange.lowlast: 600
net.inet.ip.portrange.first: 1024
net.inet.ip.portrange.last: 5000
net.inet.ip.portrange.hifirst: 49152
net.inet.ip.portrange.hilast: 65535

To change this, edit /etc/sysctl.conf and add (or change existing) lines such as:

net.inet.ip.portrange.first=32768
net.inet.ip.portrange.last=49151
net.inet.ip.portrange.hifirst=49152
net.inet.ip.portrange.hilast=65535

This sets the regular ephemeral port range to use ports 32768 through 49151, the alternate ephemeral port range to 49152 through 65535, and leaves the reserved port range unchanged.  The system will need to be rebooted for the changes to /etc/sysctl.conf to take effect (although you could just use the sysctl program manually to make the changes immediately).

Note that NcFTPd uses the alternate range, whose default values are acceptable.  Therefore, no tuning is necessary unless you want to change the behavior of other programs which may not explicitly attempt to use the alternate range like NcFTPd does.

 

HP-UX

HP-UX uses the "ndd" utility program to change tunable IP stack parameters.  The ephemeral ports on HP-UX can be tuned individually for both TCP and UDP, so there are really two separate ephemeral port ranges.  HP-UX also provides options to change the privileged port range (ports only processes running with superuser privileges can use).

The good news is that HP-UX uses our recommended port range (49152 through 65535) so it is unlikely you will need to change the range from the default values.

The example below shows how to query the existing values for the TCP ephemeral ports, and change the range to 50001 through 61000:

# /usr/bin/ndd /dev/tcp tcp_smallest_anon_port tcp_largest_anon_port
49152

65535
# /usr/bin/ndd -set /dev/tcp tcp_smallest_anon_port 50001
# /usr/bin/ndd -set /dev/tcp tcp_largest_anon_port 61000
# /usr/bin/ndd /dev/tcp tcp_smallest_anon_port tcp_largest_anon_port
50001

61000

Note that if you change the range values, you must do it each time the system boots.  As we've mentioned, the default values are sufficient so you do not need to change the range values, but if you decide to proceed, the preferred way to do this for HP-UX is to edit the file /etc/rc.config.d/nddconf and add entries.  For example, you might append these lines to your /etc/rc.config.d/nddconf file:

TRANSPORT_NAME[0]=tcp
NDD_NAME[0]=tcp_largest_anon_port
NDD_VALUE[0]=65535

TRANSPORT_NAME[1]=tcp
NDD_NAME[1]=tcp_smallest_anon_port
NDD_VALUE[1]=49152

If you do that, be sure that the entries are numbered accordingly.  For example, if there are 4 entries already present, you would see them numbered 0 through 3 (i.e. TRANSPORT_NAME[3]=...).  In that case, the entries you append need to be numbered after the existing entries.

Another option instead of editing /etc/rc.config.d/nddconf you could create a startup script to do the same thing.  Below is an example:

#!/bin/sh
#
# Copy me to /sbin/init.d/ephemports, then do
# "ln -s /sbin/init.d/ephemports /sbin/rc2.d/S341ephemports".
#
EPHEM_HI="65535"
EPHEM_LO="49152"
NDD=/usr/bin/ndd

if [ "$#" -eq 0 ] ; then arg="start" ; else arg="$1" ; fi
case "$arg" in
'start')
	;; # Fall through -- rest of script is the initialization code

'stop'|'start_msg'|'stop_msg')
	exit 0
	;;

'status')
	EPHEM_HI=`${NDD} /dev/udp udp_largest_anon_port`
	EPHEM_LO=`${NDD} /dev/udp udp_smallest_anon_port`
	echo "UDP ephemeral port range is ${EPHEM_LO}..${EPHEM_HI}."
	EPHEM_HI=`${NDD} /dev/tcp tcp_largest_anon_port`
	EPHEM_LO=`${NDD} /dev/tcp tcp_smallest_anon_port`
	echo "TCP ephemeral port range is ${EPHEM_LO}..${EPHEM_HI}."
	exit 0
	;;

*)
	echo "Usage: $0 { start | stop | status }"
	exit 1
	;;
esac

${NDD} -set /dev/udp udp_smallest_anon_port "${EPHEM_LO}"
${NDD} -set /dev/udp udp_largest_anon_port "${EPHEM_HI}"
${NDD} -set /dev/tcp tcp_smallest_anon_port "${EPHEM_LO}"
${NDD} -set /dev/tcp tcp_largest_anon_port "${EPHEM_HI}"

EPHEM_HI=`${NDD} /dev/udp udp_largest_anon_port`
EPHEM_LO=`${NDD} /dev/udp udp_smallest_anon_port`
echo "UDP ephemeral port range is ${EPHEM_LO}..${EPHEM_HI}."
EPHEM_HI=`${NDD} /dev/tcp tcp_largest_anon_port`
EPHEM_LO=`${NDD} /dev/tcp tcp_smallest_anon_port`
echo "TCP ephemeral port range is ${EPHEM_LO}..${EPHEM_HI}."

exit 0

For more information, see:

 

IRIX

Unfortunately IRIX does not seem to let you tune the ephemeral port range, and is statically set to 1024 through 65535.  Excerpted from /usr/include/netinet/in.h:

/*
 * Local port number conventions:
 * Ports < IPPORT_RESERVED are reserved for
 * privileged processes (e.g. root).
 * Ports > 5000 used to be reserved for non-root servers,
 * but this convention can no longer be used with large scale systems.
 * All well-known ports should be registered with the Internet Assigned
 * Numbers Authority.
 */
#define IPPORT_RESERVED         1024
#define IPPORT_MAXPORT          65535

There is also not an option listed for the systune program, although there are other IP and TCP/IP related options that can be set.

 

Linux

Linux allows you to view and change the ephemeral port range by simply using the file /proc/sys/net/ipv4/ip_local_port_range.  For example, this shows the default configuration on a kernel 2.2 system:

$ cat /proc/sys/net/ipv4/ip_local_port_range 
1024 4999

To change this to the preferred range, you could do (as superuser):

# echo "49152 65535" > /proc/sys/net/ipv4/ip_local_port_range 

Note that you would need to do this each time the system boots, so be sure to add a line to a system startup script such as /etc/rc.local so your range is always used.

Also note that the Linux 2.4 kernel will default the range of 32768 through 61000 if adequate kernel memory is available, so changing the range may not be necessary on newer Linux systems.

Finally, also note that you may be able to use the sysctl interface to change the settings rather than using the /proc filesystem. The name of the sysctl parameter is "net.ipv4.ip_local_port_range".  Edit the /etc/sysctl.conf file if you have it, or have a startup script run the sysctl command manually if you want to change this parameter using sysctl.

 

OpenBSD

OpenBSD uses the sysctl command to tune kernel parameters.  The ephemeral ports on OpenBSD are actually two separate ranges, the regular range, and the alternate "high" range.  Below is an example showing how to use sysctl to view the current configuration of these two ranges:

# /usr/sbin/sysctl net.inet.ip.portfirst net.inet.ip.portlast net.inet.ip.porthifirst net.inet.ip.porthilast
net.inet.ip.portfirst = 1024
net.inet.ip.portlast = 49151
net.inet.ip.porthifirst = 49152
net.inet.ip.porthilast = 65535

To change this, edit /etc/sysctl.conf and add (or change existing) lines such as:

net.inet.ip.portfirst=32768
net.inet.ip.portlast=49151
net.inet.ip.porthifirst=49152
net.inet.ip.porthilast=65535

This sets the regular ephemeral port range to use ports 32768 through 49151, and the alternate ephemeral port range to 49152 through 65535.  The system will need to be rebooted for the changes to /etc/sysctl.conf to take effect (although you could just use the sysctl program manually to make the changes immediately).

Note that NcFTPd uses the alternate range, whose default values are acceptable.  Therefore, no tuning is necessary unless you want to change the behavior of other programs which may not explicitly attempt to use the alternate range like NcFTPd does.

 

Solaris

Solaris uses the "ndd" utility program to change tunable IP stack parameters.  The ephemeral ports on Solaris can be tuned individually for both TCP and UDP, so there are really two separate ephemeral port ranges.  Solaris also provides options to change the privileged port range (ports only processes running with superuser privileges can use).

The good news is that Solaris by default provides a large range at the end of the port range (32768 through 65535, or the upper 50%) so it is unlikely you will need to change the range from the default values.

The example below shows how to query the existing values for the TCP ephemeral ports, and change the range to 49152 through 61000:

# /usr/sbin/ndd /dev/tcp tcp_smallest_anon_port tcp_largest_anon_port
32768

65535
# /usr/sbin/ndd -set /dev/tcp tcp_smallest_anon_port 49152
# /usr/sbin/ndd -set /dev/tcp tcp_largest_anon_port 61000
# /usr/sbin/ndd /dev/tcp tcp_smallest_anon_port tcp_largest_anon_port
49152

61000

Note that if you change the range values, you must do it each time the system boots.  Although we recommend that you just use the default range which is sufficient, here is a sample script you can use to change the range at startup:

#!/sbin/sh
#
# Copy me to /etc/init.d/ephemports, then do
# "ln -s /etc/init.d/ephemports /etc/rc2.d/S70ephemports".
#
EPHEM_HI="65535"
EPHEM_LO="49152"

if [ "$#" -eq 0 ] ; then arg="start" ; else arg="$1" ; fi
case "$arg" in
'start')
	;; # Fall through -- rest of script is the initialization code

'stop')
	exit 0
	;;

'status')
	EPHEM_HI=`/usr/sbin/ndd /dev/udp udp_largest_anon_port`
	EPHEM_LO=`/usr/sbin/ndd /dev/udp udp_smallest_anon_port`
	echo "UDP ephemeral port range is ${EPHEM_LO}..${EPHEM_HI}."
	EPHEM_HI=`/usr/sbin/ndd /dev/tcp tcp_largest_anon_port`
	EPHEM_LO=`/usr/sbin/ndd /dev/tcp tcp_smallest_anon_port`
	echo "TCP ephemeral port range is ${EPHEM_LO}..${EPHEM_HI}."
	exit 0
	;;

*)
	echo "Usage: $0 { start | stop | status }"
	exit 1
	;;
esac

/usr/sbin/ndd -set /dev/udp udp_smallest_anon_port "${EPHEM_LO}"
/usr/sbin/ndd -set /dev/udp udp_largest_anon_port "${EPHEM_HI}"
/usr/sbin/ndd -set /dev/tcp tcp_smallest_anon_port "${EPHEM_LO}"
/usr/sbin/ndd -set /dev/tcp tcp_largest_anon_port "${EPHEM_HI}"

EPHEM_HI=`/usr/sbin/ndd /dev/udp udp_largest_anon_port`
EPHEM_LO=`/usr/sbin/ndd /dev/udp udp_smallest_anon_port`
echo "UDP ephemeral port range is ${EPHEM_LO}..${EPHEM_HI}."
EPHEM_HI=`/usr/sbin/ndd /dev/tcp tcp_largest_anon_port`
EPHEM_LO=`/usr/sbin/ndd /dev/tcp tcp_smallest_anon_port`
echo "TCP ephemeral port range is ${EPHEM_LO}..${EPHEM_HI}."

exit 0

For more information about tuning Solaris, refer to the following sources:

 

Tru64 UNIX

Compaq's Tru64 UNIX (formerly Digital UNIX and Digital OSF/1) uses the traditional BSD range of 1024 through 4999 for its ephemeral port range.  The following example uses the sysconfig command to query the current range:

# /sbin/sysconfig -q inet | fgrep ipport_userreserved
ipport_userreserved = 5000
ipport_userreserved_min = 1024

This next example shows how to use sysconfig to use our preferred ephemeral port range:

# /sbin/sysconfig -r inet ipport_userreserved=65535 ipport_userreserved_min=49152
ipport_userreserved: reconfigured
ipport_userreserved_min: reconfigured

# /sbin/sysconfig -q inet | fgrep ipport_userreserved                         
ipport_userreserved = 65535
ipport_userreserved_min = 49152

Using the sysconfig command only applies the changes for the current boot cycle.  To have the changes applied automatically each time the system boots, you can either create a system startup script to run the sysconfig command, or better, use the sysconfigdb command to manage the /etc/sysconfigtab file.  Here's an example:

/sbin/sysconfigdb -a -f /tmp/inet.stanza inet

The inet.stanza file we referenced in the example should look like the following.  Make sure that your file has "inet:" by itself on the first line, and the next two lines are preceded by a single tab character (do not use space characters).

inet:
    ipport_userreserved = 65535
    ipport_userreserved_min = 49152

See also:

 

Microsoft Windows

As of Windows Vista and Windows Server 2008, Windows now uses a large range (49152-65535) by default, according to Microsoft Knowledgebase Article 929851. That same article also shows how you can change the range if desired, but the default range is now sufficient for most servers.

For older Windows operating systems (Windows XP and older), Windows uses the traditional BSD range of 1024 through 4999 for its ephemeral port range.  Unfortunately it appears that you can only set the upper bound of the ephemeral port range.  Here is information excerpted from Microsoft Knowledgebase Article 196271:

Note: There is another relevant KB article (812873) which claims to allow you to set an exclusion range, which could mean that you could exclude ports 1024-9999 (for example) to have the ephemeral port range be 10000-65534. However, we have not been able to get this to work (as of October 2004).


© Copyright 2001 by Mike Gleason, NcFTP Software.
All Rights Reserved.