명령 줄에서 수동으로 포트 닫기


112

클라이언트와 서버 응용 프로그램 사이에서 청취 모드에있는 열린 포트를 닫고 싶습니다.

Linux에서 포트를 닫는 수동 명령 행 옵션이 있습니까?

참고 : "연결된 소켓을 소유 한 응용 프로그램 만 소켓을 닫아야합니다. 응용 프로그램이 종료 될 때 발생합니다."

나는 그것이 그것을 여는 응용 프로그램에서만 가능한 이유를 이해하지 못합니다 ...하지만 여전히 다른 방법이 있는지 알고 싶습니다.


5
아니요, 열린 포트 해당 포트 를 연 프로세스 에 속하며 외부에서 제어 할 수 없습니다. 좋은 일이거나 모든 응용 프로그램이 열려있는 포트 (및 파일)가 엉망이 될 것으로 예상해야합니다. 그러나 방화벽 (iptables)을 통해 포트에 대한 트래픽을 차단할 수 있지만 다른 용도로 포트를 닫고 포기하지는 않습니다.
Jürgen Strobel

10
많은 응답자들이이 질문의 요점을 놓쳤다. 포트를 소유 한 응용 프로그램 만 포트를 분리 할 수 ​​있다고 선언하는 것은 말이되지 않습니다. 상자 위로 걸어 이더넷 케이블을 소켓에서 빼거나 ​​연결의 다른 쪽 끝에서 응용 프로그램을 종료하여 연결을 끊을 수 있습니다! 이를 처리하려면 애플리케이션을 작성해야합니다. 따라서 --- 다른 컴퓨터를 물리적으로 개입하거나 제어하지 않고도 응용 프로그램이 올바르게 작성되었는지 확인하려면 어떻게 테스트합니까?
데일 윌슨

"... 외부에서 제어 할 수 없습니다." 그것은 중요한 발언입니다. 다음 질문으로 안내합니다. 어떻게 외부에서 프로세스의 일부가 될 수 있습니까? GDB.
Dankó Dávid 12

@ JürgenStrobel 실제로 외부에서 제어 할 수 있습니다. tcpkill과 ss 모두 요청 된 내용을 정확하게 수행 할 수 있습니다. 열린 포트는 실제로 프로세스에 속하지 않기 때문입니다. 그것들은 프로세스에 할당 된 일부 권한을 가진 커널 리소스이지만 여전히 커널의 즐거움으로 만 존재합니다.
Tom Anderson

@ tom-anderson DaleW : tcpkill은 방화벽 도구이며이 옵션에 대해 언급했습니다. 포트 (소켓)를 닫는 것과 다른 포트로의 트래픽을 방지 할 수 있습니다.
위르겐 스트로벨

답변:


134

나는 같은 문제가 있었다. 프로세스는 살아 있어야하지만 소켓은 닫아야합니다. 실행중인 프로세스에서 소켓을 닫는 것은 불가능하지 않지만 어렵습니다.

  1. 프로세스를 찾으십시오.

    netstat -np
    

    당신은 source/destination ip:port portstate pid/processname지도를 얻을

  2. 프로세스에서 소켓의 파일 디스크립터를 찾으십시오.

    lsof -np $pid
    

    프로세스 이름, pid, 사용자, fileDescriptor, ... 연결 문자열 목록이 표시됩니다.

    연결과 일치하는 fileDescriptor 번호를 찾으십시오. "97"을 의미하는 "97u"와 같은 것입니다.

  3. 이제 프로세스를 연결하십시오.

    gdb -p $pid
    
  4. 이제 소켓을 닫습니다 :

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

    예:

    call close(97)
    

    그런 다음 gdb를 분리하십시오.

    quit
    

    그리고 소켓이 닫힙니다.


1
sudo lsof -np $pid약 200 라인을 제공하고 원하는 FD를 찾는 방법에 대해 혼란 스럽습니다. 필자의 경우 프로세스는 Chrome 탭이며 열린 웹 소켓을 닫으려고합니다 ...
SET

