コマンドラインから手動でポートを閉じる


112

クライアントとサーバーアプリケーション間でリッスンモードになっている開いているポートを閉じたい。

Linuxにポートを閉じるための手動のコマンドラインオプションはありますか?

注: 私はことを知っているようになった「接続されたソケットを所有する唯一のアプリケーションは、アプリケーションが終了したときに起こるであろう、それを閉じる必要があります。」

なぜそれを開くアプリケーションによってのみ可能になるのか理解していません...しかし、私はまだ他の方法があるかどうかを知りたいと思っています。


5
いいえ、開かれたポートそれらを開いたプロセスに属し、外部からの制御はできません。これは良いことです。または、すべてのアプリケーションが、開いているポート(およびファイル)が台無しになることを予想する必要があります。ただし、ファイアウォール(iptables)によってポートへのトラフィックをブロックすることはできますが、ポートを閉じて他の使用のためにポートを放棄することはありません。
ユルゲンストロベル

10
多くの回答者がこの質問の要点を逃しました。ポートを所有しているアプリケーションのみがポートを切断できると宣言するのは無意味です。ボックスまで歩いてソケットからイーサネットケーブルを引き抜くか、接続の反対側でアプリケーションを強制終了することで、接続を切断できます!これを処理するようにアプリケーションを作成する必要があります。---物理的な介入や他のコンピューターの制御を必要とせずに、アプリケーションが適切に記述されていることを確認するために、どのようにテストしますか?
デールウィルソン14

「...外部からの制御は不可能です。」それは重要な発言であり、次の質問に私を導いた、どうすれば外部からのプロセスの一部になれますか?GDB。
ダンコダビッド

@JürgenStrobel確かに外部からの制御が可能です-tcpkillとssの両方がまさに求められていることを行うことができます。開かれたポートは実際にはプロセスに属していません。それらはプロセスに割り当てられたいくつかの権限を持つカーネルリソースですが、カーネルの喜びでのみ存在します。
トムアンダーソン

@ tom-anderson DaleW:tcpkillはファイアウォールツールであり、このオプションについて言及しました。ポート(ソケット)を閉じることとは異なる、ポートへのトラフィックを防ぐことができます。
ユルゲンストロベル

回答:


134

私は同じ問題を抱えていました。プロセスは生き続けなければなりませんが、ソケットは閉じなければなりません。実行中のプロセスでソケットを閉じることは不可能ではありませんが困難です。

  1. プロセスを見つけます:

    netstat -np
    

    source/destination ip:port portstate pid/processname地図を取得します

  2. プロセスでソケットのファイル記述子を見つけます

    lsof -np $pid
    

    リストを取得します:プロセス名、pid、user、fileDescriptor、...接続文字列。

    接続に一致するfileDescriptor番号を見つけます。「97u」のような「97」を意味します。

  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を見つける方法について混乱しています。私の場合、プロセスは、クロームのタブであり、私は...開けWebSocketををクローズしようとしている
SET

2
行は、典型的には、次のようになります。IPv4の97uのFirefox 14812 szupervigyor 32814564 0t0 TCP 192.168.2.4:40385->173.194.39.65:https(ESTABLISHED)として:PROCESS_NAMEのPIDユーザは[opened_for]プロトコルデバイスiノードprotocol_data_toString fdが
ダンコデビッド

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] protocol device inode protocol_data_toStringリモートIPを知る必要がありますアドレスと最後の列で見つけます。私の例では、97はFileDescriptorです。ターゲットホストへの複数の接続を開いた場合、検索は困難です。
ダンコダビデ14

7
これは華麗なソリューションです
marcorossi

8
あなたがリモートエンド(例えばピア射出)によって閉鎖されているソケットをシミュレートしたい場合には、使用することをお勧めしますshutdowncall shutdown($fileDescriptor, 0)
ecatmur

75

ここで間違った質問をしているようなものです。それをリッスンするソケットを開いたアプリケーションの外部から単純に「ポートを閉じる」ことは実際に不可能です。これを行う唯一の方法は、ポートを所有するプロセスを完全に終了することです。その後、約1〜2分で、ポートが再び使用可能になります。進行状況は次のとおりです(気にしない場合は、最後までスキップして、特定のポートを所有しているプロセスを強制終了する方法を示します)。

