いますぐ実践! Linuxシステム管理

いますぐ実践! Linux システム管理 / Vol.248 / 読者数:2461名

こんばんは、うすだです。

…た、たいへん、ご無沙汰いたしておりました。

やや大げさに書くと、我が家の今後の生活が大きく変わるかもしれない、 という事態が先月発生し、発行する余裕を失ってしまっておりました。

…いえ、発行しようと思えばできましたが、 それを理由にしてラクな道を選んでしまった、というのがおそらく真実です。

結局、我が家の今後の生活は大きく変わるものの、 誰かがいなくなったりということはなく、 基本的には概ねいままで通りの生活に戻っていけそうな感じです。

ですので、2回ほどすっ飛ばしてしまいましたが、再開いたします。
今後も、月2回発行を続けていきますので、よろしくお願いいたします。

発行していなくても読者は増えるなあ…じゃあ頻度を減らしても… という悪魔のささやきを追い出しつつ、今回もはりきってまいります。

今回のお題 - SSH でVPNを実現する

いまさらですが、「SSH(Secure SHell)」は便利ですよね。

暗号化されているので安心だし、リモートログインだけでなく、 ファイルのコピーやポートフォワーディングまでやってくださいます。

じゃあ、いっそのこと、ネットワークもつなげられたらいいのに…と思うのは、 きっと貴兄だけではないと思います。

そして、お察しの通り、かつタイトルの通り、 SSH で遠隔ログインした先と元のマシンを、仮想的に直接つなぐことができます。

というわけで今回は、「VPN(Virtual Private Network)」を SSH で実現する方法を、 さらっとご紹介します。

SSH でVPNの概要

SSH は、TCPの22番ポートを使ってやりとりします。

ポートフォワーディングの場合、 この22番ポートに別のポートのデータをトンネリングして渡すことで、 転送を実現しています。

VPN の場合は、すごく簡単に言ってしまえば、TCPセグメントの代わりに、 IPパケットもしくは Ethernetフレームをトンネリングしています。

これのありがたい点は、SSH でログインできる間柄であれば、 双方の設定次第で VPN ができてしまうということです。
間の経路で、ファイアウォールなどの設定を変更しなくて済みます。

ただ、「TUN」または「TAP」という仮想ネットワークドライバを使用するため、 双方で root の権限を必要とします。
また、コネクション型通信であるTCPの上で、 到達や順序の保証のないIPパケットまたは Ethernetフレームを流すため、 再送のタイミングがかみ合わないと、効率がとっても悪くなる可能性があります。

ですので、あくまでも、直接通信できたら便利、くらいの用途で、 個人的に使っていただくのが、無難ではないかと思います。

前提条件とか前準備とか

以降では、TUNを使ったIP接続と、TAPを使ったEthernet接続の手順を紹介します。

が、その前に、どちらにも必要な前提条件や前準備について説明します。

 

まず、SSHクライアントのIPアドレスが「192.168.1.2」、 SSHサーバのIPアドレスが「172.16.1.1」という前提で、話を進めます。
また、SSHでIP接続もしくはEthernet接続する際に設定するアドレスを、 それぞれ「10.0.0.2」「10.0.0.1」とします。

もし違っていましたら、各自、脳内などで置き換えてお読みください。

 

それから、SSHクライアントの rootユーザから、 SSHサーバの rootユーザとしてログインする必要があります。
デフォルトでは、rootユーザとしてログインすることは許可されていないため、 SSHサーバ側で許可する必要があります。
(厳密には、設定の記述がなければ許可ですが、 たいていは拒否の設定がデフォルトで入っています。)

具体的には、SSHサーバの設定ファイルである「/etc/ssh/sshd_config」に、 「PermitRootLogin」キーワードを使って許可します。

  PermitRootLogin forced-commands-only

「yes」を指定するのはちょっと怖いので、 コマンド実行だけを許可する「forced-commands-only」を指定しています。
ただ、もともと yes に設定されているなら、 だれかがそれを必要としている可能性があるため、その設定を変えないほうが無難です。

また、設定を反映するため、本来はここでsshサービスの reload を行いますが、 後で設定を付け足しますので、いまは行いません。

 

あと、「ssh-keygen」コマンドを使って、鍵を生成します。
SSHクライアントで、以下のように実行すると、「/root/.ssh/」の下に、 秘密鍵「vpntest」と公開鍵「vpntest.pub」が作られます。

  client# ssh-keygen -f ~/.ssh/vpntest
  Generating public/private rsa key pair.
  Enter passphrase (empty for no passphrase): (リターン)
  Enter same passphrase again: (リターン)
  Your identification has been saved in /root/.ssh/vpntest.
  Your public key has been saved in /root/.ssh/vpntest.pub.
  The key fingerprint is:
  ...後略...

最後に自動起動をやりますので、パスフレーズなしで設定しています。

