如何确定源端口以及如何强制其使用特定端口


26

当我连接到https://www.google.co.uk时,它将更改为216.58.198.228:443。然后,在[我的IP地址]:63998上打开与我的连接。

我的问题是如何选择63998端口,是否有办法将其强制为63999。


9
有没有办法强制将其设置为63999,您有任何理由尝试这样做吗?
AL

1
如果要编写应用程序,则可以打开所需的任何(未使用的)源端口。但这不是一个好主意,也不清楚为什么要这么做?
pjc50

6
@ pjc50实际上,这个问题似乎可能是XY问题
2016年

1
我已经提交了一个编辑,将标题更改为“源”而不是“本地”,因为目标端口号对于目标计算机而言是“本地”,但是初始TCP SYN数据包的源无疑是该设备的发起方的源。连接。
蒙蒂哈德

Answers:


39

如何确定本地端口

该端口号由TCP实施软件从称为“ 临时端口”的一系列端口号中选择。

选择端口号和要使用的范围的确切机制取决于操作系统。


有没有办法将其强制为63999。

这可以通过更改TCP实现软件的配置来完成。

有关更改各种临时操作系统的临时端口范围的说明,请参见“ 更改临时端口范围”

  • 下面的答案中包含Linux和Windows的说明,以供参考。

但是,例如,将范围限制为单个端口不是一个好主意63999

  • 实际上,在Windows上这是不可能的,因为:

    可以设置的最小端口范围是255。


临时港口范围

一个TCP / IPv4连接由两个端点组成,每个端点由一个IP地址和一个端口号组成。因此,当客户端用户连接到服务器计算机时,可以将建立的连接视为(服务器IP,服务器端口,客户端IP,客户端端口)的4元组。

通常,这四个中的三个是众所周知的-客户端计算机使用其自己的IP地址,并且在连接到远程服务时,需要服务器计算机的IP地址和服务端口号。

不能立即看出的是,当建立连接时,该连接的客户端使用端口号。除非客户端程序明确请求特定的端口号,否则使用的端口号是临时端口号。

临时端口是由机器的IP堆栈分配的临时端口,并且为此目的从指定的端口范围分配。当连接终止时,临时端口可用于重用,尽管大多数IP堆栈在使用了所有临时端口池之前不会重用该端口号。

因此,如果客户端程序重新连接,则会为其新连接的端分配一个不同的临时端口号。

来源临时港口范围


更改临时端口范围

Linux:

Linux允许您仅通过使用文件来查看和更改临时端口范围/proc/sys/net/ipv4/ip_local_port_range。例如,这显示了内核2.2系统上的默认配置:

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

要将其更改为首选范围,您可以(以超级用户身份)执行以下操作:

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

请注意,每次系统启动时都需要执行此操作,因此请确保在系统启动脚本中添加一行,例如,/etc/rc.local 以便始终使用范围。

还要注意,如果有足够的内核内存,Linux 2.4内核的默认范围是32768到61000,因此在较新的Linux系统上可能不需要更改范围。

最后,还要注意,您也许可以使用sysctl界面来更改设置,而不是使用/proc文件系统。sysctl参数的名称是“ net.ipv4.ip_local_port_range”。/etc/sysctl.conf如果有,请编辑该文件;如果sysctl要使用更改此参数,请让启动脚本手动运行该命令sysctl

Windows Vista / Windows Server 2008及更高版本:

根据Microsoft知识库文章929851,从Windows Vista和Windows Server 2008开始,Windows现在默认使用大范围(49152-65535)。同一篇文章还显示了如何根据需要更改范围,但是默认范围对于大多数服务器来说已经足够了。

更改临时端口范围

您可以使用以下netsh命令在运行Windows Vista或Windows Server 2008计算机的计算机上查看动态端口范围 :

netsh int ipv4 show dynamicport tcp
netsh int ipv4 show dynamicport udp
netsh int ipv6 show dynamicport tcp
netsh int ipv6 show dynamicport udp 

笔记:

  • 分别为每种传输方式和IP版本分别设置范围。
  • 现在,端口范围实际上是一个具有起点和终点的范围。
  • 如果内部网络上使用了防火墙,则部署运行Windows Server 2008的服务器的Microsoft客户可能会在服务器之间的RPC通信方面遇到问题。
  • 在这些情况下,我们建议您重新配置防火墙,以允许在动态端口范围49152 通过的服务器之间进行通信65535
  • 此范围是服务和应用程序使用的知名端口的补充。
  • 或者,可以在每个服务器上修改服务器使用的端口范围。

您可以使用以下netsh命令来调整此范围:

netsh int <ipv4|ipv6> set dynamic <tcp|udp> start=number num=range

此命令设置TCP的动态端口范围。起始端口是数字,端口总数是范围。以下是示例命令:

netsh int ipv4 set dynamicport tcp start=10000 num=1000
netsh int ipv4 set dynamicport udp start=10000 num=1000
netsh int ipv6 set dynamicport tcp start=10000 num=1000
netsh int ipv6 set dynamicport udp start=10000 num=1000

这些示例命令将动态端口范围设置为从端口10000开始并在端口10999(1000个端口)结束。

