LoginSignup
19
18

More than 5 years have passed since last update.

自宅LAN内のサーバに同じホスト名でSSHしたい

Last updated at Posted at 2016-06-22

外から自宅鯖に繋ぐ設定について

自宅内に複数のサーバがあって、外からssh出来るように例えば以下のように静的NATの設定をルータにしてあったとする。(この辺の設定は各ご家庭のルータによるので割愛)

グローバルIP:22016 → 192.168.1.16:22
グローバルIP:22017 → 192.168.1.17:22

この時点で外から自宅の 192.168.1.16 の鯖に繋ぐには以下のようにして繋がるわけだ。

ssh home.example.jp:22016

で、普段持ち歩く Macbook から外から簡単に繋げられるよう、まず以下の様な設定が元々してあったんだ。

~/.ssh/config
Host h16
  HostName home.example.jp
  Port 22016

Host h17
  HostName home.example.jp
  Port 22017

これで外から自宅の 192.168.1.16 の鯖に繋ぐには以下のように出来るようになる。

ssh h16

うん、便利。

問題と解決

問題:自宅LAN内から同じホスト名で繋げられない

うちの自宅ルータは糞なので、LAN内のアドレスから自分のグローバルアドレスに繋げることが出来ない!(多分ルータ内部のNAT実装が微妙で書き換えしくってるんだろうなぁ…。)

なので自宅からは home.example.jp:22016 とかのアドレスではタイムアウトしちゃって繋ぐことが出来ない。ので当然 ssh h16 とかも出来ない。
しかたがないのでこないだ迄は以下のように設定を追加して ssh h16l とかで繋げてたんだわ。

Host h16
  HostName home.example.jp
  Port 22016
Host h16l
  HostName 192.168.1.16
  Port 22

Host h17
  HostName home.example.jp
  Port 22017
Host h17l
  HostName 192.168.1.17
  Port 22

まぁ、何もないよりは大分楽っちゃ楽なんだがやっぱし時々、自宅なのに l 無しで繋げようとしたりその逆だったりで接続待ちと見せかけてタイムアウトとか言うことがしばしばありストレスが溜まってた。

ちなみに自宅LAN内にローカルDNSリゾレーションサーバ立てて一部ホストはローカルIP返してそれ以外は外部リゾルバにパススルーとかすればいいんじゃね?って意見もあるかと思う。が面倒くさい。昔やってたこともあるけど、DNS立てるのがまず面倒だし、DNS担当のLAN内サーバのメンテ中とか解決できなくてやっぱし不便だし、労多くして益少なしで嫌だった。
特に可用性確保が面倒くさい。こういうのは99.9%使えてても使えない0.1%の時のストレスが半端ないからなー。

解決: Match 便利!

でも最近は心穏やかさ。EL Capitanにアップデートした際に OpenSSH が上がって ~/.ssh/configMatch が使えるようになったからね!

今は以下の様な設定が書いてあり、外でも自宅でも ssh h16 で目的のサーバに繋げられるようになっている。

~/.ssh/config
Match host h16 exec "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | grep -qE '^ +SSID: KWZ-HOME-[ag]$'"
  HostName 192.168.1.16
  Port 22
Host h16
  HostName home.example.jp
  Port 22016

Match host h17 exec "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | grep -qE '^ +SSID: KWZ-HOME-[ag]$'"
  HostName 192.168.1.17
  Port 22
Host h17
  HostName home.example.jp
  Port 22017

これは何かっていうと、今までは Host によるホスト名の条件分岐(精々ワイルドカードが使える程度) しかできなかったのが、Match を使うことでホスト名マッチングの他に、接続先または接続元のユーザ名や、果てはローカルコマンドの実行結果を複数ANDで組み合わせて条件が書けるようになったのだ(詳しくはman ssh_config)。

上記の設定ではまず host h16 の部分がホスト名一致、続いて exec "(略)" が書いてある。これは exec に渡したコマンドの終了ステータスが 0 なら真という条件になる。

ちなみに /(略)/airport -I は例えば以下の様な出力が出てくる。

     agrCtlRSSI: -57
     agrExtRSSI: 0
    agrCtlNoise: -87
    agrExtNoise: 0
          state: running
        op mode: station
     lastTxRate: 130
        maxRate: 144
lastAssocStatus: 0
    802.11 auth: open
      link auth: wpa2-psk
          BSSID: 1c:b1:7f:70:16:20
           SSID: KWZ-HOME-a
            MCS: 15
        channel: 11

これは現在接続中の WiFi 情報で、Match exec の中ではこの出力に grep -qE '^ +SSID: KWZ-HOME-[ag]$' と grep をかけている。KWZ-HOME-[ag] は自宅WiFiの SSID (例)です。電波帯別に2種類のSSIDがあるのでこのどっちかにつながってたら自宅と判定しているわけだ。

うん凄い快適。

ちなみに Match に複数条件を書くと前の条件から順にテストして true なら次の式をテストし、一つでも失敗したらそれより右のチェックは行わないという仕様なので、頭に host h16 と書いておくことで h16 というホスト名で接続しようとした時のみに後半のコマンドが実行されるので無駄に exec される事が避けられるようにしている。

ちなみに ssh_config の設定は上の方で確定した設定は後半でマッチしても上書きされない、設定項目毎に先勝ちルールなのでその点を考慮しつつ設定を書く場所の順番を決めましょう。

19
18
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
18