我想关闭客户端和服务器应用程序之间处于侦听模式的开放端口。

Linux中是否有任何手动命令行选项可以关闭端口?

注意:我知道“只有拥有连接套接字的应用程序才能关闭端口,当应用程序终止时会发生这种情况。“

我不明白为什么只有打开它的应用程序才有可能...但是我仍然很想知道是否还有其他方法去做。

评论

不,打开的端口属于打开它们的过程,无法从外部进行控制。这是一件好事,否则所有应用程序都必须预料到其打开的端口(和文件)会混乱。但是,您可以通过防火墙(iptables)阻止到端口的流量,但这不会关闭并放弃该端口供其他使用。

许多回答者都没有回答这个问题。声明只有拥有该端口的应用程序可以断开它是毫无意义的。我可以走到盒子前,将以太网电缆从插座中拉出,或者通过杀死连接另一端的应用程序来断开连接!必须编写应用程序来处理此问题。那么---您如何进行测试以确保应用程序正确编写,而无需物理干预和/或控制另一台计算机?

“ ...无法从外部进行控制。”这是重要的一句话,将我引向下一个问题,我如何才能从外部参与过程? GDB。

@JürgenStrobel确实可以从外部进行控制-tcpkill和ss都可以完全满足要求。因为打开的端口并不真正属于进程;它们是内核资源,为进程分配了一些权限,但仍然仅在内核乐意下存在。

@ tom-anderson DaleW:tcpkill是防火墙工具,我确实提到了此选项。您可以阻止到端口的通信,这与关闭端口(套接字)不同。

#1 楼

我遇到了同样的问题,进程必须保持活动状态,但套接字必须关闭。
在运行的进程中关闭套接字不是不可能,但很困难:



查找该过程:

netstat -np


您将获得一个source/destination ip:port portstate pid/processname映射


在该过程中找到套接字的文件描述符

lsof -np $pid


您将得到一个列表:进程名称,pid,user,fileDescriptor,...一个连接字符串。

找到用于连接的匹配的fileDescriptor编号。这将是类似于“ 97u”的意思,即“ 97”。


现在连接该过程:

gdb -p $pid



现在关闭插座:

call close($fileDescriptor) //does not need ; at end.


示例:

call close(97)


然后分离gdb:

quit


并且插座已关闭。



评论


sudo lsof -np $ pid给了我大约200行,而我对于如何找到所需的FD感到困惑。就我而言,过程是Chrome标签页,我正在尝试关闭打开的websockets ...

– SET
2014年6月10日9:25



通常行如下所示:firefox 14812 szupervigyor 97u IPv4 32814564 0t0 TCP 192.168.2.4:40385->173.194.39.65:https(ESTABLISHED)as:process_name pid user fd [opened_for]协议设备inode protocol_data_toString

–丹科·达维德(DankóDávid)
2014年6月11日23:32



*通常如下所示:firefox 14812 szupervigyor 97u IPv4 32814564 0t0 TCP 192.168.2.4:40385->173.194.39.65:https(ESTABLISHED)as:process_name pid user fd [opened_for]协议设备inode protocol_data_toString您需要知道远程ip地址并在最后一个栏上找到。在我的示例中,97是FileDescriptor。如果打开了到目标主机的多个连接,搜索将很困难。

–丹科·达维德(DankóDávid)
2014年6月11日23:38

这是一个绝妙的解决方案

– marcorossi
15年1月22日在12:55

如果要模拟套接字被远端关闭(例如对等端退出),最好使用shutdown:调用shutdown($ fileDescriptor,0)。

– ecatmur
16年4月22日在10:19

#2 楼

您在这里提出了错误的问题。从打开侦听套接字的应用程序外部简单地“关闭端口”实际上是不可能的。唯一的方法是完全杀死拥有该端口的进程。然后,大约一两分钟后,该端口将再次可用。这是正在发生的事情(如果您不关心,请跳到最后,向我展示如何杀死拥有特定端口的进程):

端口是操作系统分配给不同进程的资源。这类似于要求操作系统提供文件指针。但是,与文件指针不同,一次只能有一个进程拥有一个端口。通过BSD套接字接口,进程可以发出侦听端口的请求,然后操作系统将批准该端口。操作系统还将确保没有其他进程获得相同的端口。在任何时候,该过程都可以通过关闭套接字来释放端口。然后,操作系统将收回该端口。或者,如果进程在没有释放端口的情况下结束,则操作系统最终将收回该端口(尽管不会立即发生:这将需要几分钟)。

现在,您要执行的操作(仅从命令行关闭端口)由于两个原因而无法实现。首先,如果可能的话,这意味着一个进程可以简单地窃取另一个进程的资源(端口)。除非限于特权进程,否则这将是错误的策略。第二个原因是,如果让端口继续运行,尚不清楚拥有该端口的进程将发生什么情况。假定过程拥有该资源,则编写该过程的代码。如果我们只是将其拿走,它最终将自行崩溃,因此即使您是特权进程,OS也不允许您这样做。取而代之的是,您只需要简单地杀死它们即可。

