SSHでホストごとに2つの異なるIPアドレスを使用する


23

という名前のサーバーがありgamma、常に稼働しています。自宅から接続することもありますが、その場合はパブリックIPアドレスを使用します55.22.33.99。時々、仕事中に接続し、不必要にパケットをバウンスさせるのではなく、ローカルIPアドレスを介して接続します192.168.1.100

現時点では、それらを2つの異なるエントリに分割しています ~/.ssh/conf

Host gamma-local
        HostName 192.168.1.100
        Port 22
        User andreas

Host gamma-remote
        HostName 55.22.33.99
        Port 12345
        User andreas

ですから、私が仕事をしている場合、入力しなければならないのはssh gamma-local、私だけです。私が家にいる(または世界のどこかにいる)場合は、実行しssh gamma-remoteます。

サーバーに接続するとき、どこにいるかに応じて別の名前を入力する必要はありません。その部分は自動的に行われます。たとえば、場合によっては、自分がどこにいるかわからない人を接続する自動化されたスクリプトがあります。

Bashスクリプトを使用して最初にローカルの接続に「試行」し、接続しない場合はリモートIPアドレスに接続してみて、この問題を解決する質問があります。これは便利ですが、(1)効率が悪いようです(特に、すぐにエラーが返されるとは限らないため、接続がタイムアウトするのを「待たなければならない」ことがあります)。

Bashスクリプトの使用に依存せず、接続が最初に機能するかどうかを「テスト」することなく、これを達成する別の方法はありますか?


私が見つけようとしているのは、/etc/hostsこれを達成するためにSSH構成ファイルをいじることができるかどうかです?または、現在接続しているLANを「検出」する方法はありますか?
IQAndreas 14

オフィスネットワークで使用するネームサーバーのセットはありますか?
スリー14

@スリーああ、あなたはこれでどこに向かっているのかわかります。賢い!現時点ではネームサーバーを実行していませんが、1台のマシンを1台に確実に変換できました。
IQAndreas 14

@スリー「オフィスネットワークにネームサーバーがある場合...」
IQAndreas 14

やった 自由に投票してください:)
スリー

回答:


28

どのネットワークに接続しているかを認識する方法がある場合は、Matchキーワードin ~/.ssh/configを使用して目的の操作を実行できます。これにはOpenSSH≥6.5が必要です。

私は似たようなものを使用します

Match originalhost gamma exec "[ x$(/sbin/iwgetid --scheme) != xMyHomeESSID ]"
  HostName 192.168.1.100
  Port 22

Host gamma
  User andreas
  Port 12345
  HostName 55.22.33.99

だから私は使用されているwifiネットワークの識別子を使用して、SSH接続のために自宅にいるかどうかを判断しますが、あなたのコンピュータに割り当てられたIPアドレスまたは2つのネットワークを区別する他のものも使用できます。


+1の賢い使い方Match、ありがとう!ゼロまたはゼロ以外の終了ステータスで終了するスクリプトに検出をラップすると、再利用可能になるため、よい考えかもしれません。
ペテルフ14

@peterphは確かに外部スクリプトに抽象化できますが、今まで必要だったのは1か所だけだったので、3つのルールはまだ導入されていません。
ミチャウポリトウスキ14

あなたが仕事をしていても、実際に他のマシンに接続したい場合はどうなりますか?HomeESSIDでWiFiを使用していないため、execステートメントは一致しないので、ホスト名を192.168.1.100に設定しますか?
なくなって

@gone私は質問を理解していません。一致はターゲットホストにもあります。
ミハウポリトウスキ

1
@typelogic私の知る限り、簡単ではありません。を使用してみることもできますProxyCommand nc $address sshが、たとえば すべてのデバイスに同じホストキーがありますか?とにかく環境変数を設定する必要がある場合、直接接続するアドレスを引数として与えるだけでは簡単ではないsshでしょうか?
のMichałPolitowski

5

