〜/ .ssh / configの条件付きProxyCommand?


14

私は自分のしている~/.ssh/config私たちの会社VPNの中、またはSSHプロキシサーバを経由してのいずれかにアクセスしているさまざまなホストで構成します。

今のところ

Host internal-server
    ProxyCommand ssh -W internal.ip:22 external-server

ただし、内部ネットワークにいる場合は、内部IPに直接アクセスできるため、外部サーバーを介したプロキシは接続に遅延を追加するだけです。

内部IPに到達できない場合に暫定的にプロキシし、それ以外の場合は直接接続する方法はありますか?

回答:


8

私は通常、このようなものをセットアップします。中間ホストが名前を解決できると想定しています。

Host *%homeproxy
    ProxyCommand ssh user@proxyhost /bin/netcat -w 1 $(echo %h | cut -d%% -f1) 22

だから私は好きに接続しssh blah%homeproxyます。


私のgoogle-fuが失敗しています。これをもっと説明できますか?この*%構文を見たことはありません。
-fukawi2

3
%キャラクターについて特別なことは何もありません。本当に何でも使えます。パーセントは、ホスト名またはユーザー名では有効ではないため使用されます。cutProxyCommandをwithingコマンドが使用する%ホスト名を引き出すための区切り文字として。
ゾレダチェ

1
これは良いことですが、sshエイリアスではなく完全なホスト名を入力する必要があることを意味します。
alt

@mobiusnz実際には、接続のさまざまな手段ごとに異なる名前が必要なことを意味します。私の場合、たとえば、自宅にいる場合は、を使用しますssh targetH。つまり、自宅からのターゲットを意味します。ターゲットにするローカルネットワークの場合は、単にssh target。しかし、答えでこれをもっと簡単に述べてくれてうれしかったです。
ルーベンス

4

Matchを使用して別の方法を使用します。私の場合、ローカルプロキシが実行されている場合はそれを使用し、実行されていない場合は使用します。次のディレクティブはこれをうまく実現します。

Match Exec "nc -z 127.0.0.1 1086"
    ProxyCommand nc -X 5 -x 127.0.0.1:1086 %h %p

すべてのssh試行に一致し、使用ncしているプロキシが1086で稼働しているかどうかを確認するクイックチェックを実行します(この場合、ncエラーなしで終了します)。その場合、ProxyCommandを設定します。


2

10年前、この種のシナリオ用のプロキシコマンドを作成しました。あなたの使用例では、私のプロキシコマンドは次のように使用できます:

Host internal-server
    ProxyCommand ssh-multipath-proxy %h:%p -- ssh -W %h:%p external-server

いくつかの注意点:IPv6を処理せず、ホスト名ごとに1つのIPアドレスしか試行しないことを認めるのは少し恥ずかしいです。また、サーバーバナーが送信される前にクライアントバナーをサーバーに転送しません。しかし、それが問題を引き起こす可能性は低いです。


2

@till の回答に感謝します。

で接続を強制的にリダイレクトできることがわかりましたProxyCommand nc dst dst-port

たとえば、使用すると実際に接続しB.comます

ssh A.com -o ProxyCommand="nc B.com 22"

しかし、UserKnownHostsFileまだ記録されますA.com

したがって、ドメイン「auto」を追加できます ssh_config

Host auto.internal-server
  Hostname {internal-server ip or domain}
  ProxyCommand bash -c '(timeout 0.1 nc -z %h %p) && nc %h %p || ssh -W %h:%p external-server'

に置き換えましたnc -w 1 %h %p(timeout 0.1 nc -z %h %p) && nc %h %p、100ミリ秒以内に内部サーバーに到達できれば、より高速になります。

またはping、に置き換えることもできますが、のようなTCPベースのプロキシを使用している場合proxychains、またはサーバーがICMPエコーを許可しない場合、不適切な情報を示している可能性があります。

Host auto.internal-server
  Hostname {internal-server ip or domain}
  ProxyCommand bash -c '(ping %h &>/dev/null) && nc %h %p || ssh -W %h:%p external-server'

(timeout 0.1 nc -z %h %p)内部サーバーにいるかどうかを検出するものに置き換えることができます。

複数の候補IPがある場合は、これも使用できます。

Host auto.internal-server
  Hostname {internal-server ip or domain}
  ProxyCommand bash -c 'f(){(timeout 0.1 ping -c 1 $1 &>/dev/null) && nc $1 %p;}; f 1.1.1.1 || f 2.2.2.2 || f 3.3.3.3'

接続1.1.1.1に失敗し、接続2.2.2.2に失敗すると、接続を試行し3.3.3.3ます。


0

ファイアウォールの背後にいなくてファイアウォールが拒否しない場合、これはわずかに1秒の遅延を追加することで、もう少し自動的に機能します。

Host proxyhost.example.com
ProxyCommand none

Host *.example.com
ProxyCommand sh -c "nc -w 1 %h %p || ssh -W  %h:%p proxyhost.example.com"

0

通常、このような別のエントリを作成します-

Host myVM
    ProxyCommand ssh -W internal.ip:22 external-server
    User ubuntu

Host myVM-np
    User ubuntu

次に、現在のプロキシ環境に応じて、必要なものを呼び出します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.