経緯
自宅サーバーは基本的にIPv6のリンクローカルアドレスでアクセスしている。
このリンクローカルアドレスというのは、(物理インターフェースの場合)NIC固有のMACアドレスから生成されるため、ネットワークに依存しないという特徴がある。
具体的な運用上のメリットとしては
- 手動によるIPの固定が必要ないため、設定が一つ減らせて楽。
- 障害が起きた場合に、別の回線に変更しても設定を変える必要がない。
実際に今回メインの回線が繋がらなくなったものの、自宅の機器をすべてもう一つの回線に切り替える1ことで問題なく機能している様子。2
ただ、あとになってsshが直接繋げないという問題が発覚したため、調べた。3
前提
sshのバージョンについて
$ ssh -V
OpenSSH_8.4p1, OpenSSL 1.1.1h 22 Sep 2020
結論
リンクローカルアドレスはどのNICも同じネットワークに見えてしまうため、どのインターフェイスから通信を送るかを指定する必要がある
Zone indexを用いたやり方
以下のようにリンクローカルアドレスの後ろに%
とzone index
(詳しくは後述)をつける。
ssh user@fe80::1111:2222:3333:4444%eth0
これを~/.ssh/config
に書く際は以下のようにパーセントを2つにする必要がある
Host example-server
User user
HostName fe80::1111:2222:3333:4444%%eth0
Zone indexについて補足
- Linuxの場合インターフェース名(例:
eth0
)がそのまま使われる。 - このインターフェース名はsshのクライアントから見たサーバー宛につながるNICであり、サーバーのインターフェースとは関係ない。
Bind interfaceを用いたやり方
宛先のインターフェースを特定できればいいのであれば、わざわざzone index
という特殊な書き方をしなくても他に方法があるのではないか?
そう思って探したらbind interface
というオプションがあったので試してみたら接続できた。
コマンドで指定する場合
ssh -B eth0 user@fe80::1111:2222:3333:4444
configで設定する場合
Host example-server
User user
HostName fe80::1111:2222:3333:4444
BindInterface eth0
このほうがホストのアドレスとクライアントのインターフェースを切り分けられるので良さそう。
実際の設定例
以下のように分けた。
- .ssh
- config
- conf.d
- interface.conf(これだけクライアント別に作成)
- hosts.conf
Include ~/.ssh/conf.d/*.conf
Host *-locallink
BindInterface eth0
Host example1-locallink
User user
HostName fe80::1111:2222:3333:4444
Host example1-vpn
(中略)
Host example2-locallink
(中略)
このような感じでinterface.conf
だけクライアント別に作成し、ほかは共通にできるようにした。
反省
wireguardが問題なく動いてたから油断してたけど、sshに限らずほかもちゃんと指定したほうが良さそう。
参考
IPv6アドレス#リンクローカルアドレスとゾーンインデックス - wikipedia
-
アパートが契約した無料インターネット回線。この回線、自分が入居した当初にはなかったので当時自分で契約した回線がまだ契約が続いていて、そのままメインで使っている。無駄だと思っていたのに役立つときが来るとは思わなかった。 ↩
-
問題ないといってもリンクローカルアドレスで確実に問題なく機能していると言えるのはWireguad VPNのエンドポイントだけで、他の通信はほぼVPNで別に割り振ったIPアドレスでアクセスしている。 ↩
-
通常はsshも上記のようにVPN経由でアクセスしていたので問題なかった。とはいえwireguardなどのサービスを設定するのにsshが必要なので、いざというときに直接アクセスできないのは困る。 ↩