Manually closing a port from commandline

116

88

I want to close an open port which is in listening mode between my client and server application.

Is there any manual command line option in Linux to close a port?

NOTE: I came to know that "only the application which owns the connected socket should close it, which will happen when the application terminates."

I don't understand why it is only possible by the application which opens it ... But I'm still eager to know if there is any other way to do it.

codingfreak

Posted 2010-04-06T03:39:57.320

Reputation:

10A lot of responders missed the point of this question. It is nonsense to declare that only the application that owns the port can disconnect it. I can disconnect it by walking up to the box and pulling the ethernet cable out of the socket, or by killing the application at the other end of the connection! The application must be written to handle this. So --- how do you test to be sure the application is written properly without requiring physical intervention and/or control of the other computer? – Dale Wilson – 2014-09-22T19:39:34.343

"... there is no control possible from outside." That's an important remark, that's guided me to the next question, how can i be the part of the process from the outside? GDB. – Dankó Dávid – 2018-05-17T12:57:26.763

@JürgenStrobel There is indeed control possible from outside - both tcpkill and ss can do exactly what is asked for. Because opened ports do not truly belong to a process; they are kernel resources, with some rights assigned to a process, but still existing only at the kernel's pleasure. – Tom Anderson – 2019-08-07T15:19:49.097

@tom-anderson DaleW: tcpkill is a firewalling tool, and I did mention this option. You can prevent traffic to a port, which is different than closing a port (socket). – Jürgen Strobel – 2019-08-10T18:32:05.950

5No, opened ports belong to the process which opened them, there is no control possible from outside. Which is a good thing, or all applications would have to anticipate their open ports (and files) being messed with. However, you can block traffic to a port by firewalling (iptables), but that will not close and give up the port for other use. – Jürgen Strobel – 2011-10-06T00:26:20.053

Answers

137

I had same problem, the process must keep alive but the socket must close. Closing a socket in a running process is not impossible but difficult:

  1. locate the process :

    netstat -np
    

    You get a source/destination ip:port portstate pid/processname map

  2. locate the the socket's file descriptor in the process

    lsof -np $pid
    

    You get a list: process name, pid, user,fileDescriptor, ... a connection string.

    Locate the matching fileDescriptor number for the connection. It'll be something like "97u" which means "97".

  3. Now connect the process:

    gdb -p $pid
    
  4. Now close the socket:

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

    example:

    call close(97)
    

    Then detach gdb:

    quit
    

    And the socket is closed.

Dankó Dávid

Posted 2010-04-06T03:39:57.320

Reputation: 1 501

8this is a brilliant solution – marcorossi – 2015-01-22T12:55:24.827

<slowclap.gif> - this is truly a life saver. – mik – 2016-01-25T19:44:52.657

8If you want to simulate the socket being closed by the remote end (e.g. the peer exiting) it's better to use shutdown: call shutdown($fileDescriptor, 0). – ecatmur – 2016-04-22T10:19:45.950

Amazing, exactly what I needed. – 0atman – 2016-05-20T12:09:38.650

1Never thought of this. My redis server was not accepting any connections. But I need to keep it alive. This helped me solve the problem. life saver – Shiplu Mokaddim – 2016-09-15T10:33:26.413

I wonder why it's so twisted in Linux. In Windows I can just launch Process Explorer (download from MS website), see a list of handles per process, and close them one by one using the mouse. Using gdb even pauses the program which is a pita because of timeouts etc. – Mark Jeronimus – 2017-12-15T09:12:06.320

I have a node process running with a very long timeout (~5hrs) and has a few connections open that will eventually fail so I tried calling both shutdown and close on each of these sockets but the process continued to be blocked. I can confirm from lsof output that these sockets are no longer there. Is there something else that I can do instead of waiting for 5hrs for it to timeout normally? – haridsv – 2018-05-16T07:27:14.720

Well i don't want to be a troll, but in unixes the /proc is the native process explorer in the system. However we can construct a really dummy command to close an fd of a process:
#!/bin/bash echo -e "call close($2)\ndetach\nquit\n" | gdb -p $1 > /dev/null 2>&1 close-proc-fd $pid $fd