2
행은 전형적으로 보이는 같은 IPv4의 97u 파이어 14,812 szupervigyor 32,814,564 0t0 TCP 192.168.2.4:40385->173.194.39.65:https (중)과 같이 process_name의 PID 사용자는 [opened_for] 프로토콜 디바이스 아이 노드가 fd protocol_data_toString
단코 데이비드

2
* 행은 일반적으로 다음과 같습니다. 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 2016 년

7
이것은 훌륭한 해결책입니다
marcorossi

8
원격 엔드 (예 : 피어 종료)에 의해 닫힌 소켓을 시뮬레이트하려면 shutdown다음 을 사용하는 것이 좋습니다 call shutdown($fileDescriptor, 0)..
ecatmur

75

당신은 여기서 잘못된 질문을하고 있습니다. 소켓을 청취 한 응용 프로그램 외부에서 단순히 포트를 "닫는"것은 실제로 불가능합니다. 이를 수행하는 유일한 방법은 포트를 소유 한 프로세스를 완전히 종료하는 것입니다. 그런 다음 약 1-2 분 후에 포트를 다시 사용할 수있게됩니다. 여기에 무슨 일이 일어나고 있습니까?

포트는 OS가 다른 프로세스에 할당 한 리소스입니다. 이것은 OS에 파일 포인터를 요청하는 것과 유사합니다. 그러나 파일 포인터와 달리 한 번에 하나의 프로세스 만 포트를 소유 할 수 있습니다. BSD 소켓 인터페이스를 통해 프로세스는 포트에서 수신 대기하도록 요청하여 OS가 승인합니다. 또한 OS는 다른 프로세스가 동일한 포트를 얻지 않도록합니다. 언제든지 프로세스는 소켓을 닫아 포트를 해제 할 수 있습니다. 그런 다음 OS는 포트를 회수합니다. 또는 포트를 해제하지 않고 프로세스가 종료되면 OS는 결국 포트를 회수합니다 (즉시 발생하지는 않지만 몇 분 정도 소요됨).

이제 두 가지 이유로 할 수있는 작업 (명령 줄에서 포트를 간단히 닫기)이 불가능합니다. 첫째, 가능하다면 한 프로세스가 단순히 다른 프로세스의 리소스 (포트)를 훔칠 수 있음을 의미합니다. 권한있는 프로세스로 제한되지 않는 한 잘못된 정책입니다. 두 번째 이유는 포트를 계속 실행 시키면 포트를 소유 한 프로세스에 어떤 일이 발생하는지 명확하지 않기 때문입니다. 프로세스의 코드는이 리소스를 소유하고 있다고 가정합니다. 우리가 단순히 그것을 제거했다면, 그것은 자체적으로 충돌하게 될 것입니다. 따라서 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-자세한 설명 감사합니다. 약간의 의심 .. 커널이 갑자기 종료 된 프로세스에 의해 열린 포트를 어떻게 되 찾을까요? .. 제공 한 솔루션은 포트를 보유한 프로세스를 죽이고있는 것 같습니다 ...

3
@codingfreak 커널은 프로세스가 사라 졌음을 알고있다. 포트를 회수 할 수 있다는 것을 알고 있습니다. 실제로 포트를 닫는 타이밍에는 'net에 떠 다니는 패킷이 없는지 확인하는 규칙이 있습니다. 이러한 리소스가 있다는 것을 어떻게 알 수 있습니까? 그것이 커널이하는 일을 추적합니다.
Rich Homolka

누군가 unix.tools.port.close(<my port number>)내가 사용하는 것처럼 합리적인 것을 게시 할 때까지 init 6.
Snowcrash

이것은 다른 질문에 대한 훌륭한 답변입니다. 이 질문은 디버거를 연결하고 해당 프로그램이 파일 설명자에서 함수를 호출하도록 실행중인 프로그램을 변경하는 것에 관한 것입니다.
Arthur Ulfeldt

19

퓨저도 사용 가능

fuser -k -n *protocol portno*

여기서 프로토콜은 tcp / udp이고 portno는 닫으려는 숫자입니다. 예 :

fuser -k -n tcp 37

퓨저 매뉴얼 페이지 에서 추가 정보


소유 프로세스를 죽이는 것은 효과가 없었지만 퓨저는 그랬습니다. 고마워!
webwurst