无论如何,这是杀死具有特定端口的进程的方法:

sudo netstat -ap | grep :<port_number>


将输出与过程保持端口对应的线,例如:

tcp  0  0 *:8000   *:* LISTEN  4683/procHoldingPort


在这种情况下,procHoldingPort是打开端口的进程的名称,4683是其pid,而8000(请注意它是TCP)是其持有的端口号。

然后,在最后一列,您将看到/。然后执行以下命令:

kill  <pid>


如果不起作用(您可以通过重新运行netstat命令进行检查)。为此:

kill -9 <pid>


通常,最好避免发送SIGKILL。这就是为什么我告诉您在kill之前尝试kill -9的原因。只需使用kill,即可发送较柔和的SIGTERM。

就像我说的那样,如果要重新打开端口,仍然需要几分钟。我不知道有什么方法可以加快速度。如果有人这样做,我很想听听。

评论


@smehmood-感谢您的详细解释..一个小小的疑问..内核如何通过突然终止的进程回收开放的端口? ..您提供的解决方案似乎正在终止持有端口的进程...

–codingfreak
10-4-6在4:17

@codingfreak内核知道进程已经消失。它知道它可以收回端口。实际上,有关于关闭端口的时间的规则,以确保在网络上没有任何杂散数据包。它怎么知道它拥有这些资源?这就是内核的工作,可以跟踪情况。

– Rich Homolka
13年1月1日于2:05

除非有人发布诸如unix.tools.port.close(<我的端口号>)之类的明智信息,否则我将使用init 6。

–雪崩
17-2-10在20:57



这是一个不同问题的绝佳答案。这个问题是关于附加调试器并更改正在运行的程序以使该程序调用文件描述符上的函数的。

– Arthur Ulfeldt
19年10月1日在21:14

#3 楼

也可以使用定影器

fuser -k -n *protocol portno*


这里的协议是tcp / udp,而portno是您要关闭的号码。
例如


fuser -k -n tcp 37


热熔器手册页上的更多信息

评论


只是取消拥有过程对我来说不起作用,但热熔器确实有效。谢谢!

– webwurst
13年5月13日在10:06

我得到的结果参差不齐,即使使用了定影器之后,当尝试从已终止的应用程序重用端口(甚至以root身份使用)时,也出现了“ socket已经在使用中”的信息。另一方面,释放插槽的时间似乎比以前要短,所以还是要谢谢。

– Jan Vlcinsky
2014年4月14日在8:16



@JanVlcinsky也许有一个“守护程序”进程可以在运行热熔器后重新启动被终止的进程?

– RedBaron
2014年4月15日下午5:12

@RedBaron:根据评论superuser.com/a/415236/153413,我的问题出在编写不良的应用程序中,该应用程序无法清理/关闭处于终止状态的套接字。因此,fuser会使用该端口找到该进程并将其终止,但无法解决套接字未关闭的事实。 60秒,内核为我完成。

– Jan Vlcinsky
2014年4月15日在16:25



#4 楼

您也可以使用iptables:

iptables -I INPUT -p tcp --dport 80 -j DROP


它基本上完成了您想要的。这会将所有TCP通信丢弃到端口80。

评论


不,这将保持套接字打开,直到所有超时关闭它们为止。 (它将隐藏拥有进程中的所有流量,然后它们无法知道应该关闭它。)您可以使用-j REJECT返回TCP重置标志,然后才能在拥有进程中看到它(但仅当另一方尝试发送东西)。

– Marki555
15年5月15日在17:07

#5 楼

您可以使用ss关闭监听套接字:

sudo ss --kill state listening src :1234


其中1234是您的端口号。

ss是iproute2软件包的一部分,因此它已经在现代Linux上进行了很大的更改。

我从一个相关问题的答案中学到了这一点。

#6 楼

netstat -anp | grep 80


它应该告诉您,如果您正在运行apache,则为“ httpd”(这只是一个示例,请使用您的应用程序正在使用的端口而不是80)

pkill -9 httpd 




killall -9 httpd


评论


在诉诸-9之前尝试正常杀死

– Thilo
2010-4-6的3:49

@omfgroflmao-但是它将杀死打开端口的进程?

–codingfreak
10-4-6在4:13

@codingfreak持有端口的进程,是的,它将杀死它。

–匿名
10-4-6在4:48

#7 楼

您可能只需要找出哪个进程打开了与端口相关的套接字,然后终止该进程即可。