職場にプライベートネームサーバーがあり、オフィスと自宅で同じラップトップを使用している場合、これを利用してこれを実現できます。

  1. nsswitch.conf最初にDNSをチェックインするようにマシンを変更します
  2. gammaオフィスのプライベートDNSで192.168.1.100に解決するためのDNSエントリを作成します。
  3. マシンの/ etc / hostsファイルにエントリを作成して、gamma55.22.33.99 に解決します。

このように、ssh gammaオフィスからあなたがオフィスのDNSから192.168.1.100に解決し、自宅から接続すると、hostsファイルから55.22.33.99に解決します。

PS:この回答は、ガンマにパブリックDNSエントリを持たせたくないと仮定しています。また、WindowsマシンからサーバーにSSHで接続している場合は、nssswitch.confファイルに相当する場所があり、hostsファイルのエントリを上書きする必要があると思います。


あります-それはホストファイルです。そして、これはまさに私がそれを行う方法です-自宅で私のパブリックドメインは私のローカルIPに解決します。素晴らしい答え-それも私が最初に考えたものでした。まあ...今日、つまり、数年前に設定したとき、解決策を見つけるためにたくさんのグーグルをしなければなりませんでした。
mikeserv 14

2

これを実行できるかどうかはわかりません~/.ssh/configが、別のアプローチは、外部IPアドレスに基づいてどちらかに接続することです。おそらく、仕事中はIPがになるので55.22.33.NNN、次のようなものを実行できます。

