147

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.

Glorfindel
  • 4,099
  • 6
    No, 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 Oct 06 '11 at 00:26
  • 14
    A 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 Sep 22 '14 at 19:39
  • "... 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 May 17 '18 at 12:57
  • 1
    @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 Aug 07 '19 at 15:19
  • 1
    @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 Aug 10 '19 at 18:32

15 Answers15

178

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.

Albin
  • 10,559
  • 1
    sudo 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 Jun 10 '14 at 09:25
  • 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

    – Dankó Dávid Jun 11 '14 at 23:32
  • 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 Jun 11 '14 at 23:38
  • 12
    this is a brilliant solution – marcorossi Jan 22 '15 at 12:55
  • <slowclap.gif> - this is truly a life saver. – mik Jan 25 '16 at 19:44
  • 10
    If 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 Apr 22 '16 at 10:19
  • Amazing, exactly what I needed. – 0atman May 20 '16 at 12:09
  • 1
    Never 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 Sep 15 '16 at 10:33
  • 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 Dec 15 '17 at 09:12
  • 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 May 16 '18 at 07:27
  • 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 May 17 '18 at 12:30
  • "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 May 17 '18 at 12:36
  • 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 Feb 20 '19 at 14:30
  • Great Solution :) @SET , You can use lsof -i @<ipaddress> to list only sockets which are started on that particular IP. – Prasad Bonthu May 07 '19 at 15:38