そうしましたら、公開鍵を、一般ユーザ経由などでSSHサーバ側へ持っていき、 「/root/.ssh/authorized_keys」へ追加します。

  (もし /root/.ssh がなければ、以下の手順で作ります)
  server# mkdir /root/.ssh
  server# chmod go-rwx /root/.ssh
  (authorized_keys に公開鍵を追加します)
  server# mv /some/where/vpntest.pub /root/.ssh/
  server# cat /root/.ssh/vpntest.pub >> /root/.ssh/authorized_keys
  server# rm /root/.ssh/vpntest.pub
  (authorized_keys がなかった場合は、パーミッションを設定します)
  server# chmod go-rwx /root/.ssh/authorized_keys
  (最後に、念のため確認します)
  server# ls -l /root/.ssh/authorized_keys
  -rw------- 1 root root 392  9月  1 08:41 /root/.ssh/authorized_keys

この状態では、authorized_keys に「command」オプションがないため、 rootユーザでログインすることはできません。ご安心ください。
(sshサービスを reload していないので、そもそも問題ないはずです。)

TUN を使ってIP接続します

準備ができたところで、まずは TUN によるIP接続をやってみましょう。

まずは、SSHサーバ側の設定からです。
先ほど追加した authorized_keys の行の先頭に、 以下の文言を追加してください。
(1行目の行末を \ で折り返して複数行にしていますが、 実際は \ がなく 1行で書きます。)

  no-X11-forwarding,no-agent-forwarding,no-pty,command="ifconfig \
  tun0 10.0.0.1 pointopoint 10.0.0.2" ssh-rsa A...

「ssh-rsa A...」の部分が元の行ですので、 それより前の部分を追加してください。
「no-X11-forwarding」「no-agent-forwarding」「no-pty」 オプションでいろいろと禁止をした後、 「command」オプションで実行するコマンドを指定しています。
ここでは、インターフェース「tun0」の設定をしています。

それから、前述の sshd_config に、トンネリングの設定を追加します。

  PermitTunnel point-to-point

「point-to-point」でIP接続を許可しています。
sshd_config を変更したので、sshサービスを reload します。

  server# service ssh reload   (Debian系の場合)
  server# service sshd reload  (RedHat系の場合)

 

次に、SSHクライアント側の設定です。
SSHクライアントの設定ファイル「/root/.ssh/config」に、 以下のようなエントリを追加します。

Host vpntest
  HostName 172.16.1.1
  IdentityFile ~/.ssh/vpntest
  Tunnel point-to-point
  TunnelDevice 0:0
  RequestTTY no
  PermitLocalCommand yes
  LocalCommand ifconfig tun0 10.0.0.2 pointtopoint 10.0.0.1

「TunnelDevice」で、双方のインターフェースの番号を指定しています。
もし他ですでに使っている場合は、違う番号を指定してください。
最後の2行で、SSHクライアントのインターフェース「tun0」の設定をしています。

あとは、sshコマンドでつなぐだけです。
最初は、念のため「-v」オプションをつけて実行すると、 うまくいかないときにメッセージから手がかりが得られるので、便利です。

  client# ssh -v 172.16.1.1
  ...後略...

試しに、ping などしてみましょう。
うまくいっていれば、通るはず…です。

  client$ ping 10.0.0.1

いらなくなったら、ssh コマンドのプロセスを、(Ctrl-Cなどで)終了してください。

TAP を使ってEthernet接続します

お次は、TAP によるEthernet接続です。

SSHサーバ側の設定ですが、まず、 authorized_keys では、command の中が少し異なります。

  no-X11-forwarding,no-agent-forwarding,no-pty,command="ifconfig \
  tap0 10.0.0.1 netmask 255.255.255.0" ssh-rsa A...

インターフェース「tap0」に対して設定をしています。
ネットマスクは、ここではクラスCの24ビットに設定していますが、 他の値でも問題ありません。(双方で同じ値を用いればよいです。)

また、sshd_config では、PermitTunnel に「ethernet」を指定します。

  PermitTunnel ethernet

そしてお約束の、sshサービスの reload をします。

  server# service ssh reload   (Debian系の場合)
  server# service sshd reload  (RedHat系の場合)

 

SSHクライアントの /root/.ssh/config には、先ほどと同等のエントリを追加します。

Host vpntest2
  HostName 172.16.1.1
  IdentityFile ~/.ssh/vpntest
  Tunnel ethernet
  TunnelDevice 0:0
  RequestTTY no
  PermitLocalCommand yes
  LocalCommand ifconfig tap0 10.0.0.2 netmask 255.255.255.0

あとは、同様に試すだけですね。

  client# ssh vpntest2 &
  client# ping 10.0.0.1

最後に自動起動を

できれば、必要な際に手動で起動するのではなく、 自動的に起動して VPN がいつでも使えると、うれしいですよね。

というわけで、Ubuntu の「Upstart」用だけになりますが、 ちゃちゃっと書いてみました。
設定ファイルは、仮に、「/etc/init/ssh-vpn.conf」としておきます。

description	"SSH vpn"

start on net-device-up IFACE=eth0
stop on runlevel [!2345]

respawn
exec ssh vpntest2 > /dev/null 2>&1