ポートは、OSによって異なるプロセスに割り当てられるリソースです。これは、OSにファイルポインターを要求することに似ています。ただし、ファイルポインターとは異なり、一度に1つのプロセスだけがポートを所有できます。BSDソケットインターフェイスを介して、プロセスはポートでリッスンする要求を行うことができ、OSはそれを許可します。OSは、他のプロセスが同じポートを取得しないようにします。いつでも、プロセスはソケットを閉じることでポートを解放できます。その後、OSはポートを再利用します。または、ポートを解放せずにプロセスが終了した場合、OSは最終的にポートを回収します(すぐには発生しませんが、数分かかります)。

さて、あなたがしたいこと(単にコマンドラインからポートを閉じる)は、2つの理由で不可能です。まず、可能であれば、1つのプロセスが別のプロセスのリソース(ポート)を単純に盗むことを意味します。特権プロセスに制限されない限り、これは悪いポリシーです。2番目の理由は、ポートを実行し続けた場合にポートを所有していたプロセスに何が起こるかが不明であるためです。プロセスのコードは、このリソースを所有していると想定して記述されています。単純にそれを取り除いた場合、それはそれ自体でクラッシュすることになります。したがって、特権プロセスであっても、OSはこれを許可しません。代わりに、単にそれらを殺す必要があります。

とにかく、特定のポートを所有するプロセスを強制終了する方法は次のとおりです。

sudo netstat -ap | grep :<port_number>

portを保持しているプロセスに対応する行が出力されます。例:

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カーネルはプロセスがなくなったことを知っています。ポートを回収できることを知っています。実際には、ポートを閉じるタイミングに関するルールがあり、「ネット上に浮遊パケットが浮遊していないことを確認します。これらのリソースがあることをどのように知るのですか?それはカーネルが行うことであり、物事を追跡します。
リッチホモルカ

誰かがunix.tools.port.close(<my port number>)私が使うような賢明なものを投稿するまでinit 6
スノークラッシュ

これは、別の質問に対する優れた回答です。この質問は、デバッガを接続し、実行中のプログラムを変更して、そのプログラムがファイル記述子の関数を呼び出すようにすることです。
アーサーウルフェルト

19

フューザーも使用できます

fuser -k -n *protocol portno*

ここで、プロトコルはtcp / udpであり、portnoは閉じたい番号です。例えば

fuser -k -n tcp 37

詳細は、fuserのmanページをご覧ください


所有プロセスを殺すだけではうまくいきませんでしたが、フューザはうまくいきました。どうも!
webwurst

フューザーを使用した後でも、ルートとして使用しても、強制終了されたアプリからポートを再利用しようとすると、「ソケットは既に使用されています」という結果になりました。一方、ソケットを解放する時間は以前よりも短いように見えたので、とにかく感謝します。
1月Vlcinsky

@JanVlcinsky fuser実行された後、強制終了されたプロセスを再起動する「ガーディアン」プロセスがあるかもしれません。
レッドバロン14

@RedBaron:コメントによると、superuser.com / a / 415236/153413の問題は、不完全に書かれたアプリケーションに起因し、終了時にソケットをクリーンアップ/クローズしません。そのfuserため、ポートを使用してプロセスを見つけて強制終了しますが、ソケットが閉じられていないという事実は解決しません。60秒で、カーネルがそれを行います。
ヤンヴルチンスキー14

6

または、iptablesを使用することもできます。

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

それは基本的にあなたが望むものを達成します。これにより、すべてのTCPトラフィックがポート80にドロップされます。


4
いいえ、これにより、すべてのタイムアウトが終了するまでソケットが開かれたままになります。(所有プロセスからすべてのトラフィックを非表示にし、それを閉じる必要があることを知る手段がありません。)-j REJECTTCPリセットフラグを返すために使用できます。何かを送信します)。
Marki555

3
netstat -anp | grep 80

Apacheを実行している場合、「httpd」(これは単なる例です。80ではなく、アプリケーションが使用しているポートを使用してください)

pkill -9 httpd 

または

killall -9 httpd

4
-9に頼る前に通常のキルを試してください
Thilo

@omfgroflmao-しかし、それはポートを開いたプロセスを殺しますか?

