ssh -R 8888:localhost:80 myuser@myhost
を使用してリモートマシンから開いたローカルポート(たとえば8888)でリッスンしているsshトンネルがあります。このトンネルを閉じる「myhost」の「myuser」のスクリプトを作成する必要があります。
スクリプトは「myhost」の「myuser」によって実行されます。ルートによって実行されることも、Sudoによって実行されることもありません。
1つのアプローチは、lsofまたはnetstatを使用して8888でリッスンしているプロセスのPIDを見つけて、プロセスを強制終了することです。ただし、lsofとnetstatはどちらも、Sudoを使用せずにPIDを提供することを拒否します。 netstatを使用すると、Sudoなしで「PID /プログラム名」の代わりに-
を取得します。
ルート権限なしで特定のポートでリッスンしているプロセスのPIDを見つける方法はありますか?このポートでリッスンしているプロセスは、私たちと同じユーザーの下で実行されています。または、sshトンネルをその外側から閉じる他の方法はありますか?
トンネル内にいるのでnotなので、sshエスケープシーケンスを使用して接続をリセットすることは解決策ではないことに注意してください。スクリプトは、同じユーザーが同じホスト上でトンネルとは別に実行する必要があります。
また、killall sshd
を実行するだけでは解決策ではないことに注意してください。これは、これだけでなく他のすべてのssh接続を強制終了するためです。
私が見つけた受け入れられた回答はすべてルート権限を必要とするか、すべてのssh接続を強制終了するため、この質問は多くの同様の質問の複製ではありません。
ホスト「myhost」はUbuntu12.04.5を実行しています。
編集:@Jakujeによって要求されたディスカッションの要約:
@Patrickは、setuid
を使用するか、/etc/sudoers
を変更して、ユーザーが完全なSudoを使用せずにroot権限でスクリプトを実行できるようにするアプローチを提案しました。ただし、setuid
の場合は、スクリプトの代わりにバイナリを記述する必要があります。ただし、ユーザーがルート権限でスクリプトを実行できるようにすることは、潜在的なセキュリティリスクになる可能性があります。それでも、このソリューションは、ユーザーがルートアクセス権をまったく持っていない場合をカバーしていないため、/etc/sudoers
を変更することはできません。 @Patrickがこれを回答として書いた場合、私は間違いなく賛成しますが、まだ承認済みとはマークしません。
@EricRenoufは、sshdがソケットをユーザーにchownするため、ユーザーが/proc/*/fd
を使用してソケットを持つプロセスを見つけることができないことを発見しました。おそらく、lsofもnetstatもそれを表示しないのはそのためです。
その他のアイデア:
@EricRenoufが見つけたように、開いたソケットポート番号またはiノードによってsshdPIDを取得する方法はおそらくありません。しかし、このsshd PIDを見つける方法や、接続を閉じるように指示する方法が他にないかどうか知りたいです。多分どういうわけかsshdで直接。
たとえば、sshdデバッグモードsshd -d
を有効にすると、ユーザーが読み取り可能な/var/log/auth.log
のどのポートへのトンネルを開いたsshdプロセスがログに記録されます。したがって、スクリプトはログを解析し、そこでPIDを見つけることができます。ただし、デバッグモードのsshdを実行することはお勧めできません。実際には、デバッグモードがなくても開いているトンネルをログに記録するための sshdの単純なパッチ があります。しかし、パッチを適用したsshdを実行するのも良い考えかどうかはわかりません。
他にトリックはありますか?
「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'
他の基準をチェックするスクリプトを代用して、いつ終了するかを決定することもできます。これはおそらく、これを処理するためのよりクリーンな方法です。