このセクションでは VPN システムの構築法について順番に説明します。まずサーバから 始め、次にクライアントへと移っていきます。例とするために、異なる 2 種類の VPN 設定を必要とする状況を考えてみます。
mycompany.com という会社を持っていると想像してみてください。本社 オフィスで、予約されたネットワーク 192.168.0.0 を使っており、 経路設定を許すようにクラス B ネットワークを 256 のクラス C に しています。ちょうど 2 つの小さな離れた所にあるオフィスを設定したところで、 それらをネットワークに追加したいと思っています。また 自宅から仕事している従業員に、彼らがダイヤルアップする代わりに DSL や ケーブルモデムで接続できるようにさせたいとも思っています。 始めるためには少しばかり計画を立てなくてはなりません。
それぞれの離れた所にあるオフィスで必要に応じて拡張できるよう、クラス C ネットワークの範囲を割り当てることにします。そこで、192.168.10.0 と 192.168.11.0 ネットを予約します。自宅ユーザに対しても VPN サーバ側でマスカレードする必要のない十分な数を確保することにします。 各クライアントはそれ自身の内部 IP を取得します。そこで、そのために 他のクラス C、192.168.40.0 を予約する必要があります。 今やらなくてはならないのは、ルータにそれらの範囲を追加することです。 私たちの会社が、OC1 を通過するトラフィック全てを取り扱う小さな Cisco (192.168.254.254) を所有していると思ってください。それらの予約された ネットから VPN サーバ (192.168.40.254) へ向かうトラフィックを Cisco 上で経路設定してください。 私は後で明かす理由のため、VPN サーバを自宅ユーザのネットに組み入れます。 サーバの外部インターフェースは vpn.mycompany.com 、 内部インターフェースは vpn-internal.mycompany.com と名づけることに します。
外部番号について、はっきりと知っておく必要はありません。 ISP によって割り当てられた自分自身の番号を知っているべきです。
多少、ソフトウェアが必要になってきました。 次に挙げるパッケージを取得して、指定された場所にインストールしてください。
最初に、多分、あなたはサーバのためにカーネルを再構築する必要があるでしょう。 基本ネットワークやその他の必要な項目に加えて、必ず以下のオプションをオンにしてください。 もし以前にカーネルを構築したことがなければ、 Kernel HOWTOを読んでください。 [訳注:日本語訳は http://www.linux.or.jp/JF/JFdocs/Kernel-HOWTO.html にあります。]
2.0 カーネルに対して -
2.2 カーネルに対して -
ネットワークカード 1 枚しかないサーバを構築しようとしているのであれば、 もう 1 枚買って、新たに配線することを検討するよう勧めます。 ネットワークの非公開性をそのままにしておく一番良い方法は、それを それ自身の線に割り当てることです。もし 2 枚のネットワークカード を持っているのであれば、それぞれの設定方法を知る必要があります。 私たちは外部インターフェースに eth0、内部インターフェースに eth1 を使います。
最初にサーバの外部インターフェースを設定する必要があります。 既にどうすれば良いか知っているはずですし、多分、既に設定してしまった事でしょう。 まだであれば、すぐにやってください。どうすれば良いか分からなければ、戻って Networking HOWTO を読んでください。
では内部インターフェースを設定します。番号は私たちの選択によって、 サーバの内部インターフェースが 192.168.40.254 です。 ではそのインターフェースを設定しましょう。
2.0 カーネルでは次を使ってください -
# /sbin/ifconfig eth1 192.168.40.254 netmask 255.255.255.0 broadcast 192.168.40.255 # /sbin/route add -net 192.168.40.0 netmask 255.255.255.0 dev eth1
2.2 カーネルでは次を使ってください -
# /sbin/ifconfig eth1 192.168.40.254 netmask 255.255.255.0 broadcast 192.168.40.255
それで基本インターフェースが用意できます。これで両方の ローカルネットワークによってサーバに繋がったマシンに話しかけることが できます。
私たちはローカルネットにあるマシンと話すことはできる様になりましたが、 内部ネットワークの残りとは話すことができません。 そうするにはもう数行コードが必要です。他のサブネットにあるほかのマシン に到達するためには、トラフィックが Cisco ルータに向かうような経路を 知る必要があります。次のようにします -
# /sbin/route add -net 192.168.0.0 gw 192.168.254.254 netmask 255.255.0.0 dev eth1
その行は、192.168.0.0 ネットワークに行くことになっているいくつかのトラフィック は eth1 を出るべきで、それは Cisco に伝えられるべきであるということを カーネルに伝えます。 ルーティングテーブルがネットマスクのサイズで決められるため、 ローカルネットに向かうトラフィックには、まだ向かうべき場所が分かっています。 もし他にもネットワークの中に内部的なネットワークがあるなら、それぞれに 対して、上記のような指定をすることになります。
OK, 必要とされ得るマシン全てに到達できるようになりました。 今度は、VPN サーバを通してアクセスを許すか許さないかという、 ファイアウォールのフィルタ規則を記述しなくてはなりません。
ipfwadm
で規則を指定するには、次のようにします -
# /sbin/ipfwadm -F -f # /sbin/ipfwadm -F -p deny # /sbin/ipfwadm -F -a accept -S 192.168.40.0/24 -D 192.168.0.0/16 # /sbin/ipfwadm -F -a accept -b -S 192.168.10.0/24 -D 192.168.0.0/16 # /sbin/ipfwadm -F -a accept -b -S 192.168.11.0/24 -D 192.168.0.0/16
ipchains
で規則を指定するには、次のようにします -
# /sbin/ipchains -F forward # /sbin/ipchains -P forward DENY # /sbin/ipchains -A forward -j ACCEPT -s 192.168.40.0/24 -d 192.168.0.0/16 # /sbin/ipchains -A forward -j ACCEPT -b -s 192.168.10.0/24 -d 192.168.0.0/16 # /sbin/ipchains -A forward -j ACCEPT -b -s 192.168.11.0/24 -d 192.168.0.0/16
これはカーネルに、192.168.40.0/24 ネットワークから来て 192.168.0.0/16 ネットワークに向かうものを除いた、全てのトラフィックを拒絶するように 伝えます。それはまた、192.168.10.0/24 と 192.168.0.0/16 ネットとの間で やりとりされるトラフィックを許可するということをも伝えます。 192.168.11.0 ネットに対しても同様です。これらの最後 2 つは双方向の規則で、 これは双方向にやりとりできるよう経路を定めるためには重要なことです。
自宅ユーザにとっては、ここまでで全てがうまく動作するでしょう。
しかし、離れた所にあるオフィスのためにはいくらか経路を設定しなくてはなりません。
まず最初に、メインルータ、すなわち Cisco に、離れた所にあるオフィス
は VPN サーバの影に隠れているということを教えてやる必要があります。
ですから Cisco に対して、離れた所にあるオフィス行きのトラフィックを
VPN サーバに送るような経路を指定してください。
それがすんだら、今度は離れたオフィスに向かうトラフィックをどうすべきか
VPN サーバに教えてやらなくてはなりません。
これをするには route
コマンドをサーバで実行します。
route
コマンドを動作させる上での唯一の問題は、
リンクは確立されていなくてはならず、もし切れてしまうと経路が失われて
しまうということです。解決策は、クライアントが接続してきたら
経路を追加してやる、あるいは、route コマンドは必要以上に実行しても問題無いので、
より簡単な方法としては、それを度々実行してやることです。
では、スクリプトを作成して、数分毎に実行されるようそれを crontab
に加えてください。その中には次のように書いてください -
/sbin/route add -net 192.168.11.0 gw 192.168.10.253 netmask 255.255.255.0 /sbin/route add -net 192.168.10.0 gw 192.168.11.253 netmask 255.255.255.0
pppd
を設定する
さて今度は VPN 接続を取り扱うためにサーバの pppd を設定しましょう。 もしこのサーバを、ダイヤルアップユーザを処理するのに使っている、 あるいはあなた自身がダイヤルするのに使っているのであれば、これらの 変更がそれらのサービスに影響を与えるかもしれないということを覚えて おくべきです。このセクションの最後で、いかにして衝突を回避するか検討 します。
/etc/ppp/
このディレクトリにはたくさんのファイルがあるかもしれません。多分
あなたは既に、options
と呼ばれるファイルを持っている
でしょう。このファイルには pppd
に対する大域的なオプション
の全てが入っています。これらのオプションは pppd
の
コマンドラインで無効にすることはできません。
/etc/ppp/options
options
ファイルは少なくとも次のような記述を
含んでいるはずです -
ipcp-accept-local ipcp-accept-remote proxyarp noauth
最初の 2 行は pppd
に、他の端が IP アドレスとして指定したものを
受け入れるよう指示します。これは離れた所にあるオフィスに接続するときには
必要ですが、しかし自宅のユーザに接続しているのならば無効にすることができます。
それはサーバがアドレスを割り当てることを妨げはしませんので有効にしておいて
構いません。それはクライアントが求めてきたことを受け入れて良い
ということを伝えるだけです。
3 行目は非常に重要です。pppd
のマニュアルページによると -
proxyarp このシステムの ARP [Address Resolution Protocol] テーブルに対して ピアの IP アドレスとこのシステムのイーサネットアドレスを付け加えます。 これによって、ピアが他のシステムから見てローカルなイーサネットに あるように見えるという効果がもたらされます。
それが為されていなければ ローカルなトラフィックがトンネルを通って 戻って来れなくなるため、これは非常に重要です。
最後の行も同じく重要です。これは pppd
にユーザ名とパスワード
無しで接続を許すよう指示します。これは sshd
によって既に
認証が為されているので安全です。
もしあなたが pppd
で他のサービスを扱っているなら、それらの
他のサービスの設定は VPN システムが必要としているものとは異なっているかも
知れないということを考えてみるべきです。pppd
は
/etc/ppp/options
メインオプションファイルの中のオプション
は実行時に指定されたオプションによって無効にできないように設計されて
います。これはセキュリティ上の理由に拠ります。衝突を避けるため、
どのオプションが衝突を起こしているか特定して下さい。そしてそれらを
メインファイルから pppd
の特定のアプリケーション実行中に
ロードされる分離されたオプションファイルに移してください。
sshd
を設定する
次に挙げるのは私の /etc/sshd_config
ファイルの内容です。
あなたのファイルも、同じか、または似た形式をしているはずです -
# This is the ssh server system wide configuration file. Port 22 ListenAddress 0.0.0.0 HostKey /etc/ssh_host_key RandomSeed /etc/ssh_random_seed ServerKeyBits 768 LoginGraceTime 600 KeyRegenerationInterval 3600 PermitRootLogin yes IgnoreRhosts yes StrictModes yes QuietMode no FascistLogging yes CheckMail no IdleTimeout 3d X11Forwarding no PrintMotd no KeepAlive yes SyslogFacility DAEMON RhostsAuthentication no RhostsRSAAuthentication no RSAAuthentication yes PasswordAuthentication no PermitEmptyPasswords no UseLogin no
気をつけておくべき重要な点は、パスワード認証は "r" サービス全て
において無効になっているということです。私は、メールチェックやその日の
メッセージも、クライアント側から pppd
を混乱させ得るので
無効にしています。root ログインは許可していますが、それはキーなしには実行できないため、
十分に安全です。
次はユーザアカウントを設定します。
vpn-users
グループを追加する実行してください。
# /usr/sbin/groupadd vpn-users
では /etc/group
ファイルを cat して最後の行を見てください。
それは vpn-users グループのためのエントリになっているはずです。
3 番目のフィールドに注意してください。これはグループ ID (GID) です。
すぐに必要になるのでそれを書き留めておいてください。
この例では GID は 101 です。
vpn-users
のホームディレクトリを作る私たちはユーザ全てのために一つのホームディレクトリを使おうとしています。 では実行してください -
# mkdir /home/vpn-users
.ssh
ディレクトリ.ssh
ディレクトリを vpn-users
ホームディレクトリ
の中に作成します。
# mkdir /home/vpn-users/.ssh
さて面白い部分にやってきました。これから /etc/passwd
ファイルを
手で編集するわけです。:) 通常はシステムに操作させるファイルなのですが、
こういう変わった設定を行うときには自分で書き換える方が簡単です。
最初に /etc/passwd
ファイルを開いてそこに何があるか
見てみましょう。ここは次の例のようになっているはずです -
.... nobody:x:65534:100:nobody:/dev/null: mwilson:x:1000:100:Matthew Wilson,,,:/home/mwilson:/bin/bash joe:*:1020:101:Joe Mode (home),,,:/home/vpn-users:/usr/sbin/pppd bill:*:1020:101:Bill Smith (home),,,:/home/vpn-users:/usr/sbin/pppd frank:*:1020:101:Frank Jones (home),,,:/home/vpn-users:/usr/sbin/pppd ....
殆どのシステムに最初の行のユーザが見つかるでしょう。
2 番目のユーザは私です。:) その次は何人かの作成された vpn-user です。
最初のフィールドはユーザ名で、2 番目はパスワードのフィールドです。
3 番目はユーザ ID (UID) で 4 番目はグループ ID (GID) です。
つづく 5 番目のフィールドは各ユーザの個人情報です。
6 番目のフィールドはユーザのホームディレクトリで、最後は彼らのシェル
です。ご覧のとおり、各フィールドはコロンで区切られています。最後の
3 行を見てください。それらの間での唯一の違いは、最初のフィールドの
ユーザ名と、5 番目のフィールドのユーザ情報です。やりたいのは、
各ユーザに対してこのような行を作成することです。接続全てに単一の
ユーザを使わないでください。もしそうすると、彼ら個々を
見分けることはできなくなります。そこで、上に示したような内容になるよう、
このファイルの最後の行をコピーしてそれを編集してください。2 番目の
フィールドにアスタリスク (*) があることを確認してください。3 番目の
フィールドは、そのファイルの他の ID 全てと違っているべきです。
私は 1020 を使いました。普通 1000 未満はシステムの利用のために
予約されていますので、それ以上を使うべきです。
4 番目のフィールドは vpn-user のグループ ID のはずです。私は
書き留めておくよう言いました。それが必要なときがやってきました。
ではグループ ID をそこに入れてください。最後に、ホームディレクトリを
/home/vpn-users
、シェルを /usr/sbin/pppd
に変更してください。できました。ではその行を他のユーザを作成するために
コピーしてください。1 番目と 5 番目のフィールドを編集して設定するだけです。
ユーザアカウントに対してこのシステムを利用することの利点の一つは、 UNIX ユーザ管理コマンドを利用することができるということです。 クライアントはユーザとしてログインしていますので、あなたはユーザの統計を 得るために標準的な方法を使うことができます。次に挙げるのは、全てが どうなっているのか見るために私が好んで使っている、少数のコマンドです。
現在ログインしているユーザ、それから彼らが何時、どこ (名前か IP) から、 どのポートでログインしたかを表示します。
このコマンドは現在ログインしている人についてより広範囲なリストを表示します。
それはシステムの利用時間と平均負荷も知らせてくれます。またユーザの、
アイドル時間を含む現在のプロセス (VPN クライアントにとっては -pppd の
はずです)、それから現在のプロセスを含む全てのプロセスの CPU 利用方法も
表示します。これ以上の情報については w
のマニュアルページを
読んでください。
これは指定されたユーザ、あるいはユーザ名が指定されなければ全ての
ユーザのログイン履歴を表示します。それはユーザがログインしていた時間、
あるいはユーザがまだログインしていることを示すので、トンネルがいかに
うまく動作しているか確かめるには最も便利な方法です。システムが長い
時間 起動しつづけていると、このリストは非常に長くなり得るという
ことを警告しておきます。パイプは grep
あるいは head
を通って、知りたいことを確実に見つけます。
/home/vpn-users/.ssh/authorized_keys
ファイルを変更して、
接続を許可するユーザを制御することもできます。もし
そのユーザの公開キーの行をこのファイルから削除すると、彼らはログインする
ことができなくなるでしょう。
クライアントに移りましょう。最初に、必要とする機能全てをサポートできるように、 カーネルを再構築しなくてはなりません。最低限求められるのは、カーネル内に ppp を 組み込むことです。その後、他のマシンに対してトンネルへのアクセスを 許可しようとしている場合に限ると、フォワーディング、ファイアウォール、ゲートウェイ機能が 必要となるでしょう。この例では、例として示したレイアウトの中の、離れたところにあるオフィスの マシンのうちの一台を設定することにします。 次に挙げるオプションを追加してください。繰り返しになりますが、 もしあなたが以前にカーネルを構築したことがないのであれば、 Kernel HOWTOを読んでください。 [訳注:日本語訳は http://www.linux.or.jp/JF/JFdocs/Kernel-HOWTO.html にあります。]
2.0 カーネルに対して -
2.2 カーネルに対して -
さて、クライアントボックスを設定しましょう。外部ネットワークの 設定が済んで、それが動作していると想像しましょう。今度は、 イントラネットをサービスするためにクライアントの内部インターフェースを 設定することになるでしょう。
まず最初に内部ネットワークインターフェースを設定する必要があります。
これをやるには次を /etc/rc.d/rc.inet1
(あるいはそれに
相当する) ファイルに追加してください -
2.0 カーネルに対して -
/sbin/ifconfig eth1 192.168.10.253 broadcast 192.168.10.255 netmask 255.255.255.0 /sbin/route add -net 192.168.10.0 netmask 255.255.255.0 dev eth1
2.2 カーネルに対して -
/sbin/ifconfig eth1 192.168.10.253 broadcast 192.168.10.255 netmask 255.255.255.0
離れた所にあるオフィスを設定するために、トンネルを通して
双方向にトラフィックが行き来することを許すようなフィルタ規則を設定
した方がよいでしょう。
次に挙げる行を /etc/rc.d/rc.inet1
(またはそれに相当する) ファイルに追加してください -
2.0 カーネルに対して -
/sbin/ipfwadm -F -f /sbin/ipfwadm -F -p deny /sbin/ipfwadm -F -a accept -b -S 192.168.10.0/24 -D 192.168.0.0/16
2.2 カーネルに対して -
/sbin/ipchains -F forward /sbin/ipchains -P forward DENY /sbin/ipchains -A forward -j ACCEPT -b -s 192.168.10.0/24 -d 192.168.0.0/16
あなたは、これらの行がサーバにあるものと似ていることに 気づいたかもしれません。なぜかというとそれは同じものだからです。 この規則はまさに、これらの 2 つのネットワークの間でトラフィックが 向かうことができる場所を述べています。
唯一必要な特別の経路はトンネルを構築するスクリプトによって 作られます。
pppd
を設定する
クライアントの /etc/ppp/options
ファイルを編集する必要は
全くないかもしれません。"auth" オプション、あるいは他の特権オプション
が与えられた場合はその必要があるでしょう。やってみて駄目だったら、不正な
/etc/ppp/options
が動作するでしょう。
どれ(もしそれが明白でなければ)がおかしくしたのかを見つけるために、
古いファイルからオプションを追加しつづけ、それを回避できるかどうか見極めてください。
それらは全く必要ないかもしれません。
あなたが pppd
を他のことに使っていなければ、多分必要ないでしょう。
ssh
を設定する
クライアントの root で次の行を実行してください -
# mkdir /root/.ssh # ssh-keygen -f /root/.ssh/identity.vpn -P ""
これは .ssh
ディレクトリに identity.vpn
と
identity.vpn.pub
の 2 つのファイルを作成するでしょう。
最初はあなたのプライベートキーで、そのままにしておくべきです。
暗号化されたセッションを通すのでない限り、ネット上でこれを絶対に送信しないで
ください。2 番目のファイルはあなたの公開キーで、あなたが他のシステムにアクセス
することを許可するだけで、あなたのシステムに入るために使うことはできないので、
これは何処でも好きなところへ送ることができます。
それは実際のキーを 1 行含むテキストファイルです。行の最後は、キーを壊すことを
怖がらずに変更できるコメントフィールドです。
例えばキーは次のようなものです -
1024 35 1430723736674162619588314275167.......250872101150654839 root@vpn-client.mycompany.com
実際にはそれよりかなり長いですが、全部を見せたとしてもページには
そぐわないでしょう。サーバの /home/vpn-users/.ssh/authorized_keys
ファイルにキーをコピーしてください。1 行あたり 1 つのキーがあり、
各キーが複数行にまたがって壊れていないことを確認してください。
どの行がどのユーザに対応するのか思い出す助けになるよう、コメントフィールド
全てを好きなように変更することができます。私はそうすることを強く勧めます。
では VPN サーバに実際に接続してみましょう。まず、単一の接続を行い、
ssh
のknown_hosts ファイルの設定をする必要があります。
これを実行してください -
# ssh vpn.mycompany.com
接続を続けたいかどうか質問されたときに ''yes'' と答えてください。 サーバは ''permission denied'' と言うかも知れませんが、大丈夫です。 サーバに対して、接続スクリプトの中で使っているのと同じ名前を 使うということは重要です。では、次の行を実行してください。 きっと、設定を適合させるためにオプションの殆どを変更する必要が あるでしょう。
# /usr/sbin/pty-redir /usr/bin/ssh -t -e none -o 'Batchmode yes' -c blowfish -i /root/.ssh/identity.vpn -l vpn-user vpn.mycompany.com > /tmp/vpn-device (10 秒ほど待ちましょう) # /usr/sbin/pppd `cat /tmp/vpn-device` 192.168.10.254:192.168.40.254
pppd の行で指定されている IP アドレスに注意してください。最初はトンネルの クライアント側の端のアドレスです。2 番目はトンネルのサーバ側の端のアドレスで それはサーバの内部アドレスになっています。もしそれらの全てが動作 しているようなら、続けてください。もしそうでないなら、指定した オプション全てに対して、それらが正しくつづられているかチェックして ください。もしまだ何かがうまくいかないなら、 落とし穴 セクションをチェックしてみてください。
では、経路を、トンネルを通してトラフィックを送るように設定してください。 これを実行するだけです -
# /sbin/route add -net 192.168.0.0 gw vpn-internal.mycompany.com netmask 255.255.0.0
これでトンネルの他端にあるマシンと通信できるようになっているはずです。
やってみてください。すんなりいった? もしうまく動かないなら、
どこに問題があるのかを突き止めるためにping
や traceroute
を使ってみてください。もし実は動いているなら、スクリプトがあなたのために
その仕事をしてくれるよう設定を続けてください。
私が ここ で示した vpnd スクリプトを使ってください。 ただ、少し変更する必要があります。次の変更を行ってください -
bash スクリプトは普通安定していますが、失敗することが知られています。
vpnd
スクリプトが動作を続けていることを確かめるためには、
クライアントの crontab に check-vpnd
スクリプトを起動する
エントリを追加してください。私は 5 分かそこいら毎に私のものを起動
しています。もし vpnd
が本当に実行されているとしても、
check-vpnd
はそれ程多くの CPU を使用しません。