インターフェースeth0が使えるようになったとき起動し、 シャットダウンや再起動のときに停止します。
「ssh vpntest2」を実行しますが、「spawn」がありますので、 もし終了しても、また実行してくれます。

上記ファイルを作成したら、とりあえず手動で動かしてみましょう。

  client# start ssh-vpn
  ssh-vpn start/running, process 12905
  client# status ssh-vpn
  ssh-vpn start/running, process 12905

プロセスIDが 12905(実行の度に変わります) で動き出しました。

  client# ping -c 1 10.0.0.1
  PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
  64 bytes from 10.0.0.1: icmp_req=1 ttl=64 time=2.87 ms
  ...後略...

ping も通ります。

さて、ここで、イジワルをしてみましょう。
サーバ側で、対応する sshd のプロセスを抹殺します。

  client# status ssh-vpn
  ssh-vpn start/running, process 12917

試し終わって、特に必要なければ、ファイルは消しておいてください。
(もしくは /etc/init/*.conf でないファイル名に改名してください。)

おわりに

以上、SSH で VPN する2つの方法を、ご紹介しました。

さて、結局のところ、TUN を使った方がいいのか、TAP を使った方がいいのか、 これだけではよくわからないのではないか、と思います。

正直に申し上げますと、わたしもよくわかりません。OTZ
TAP の方が Ethernetヘッダがある分、 オーバーヘッドが大きくて損だな…と思うのですが、 それなら TAP に設定できなくてもええやん、ということになってしまいます。

というわけですので、謎が解けましたら、ちらっとご紹介します。
もし、答えをご存じな方がいらっしゃいましたら、ご教示くださいませ。

宿題の答え

前回の宿題は、

  ssh_configで、複数の設定を1つのHostで記述してみてください。

でした。

たとえば、なんとか.dev.usupi.org というホストにログインする際は、 必ず devuser というユーザ名で、 かつ ~/.ssh/id_rsa.dev を鍵にするという決まりがあるなら、 以下のように記述できます。

Host *.dev.usupi.org
  User devuser
  IdentityFile ~/.ssh/id_rsa.dev

/etc/hosts に server1〜9 が登録されていて、 ~/.ssh/id_rsa.ホスト名を鍵にしたいなら、以下のように記述します。

Host server?
  IdentityFile ~/.ssh/id_rsa.%h

また、ログインしたときメールでその旨を通知したいときは、 以下のように記述できます。(\ で折り返していますが、実際は1行です。)

Host 192.168.0.*
  PermitLocalCommand yes
  LocalCommand echo "login from %u@%l to %r@%h" | /usr/bin/Mail -s "[ssh] %l to %h" root

ただ、メールで通知という仕込みは、本来ログインした先でやるべきことです。 わたしは、以下のようなものを、~/.ssh/rc にしています。

#!/bin/sh
if [ "z$TERM" != z ]; then
    echo "Connection : ${SSH_CONNECTION}" | \
        /usr/bin/Mail -s "[ssh] ${SSH_CLIENT}" root
fi

今回の宿題

今回の宿題は、

  SSHのポートフォワーディングを使って接続したSSHで、VPNが動作する
  か、試してみましょう。

です。

ファイアウォールやプライベートなネットワークなどのため、 直接つなぐことのできないマシン同士でも、 ポートフォワーディングを駆使してSSHで接続できるなら、VPNだってできそうです。

でも、ほんとにできるかどうか、ちょっと自信がありません。
ですので、ほんとに動作するか、実際にやってみましょう。
もし万が一ダメだったら…ダメだった、という回答を、 その理由とともに提示いたします。はい。

あとがき

息子が、下記の催しに申し込んでいたのですが、 一緒に行くはずの息子の友人が参加できなくなったため、代理で行ってきました。
(高校生限定! ではなかったため、社会人の方もたくさんおられました。)

先進科学塾@名大
http://asw.flab.phys.nagoya-u.ac.jp/

テーマは「音を見る」ということで、音に関する実験をいろいろ体験する催しでした。

音が波で、打ち消しあったり増幅しあったりする、 というくらいの知識は持っているつもりでしたが、 あらためて聞かれたり実験をすると、 自分の理解が曖昧であることがよくわかりました。気持ちのよい体験でした。

社会人になると、時間に追われて、不思議に思うことも、 グーグル様などに伺って済ませてしまうことが多いのではないかと思います。

ですが、すぐ答えを知ってしまうのではなく、 自分で経験して確かめるということも大事なのではないか、と思いました。

また、筒の先端で音が反射する理由の説明が、 講師の方によっていろいろ違ったというのも、興味深かったです。 真実は一つだけど、見ているモノや方向が人によって違う、ということでしょうか。

…ま、私の理解の方は、かなーり怪しいままなんですけど。

 

ちなみに、組み込みの会社にいるのに、 オシロスコープをはじめて真面目に触ったということは、 内緒にしておいていただけますと幸いです。

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、10月20日(日) の未明にお会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」- ミスドの栗、まだやってますか…。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)
http://twitter.com/kuriking/ (栗つぶやき)
http://facebook.com/kuriking3 (栗顔本)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本