[[ $(wget -qO - http://wtfismyip.com/text) =~ ^'55.22.33.' ]] && 
    ssh 192.168.1.100 ||
    ssh -p 12345 55.22.33.99

さらに簡単なアプローチは、内部IPを使用することです。あなたの2つのネットワークがどのように設定されているかわかりませんが、あなたのIPを介して仕事中かどうかを簡単に判断できる場合(たとえば、特定のIPを仕事中に持っている場合など192.168.1.12)、あなたはそれを行うことができます(eth0ネットワークカードの名前に変更します):

[[ $(ip address show dev eth0 | grep -Po 'inet \K[\d.]+') = '192.168.1.12' ]] && 
    ssh 192.168.1.100 ||
    ssh -p 12345 55.22.33.99

どちらを使用する場合でも、シェルにエイリアスとして追加できます(~/.bashrc使用している場合は、シェルの初期化ファイルにこの行を追加しますbash)。

alias gamma="[[ $(wget -qO - http://wtfismyip.com/text) =~ ^'55.22.33.' ]] && ssh 192.168.1.100 || ssh -p 12345 55.22.33.99

他のスクリプトがアクセスできるようにする場合は、スクリプトにすることもできます(.bashrcスクリプトの実行時にエイリアスは読み込まれません)。


2

~/.ssh/configIPアドレスをホスト名として使用する場合、これを実現することはできません。追加の複雑さは、異なるIPアドレスに接続するだけでなく、異なるポートにも接続するという事実によって導入されます。これは、DNSリゾルバーの調整をほとんど排除するためです。

私は修正済みです- Match originalhost ... exec ...コンボを使用できます~/.ssh/config- @MichałPolitowskiの答えをご覧ください。ただし、OpenSSHの場合は完全に機能しますが、他のSSHクライアントで同様の機能が見つかるとは限りません。

のための単純なラッパー(シェル関数またはさまざまなシェルから使用する必要がある場合はスクリプト)を使用して問題を回避できます。これにより、現在使用してsshいるネットワークを確認し、適切なHostエントリを使用します。大きな問題は、どのネットワークにいるのかを確実に検出する方法です。ローカルIPアドレスが思い浮かびますが、信頼できるものではありません。仕事用ネットワークと同じサブネットを使用するLANからも接続している可能性があるためです。

ローカルネットワークとリモートネットワークの両方に同じポートを使用できる/etc/resolv.conf場合は、使用しているネットワークに応じて編集できます。明らかに、自動的に実行する必要があります(ほとんどの場合、DHCPクライアントのフックスクリプトから)。または-より良い-ローカルネームサーバー(たとえばなどdnsmasq)を実行し、適切な構成を指定します。しかし、それはこの質問の範囲を超えています。

別のオプション-対話的にのみ接続する必要がある場合-は、スキャンするコマンド補完を使用すること~/.ssh/configです。これにより、いくつかの入力を節約できます(特に、十分な数のHostエントリを持っている場合)。次のようなもの(bash初期化用):

# complete session names for ssh
declare -g _ssh_complete_hostlist 2> /dev/null
function _ssh_complete_init () {
    _ssh_complete_hostlist=$( \
        sed -nr '/^\s*Host\s*=/{s/^[^=]+= *//;s/ /\n/g;p}' ~/.ssh/config \
        | sort )
}
_ssh_complete_init

function _ssh_complete () {
    local match=${COMP_WORDS[${COMP_CWORD}]}
    local hosts=
    local default=
    for h in $_ssh_complete_hostlist; do
        if [[ $h =~ ^$match ]]; then
            hosts="$hosts $h"
        fi
    done
    if ! (( ${COMP_CWORD} == ${#COMP_WORDS[@]}-1 )); then
        default=$( compgen -f ${COMP_WORDS[${COMP_CWORD}]} )
    fi
    COMPREPLY=($hosts $default)
}
complete -F _ssh_complete ssh

最初の関数は、ホストが完了するリストを作成します(通常、すべてのシェルでこれを1回実行するだけで十分です)。コマンドラインの最後のトークン。

このすべてに、この問題に対処する正しい方法は、VPNを介して職場のネットワークに接続し、オフィスにいるかのようにローカルの職場のIPアドレスにアクセスできるようにすることです。次に、アドレスを、好きなレイヤーに組み込むことができます:~/.ssh/config/etc/resolv.confまたは(最適なオプション)オフィスネームサーバー。


港は石造りではありません。gamma物事を簡単にするなら、間違いなくローカルSSHポートをリモートポートに一致するように変更できます。
IQAndreas 14

2

数年前、私は同様の目的でプログラムを書きまし。ニーズに合っているかもしれません。そのプログラムでは、sshの構成は次のようになります。

Host gamma
    ProxyCommand ssh-multipath-proxy 192.168.1.100:22 55.22.33.99:12345
    User andreas

1

さらに別の解決策は、SSHに2つの異なる構成ファイルを使用することです。1つの構成ファイルにすべてを含めるよりも、このエレガントさはやや劣ると考えるかもしれませんが、保守は簡単です。

で使用する設定ファイルを選択します-F <configfile>


ありがとう。私は-Fオプションが好きです。
タイプロジック

0

部分的な答え:

上記の多くの回答は、「現在使用しているネットワークを検出できる場合」から始まります。これには、インターフェイスが接続されているときに実行されるスクリプトを使用して、通常のネットワークの1つに接続するときにさまざまなもの(通常はVPN)を開始します。テクニックは、ARPを使用してゲートウェイのMACアドレスを取得することです。

function identifyConnection {
    gatewayIP=$(route -n | grep -e '^0\.0\.0\.0' | tr -s ' ' | cut -d ' ' -f 2)

    if [[ ! -z "$gatewayIP" ]]
    then
        # Identify the gateway by its MAC (uniqueness...)
        log "Gateway IP address=$gatewayIP"
        log "Obtaining corresponding gateway MAC address"
        gatewayData=($(arp -n $gatewayIP | grep -e $gatewayIP | tr -s ' '))
        if [[ "${gatewayData[1]}" == "(incomplete)" ]]
        then
            log "Status of gateway $gatewayIP "incomplete""
            echo ""
        elif [[ "${gatewayData[2]}" == "--" ]]
        then 
            log "No MAC address found for $gatewayIP"
            echo ""
        else
            log "Gateway MAC address=[${gatewayData[2]}]"
            echo "${gatewayData[2]}"
        fi
    fi
}

そして、ネットワークをゲートウェイMACに関連付けるルックアップテーブルがあります。もちろん、そのテーブルは同じネットワークの複数のMACを保持できます(典型的なケースは、大規模な企業サイトのさまざまなWifiホットスポットです)。別のルックアップテーブルを使用して、そのネットワークで実行するスクリプトを決定します。

私の場合、スクリプトはPlasmaデスクトップ通知を使用して実行されるため、すべてがユーザーランドにあります。

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