SSHを利用して遠隔のネットワークに接続する
先日ゼミ内のVPNサーバに障害が発生し,ゼミネットワーク内に設置した各種マシンへアクセスできない状況になった.
幸いにも外部ネットワークからアクセスできるSSHサーバが存在するため,そのサーバを踏み台にしてゼミネットワーク内のサービスにアクセスできた.
この際に調べた事項のまとめ.
既存技術をまとめ直しているだけであり,特に目新しい情報はないのであしからず.
前提
参考サイト
https://qiita.com/ymd_/items/5eb833ad757bd8b3e6c3 http://inaz2.hatenablog.com/entry/2013/04/30/221348
遠隔マシンへの多段SSH
遠隔ネットワーク内のマシンへSSHしたい場合,DMZのSSHサーバを中継サーバとして多段のSSHをすることになる.
以下説明のため,次のようなサーバ構成だと仮定する.
サーバ種別 | ホスト名 | サーバアドレス | ユーザ名 |
---|---|---|---|
クライアントマシン | client | client-machine | clientUser |
DMZのSSHサーバ | dmz | dmz-server | dmzUser |
目的の接続先 | remote | remote-server | remoteUser |
単純に考えるとまずはDMZのSSHサーバにSSHし,そこから目的サーバにSSHすれば良いように感じる.
しかしこの手法は煩雑なので,次のようにすることでコマンド一発で多段のSSHを実現できる.
$ ssh dmzUser@dmz-server -t ssh remoteUser@remote-server
これは,sshコマンドに任意のコマンドを渡すことでssh先でコマンドを実行できる機能を利用して,ssh先でsshコマンドを実行している.
このとき,ssh先でttyを利用するので -t
オプションを指定する必要がある.
毎度このコマンドを打つのは冗長なので,~/.ssh/config
に設定を加えることで簡便に多段のsshを実現できる.
Host 中継機のホスト名 HostName 中継機のサーバアドレス User 中継機のユーザ名 Host 目的サーバのホスト名 HostName 目的サーバのアドレス User 目的サーバのユーザ名 ProxyCommand ssh -W %h:%p dmzのホスト名
ホスト名はsshコマンドでの指定に用いる名前で好きにつけることができる.
サーバアドレスは名前解決ができるならばFQDNでもIPアドレスでも構わない.
このとき,ProxyCommandを実行するのは中継機であるため,目的サーバのHostNameは中継機から名前解決できる必要がある.
例示したサーバ構成であれば次のような例になる.
Host dmz HostName dmz-server User dmzUser Host remote HostName remote-server User remoteUser ProxyCommand ssh -W %h:%p dmz
なお, -W
オプションは,%h %p が 本来の接続先である目的接続先名のHostNameとそのポートに置換される.
つまるところ以下の書き換えなのだが,中継機の情報が変更されることを考えると -W
オプションが利用できると便利.
$ ssh dmzUser@dmz-server -t ssh remoteUser@remote-server
以上のように ~/.ssh/config
に記述することで以下のコマンドを実行することで多段のSSHが実現される.
$ ssh remote
SSHエージェントの中継(ssh agent forwarding)
クライアントマシンの秘密鍵を用いて目的サーバへ公開鍵認証したい場合,中継機にクライアントマシンの秘密鍵を設置してしまうと中継機のroot権限を持つユーザに秘密鍵を悪用される可能性があり危険である.
このとき,ssh agent forwardingを利用することで,中継機にクライアントマシンの秘密鍵を設置する必要がなくなる.
sshの公開鍵認証は電子署名の仕組みを利用して認証を行っているが,中継機が目的サーバにSSHする際に求められる署名をクライアントマシンに肩代わりしてもらうことによって実現する.SSHの公開鍵認証の仕組みについては次のサイトなどが参考になる.
https://qiita.com/angel_p_57/items/2e3f3f8661de32a0d432
サーバ側の設定
中継機のsshd_configに AllowAgentForwarding yes
と設定する必要がある.
https://www.freebsd.org/cgi/man.cgi?sshd_config(5) や https://euske.github.io/openssh-jman/ssh_config.html を見る限り,デフォルトでyesの設定になっている.
ssh-agentの起動
まずssh-agentを起動する必要がある.
詳細は次のサイトが参考になる.
https://qiita.com/isaoshimizu/items/84ac5a0b1d42b9d355cf
agent fowarding
agent fowarding を利用する際には中継機へのssh実行時に -A
オプションを渡す.
ssh -A dmzUser@dmz-server -t ssh remoteUser@remote-server
なお,sshコマンド実行時に-Aオプションの指定を省略したい場合は ~/.ssh/config
にて中継機に ForwardAgent yes
と設定すればよい.
Host dmz HostName dmz-server User dmzUser ForwardAgent yes Host remote HostName remote-server User remoteUser ProxyCommand ssh -W %h:%p dmz
sftp
sftpにて多段の接続を行う場合は以下のようなコマンドが利用できる.
$ sftp -o "ProxyCommand ssh dmzUser@dmz-server -W %h:%p" remoteUser@remote-server
なお,sftpはsshを利用して実行されるため, ~/.ssh/config
の設定が適応される.
そのため,上述した設定が施されている場合,以下のコマンドで多段のsftpが利用できる.
$ sftp remote
scp
scpにて多段の接続を行う場合は以下のようなコマンドが利用できる.なお,この例ではlocalからremoteへファイルを転送する.
$ scp -r -o "ProxyCommand ssh dmzUser@dmz-server -W %h:%p" /local/path remoteUser@remote-server:/remote/path
なお,scpはsshを利用して実行されるため, ~/.ssh/config
の設定が適応される.
そのため,上述した設定が施されている場合,以下のコマンドで多段のscpが利用できる.
$ scp -r -o /local/path remoteUser@remote-server:/remote/path
Port Forwarding
sshコマンドはオプションを与えることでポートフォワーディングが行え,proxyサーバとして利用できるようになる.
Local Port Forwarding
いわゆる普通の Port Forwarding.
$ ssh -L 8080:remote-server:80 dmzUser@dmz-server
と実行することで,クライアントマシンにてlocalhostの8080番ポートにアクセスすると中継機からremote-serverの80番ポートにアクセスしたことになる.
ただし,HTTPリクエスト中のHostヘッダは書き換えられない(この場合はそのままlocalhost:8080となる)ため,HTTPサーバ側でVirtualHostを利用している場合はうまく表示されない可能性がある.
これを解決するためには,/etc/hostsを使って,アクセスしたい先のホスト名を127.0.0.1に名前解決するようにする.
127.0.0.1 httpserver.remote-server.com
なお,sshコマンド実行時に接続先の制御端末が表示されるのを抑制したい場合は -fN
オプションが利用できる.
$ ssh -fNL 8080:remote-server:80 dmzUser@dmz-server
Remote Port Forwarding
firewallなどによって,中継機へssh接続できない場合に利用できる可能性がある.
この手法では,クライアントマシンにsshサーバを立て,中継機からクライアントマシンへssh可能である必要がある.
以下のようにすることで,remote-serverへのアクセスが全て禁止されている状態でも,remote-serverから外部に接続できるportが存在すればproxyとして利用できる.
- クライアントマシン上にSSHサーバを立て,中継機からssh可能な状態にする
- 中継機からクライアントマシンへSSHする
$ ssh -R 8080:remote-server:80 clientUser@client-machine
- クライアントマシンでのlocalhost:8080へのアクセスが中継機からのremote-server:80のアクセスとなる
なお,sshコマンド実行時に接続先の制御端末が表示されるのを抑制したい場合は -fN
オプションが利用できる.
$ ssh -fNR 8080:remote-server:80 clientUser@client-machine
Dynamic Port Forwarding
sshdサーバをSOCKS Proxyとして使うことができる. これにより,VirutalHostを使用しているHTTPサーバにアクセスしたり,手元のネットワークのファイアウォールを迂回することができる. 非常に便利.
client-machineから dmz-serverへ -Dオプションを指定して ssh接続することで,client-machine上では socks5://localhost:1080
がSOCKSプロキシとして利用できるようになり,利用した通信は dmzUser@dmz-server 経由のアクセスとなる.
$ ssh -D 1080 dmzUser@dmz-server
ここでproxyを socks5://localhost:1080
とすると名前解決はクライアントマシンで行う必要があるが, socks5h://localhost:1080
といった風に設定すると,proxyサーバ側で名前解決を行うようになる.
なお,sshコマンド実行時に接続先の制御端末が表示されるのを抑制したい場合は -fN
オプションが利用できる.
$ ssh -fND 1080 dmzUser@dmz-server
FreeBSD-STABLE からおさらばする
概要
FreeBSD 11.0 STABLE amd 64の環境を作ってしまったところ,満足にpackagesを利用できなかったので11.2-RELEASE にアップグレードした際の記録.
紆余曲折をメモしているので,アップグレードの流れをサクッと知りたい場合はここ以降を参考に.
環境
対象の方
なりゆき
眼の前にISOイメージがあったので 深く考えないで 11.0 STABLE amd 64
の仮想マシンを作成した.
その環境下でvimをインストールし起動すると,エラーが発生して利用できなかった.
$ sudo pkg install vim $ vim Shared object "libdl.so.1" not found, required by "vim"
どうやらlibdl.so.1
が見つからないらしい.
ネットで検索してみると,様々なフォーラムにおいて,FreeBSD 11.1以前は libdl.so.1
がないとの報告があり,この状況の説明としては,以下の回答がとても良くまとまっていた.
The FreeBSD package collection targets the oldest supported release on the branch - i.e., 11.2 for the 11.x branch. So pkg install python3 installs a python built for 11.2, which picked up a dependency on libdl.so.1 not found in 11.1.
FreeBSD 11.1: Shared object "libdl.so.1" not found · Issue #110 · cirruslabs/cirrus-ci-docs
つまり,The FreeBSD package collection は現在サポートされている最も古いリリースを対象とするものであり,すでにサポートが切れているFreeBSD 11.1 以前ではインストールされていないlibdl.so.1
を依存関係に含んだものに変わってしまっているということらしい.
現在のサポート状況は以下のページで参照できる.
なお,本記事執筆時点でのサポート状況は次の通りである.
Branch | Release | Type | Release Date | Expected EoL |
---|---|---|---|---|
stable/12 | n/a | n/a | n/a | June 30, 2024 |
releng/12.0 | 12.0-RELEASE | n/a | December 11, 2018 | 12.1-RELEASE + 3 months |
stable/11 | n/a | n/a | n/a | September 30, 2021 |
releng/11.2 | 11.2-RELEASE | n/a | June 28, 2018 | 11.3-RELEASE + 3 months |
対応策としては,package collection に頼らないで vim をインストールするものと,FreeBSDのバージョンを上げるものが考えられる.執筆時点での11系の最も古いサポート版は 11.2-RELEASE
であり, 11.0 STABLE
はサポートされていないので今後も何かしらの問題に直面する可能性が高い.そのため,今回はFreeBSDのバージョンを上げることにする.
FreeBSDのブランチのことを何も知らずに,STABLEというからには安定版なんだろうと思いこみ, FreeBSD STABLE
をインストールしたのがそもそもの間違いであった.FreeBSDには RELEASE
, CURRENT
, STABLE
という三つのブランチが存在し,CURRENT
と STABLE
は開発ブランチである.
FreeBSDのバージョンを上げる
FreeBSDのバージョンを上げる際には freebsd-update
ユーティリティが利用できる.
公式ドキュメント[17.2. FreeBSD Update] によると,マイナーバージョンのアップグレードもメジャーバージョンのアップグレードも以下のようにできるらしい.
# freebsd-update -r [目的のリリース番号のターゲット] upgrade
そこで,実際に以下のコマンドにて 11.2-RELEASEへのアップグレードを試みた.
# freebsd-update -r 11.2-RELEASE upgrade src component not installed, skipped Looking up update.FreeBSD.org mirrors... none found. Fetching public key from update.FreeBSD.org... failed. No mirrors remaining, giving up.
失敗した. 外部ネットワークには接続できているのにもかかわらず,ミラーサーバが見つからないと言っている. なにかネットワーク以外の問題がありそうである.
調べていると,同様の問題に悩まされていそうな投稿を見つけた.
freebsd-update fetch ... Looking up update.FreeBSD.org mirrors... none found | The FreeBSD Forums
# drill update.FreeBSD.org ;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 41307 ;; flags: qr rd ra ; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 5 ;; QUESTION SECTION: ;; update.FreeBSD.org. IN A ;; ANSWER SECTION: update.freebsd.org. 3211 IN A 163.237.247.16 update.freebsd.org. 3211 IN A 204.15.11.117 ;; AUTHORITY SECTION: freebsd.org. 3211 IN NS ns1.isc-sns.net. freebsd.org. 3211 IN NS ns3.isc-sns.info. freebsd.org. 3211 IN NS ns2.isc-sns.com. ;; ADDITIONAL SECTION: ns1.isc-sns.net. 156722 IN A 72.52.71.1 ns2.isc-sns.com. 156722 IN A 63.243.194.1 ns3.isc-sns.info. 1584 IN A 63.243.194.1 ns1.isc-sns.net. 156722 IN AAAA 2001:470:1a::1 ns3.isc-sns.info. 1584 IN AAAA 2001:5a0:10::1 ;; Query time: 0 msec ;; SERVER: 10.1.3.21 ;; WHEN: Tue Apr 30 15:02:12 2019 ;; MSG SIZE rcvd: 275
問題なくDNSはひけているように見えるし,ミラーサーバに問題があるとも考えにくい. 何か他に原因がありそうである.
調べていると,次のようなページを見つけた.
freebsd-updateを使いたければRELEASEにしとかないとだめ - N.E.E.T―Never Ending Engineer’s Tragicomedy別館
ページタイトルにも書いているが,要するにfreebsd-update
はRELEASE版のみをサポートしているらしい.
RELEASEブランチへの変更
STABLEからはアップグレードできないらしいので,まずはRELEASE版にする必要がある.
検索してみるとそのままズバリなサイトが見つかった.
FreeBSD 11-STABLEを11.1-RELEASEに変更する [クソゲ〜製作所]
このサイトに従って実際にコマンドを打っていく.
# cd /usr/src # svn info svn: Command not found.
svn
がないと言われた.
調べてみると svn
というのはFreeBSDが現在利用しているバージョン管理システムの subversion
のことらしい.
公式ドキュメントによると, svn
は pkg
などからインストールできるが, より軽量である svnlite
というものがすでに標準でインストールされているらしい.
公式ドキュメント[A.3. Subversion を使う]によると,
Python もしくは Perl API が必要な時や、 最新の Subversion を使用したい時のみ必要
とのことなので,今回は svnlite
で十分そうである.
ドキュメントに従って,まずはソースコードをダウンロードする.これはかなり時間がかかる.
# cd /usr/src # svnlite checkout https://svn.FreeBSD.org/base/releng/11.2/ .
フィンガープリントの確認が出る場合は,正しいサーバなのかを判別して許可すること.
今後ブランチの中身を最新の状態にしたい場合は以下のコマンドを実行することで高速に差分のみをダウンロードできる.
# svnlite update /usr/src/
ソースのダウンロードが済んだので,以降は公式ドキュメント[17.5. ソースを用いた FreeBSD のアップデート]を参考に作業を進めていく.
最新のツールを用いてカーネルを構築するために,まずはカーネル以外をコンパイルし,後にカーネルをコンパイルする.
これは本当に時間がかかるので,CPUのコア数を確認した上で適切なジョブ数を設定するとよい.また,仮想マシンなど遠隔のマシンを対象にする場合,ローカルマシンからsshして実行すると途中でセッションが切れてビルド状況がわからなくなってしまうので,tmuxなどをいい感じに使うか,コンソールから作業する必要がある.
なお,次の記事を参考にすればコンソールから切れたプロセスを標準出力につなげなおすことも可能だ.
コンソールから切れたプロセスを標準出力につなげなおす - 絶品ゆどうふのタレ
# cd /usr/src/ # make -j6 buildworld # make -j6 kernel
なお, make kernel
は make buildkernel installkernel
と同じなので,カーネルのインストールまでがこれで終わる.
make
コマンドの j
オプションは,同時に実行可能なjob数を定義している.
今回はESXi上の仮想マシン上で実行しているが,buildworldをビルドする際にコア数1のままビルドしてしまい2日程かかった.
cpuパワーが足りていない場合はマシンをシャットダウンした上でvSphereクライアントよりコア数を変更できる.コアを追加した後に,コンパイルするとよいだろう.
hyperthreadingが有効なら, のジョブ数にするべきなのだろうが,有効かどうかを確認できていない.
buildworldをmakeすると次のようなエラーが発生した.
--- CodeGenDAGPatterns.o --- c++: error: unable to execute command: Killed c++: error: clang frontend command failed due to signal (use -v to see invocation) FreeBSD clang version 4.0.0 (tags/RELEASE_400/final 297347) (based on LLVM 4.0.0) Target: x86_64-unknown-freebsd11.0 Thread model: posix InstalledDir: /usr/bin c++: note: diagnostic msg: PLEASE submit a bug report to https://bugs.freebsd.org/submit/ and include the crash backtrace, preprocessed source, and associated run script. c++: note: diagnostic msg: ******************** PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT: Preprocessed source(s) and associated run script(s) are located at: c++: note: diagnostic msg: /tmp/CodeGenDAGPatterns-dad627.cpp c++: note: diagnostic msg: /tmp/CodeGenDAGPatterns-dad627.sh c++: note: diagnostic msg: ******************** *** [CodeGenDAGPatterns.o] Error code 254 make[3]: stopped in /usr/src/usr.bin/clang/llvm-tblgen --- _bootstrap-tools-usr.bin/clang/clang-tblgen --- A failure has been detected in another branch of the parallel make make[3]: stopped in /usr/src/usr.bin/clang/clang-tblgen *** [_bootstrap-tools-usr.bin/clang/clang-tblgen] Error code 2 make[2]: stopped in /usr/src --- _bootstrap-tools-usr.bin/clang/llvm-tblgen --- 1 error make[3]: stopped in /usr/src/usr.bin/clang/llvm-tblgen *** [_bootstrap-tools-usr.bin/clang/llvm-tblgen] Error code 2 make[2]: stopped in /usr/src 2 errors make[2]: stopped in /usr/src *** [_bootstrap-tools] Error code 2 make[1]: stopped in /usr/src 1 error make[1]: stopped in /usr/src *** [buildworld] Error code 2 make: stopped in /usr/src 1 error make: stopped in /usr/src
いきなりバージョンを大きく上げたのでエラーが発生しているのかもしれない. サポートされていないOSのバグを報告してもしょうがないので,少しずつバージョンを上げることにする.
まず,現在の /usr/src
の中身を隠しファイルも含めて適当な名前の場所に移動するか削除する.
# cd /usr/src/ # mkdir 11.2 # mv * .* 11.2
その後 ,新しく11.0-RELEASEのsrcをダウンロードする.
# cd /usr/src/ # svnlite checkout https://svn.FreeBSD.org/base/releng/11.0/ .
先程と同様の手順でビルドする.
# cd /usr/src/ # make -j6 buildworld # make -j6 kernel
ビルドが終了したら,再起動して新しいカーネルを利用しworldをインストールする.
# shutdown -r now # cd /usr/src/ # make -j6 installworld
リブートしたタイミングでカーネルのバージョンを確認するとカーネルのバージョンが上がっているのが確認できる.
# uname -r 11.0-RELEASE-p16
/etc/ に置かれている設定ファイルをアップデートしたりマージする. 途中いろいろ聞かれるので適切に対応する.
# mergemaster -Ui
新しいkernelとworldを利用するために再起動する.
# shutdown -r now
freebsd-update コマンドでアップグレードする
ここまでで OSがRELEASEブランチのものになったので, freebsd-update コマンドによって11.2-RELEASE にアップグレードする事ができるようになった.
公式ドキュメント[17.2. FreeBSD Update]を参考に作業を進める.
# freebsd-update -r 11.2-RELEASE upgrade
すべてのパッチをマージする
# freebsd-update install
アップデートされたカーネルで再起動する
# shutdown -r now
再起動後はカーネルが変わっているのが確認できる
# uname -r 11.2-RELEASE-p9
古い共有ライブラリとオブジェクトファイルを削除するために再び freebsd-update
コマンドを実行する
# freebsd-update install
メジャーバージョンをアップデートした場合はportsやpackagesの再構築が必要だが,今回はマイナーバージョンのアップデートなので関係ない.
以上で,OSバージョンのアップデートが完了した.
非常に容量を食うので,容量が足りない場合は事前に不要なファイルを削除したり,ストレージを追加する必要がある. 今回はvimに関連するファイルをすべて削除することで容量を確保した. そのため,最後にvimをインストールし直して動作することを確認した.
# pkg install vim
結論
FreeBSDを使うときはサポート期間内のRELEASE版を使え.