@codingfreakポートを保持しているプロセス、はい、それはそれを殺します。

2

おそらく、ポートが関連付けられているソケットを開いたプロセスを見つけて、そのプロセスを強制終了できます。

ただし、そのプロセスが使用していたすべての要素(ファイル、ソケット、フォーク、終了時に適切に閉じられない限り残る可能性のあるものを開く)を初期化解除するハンドラーを持たない限り、それを作成することに気づかなければなりませんシステムのパフォーマンスを引き下げます。さらに、プロセスが強制終了されたことをカーネルが認識するまで、ソケットは開いたままになります。通常、これには約1分かかります。

より良い質問は、どのポート(どのプロセスに属しているか)を停止することです。

発見したバックドアまたはウイルスに終止符を打とうとしている場合は、終了する前に少なくともどのデータが行き来しているかを知る必要があります。(wiresharkはこれに適しています)(プロセスの実行可能ファイル名であるため、削除して再起動時に戻ってくるのを防ぐことができます)または、インストールしたもの(HTTPDやFTPDなど)の場合は、既にアクセスできるはずですプロセス自体。

通常、制御プログラム(HTTPD stop | startなど)があります。または、それがシステムに関するものである場合、おそらくそれを台無しにすべきではありません。とにかく、他の皆があなたに「ハウツー」の角度を与えているので、私はあなたに警告を与えるべきだと思いました。


非常に良いコメント。私は1つのプログラムを持っていますが、終了時にソケットを閉じて、記述された動作が発生します-ソケットは約60秒間使用できません。このプロセスを停止して開始すると、アドレスとポートが既に使用されているという不満が約1分間あります。最善の解決策は、不適切に動作するプロセスを修正して適切に閉じることですが、場合によってはこれはオプションではありません。60秒よりも早くブロックされたソケットをカーネルチェックで確認する方法はありますか?
1月Vlcinsky 14

2

最初にmongoおよびノー​​ドプロセスを探し、次に次のことを行いました。

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を変更して再起動するスクリプトを作成できます。ポート上のすべてのパケットをドロップするルールを追加するための1つのスクリプト、前述のルールを削除するための別のスクリプト。

他の回答は、ポートにバインドされたプロセスを強制終了する方法を示しています-これはあなたが望むものではないかもしれません。サーバーを実行し続けたいが、クライアントからの接続を防止する場合は、プロセスを停止せずにポートをブロックします。


@Michael Shimmins ...サーバー側のポートをブロックして、クライアントがメッセージを送信しないようにすることができるので、うーんうまいことに聞こえます。

まあクライアントがメッセージを送信することができ、彼らは我々がちょうどそう彼らは得ることができない扉を閉じたたいすべて。

1

もう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コマンドを利用できませんでした。
ネイサンバサニーズ

いいえ、ここでツールを見つけることができます:killcx.sourceforge.net
shuaiming

//、私はツールを見つけることができることを知っています、それは数千のサーバーにそれをインストールするのは苦痛です。
ネイサンバサネーゼ

Puppet @NathanBasaneseを使用:)
SHOUBHIK BOSE

1

この答えは厳密に言えば質問自体に答えるものではないことを知っていますが、これを読むと関連情報になるかもしれません:

ソケットをポート(およびアドレス)にバインドするデフォルトの動作では、プロセスの突然の終了によってソケットが閉じられると、ソケットはしばらくTIME_WAITのままになります。これは、このアドレス/ポートにすぐに再バインドできないことを意味します。標準のBSDソケットインターフェイスを介してシステム自体を開発している場合は、SO_REUSEADDRソケットオプションを使用して(少なくともある程度まで)この動作を制御できます。これにより、ソケットがTIME_WAITステータスの場合、基本的に同じアドレス/ポートに再度バインドできます。ただし、ポートごとにまだ1つのソケット!

ただし、TIME_WAITがそもそも存在する理由があるため、この情報は開発支援としてのみ使用する必要があります。他の回答で既に説明しています。


// 、 右。もちろん、プロセスを強制終了することはポートを解放する最良の方法ではありません。Vagrantプロセスがハングした場合に強制終了すると、しばらくの間再び浮浪することができないことに気付きました。このTIME_WAITには何か関係があると思います。
ネイサンバサネーゼ

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.