
リモート マシンから で開かれた、ローカル ポート (たとえば 8888) でリッスンしている SSH トンネルがありますssh -R 8888:localhost:80 myuser@myhost
。このトンネルを閉じるために、「myhost」上の「myuser」用のスクリプトを作成する必要があります。
スクリプトは「myhost」上の「myuser」によって実行されます。root では実行されず、sudo も実行できません。
1 つの方法は、lsof または netstat を使用して 8888 でリッスンしているプロセスの PID を見つけて、そのプロセスを強制終了することです。ただし、lsof と netstat はどちらも、sudo を実行しないと PID を取得できません。netstat を使用すると、-
sudo を実行せずに「PID/プログラム名」のみを取得します。
ルート権限なしで、特定のポートでリッスンしているプロセスの PID を見つける方法はありますか? このポートでリッスンしているプロセスは、私たちと同じユーザーで実行されています。または、外部から SSH トンネルを閉じる他の方法はありますか?
SSHエスケープシーケンスを使用して接続をリセットすることは解決策ではないことに注意してください。ないトンネル内。スクリプトは、同じホスト上の同じユーザーによってトンネルとは別に実行する必要があります。
また、実行するだけでは、killall sshd
この接続だけでなく他のすべての SSH 接続が切断されるため、解決策にはならないことに注意してください。
この質問は、多くの類似の質問の重複ではありません。私が見つけた受け入れられた回答はすべて、ルート権限を必要とするか、すべての ssh 接続を切断するだけだからです。
ホスト「myhost」はUbuntu 12.04.5を実行しています。
編集: @Jakuje のリクエストに応じた議論の要約:
@Patrick は、完全な sudo を持たずにユーザーが root 権限でスクリプトを実行できるようにするために、を使用する
setuid
か変更するアプローチを提案しました。ただし、スクリプトの代わりにバイナリを作成する必要があります。ただし、ユーザーが root 権限でスクリプトを実行できるようにすると、潜在的なセキュリティ リスクが発生する可能性があります。また、このソリューションでは、ユーザーが root アクセス権をまったく持たず、変更できない場合はカバーされません。@Patrick がこれを回答として書いた場合、私は間違いなく賛成票を投じますが、まだ承認済みとしてマークしません。/etc/sudoers
setuid
/etc/sudoers
/proc/*/fd
@EricRenouf は、sshd がソケットをユーザーに chown するため、ユーザーがソケットを持つプロセスを見つけることができないことを発見しました。おそらくこれが、lsof も netstat もそれを表示しない理由です。
その他のアイデア:
@EricRenouf が発見したように、開かれたソケット ポート番号や inode から sshd PID を取得する方法はおそらくありません。しかし、この sshd PID を見つける方法や、接続を閉じるように指示する方法が他にないかどうか興味があります。おそらく、何らかの方法で直接 sshd で取得できるでしょう。
たとえば、sshdのデバッグモードを有効にするとsshd -d
、どのsshdプロセスがどのポートにトンネルを開いたかがログに記録され、/var/log/auth.log
そのポートはユーザーが読み取り可能です。そのため、スクリプトはログを解析してPIDを見つけることができます。しかし、デバッグモードのsshdを実行するのは良い考えではありません。実際には、sshd 用のシンプルなパッチデバッグ モードがなくても、開かれたトンネルをログに記録します。ただし、パッチを適用した sshd を実行するのが良いアイデアかどうかはわかりません。
他に何かコツはありますか?
答え1
まず、「myhost」に接続するためのカスタム SSH キーを設定します。次に、「myhost」の .ssh/authorized_keys ファイルを編集して、シェルの親 PID がファイルに書き込まれるようにします。
command="echo $PPID > tunnel.pid; bash" ssh-rsa AAA...
セキュリティのために他の設定を微調整したり、PID を書き込んでハングさせるだけのカスタム スクリプトを作成したりすることもできます。どちらの方法でも原理は同じです。
SSH セッションを開いたままにしているプロセスの PID がわかれば、あとはスクリプトを作成するだけです...
kill `cat tunnel.pid`
...プロセスを終了し、SSH セッションを閉じます。
-i
コマンドのフラグを使用して、ssh
接続に使用する秘密キーを指定できることに注意してください。
編集: アクティブな接続がある場合は、シェル プロセスを強制終了してもトンネルは閉じられないため、親 SSH プロセスを強制終了します。
編集: 自動化された SSH 接続ではまず SSH キーを使用するのが私の考えですが、同じプロセスを次のようにエミュレートすることもできます。
ssh -R 8888:localhost:80 myuser@myhost 'echo $PPID > tunnel.pid; for ((;;)); do sleep 1; done'
また、他の基準をチェックして、いつ終了するかを決定するスクリプトを代用することもできます。おそらく、これがこの問題を処理するよりクリーンな方法です。