但是,您必须意识到,除非
该进程具有一个处理程序,该处理程序会取消初始化它正在使用的所有内容(打开文件,套接字,fork,除非终止时将其正确关闭,否则该问题可能会持续存在。
那么您将创建的这拖累了系统性能。另外,套接字将保持打开状态,直到内核意识到该进程已被终止为止。通常只需要大约一分钟。

我想更好的问题是:您要停止哪个端口(属于
哪个进程)?

如果要结束发现的后门病毒或
病毒,那么在终止数据之前,至少应了解来回的数据
。 (wireshark对此很有用)(还有该进程的可执行文件名称,因此您可以删除它并防止其在重新启动时再次出现),或者,如果已安装了某些文件(例如HTTPD或FTPD等),则您应该已经可以访问过程本身。

通常它将具有一个控制程序(HTTPD停止|启动等)。或者,如果这是系统性的事情,那么您可能不应该将其弄乱。无论如何,我认为既然其他所有人都在给您“如何做”的角度,我应该给您一些警告。

评论


很好的评论。我有一个程序,该程序在终止时不会关闭套接字,这会导致所描述的行为-套接字无法使用约60秒钟。当我停止并开始该过程时,它抱怨约一分钟,表明该地址和端口已在使用中。最好的解决方案是纠正行为异常的进程以使其正常关闭,但是有时候这不是一个选择。有没有办法要求内核在60秒内检查被阻塞的套接字?

– Jan Vlcinsky
14年4月15日在16:21

#8 楼

如果要更快地释放端口,则必须设置以下值:

echo 1 > /proc/sys/net/ipv4/tcp_fin_timeout


将其从60秒(默认)设置为1秒

#9 楼

我首先查找了mongo和node进程,然后执行了以下操作:

ps -A | grep node

10418 pts/23   00:00:05 node

10551 pts/23   00:00:00 node

ps -A | grep mongo

10490 pts/23   00:00:00 mongod


一旦确定,只需使用kill命令杀死该进程。

kill -9 10418
kill -9 10490


最后,键入meteor,它应该可以再次工作。

#10 楼

您可以编写一个脚本来修改iptables并重新启动它们。一个脚本用于添加规则以丢弃端口上的所有数据包,另一个脚本用于删除该规则。

其他答案已向您展示了如何杀死与端口绑定的进程-这可能不是您所需要的想。如果希望服务器继续运行,但要阻止客户端连接,则要阻止端口,而不是停止进程。

评论


@Michael Shimmins ... hmm听起来很吸引人,因为我们可以在服务器端阻止端口,以便客户端不会发送任何消息。

–codingfreak
10-4-6在4:18

好的,客户可以发送所有他们想要的消息,我们刚刚关上门,所以他们无法进入。

– Michael Shimmins
10-4-6在4:30

#11 楼

还有一个问题:内核有时自己拥有端口。我知道NAT路由会将一些端口开放给NAT使用。您不能为此终止进程,它是一个内核,需要重新配置并重新启动。

#12 楼

您可以使用名为killcx的命令,关闭连接而不会终止任何进程。


语法:


killcx [dest_ip:dest_port] {interface}

  dest_ip              : remote IP
  dest_port            : remote port
  interface (optional) : network interface (eth0, lo etc).




示例:


killcx 120.121.122.123:1234
killcx 120.121.122.123:1234 eth0



评论


//,大多数Linux机器都具有killcx吗?我尝试过的所有程序都没有安装此killcx命令,而没有安装它们当前存储库配置不可用的软件包。

– Nathan Basanese
16年1月14日在18:43

不,您可以在这里找到该工具:killcx.sourceforge.net

–帅名
16 Jan 15'在1:51



//,我知道我可以找到该工具,在数千台服务器上安装它只是一个痛苦。

– Nathan Basanese
16年1月15日在6:37

使用人偶@NathanBasanese :)

–SHOUBHIK BOSE
16 Mar 17 '16 at 9:03

#13 楼

我知道,严格来说,这个答案并不能回答问题本身,但是读到它可能是相关的信息:

将套接字绑定到端口(和地址)的默认行为是:当套接字由于突然终止进程而关闭时,该套接字将在TIME_WAIT中停留一段时间。这将意味着您无法立即重新绑定到该地址/端口。如果要通过标准BSD套接字接口开发系统本身,则可以(至少在某种程度上)使用SO_REUSEADDR套接字选项控制此行为。如果套接字处于TIME_WAIT状态,则基本上可以使您再次绑定到相同的地址/端口。虽然每个端口仍然有一个套接字!

但是,此信息应仅用作开发辅助,因为TIME_WAIT首先存在是有原因的,在其他答案中已经对此进行了解释。 >

评论


// , 对。当然,终止进程不是释放端口的最佳方法。我已经注意到,如果我终止了Vagrant进程挂起的进程,那么一段时间后我将无法再进行升级。我敢打赌这与TIME_WAIT有关。

– Nathan Basanese
16年1月14日在18:46

#14 楼

如果您不希望通过套接字的通信,但希望保持该进程正常运行:tcpkill。

tcpkill -i eth0 host xxx.xxx.xxx.xxx and port yyyy


将启动嗅探守护程序,该守护程序拦截并丢弃该端口上的所有通信量。非常方便地测试应用程序的网络拆分。