퓨저를 사용한 후에도 루트로도 죽인 앱에서 포트를 재사용하려고 할 때 "소켓이 이미 사용 중입니다"라는 결과가 혼합되어 있습니다. 반면에 소켓을 해제하는 시간은 이전보다 짧아 보였으므로 어쨌든 감사합니다.
Jan Vlcinsky

@JanVlcinsky 어쩌면 fuser실행 후 종료 된 프로세스 순간을 다시 시작하는 "guardian"프로세스 가 있습니까?
RedBaron

@ RedBaron : 의견 superuser.com/a/415236/153413 에 따르면 내 문제는 잘못 작성된 응용 프로그램에서 발생하며 종료시 소켓을 정리 / 닫지 않습니다. 따라서 fuser포트를 사용하여 프로세스를 찾아서 종료하지만 소켓이 닫히지 않았다는 사실을 해결하지는 않습니다. 60 초와 커널이 나를 위해 그것을합니다.
Jan Vlcinsky

6

대신 iptables를 사용할 수 있습니다.

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

기본적으로 원하는 것을 달성합니다. 그러면 모든 TCP 트래픽이 포트 80으로 떨어집니다.


4
아니요, 이렇게하면 모든 시간 초과가 닫힐 때까지 소켓이 열린 상태로 유지됩니다. (이것은 소유 프로세스에서 모든 트래픽을 숨겨서 닫아야한다는 것을 알 수있는 방법이 없습니다.) -j REJECTTCP 리셋 플래그를 반환 하는 데 사용할 수 있습니다. 무언가를 보내려면).
Marki555

3
netstat -anp | grep 80

아파치를 실행하고 있다면 "httpd"라고 알려줘야한다 (이것은 단지 예일 뿐이다. 응용 프로그램이 80 대신에 사용하는 포트를 사용하라)

pkill -9 httpd 

또는

killall -9 httpd

4
-9에 의존하기 전에 정상적인 살인을 시도하십시오
Thilo

@omfgroflmao-그러나 그것은 포트를 연 프로세스를 죽일 것입니까 ??

@codingfreak 포트를 보유하고있는 프로세스입니다. 예, 포트가 종료됩니다.

2

포트와 관련된 소켓을 연 프로세스가 무엇인지 알아 내고 해당 프로세스를 종료시킬 수 있습니다.

그러나 해당 프로세스에 사용중인 모든 항목 (열린 파일, 소켓, 포크, 종료시 올바르게 닫히지 않으면 남아있을 수있는 항목)을 초기화 해제하는 핸들러가 없으면 다음과 같이 만들었을 것입니다. 시스템 성능을 끌어냅니다. 또한 소켓은 커널이 프로세스가 종료되었음을 인식 할 때까지 열린 상태로 유지됩니다. 보통 1 분 정도 걸립니다.

더 좋은 질문은 다음과 같습니다. 어떤 포트 (어떤 프로세스와 함께)를 중지하고 싶습니까?

발견 한 백도어 나 바이러스를 종식시키려는 경우 적어도 종료하기 전에 어떤 데이터가 송수신되는지 알아야합니다. (wireshark는 이것에 좋습니다) (그리고 프로세스의 실행 파일 이름은 삭제하고 재부팅 할 때 다시 나타나지 않도록 할 수 있습니다) 또는 설치 한 것 (예 : HTTPD 또는 FTPD 또는 기타) 인 경우 이미 액세스 할 수 있어야합니다 프로세스 자체.

일반적으로 제어 프로그램이 있습니다 (HTTPD 중지 | 시작 등). 또는 그것이 시스템 일이라면, 엉망이되어서는 안됩니다. 어쨌든, 나는 다른 사람들이 당신에게 "방법"각도를주기 때문에, 나는 당신에게 경고를 줄 것이라고 생각했습니다.


아주 좋은 의견. 하나의 프로그램이 있는데 종료시 소켓을 닫지 않아 설명 된 동작이 발생합니다. 소켓은 약 60 초 동안 사용할 수 없습니다. 해당 프로세스를 중지하고 시작하면 약 1 분 동안 주소와 포트가 이미 사용 중이라는 불평이 있습니다. 가장 좋은 해결책은 잘못 동작하는 프로세스를 올바르게 닫는 것을 수정하는 것이지만 때로는 옵션이 아닙니다. 60 초 이내에 소켓을 차단 한 커널 검사를 요청하는 방법이 있습니까?
Jan Vlcinsky