that you can built into a backend of the application. However this solution - especially if you start gatling this as a command - is an overkill solution. – Dankó Dávid – 2018-05-17T12:30:32.547

"Using gdb even pauses the program" yes, sadly it does anyway (https://stackoverflow.com/questions/9746018/gdb-attach-to-a-process-without-stop) but you can continue (cont) the execution right after the attach.

– Dankó Dávid – 2018-05-17T12:36:11.957

but how to send msg in gdb, send(int sockfd, const void *buf, size_t len, int flags) e.g. want to send("hello") to other end. – zhuguowei – 2019-02-20T14:30:22.597

Great Solution :) @SET , You can use lsof -i @<ipaddress> to list only sockets which are started on that particular IP. – Prasad Bonthu – 2019-05-07T15:38:15.767

1sudo lsof -np $pid gives me about 200 lines and I'm confused about how to find desired FD. In my case process is a Chrome tab and i'm trying to close opened websockets... – SET – 2014-06-10T09:25:49.893

2A row typically looks like: 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] protocol device inode protocol_data_toString – Dankó Dávid – 2014-06-11T23:32:13.373

2>

  • A row typically looks like: 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] protocol device inode protocol_data_toString

    You need to know the remote ip address and find on the last col. In my example the 97 is the FileDescriptor. Searching is difficult if you opened multiple connection to the target host. – Dankó Dávid – 2014-06-11T23:38:43.780

    78

    You're kind of asking the wrong question here. It isn't really possible to simply "close a port" from outside the application that opened the socket listening on it. The only way to do this is to completely kill the process that owns the port. Then, in about a minute or two, the port will become available again for use. Here's what's going on (if you don't care, skip to the end where I show you how to kill the process owning a particular port):

    Ports are resources allocated by the OS to different processes. This is similar to asking the OS for a file pointer. However, unlike file pointers, only ONE process at a time may own a port. Through the BSD socket interface, processes can make a request to listen on a port, which the OS will then grant. The OS will also make sure no other process gets the same port. At any point, the process can release the port by closing the socket. The OS will then reclaim the port. Alternatively, if the process ends without releasing the port, the OS will eventually reclaim the port (though it won't happen immediately: it'll take a few minutes).

    Now, what you want to do (simply close the port from the command-line), isn't possible for two reasons. First, if it were possible, it would mean one process could simply steal away another process's resource (the port). This would be bad policy, unless restricted to privileged processes. The second reason is it is unclear what would happen to the process that owned the port if we let it continue running. The process's code is written assuming that it owns this resource. If we simply took it away, it would end up crashing on it's own, so OS's don't let you do this, even if you're a privileged process. Instead, you must simply kill them.

    Anyway, here's how to kill a process that owns a particular port:

    sudo netstat -ap | grep :<port_number>
    

    That will output the line corresponding to the process holding port , for example:

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

    In this case, procHoldingPort is the name of the process that opened the port, 4683 is its pid, and 8000 (note that it is TCP) is the port number it holds.

    Then, look in the last column, you'll see /. Then execute this:

    kill  <pid>
    

    If that doesn't work (you can check by re-running the netstat command). Do this:

    kill -9 <pid>
    

    In general, it's better to avoid sending SIGKILL if you can. This is why I tell you to try kill before kill -9. Just using kill sends the gentler SIGTERM.

    Like I said, it will still take a few minutes for the port to re-open if you do this. I don't know a way to speed this up. If someone else does, I'd love to hear it.

    user32538

    Posted 2010-04-06T03:39:57.320

    Reputation:

    @smehmood - Thanks for the detailed explanation .. A small doubt .. How does the kernel reclaim a open port by an abruptly killed process ?? .. the solution u provided seems to be killing the process holding the port ... – None – 2010-04-06T04:17:17.073

    Until someone posts something sensible like unix.tools.port.close(<my port number>) I would use init 6. – Snowcrash – 2017-02-10T20:57:55.443

    This is an excellent answer to a different question. This question is about attaching a debugger and changing a running program to cause that program to call a function on a file descriptor. – Arthur Ulfeldt – 2019-10-01T21:14:21.707

    3@codingfreak The kernel knows the process is gone. It knows it can reclaim the port. There are actually rules on the timing of closing the port, to make sure there aren't any stray packets floating on the 'net. How does it know it has these resources? that's what the kernel does, keeps track of things. – Rich Homolka – 2013-11-01T02:05:40.680

    20

    Fuser can also be used

    fuser -k -n *protocol portno*
    

    Here protocol is tcp/udp and portno is the number you wish to close. E.g.

    fuser -k -n tcp 37
    

    More info at fuser man page

    RedBaron

    Posted 2010-04-06T03:39:57.320

    Reputation: 309

    Just killing owning process didn't work for me, but fuser did. Thx! – webwurst – 2013-05-13T10:06:49.287

    I got mixed results with it, even after using fuser, I got "socket already in use" when trying to reuse the port from killed app even doing so as root. On the other hand, the time to free the socket seemed to be shorter then before, so thanks anyway. – Jan Vlcinsky – 2014-04-14T08:16:28.813

    @JanVlcinsky Maybe there is a "guardian" process which restarts the killed process moments after fuser is run? – RedBaron – 2014-04-15T05:12:22.100

    @RedBaron: according to comment http://superuser.com/a/415236/153413 my problem originates in poorly written application, which does not clean up/close the socket under termination. So fuser finds the process using the port and kills it, but does not resolve the fact, that the socket is not closed. 60 seconds and kernel does it for me.

    – Jan Vlcinsky – 2014-04-15T16:25:12.747

    6

    You could alternatively use iptables:

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

    It basically accomplishes what you want. This will drop all TCP traffic to port 80.

    supercheetah

    Posted 2010-04-06T03:39:57.320

    Reputation: 836

    4No, this will keep the socket opened until all the timeouts close them. (It will hide all the traffic from the owning process which then have no means to know it should close it.) You could use -j REJECT to return TCP reset flag, which would be then seen my the owning process (but only when the other side tries to send something). – Marki555 – 2015-05-15T17:07:06.143

    3

    netstat -anp | grep 80
    

    It should tell you, if you're running apache, "httpd" (this is just an example, use the port your application is using instead of 80)

    pkill -9 httpd 
    

    or

    killall -9 httpd
    

    Ben

    Posted 2010-04-06T03:39:57.320

    Reputation: 312

    4try a normal kill before resorting to -9 – Thilo – 2010-04-06T03:49:52.037

    @omfgroflmao - But it will kill the process which has opened the port ?? – None – 2010-04-06T04:13:16.040

    @codingfreak The process that's holding the port, yes it will kill it. – None – 2010-04-06T04:48:42.263

    2

    You could probably just find out what process opened the socket that the port is associated with, and kill that process.

    But, you would have to realize that unless that process has a handler that de-initializes all the stuff that it was using (open files, sockets, forks, stuff that can linger unless it's closed properly upon termination) then you would have created that drag on system performance. Plus, the socket will remain open until the kernel realizes that that the process has been killed. That usually just takes about a minute.

    I suppose the better question would be: What port (belonging to what process) do you want to stop?

    If you are trying to put an end to a backdoor or virus that you found, then you should at least learn what data is going back and forth before you terminate it. (wireshark is good for this) (And the process' executable name so you can delete it and prevent it from coming back on reboot) or, if it's something you installed (like HTTPD or FTPD or something) then you should already have access to the process itself.

    Usually it will have a control program (HTTPD stop|start or something). Or, if it's a system thing, you probably should not mess with it. Anyway, i thought that since everyone else is giving you the "how-to" angle, i should give you the caveats.

    jackenheimer

    Posted 2010-04-06T03:39:57.320

    Reputation: 21

    Very good comment. I have one program, which under termination does ot close the socket what results in described behaviour - the socket is unusable for about 60 seconds. When I stop and start that process, it is complaining for about a minute, that the address and port is already in use. The best solution is to correct badly behaving process to close properly, but sometime this is not an option. Is there a way to ask kernel checking that blocked socket sooner than in 60 seconds? – Jan Vlcinsky – 2014-04-15T16:21:41.830

    2

    If you want your port to be released sooner, you have to set the following value:

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

    to set it from 60 seconds (default) to 1 second

    Daniel

    Posted 2010-04-06T03:39:57.320

    Reputation: 21

    2

    I first looked for the mongo and node processes, then did the following:

    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
    

    Once identified, just kill the processes with the kill command.

    kill -9 10418
    kill -9 10490
    

    Lastly, type meteor and it should be working again.

    abautista

    Posted 2010-04-06T03:39:57.320

    Reputation: 133

    1

    You could write a script which modified the iptables and restarts them. One script for adding a rule dropping all packets on the port, another script for removing said rule.

    The other answers have shown you how to kill the process bound to the port - this may not be what you want. If you want the server to keep running, but to prevent connections from clients then you want to block the port, not stop the process.

    Michael Shimmins

    Posted 2010-04-06T03:39:57.320

    Reputation: 111

    @Michael Shimmins ... hmm sounds intresting as we can block the port on server side so that the client wont send any messages. – None – 2010-04-06T04:18:30.450

    Well the client can send messages all they want we've just closed the door so they can't get in. – None – 2010-04-06T04:30:18.347

    1

    One more issue: sometime the kernel owns ports themselves. I know NAT routing holds some ports open for NAT use. You can not kill a process for this, this is a kernel, and a reconfiguration and a reboot is required.

    Rich Homolka

    Posted 2010-04-06T03:39:57.320

    Reputation: 27 121

    1

    You can use the command named killcx, closing a connection without any process to be killed.

    • syntax:
    killcx [dest_ip:dest_port] {interface}
    
      dest_ip              : remote IP
      dest_port            : remote port
      interface (optional) : network interface (eth0, lo etc).
    
    • example:
    killcx 120.121.122.123:1234
    killcx 120.121.122.123:1234 eth0
    

    shuaiming

    Posted 2010-04-06T03:39:57.320

    Reputation: 11

    // , Do most Linux machines have killcx? None of the ones I've tried have this killcx command available without installing packages unavailable to them with their current repository config. – Nathan Basanese – 2016-01-14T18:43:43.827

    no, you can find the tool here: http://killcx.sourceforge.net/

    – shuaiming – 2016-01-15T01:51:20.637

    // , I know I can find the tool, it's just a pain to instal that on thousands of servers. – Nathan Basanese – 2016-01-15T06:37:33.573

    Use Puppet @NathanBasanese :) – SHOUBHIK BOSE – 2016-03-17T09:03:27.410

    1

    I am aware that this answer does not answer the question itself, strictly speaking, but reading into it this might be relevant information:

    The default behaviour of binding a socket to a port (and address) is that when socket is closed by abrupt termination of process, the socket will stay in TIME_WAIT for a while. This will mean you cannot immediately re-bind to this address/port. If you are developing the system itself through the standard BSD socket interface, you can (at least to some extent) control this behaviour with SO_REUSEADDR socket option. This will basically allow you to bind into the same address/port again if the socket is in TIME_WAIT status. Still one socket per port though!

    However, this information should only be used as development aid, since there's a reason for TIME_WAIT to exist in the first place, already explained in the other answers.

    Tommi Tuura

    Posted 2010-04-06T03:39:57.320

    Reputation: 11

    // , Right. Of course, killing processes is not the best way to free up ports. I have noticed that when I kill the Vagrant process if it hangs, I can't vagrant up again for a while. I bet this TIME_WAIT thing has something to do with it. – Nathan Basanese – 2016-01-14T18:46:11.320

    0

    If you want no traffic over the socket but want to keep alive the process: tcpkill.

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

    Will start a sniffing daemon that intercepts and trashes all traffic on that port. Very handy for testing your applications for network splits.

    RickyA

    Posted 2010-04-06T03:39:57.320

    Reputation: 171

    0

    You can close a listening socket using ss:

    sudo ss --kill state listening src :1234
    

    Where 1234 is your port number.

    ss is part of the iproute2 package, so there is a strong change it is already installed on a modern Linux.

    I learned about this from an answer to a related question.

    Tom Anderson

    Posted 2010-04-06T03:39:57.320

    Reputation: 1 341