笔记:

  • 可以设置的最小端口范围是255
  • 可以设置的最小起始端口是1025
  • 最大末端端口(基于所配置的范围)不能超过65535
  • 若要复制Windows Server 2003的默认行为,请1025用作起始端口,然后3976用作TCP和UDP的范围。结果是的开始端口1025和结束端口5000

来源Microsoft知识库文章929851

Windows XP及更早版本:

对于较旧的Windows操作系统(Windows XP和更早版本),Windows的临时端口范围使用传统的BSD范围1024至4999。不幸的是,您似乎只能设置临时端口范围的上限。这是从Microsoft知识库文章196271中摘录的信息:

  • 启动注册表编辑器(Regedt32.exe)。
  • 在注册表中找到以下项:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

  • 在“编辑”菜单上,单击“添加值”,然后添加以下注册表值:

    值名称:MaxUserPort数据类型:REG_DWORD值:(65534例如)

    有效范围:(5000-65534十进制)默认值:0x1388(5000十进制)

    说明:此参数控制当应用程序从系统请求任何可用的用户端口时使用的最大端口号。通常情况下,短暂的(也就是短暂)端口的值之间的分配10245000包容性。

  • 退出注册表编辑器。

注意:还有另一篇相关的知识库文章(812873),该文章声称允许您设置排除范围,这可能意味着您可以排除端口1024-9999(例如)以使临时端口范围为10000-65534。但是,我们无法使其正常工作(截至2004年10月)。

更改临时端口范围


1
至少对于Windows,似乎有可能限制系统范围的端口范围。在大多数情况下,这可能是一个坏主意,特别是将其限制到一个端口将是:参见KB 929851,至少工作的命令列出在Windows 7
赛斯

@Seth是的。我不愿意提及这一点,因为OP没有提及他的操作系统,并且我不想扩大答案以涵盖N个操作系统……
DavidPostill

你是对的。毕竟有很多操作系统。这只是我最初尝试回答此问题时偶然发现的。由于您的答案越来越快,我只是想添加一下。这是一个非常好的书面答案!:)只是为了暗示有时更改配置而不是重新编程就可以了(也许我的理解是不同的-对我来说听起来像是重新编译)。
赛斯

1
实际上,在Linux中也非常简单:只需执行echo“ 49152 65535”> / proc / sys / net / ipv4 / ip_local_port_range即可。它非常简单,可以在每个命令的基础上完成。
MariusMatutiae

2
与更改临时端口范围相比,让应用程序在bind调用之前先调用系统调用会更好connect。某些应用程序可以选择执行此操作,而其他应用程序则没有。
卡巴斯德,2016年

9

David Postill的答案是完全正确的。我想补充一点,强调在Linux中更改临时端口范围是如此简单,以至于OP给出了肯定的答案。

您可以如下更改EPR:

echo "40000 60000" > /proc/sys/net/ipv4/ip_local_port_range 

您可以使用以下脚本选择端口50000(作为示例):

OLD_RANGE=$(cat /proc/sys/net/ipv4/ip_local_port_range)
MY_PORT=50000
echo "$MY_PORT $MY_PORT" > /proc/sys/net/ipv4/ip_local_port_range
sudo -u SomeUser SomeApplication  & 
echo $OLD_RANGE" > /proc/sys/net/ipv4/ip_local_port_range 

需要注意的是:由于范围中只有一个端口,因此另一个应用程序可能会在执行上述第三行和第四行之间将其从您手中夺走;同样,即使没有竞争条件,您也将使所有其他应用程序瘫痪,直到恢复大的EPR,这就是为什么我尽快恢复原始范围的原因。

因此,如果 OP的操作系统是Linux,那么答案就是可以轻松实现。

令人惊讶的是,这在BSD上并不是那么简单,其中有些甚至没有针对EPR的运行时内核设置。MacOS X,FreeBSD和OpenBSD需要修改文件/etc/sysctl.conf,但是EPR有不同的选择。

无论上述内容和操作系统如何,可以做某事的事实并不意味着应该做某事:为什么在地球上您需要这样做?我无法想到一个用例。


对于Linux示例+1。
DavidPostill

呵呵。BSD / OS需要重新编译内核:)
DavidPostill

1
@DavidPostill这真是个麻烦。
MariusMatutiae'8

您的代码示例中有一个缺陷。您的类型转换非常错误。另外,最好使它成为BIND_PORT可选的,以便仍然可以以与原始代码完全相同的方式使用代码。我认为htons(bind_port_env ? atoi(bind_port_env) : 0)这样做是对的。
卡巴斯德,2016年

1

值得补充的是,Linux内核还具有

net.ipv4.ip_local_reserved_ports

旋钮的作用有些相反,但是它可能非常有用,因为这样您可以为在临时端口范围内打开特定端口的服务“打个洞”。

摘录自文档

指定为已知的第三方应用程序保留的端口。这些端口将不会被自动端口分配使用(例如,使用端口号0调用connect()或bind()时)。显式端口分配行为不变。

用于输入和输出的格式是范围的逗号分隔列表(例如,端口1、2、3、4和10的“ 1,2-4,10-10”)。写入文件将清除所有先前保留的端口,并使用输入中给定的端口更新当前列表。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.