2

먼저 몽고 및 노드 프로세스를 찾은 후 다음을 수행했습니다.

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하면 다시 작동해야합니다.


1

iptables를 수정하고 다시 시작하는 스크립트를 작성할 수 있습니다. 포트에있는 모든 패킷을 삭제하는 규칙을 추가하기위한 스크립트와 해당 규칙을 제거하기위한 스크립트.

다른 답변은 포트에 바인딩 된 프로세스를 종료하는 방법을 보여주었습니다. 원하는 것이 아닐 수도 있습니다. 서버가 계속 실행되도록하지만 클라이언트와의 연결을 방지하려면 프로세스를 중지하지 말고 포트를 차단하십시오.


@Michael Shimmins ... 서버 측 포트를 차단하여 클라이언트가 메시지를 보내지 않도록하면서 흠 소리가납니다.

고객은 우리가 방금 문을 닫아서 원하는 메시지를 보낼 수 있습니다.

1

한 가지 더 문제 : 때때로 커널이 포트 자체를 소유합니다. NAT 라우팅에 NAT 사용을 위해 일부 포트가 열려 있음을 알고 있습니다. 이를 위해 프로세스를 종료 할 수 없습니다. 이것은 커널이며 재구성 및 재부팅이 필요합니다.


1

포트를 더 빨리 해제하려면 다음 값을 설정해야합니다.

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

60 초 (기본값)에서 1 초로 설정


1

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

아니오, 여기서 도구를 찾을 수 있습니다 : killcx.sourceforge.net
shuaiming

// 도구를 찾을 수 있다는 것을 알고 있습니다. 수천 대의 서버에 설치하는 것은 고통 스럽습니다.
Nathan Basanese 2016 년

Puppet @NathanBasanese 사용 :)
SHOUBHIK BOSE

1

나는이 답변이 질문 자체에 엄격하게 말하지는 않지만 대답을 읽는 것은 관련 정보 일 수 있음을 알고 있습니다.

소켓을 포트 (및 주소)에 바인딩하는 기본 동작은 프로세스가 갑자기 종료되어 소켓이 닫히면 소켓이 잠시 TIME_WAIT에 유지된다는 것입니다. 즉,이 주소 / 포트에 즉시 리 바인드 할 수 없습니다. 표준 BSD 소켓 인터페이스를 통해 시스템 자체를 개발하는 경우 SO_REUSEADDR 소켓 옵션을 사용하여이 동작을 (적어도 어느 정도) 제어 할 수 있습니다. 소켓이 TIME_WAIT 상태 인 경우 기본적으로 동일한 주소 / 포트에 다시 바인딩 할 수 있습니다. 그래도 포트 당 하나의 소켓!

그러나 TIME_WAIT가 다른 곳에 이미 설명되어 있기 때문에이 정보는 개발 지원으로 만 사용해야합니다.


// , 권리. 물론 프로세스 종료는 포트를 비우는 가장 좋은 방법은 아닙니다. 나는 방랑자 과정이 멈 추면 죽일 때 잠시 동안 다시 방랑 할 수 없다는 것을 알았습니다. 이 TIME_WAIT와 관련이 있다고 생각합니다.
Nathan Basanese

0

소켓을 통한 트래픽은 원하지 않지만 프로세스를 계속 유지하려면 tcpkill .

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

해당 포트의 모든 트래픽을 가로 채서 스니핑하는 스니핑 데몬을 시작합니다. 네트워크 분할에 대한 응용 프로그램 테스트에 매우 편리합니다.


0

ss를 사용하여 청취 소켓을 닫을 수 있습니다 .

sudo ss --kill state listening src :1234

여기서 1234는 포트 번호입니다.

ss는 iproute2 패키지의 일부이므로 최신 Linux에 이미 설치되어있는 강력한 변경 사항이 있습니다.

관련 질문에 대한 답변 에서 이에 대해 배웠습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.