VPNによる認証付LANの構築

以下のテキストは、執筆時当時の情報を元に書いたものであり、 現在の情勢にそぐわないことを含む場合があるので注意されたい。 また、テキストは最終提出原稿で校正を経る前のものなので、実際にUNIXUSER 本誌に記載されたものとは異なる。誤字脱字等そのままである。

致命的な誤り以外は加筆修正等は行なわないので情報の鮮度に気をつけつつ 利用して欲しい。

目次


======================================================================
■■■ Part 4  VPNによる認証付LANの構築 ■■■
					東北公益文科大学 広瀬雄二
						  yuuji@yatex.org
======================================================================

安価な常時接続環境が整ってきて、家庭や小中事業所のLANがインターネットに
つねに接している状況が当たり前になった。

いわゆる「ブロードバンドルータ」の類も、パケットフィルタリング機能を備え
たものがほとんどで、外部からの攻撃から内部(LAN)を守ることが容易にできる
ようになっている。ただしこれが前提としているのは、「外部のインターネット
から内部のLANを守る」というものであり、無線LANのような「内部すら危険」と
いう前提を置かなければいけないものは(WEPなどの)別の方策を利用する必要が
ある。

Part4ではこれまでの「LAN」の概念を考え直し、「あらゆる物理回線は危険だ」
との前提の元に無線LAN機器以外にも適用できる認証付LANの構築方法を紹介する。


■
■ 認証機構としてのVPNの利用
■

実のところ、筆者は自分の管理するLANの無線機器では802.1Xはおろか、
WEPすら利用していない。それはなぜか。

【802.1X】
    * 利用できる機器とOSが限られている
    * 将来の無線LANで802.1Xが主流であり続けるとは思えない
    * 802.1Xは導入が面倒なわりに「無線LANのセキュリティ向上」しか
      利益がない(註 た)
【WEP】
    * ほとんどの無線LAN機器とOSで使えるが安全性は低い
    * より長いキーを使えば幾分安全だが通信速度の低下は著しい
    * やはり無線LANのセキュリティを(すこし)向上させることしか
      利益がない

---[註 た]------------------------------------------------------------
Part3でも述べた通り802.1X自体は無線LANに限定したものではない。しかし個人
レベルで導入できる機器で802.1Xの利用できるものは無線LAN-AP以外に(いまの
ところ)見当たらない。
----------------------------------------------------------------------

一番大きいのは、
	「基幹LANを構成する要素のうち、危険なのは無線LAN機器だけだ」

と分けてしまっている点で、無線LAN機器だけに特別な認証方式を導入するのは
かえって面倒なだけである。そうではなく、

	「無線LAN機器も、机の上のハブも、外部インターネットも、
	  全て同じくらい危険だ」

という前提の元に、原則として基幹LANに接続するには認証付VPNを介したものに
限るということにしたほうが管理コストはぐっと低くなる。最初の設定の手間は
かかるが、この機構を一度構築してしまえば、図【と】のような様々な物理接続
ネットワークによる複数のホストをVPNで結びつけ、図【ち】のような論理LANを
構成することができる。

---[図 と]------------------------------------------------------------


  %image: lan-phys.png

  【様々な物理回線の混在したネットワーク】

----------------------------------------------------------------------



---[図 ち]------------------------------------------------------------

  %image: lan-logical.png

  【各ホストがVPNで同一の論理LAN内に位置付けられたネットワーク】

----------------------------------------------------------------------

認証付VPNを利用したLANの構築のメリットは以下のようになる。

	* 無線LANに限らずすべての回線に応用できる
	* 既存のソフトウェアだけで実現できる
	* クライアントからLANへの通信が全て暗号化される(SSH)
	* クライアントはいつでもどこでもどの機器で繋いでも同じ方法で認
	  証可能
	* クライアントのOSを選ばない(Windows/Linux/*BSD いずれでも利用
	  可能)

このような論理LANを構成するには一台の「VPN認証サーバ」を設置し、全てのク
ライアントはそのサーバにVPN接続を依頼する形式を取ることになる。このとき
に認証サーバにて

	* 各ホストの物理ネットワークインタフェースに付与されたIPアドレス
	  (無線LANカードのIPアドレス等)からの通信は認証確立のためのパケッ
	  ト以外は全て禁止する
	* 一度確立されたVPNで生成された論理ネットワークインタフェースに
	  よる通信は許可する

というパケットフィルタリングを施すことで、認証を経ていないクライアントか
らの通信は全て遮断することができる。また、認証サーバへの認証依頼を、外部
インターネットからも行なえるように設定しておけば、出先のモバイルPC等から
でもまったく同じ設定で基幹LANに参加できることになる。


以下の説明では、物理回線の種類を吸収でき、Windowsを含めた多くのプラット
フォームで利用可能な PPP over SSH で構築するVPNを利用してLANの安全性を高
める一方法を解説する。

●PPP over SSHの利用

  プライベート/グローバルアドレスいずれであるかにかかわらず、既存のイン
  ターネット回線を用いて論理的なプライベートネットワーク回線を構築するも
  のをVPN(Virtual Private Network)という。VPNを構築する手段には様々なも
  のが存在するが、

	* 余分に導入すべきソフトウェアが少ないこと
	* 設定上の制約が少ないこと
	* 多くのOSで利用できること

  ということに着目した場合、SSHを介したPPP接続によりVPNを構築する「PPP
  over SSH」がもっとも手軽な選択肢と言える。今回紹介する方式では、

	* ppp接続プログラム(pppd または FreeBSD user-ppp)
	* SSH接続プログラム(OpenSSH)
	* IPパケットフィルタリングツール(iptables, ipfw, ipfilter等)

  の3つだけが必要で、これらはほとんどのUnixに標準装備されているといって
  良いものばかりである。ただし、以下のような点も考慮に入れる必要がある。

	(1)TCP over TCPを原因とする極端なパフォーマンス低下の恐れがある
	   【註: http://sites.inka.de/sites/bigred/devel/tcp-tcp.html
		 (Why TCP Over TCP Is A Bad Idea)
		 本誌 2003年3月号 p112 コラム
		 「VPNを構成する要素の注意点」】
	(2)SSHプロトコルのオーバーヘッドによる速度低下がある
	(3)商用パッケージではないのでサポートがなくトラブルの責任転嫁を
	   することができない

  (1)に関してはPPPを張る2ホスト間の通信路の状態に強く依存するので実際に
  試してみなければ分からない面がある。(2)に関しては、実際の通信路のスルー
  プットと、その上で確立したVPN通信路でのスループットの平均値をコラム
  【い】に載せておくので参考にして欲しい。


■
■ VPNによる認証付ネットワークの設計
■

出先のダイヤルアップ回線などから、オフィスのLANに接続するときに使う、と
いうのがVPNの主な活用法だろう。このとき、インターネットの先にあるダイヤ
ルアップ回線は「信用できないネットワーク」という風にとらえ、VPN確立に必
要なポートなどのほかはアクセスを許さない設定にしているはずである。

これとまったく同じ考え方を、無線LANアクセスポイントのセグメントや、DHCP 
解放セグメントに適用し、それらのネットワークを「信用できないネットワーク」
とみなし、VPNを介したアクセスしか認めない利用形態とする。たとえば、コン
シューマ向け無線LAN-APを利用している場合、構成されるネットワークの接続を
図【ろ】のような形態にする。

---[図 ろ]------------------------------------------------------------


	〜〜基幹LAN(普段使っているLAN)〜〜〜〜〜(10.0.0.0/24)
		|
		|(基幹LANに対するホスト名とIPアドレス)
		|vpngw 10.0.0.100
	+-------+---------------+
	|	NIC-1		|
	|   VPN認証サーバ	| !! 下流のホストからはVPN確立のための  !!
	|			| !! パケット以外はすべて通過を禁止する !!
	|	NIC-2		|
	+-------+---------------+
		|(下流に対するホスト名とIPアドレス)
		| vpnsv	192.168.11.254
		|
		|  無線LANネットワーク(192.168.11.0/24)
		|  (信用できないネットワーク)
      		|
      		|192.168.11.1
      	 +------+--------------------+
      	 | 無線LAN-AP		     |
	 | (ブリッジ接続タイプ)	     |
      	 | 100BASE-TX HUB等も持つ    |
      	 |			     |
      	 +-+--------------------+----+
	   :			| [ハブ]
	   :			|
	   :192.168.11.201	|192.168.11.202
   +------------------+	  +-----+-------+
   | 無線LAN          |	  |  有線LAN	|
   | 接続端末	      |	  |  接続端末	| .........
   +------------------+	  +-------------+

----------------------------------------------------------------------

無線LAN-AP(とハブ)の繋がるネットワークを「信用できない」ものとみなし、基
幹LANとは分離する。そのために、VPNサーバとなるホストで以下のような方針の
元にパケットフィルタリングを行なう。

	a. VPNサーバへのVPN接続開始のためのSSHポートは開ける
	b. (必要なら) ping(icmp-echo) 等を許可する
	c. 外部のインターネットに対してアクセス許可して良いと
	   思われるポートがあれば許可する(例: HTTPポート)

作業手順的には、最初にフィルタリングなしでVPN設定をしたほうが早道なので、
具体的なフィルタリング例についてはVPN構築例の説明のあとで解説しよう。


■
■ PPP over SSH によるVPN接続セットアップ
■

図【ろ】の「VPN認証サーバ」に相当するホストで、PPP over SSHの待ち受け設
定を行なう。それが完了したあとで、クライアント側の設定を行なおう。

●VPN認証サーバのセットアップ

  サーバ側の設定は

  (1)IPフォワーディングの設定
  (2)VPN接続専用ユーザの作成
  (3)PPPデーモンの待ち受け設定

  という手順で進める。
  
  (1)IPフォワーディングの設定

     ルータとして機能するよう。カーネルのIPフォワーディング機能をONにす
     る。

     # sysctl -w net.inet.ip.forwarding=1     (FreeBSD, NetBSD)
     # sysctl -w net.ipv4.ip_forward=1	      (Linux)
       (システム起動時の値は /etc/sysctl.conf に記述可能)
     # ndd -set /dev/ip ip_forwarding 1	      (Solaris)
       (ネットワークインタフェースが複数ある場合は自動的にON)
     

  (2)VPN接続専用ユーザの作成

     管理面、セキュリティ面の観点からroot権限での起動を避けてVPN接続専用
     ユーザを作成し、そのユーザ権限でVPN接続を確立させるようにしたい。こ
     こでは、

	ユーザ名:		vpn
	グループ名:		vpn
	ホームディレクトリ:	/etc/ppp/vpn

     という条件でユーザを作成しよう。

     * Solaris, Linux, NetBSD の場合

       # groupadd vpn
       # useradd -g vpn -d /etc/ppp/vpn vpn
       (Linuxの場合初期設定ファイルがコピーされるので不要なものは削除し
        ておく)

     * FreeBSD の場合

       # pw useradd vpn -g network -d /etc/ppp/vpn

  (3)PPPデーモンの待ち受け設定

     ユーザ vpn でppp接続が許可されるよう以下の設定を行なう。

     * Solaris, Linux, NetBSD(pppd) の場合

       ppp接続のパスワード認証を「無し」にすることを許可するために以下の
       内容を/etc/ppp/options ファイルに追加する(註 【ほ】)。

	privgroup vpn

---[註 ほ]------------------------------------------------------------
pppdコマンドに setuid-root がない場合は、"privgroup vpn" だけでは不十分
である(多くのLinuxの場合これに該当する)。chmod u+s /usr/sbin/pppd してお
く必要がある。これを嫌う場合は、sudo等を利用して vpn ユーザがパスワード
を打つことなくroot権限でpppdを起動できるようにしておく。
----------------------------------------------------------------------

       vpnユーザのホームディレクトリ(/etc/ppp/vpn)に、以下の内容で
       vpn.option ファイルを作成する。

	proxyarp
	noauth
	notty

       vpnユーザのホームディレクトリ(/etc/ppp/vpn)に、以下の内容で待ち受
       け時のpppd起動のためのスクリプト start-client-1.sh を作成し、実行属性
       を付与する。

	# cd ~vpn
	# vi start-client-1.sh
	(以下の内容にして保存)

	#!/bin/sh
	PATH=/usr/sbin:/bin:$PATH
	# VPN上でのサーバのIPアドレス
	MYIP=10.0.0.100
	# クライアントに与えるIPアドレス
	CLIP=10.0.0.201
	exec pppd file vpn.option ${MYIP}:${CLIP}


	(保存終了後実行属性を付与)
	# chmod +x start-client-1.sh

       スクリプト中に現れる 10.0.0.201 は、VPN接続したのちにクライアント
       ホストに与えられる基幹LANセグメント内のIPアドレスである。複数のク
       ライアントがある場合は、クライアントごとにIPアドレスの割り当てを
       決定しよう(以下のFreeBSDの場合も同様)。なお、ここで指定するPPP接
       続時のサーバのIPアドレスは、クライアントから認証要求を行なうとき
       のサーバのIPアドレスとは違うものでなくてはならない。さもないと、
       PPP接続確立後にサーバへのルーティングがPPPにより上書きされてしま
       うので結果としてPPPのやりとりができなくなってしまう。今回の例でい
       えば、
		クライアントが認証要求をするアドレス	192.168.11.254
		PPP接続確立後にサーバが持つアドレス	10.0.0.100

	のように別のアドレスを用いる。

     * FreeBSD の場合(user-ppp)

       /etc/ppp/ppp.conf ファイルに以下のようなエントリを追加する。

        vpn-default:
                allow users vpn 自分のユーザ名
                set timeout 0
                set log phase chat connect lcp ipcp command proxy
                set escape 0xff
		enable proxy
        vpn-client-1:
		load vpn-default
		# set ifaddr サーバのアドレス クライアントのアドレス
		set ifaddr 10.0.0.100 10.0.0.201

       また、vpnユーザのホームディレクトリ(/etc/ppp/vpn)に、以下の内容で
       待ち受け時のpppd起動のためのスクリプト start-client-1.sh を作成し、実
       行属性を付与する。

	# cd ~vpn
	# vi start-client-1.sh
	(以下の内容にして保存)

	#!/bin/sh
	exec /usr/sbin/ppp -direct vpn-client-1

	(保存終了後実行属性を付与)
	# chmod +x start-client-1.sh

●VPN認証クライアントのセットアップ

  クライアント側の設定は

  (1)VPN接続専用ユーザの作成
  (2)SSH接続用の鍵の作成とサーバへの転送
  (3)PPPクライアントの起動設定

  という手順になる。ただし、(1)についてはサーバ側の設定と同様の手順なの
  でここでは省略する。

  ・SSH接続用の鍵の作成とサーバへの転送

    vpnユーザの権限でssh接続用の鍵を作成する。パスフレーズは空にする。

    # su vpn
    % ssh-keygen -t dsa -f ~/.ssh/vpn2vpnsv
    (パスフレーズの入力ではそのままリターン)

    ~vpn/.ssh/vpn2vpnsv.pub に公開鍵が保存されるので、これを安全な手段
    でVPN認証サーバにコピーし、~vpn/.ssh/authorized_keys ファイルに追加
    する。サーバ上にある自分の一般ユーザのアカウントにコピーするのも手
    であろう。

    % scp ~/.ssh/vpn2vpnsv <自分の一般ユーザ>@vpnsv

    コピーした vpn2vpnsv ファイルを、**サーバ上の**
    ~vpn/.ssh/authorized_keys ファイルに追加する。

    vpnsv# su vpn
    vpnsv% mkdir -m 700 ~/.ssh
    vpnsv% cat <コピーしたvpn2vpnsv.pub>  >> ~/.ssh/authorized_keys
    vpnsv% chmod 600 ~/.ssh/authorized_keys

    クライアント側に戻り、vpnユーザがパスフレーズなしでサーバに接続でき
    るか確認する(註 【は】)。

    % ssh -2 -i ~/.ssh/vpn2vpnsv vpnsv echo OK
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The authenticity of host 'vpnsv (192.168.11.254)' can't be established.
    RSA key fingerprint is 5a:a6:d3:79:82:e9:17:4d:4b:ed:86:ce:e7:07:7b:f8.
    Are you sure you want to continue connecting (yes/no)? yes
                                                           ~~~
    OK

---[註 は]------------------------------------------------------------
SSHのリモート接続では ~/.ssh/known_hosts に登録されていないサーバに対し
て接続するとサーバの公開鍵のfingerprintとともに、接続を続けるかの確認を
取って来る。あらかじめyesと答えて known_hosts ファイルに登録する必要があ
るのでこの確認作業は省略しないようにしよう。省略するとpppデーモンがsshを
呼び出したときにyes/noの入力で接続が停止してしまう。
----------------------------------------------------------------------

    パスフレーズの入力なしで、「OK」と表示されれば鍵の生成とサーバへのコ
    ピーがうまくいっている。OKと表示されたならば、この鍵を使って、サーバ
    上のPPPスタートスクリプトを起動するためのシェルスクリプトを作成する。
    シェルスクリプトは ~vpn/vpn2vpnsv.sh としよう。

    (クライアントホストで)
    % cat > ~/vpn2vpnsv.sh <<_EOF_
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #!/bin/sh
    exec /usr/bin/ssh -x -2 -i /etc/ppp/vpn/.ssh/vpn2vpnsv vpn@vpnsv dummy
    _EOF_

    % chmod +x ~/vpn2vpnsv.sh
      ~~~~~~~~~~~~~~~~~~~~~~~

    このスクリプトは、クライアント側からサーバ側のPPPデーモンを起動す
    るためのものであり、クライアント側のPPPプログラムから「ダイヤルデバ
    イス」として利用する。

    セキュリティ確保のため、もう一度サーバ側(vpnsv)に戻り、登録した鍵を
    利用した接続ではPPP開始スクリプトしか起動できないように 
    ~vpn/.ssh/authorized_keys ファイルを変更する。

    vpnsv# vi ~vpn/.ssh/authorized_keys
	   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    先ほど追加したVPN接続用SSH公開鍵の行の先頭に

	command="./start-client-1.sh"
	no-X11-forwarding
	no-pty

    の3項目をカンマで連結して(空白なし)追加する。

    【例】
    ssh-dss AAAAB3Nza...........
	↓
    command="./start-client-1.sh",no-X11-forwarding,no-pty ssh-dss AAAAB3Nza...........

    クライアント側に戻り、~vpn/vpn2vpnsv.sh を手動で起動してみる。

	% ./vpn2vpnsv.sh
	  ~~~~~~~~~~~~~~
	~}#}!}!} }2}"}&} } } } }%}&6写}'}"}4

    PPP開始の(人間には読めない)データ列が出てくることを確認し、C-cで止め
    よう。これが出ない場合は、サーバ側の authorized_keys ファイルに誤り
    がある可能性が高い。鍵を表す文字列をターミナルソフトからコピーペース
    トしたりして、余計な改行が入るとSSH接続が全くできなくなるので確認し
    よう。


  ・PPPクライアントの起動設定

    以上で接続の準備は整った。pppプログラムを起動するだけでVPN接続が行な
    えるようになっているが、将来の運用時に便利なようにppp起動のためのシェ
    ルスクリプトを作成しておこう。

    * Solaris, Linux, NetBSD の場合(pppd)

      vpnユーザのホームディレクトリに、以下の手順で connect-vpn.sh を作
      成し、実行属性を付ける。

      % cat > connect-vpn.sh <<_EOF_
      #!/bin/sh
      exec pppd defaultroute pty /etc/ppp/vpn/vpn2vpnsv.sh
      _EOF_

      % chmod +x connect-vpn.sh

      なお、クライアントホストのデフォルトゲートウェイをVPN接続先にした
      くない場合にはpppdに渡している defaultroute オプションは削る。たと
      えば、ダイヤルアップ先からの接続には defaultroute を指定しない方が
      良いだろう。

    * FreeBSD の場合(user-ppp)

      /etc/ppp/ppp.conf にリスト【に】のエントリを追加する。

---[リスト に]--------------------------------------------------------
vpn-default:
 allow user vpn
 set dial
 set timeout 0
 set ifaddr 10.0.0.0/24 10.0.0.0/24
 add default HISADDR
vpnsv:
 load vpn-default
 set server /var/tmp/vpnsv "" 0177
 set device !/etc/ppp/vpn/vpn2vpnsv.sh
----------------------------------------------------------------------

      pppdの場合と同様、クライアントホストのデフォルトゲートウェイを変え
      たくない場合には "add default HISADDR" は削除する。

      つぎにvpnユーザのホームディレクトリに、以下の手順で connect-vpn.sh 
      を作成し、実行属性を付ける。

      % cat > connect-vpn.sh <<_EOF_
      #!/bin/sh
      exec ppp -ddial vpnsv
      _EOF_

      % chmod +x connect-vpn.sh


  ・PPPクライアントの起動

    ~vpn/connect-vpn.sh を起動することで、vpnsvに図【ろ】における基幹LAN 
    セグメントのIPアドレスが付与される。

    (クライアントホストのvpnユーザ権限で)
    % ~/connect-vpn.sh
      ~~~~~~~~~~~~~~~~
    (コンソール出力を見ながらしばらく待つ)
    % ifconfig -a
      ~~~~~~~~~~~
    としてネットワークインタフェース一覧を確認すると

    ppp0: flags=8051 mtu 1500
	inet 10.0.0.201 -> 10.0.0.100 netmask 0xff000000
	inet6 fe80::203:47ff:fe8a:9035%ppp0 ->  prefixlen 64 scopeid 0x3

    と基幹LANセグメントのIPアドレスが付与されているものが確認できるはず
    である(註 【へ】)。
---[註 に]------------------------------------------------------------
pppd であれば ppp* インタフェース、user-pppであれば tun* インタフェース
になる。
----------------------------------------------------------------------

    vpnsvのPPP起動設定では proxy arp を設定しているので、基幹LAN に所属
    する他のホストや、VPNで接続するさらに別のクライアントホストとも(みか
    け上)直接通信できるようになる。また、今回の設定例のように、クライア
    ントホストの default route をvpnsvに向けた場合は、外部に対する接続も
    すべて基幹LANを経由して出て行くことになる。

    接続確立までのエラーは

	pppd		/var/log/messages
	user-ppp	/var/log/ppp.log

    を参照して調べれば良い(設定により異なるシステムもある)。


  ・PPPの終了(VPNの切断)

    pppd の場合は起動した pppd の PID に INTまたはTERM シグナルを送る。
    user-ppp の場合は、リスト【に】においてPPPコントロールソケットファイ
    ルを /var/tmp/vpnsv に指定しているので、

	% pppctl /var/tmp/vpnsv
	  ~~~~~~~~~~~~~~~~~~~~~
	PPP ON client> quit all
		       ~~~~~~~~
    とすることでPPPセッションを終了できる。


---[コラム い スループット]-------------------------------------------

筆者の環境で VPN/PPP over SSH でLAN接続した場合と、物理ネットワーク接続
のまま通信したときのスループットを比較してみた。クライアントとサーバ間に
存在するネットワークのうちボトルネックとなる回線が100BASE-TX, 10BASE-T 
と、801.11b という3通りについてVPNなしで繋いだ場合と PPP over SSH による
VPNで繋いだ場合のスループットを比較した。サーバからクライアント方向への
HTTPによるファイル転送速度と、クライアントからサーバに対するpingのRTTを
測定した。マルチユーザモードのまま測定したのでバラツキが大きい結果だと思
われるが、大まかな参考にはなるだろう。

【VPN認証サーバ】
  CPU	Celeron 1.2MHz
  OS	Vine Linux 2.6r4 (kernel 2.4.22, pppd 2.4.1)
  SSH	OpenSSH_3.6.1p2

【クライアント】
  CPU		Celeron 700MHz
  OS		NetBSD 2.0E (pppd 2.4.1)
  SSH		OpenSSH_3.6.1 NetBSD_Secure_Shell-20030917
		(Cipherはデフォルトのaes128-cbc)


--------------------------------------------------
律速回線 100BASE-TX(100Mbps)
		http		http		ping-RTT
		(Kbps)		(Kbps)		(ms)		(ms)
		Ether		VPN		Ether		VPN
	平均	23937		15237		1.195		1.628
      標準偏差	 737.6		456.9		0.029		0.065
--------------------------------------------------
律速回線 10BASE-T(10Mbps)
		http		http		ping-RTT
		(Kbps)		(Kbps)		(ms)		(ms)
		Ether		VPN		Ether		VPN
	平均	7252		4366		0.706ms		1.414ms
      標準偏差	 6.9		580.4		0.062		0.129
--------------------------------------------------
律速回線 802.11b(11Mbps)
		http		http		ping-RTT
		(Kbps)		(Kbps)		(ms)		(ms)
		40bit-WEP	WEP無し+VPN	40bit-WEP	VPN
	平均	1255		2717		5.940		5.044
    標準偏差	210.7		32.8		0.442		0.240


10MbpsのEthernet回線をそのまま使う場合、実効で7Mbps程度出ていたものが
PPP/SSH のオーバーヘッドによって4Mbps程度に減少している。いっぽう、
802.11b回線での比較に関しては、少なくとも802.11b回線をWEPなしで使うこと
は(危険なので)あり得ないと考えて、WEP(40bits)をかけた場合と、WEPなしにし
てVPNを利用する場合を比べてみた。

表から直ちに分かる通り、802.11bでは「WEP無し+VPN」のほうが約2倍のスルー
プットが得られることが観察された。これは、WEPそのものの暗号/復号化処理の
オーバーヘッドが、SSHの暗号/復号化処理と比べて小さくないことを示している
(もちろん無線LAN-APが非力であるという要素も含まれる)。

筆者の感覚では、Webブラウズやメイルの送受信がメインで使う分には実効速度
がモデム並に低下しなければあまり気にならない。また、SSHログインなど、イ
ンタラクティブにCUIを使う接続の場合にはもともと通信量が少ないので実効速
度が1Mbps程度以上出ていればあまり不満を感じない。

以上のことを考えると、音声や動画ファイルなど、巨大なファイルのコピーを行
なう場合でなければSSHによるVPNで構築されたネットワークの利用でもそこそこ
満足できるスループットが得られるのではないかと考えられる。

もっとも、一つ付け加えるとすれば、筆者の利用している802.11gカードは(APと
の相性の問題なのか)物理回線のパケットロスが多く、VPNセッションの確立が不
安定で実用に堪えなかった。物理回線品質が低い場合はSSH接続も安定して確立
できないことがあるので、そのような場合は別の認証手段に頼らざるを得ないだ
ろう。

----------------------------------------------------------------------

■
■ Windowsクライアントからの接続
■

PPP over SSHを Windows 上で実現するモジュールが、京大マイコンクラブ「も
ぐらプロジェクト」により開発されている。これを利用することで、今回設定し
たVPNを用いた認証機構を Windows 2000や Windows XP からも利用することがで
きる。

もぐらプロジェクトのホームページ
http://www.kmc.gr.jp/proj/vpn/

より、ダウンロードリンクをたどった
http://www.kmc.gr.jp/proj/vpn/download.html
に、PPPoverSSHTool へのリンクが記載されている。本稿では、執筆時の最新版
である 0.3-pre を利用した設定例を紹介する。

	ファイル名	PPPoverSSHTool-0.3-pre.zip
	ファイルサイズ	300546バイト
	MD5値		6dd0ba92df1e81dfab5505003dfa1245

アーカイブに格納されているインストールマニュアルは、Webページにある「ド
キュメント」と同じく、PPPoverSSHTool-0.2 をベースに書かれているものなの
で、付属ドキュメントを参考にしたい場合は PPPoverSSHTool-0.2 のほうを利用
するのが良い。

●PPPoverSSHTool-0.3-preのインストール

  0.3-preのインストールはいたって簡単である。ZIPアーカイブを展開すると、
  PPPTunUtil.msi ファイルが出てくるのでこれをダブルクリック(または右クリッ
  クして「インストール(I)」を選択)するとインストーラが起動する。インストー
  ルパスや、ドライバインストールの最終的確認画面などが表示されるが、とく
  に問題はないだろう。ここではインストーラ終了後の設定について説明しよう。

  ・SSH鍵の作成とサーバへのインストール

  「スタートメニュー」→「全てのプログラム」→「PPP over SSH Tool」
  より PuTTYgen を起動する。

       [SSH2/DSA] を選択
       [Generate] をクリック
       マウスを適当に動かす

  とするとDSA鍵が生成される。生成された鍵の公開鍵文字列が内部の枠内に表
  示されて選択された状態になっているのでこれをコピー(C-c)する。

  メモ帳(notepad)などを起動して公開鍵文字列をペースト(C-v)し、保存する。

  PuTTYgenに戻り パスフレーズは何も記入しないまま "Save public key" と
  "Save private key" によりそれぞれの鍵を適当な場所に保存しておく。保存
  した場所とファイル名は覚えておく。

  メモ帳などで保存した公開鍵文字列のファイルを安全な手段で認証サーバにコ
  ピーし、Unixクライアントのときと同じ方法で ~vpn/.ssh/authorized_keys 
  ファイルに追加する(1行であることに注意)。autorized_keys に追加する1行
  の鍵が、

	ssh-dss AAAAB3NzaC1kc3MAAACAfMNlssXD...........

  のようなものだったとすると、その前に

	command="./start-client-xp.sh"

  を追加し、

	command="./start-client-xp.sh" ssh-dss AAAAB3NzaC1kc3MAAACAfMNlssXD...........

  とする。つまりこの鍵によるログインでは、自動的にサーバ側の 
  start-client-xp.sh を起動するように設定する。start-client-xp.sh スクリ
  プトは、

	#!/bin/sh
	exec /usr/sbin/pppd file vpn.option 10.0.0.100:10.0.0.202

  のようにする。コロンの前の部分が、認証サーバの基幹LANでのIPアドレスで、
  コロンより後の部分が Windows XP(または 2000)ホストに付与する基幹LAN内
  IPアドレスである。start-client-xp.sh に実行属性を付けることも忘れない。

  ・PPP接続先の設定

  「スタートメニュー」から「コントロールパネル」を開き、「クラシック表示」
  を選択すると「PPP over SSH」のアイコンがあるのでこれをクリックする。

  「追加(A)」をクリックし、適当な「接続名」を付けてから、

  「接続先ホスト」に認証サーバ、
  「ユーザ名」にvpn
  「秘密鍵の位置」に PuTTYgen から保存した秘密鍵の位置

  を埋めて、[OK]を押して完了する。

  ・SSH接続できるか確認

  Windows上で作成した鍵を利用してサーバのpppデーモンが起動できるかどうか
  を確かめるために PuTTY(註 【ぷ】) をインストールして実際に接続してみる
  のが良いだろう。PuTTYを起動し、設定ツリーの「接続」→「SSH」→「認証」
  にPuTTYgen で作成した鍵を指定し、ユーザ名vpnでサーバにログインできるか
  を確かめよう。Unixクライアントでサーバ上のpppdを起動したときと同様、
  ppp 開始データ列が表示されれば鍵の生成と、サーバ上への登録はうまく行っ
  ている。

---[註 ぷ]------------------------------------------------------------
PuTTYオリジナルサイト
http://www.chiark.greenend.org.uk/~sgtatham/putty/

PuTTYでISO2022による日本語入力・表示を可能にするパッチ
http://hp.vector.co.jp/authors/VA024651/#PuTTYkj_top

PuTTY を INIファイル対応にするパッチ
http://www007.upp.so-net.ne.jp/bemax/arita/putty.html
----------------------------------------------------------------------

  ・接続の作成

  「マイネットワーク」→「ネットワーク接続を表示する」→「新しい接続の作
  成」で、「新しい接続ウィザード」を起動する。
  「職場のネットワークへ接続」→「ダイヤルアップ接続」を選び、
  「会社名」は適当なものを入れ、
  「電話番号」に「コントロールパネルのPPP over SSH」で作成した接続名
  を間違えないように入れる。

  ・接続

  作成できた接続をクリックすると接続ウィンドウが出てくるので、
  「ユーザ名」と「パスワード」は空のまま「ダイヤル(D)」をクリック。
  以上で接続が開始する。

  %
  % ページ数に余裕があればここはもっと詳しく書きます。
  %

●サーバ側の設定

  FreeBSD user-ppp を利用する場合は待ち受けサーバ側設定はそのままで良い。
  pppdを利用する場合は、オプションファイルを別に用意する必要がある。
  今回作成したvpnユーザのホームディレクトリ(/etc/ppp/vpn)に以下の内容で
  vpn-windows.option を作成する(Unixクライアントのオプションファイルから
  notty を削除)。

	proxyarp
	noauth

  pppスタートスクリプトは、このオプションファイルを利用するように記述す
  る。その他は、Unixクライアントのときと全く同じ設定で良い。



■
■ VPN確立用パケット以外のフィルタリング
■

クライアントホストから PPP over SSH によりVPNの確立が確認できたら、すぐ
に物理インタフェース(図【ろ】では 192.168.11.* サブネット)にフィルタをか
けよう。このインタフェースに届くパケットは、SSHプロトコルのみを通過させ、
それ以外はすべて遮断するようにしておこう。これを怠ると、無線LANから基幹
LANへのアクセスが自由なものとなってしまう。

---[図 り]------------------------------------------------------------

【下流(クライアントPC側)】

   +--------------------- 物理インタフェース   +-------------------+
   |                    |   192.168.11.201     | 認証サーバ	   |
   |                    |-------------------->[ ]eth0 22/tcpのみOK |
   | クライアントホスト |		       |		   |
   |                    |-------------------->[ ]ppp0 すべてOK	   |
   |                    |  10.0.0.201	       |		   |
   +--------------------- 論理インタフェース   +-------------------+


----------------------------------------------------------------------


●SSHプロトコルのみの通過許可

  もう一度図【ろ】を確認して欲しい。認証サーバからVPN接続のみを許すよう
  にするには、

	下流ネットワーク(192.168.11.0/24)の繋がる物理インタフェースに
	来るパケットは
		ソースアドレス	192.168.11.0/24
		宛先アドレス	192.168.11.254
		宛先ポート	22/tcp

	のみを許可する

  という設定をすれば良い。VPN確立後に生じた論理インタフェース(ppp0,
  ppp1, ...)には特別なフィルタリングを行なわなくても良い。ただし、物理的
  な回線接続がうまくいっているかどうかの確認のためにping導通試験が使えな
  ければ作業効率が上がらないので、上記に加えて icmp(echo) リクエストも通
  るように設定することとする。

  以下、様々なシステムの例でフィルタリングの例を挙げよう。ただし、下記の
  例では「PPP over SSHを許可する」という項目しか記述しないので、既にパケッ
  トフィルタを稼動させている場合はそれらを考慮した上で、下記の項目をうま
  く追加するように注意して欲しい。

  ・認証サーバがLinuxの場合(iptables)
    ---------------------------------

    iptablesを利用したパケットフィルタリングの記述例を示そう。認証サーバ
    が上位ネットワーク/下位ネットワークに接続しているネットワークインタ
    フェースがそれぞれ eth0, eth1 であると仮定する(図 【ぬ】)。

---[図 ぬ]--------------------------------------------------------------------
  【Linux による認証サーバの物理インタフェース例】

  |   下位ネットワーク   +----------------------------+ 上位ネットワーク |
  |  [192.168.11.0/24]   |  [[[Linux認証サーバ]]]     | [10.0.0.0/24]    |
  +----------------------= eth1                  eth0 =------------------+
  |			 | 192.168.11.254  10.0.0.100 |		         |
  |			 +----------------------------+		         |
  |									 |
  |									 |

------------------------------------------------------------------------------

    iptablesにて、INPUT, FORWARD チェインに対する入力パケットを制限する
    例としてリスト【る】を示す。

---[リスト る]--------------------------------------------------------
#!/bin/sh
# デフォルトポリシーが ACCEPT のまま変えていないと仮定する
# 既にiptablesを使っている場合は-FによるFlushは注意
iptables -F FORWARD
iptables -F INPUT

# 確立済みTCPパケットとフラグメントパケットは通過
iptables -A INPUT -p tcp -m state --stat ESTABLISHED -j ACCEPT
iptables -A INPUT -f -j ACCEPT
iptables -A FORWARD -p tcp -m state --stat ESTABLISHED -j ACCEPT
iptables -A FORWARD -f -j ACCEPT

# 192.168.11.0/24 から自身への22/tcpを許可
iptables -A INPUT -s 192.168.11.0/24 -p tcp --dport 22 -i eth1 -j ACCEPT

# 自身に対するICMP(echo-request)を許可
iptables -A INPUT -p icmp -m icmp --icmp-type echo-request -i eth1 -j ACCEPT

# 上記以外の eth1 宛のものはすべてDROP(tcpは tcp-reset を返す)
iptables -A INPUT -p tcp -i eth1 -j REJECT --reject-with tcp-reset
iptables -A FORWARD -p tcp -i eth1 -j REJECT --reject-with tcp-reset
iptables -A INPUT -i eth1 -j DROP
iptables -A FORWARD -i eth1 -j DROP

----------------------------------------------------------------------

  ・認証サーバがFreeBSDの場合(ipfw)
    -------------------------------

    Linuxでのiptablesと同様のフィルタリングをipfw(またはipfw2)で行なう例
    を示そう。FreeBSDでの認証サーバの物理インタフェースが図【か】のよう
    になっているものと仮定する。なお、FreeBSDでも IPFilter を利用したい
    場合は、次節のIPFilterの説明を参照して欲しい。

---[図 か]--------------------------------------------------------------------
  【Linux による認証サーバの物理インタフェース例】

  |   下位ネットワーク   +----------------------------+ 上位ネットワーク |
  |  [192.168.11.0/24]   |  [[[FreeBSD認証サーバ]]]   | [10.0.0.0/24]    |
  +----------------------= fxp1                  fxp0 =------------------+
  |			 | 192.168.11.254  10.0.0.100 |		         |
  |			 +----------------------------+		         |
  |									 |
  |									 |

------------------------------------------------------------------------------

---[リスト を]--------------------------------------------------------

#!/bin/sh
# 既にipfwによるフィルタリングを使っている場合はflushは注意
ipfw -f flush

# まず確立済みTCPパケットとフラグメントパケットは通過
ipfw add allow tcp from any to any established
ipfw add allow ip from any to any frag

# 192.168.11.0/24 から自身への22/tcpを許可
ipfw add allow tcp from 192.168.11.0/24 to me 22 via fxp1

# 自身に対するICMP(echo-request)を許可
ipfw add allow icmp from 192.168.11.0/24 to me via fxp1 icmptypes 8

# 上記以外の fxp1 宛のものはすべてdeny(tcpは tcp-reset を返す)
ipfw add reset tcp from any to any in via fxp1
ipfw add deny ip from any to any in via fxp1

# 基幹LANから外部へのTCP接続許可
ipfw add allow tcp from 10.0.0.0/24 to any setup

# 以下に基幹LAN内のパケットを許可する設定が続く(サイトの事情により異なる)
ipfw add allow ip from any to 10.0.0.0/24 via fxp0
ipfw add allow ip from 10.0.0.0/24 to any out via fxp0

#重要なUDPを許可
ipfw add allow udp from 10.0.0.0/24 to any 53 keep-state
ipfw add allow udp from 10.0.0.0/24 to any 123 keep-state

# 外部から参照を許すサービスを許可(例)
# ssh
ipfw add allow tcp from any to me 22
# smtp
ipfw add allow tcp from any to me 25

# 上記以外すべてを拒否
ipfw add 65535 deny log ip from any to any
----------------------------------------------------------------------

  ・認証サーバが NetBSD, FreeBSD, Solaris 等の場合(IPFilter)
    --------------------------------------------------------

    Linux以外の主なOSで利用できる(註 よ)パケットフィルタであるIPFilterを
    利用する場合の設定例をリスト【わ】に示す。ここでは、図【か】と同様、
    下流側のインタフェースを fxp1、上流側のものをfxp0であると仮定する。

---[註 よ]------------------------------------------------------------
OpenBSDではIPFilterが外され、それに似たルールセットの文法を持つPFが導入
された。PFはIPFilterと同様「最後にマッチしたものが採用される」形式なので、
IPFilterによるルールセットとほぼ同様の構成で記述できる。
----------------------------------------------------------------------


---[リスト わ]--------------------------------------------------------
# VPN by PPP over SSH でのフィルタリングの例(IPFilter)
# このファイルを vpn-filter という名前で保存したならば
# ipf -Fa -f vpn-filter
# によってルールを登録する

# fxp1からクライアントに出て行くtcpとestablishedを通過
pass out quick on fxp1 proto tcp from any to any keep state

# fxp0, fxp1を グループ化する(物理インタフェースが変わったらここを書き換え)
# 同時にデフォルトルールをblockまたはpassにする
block in  on fxp0 all head 100
pass  out on fxp0 all head 110
block in  on fxp1 all head 200
block out on fxp1 all head 210


# 自分(192.168.11.254)宛のパケットを全てグループ201に導く
block in from any to 192.168.11.254 head 201 group 200

# 192.168.11.0/24 から自身への22/tcpを許可
# (グループ201は自分宛のみなので any to any でよい)
pass in quick proto tcp from any to any port = ssh keep state group 201

# 自身に対するICMP(echo-request)を許可
pass in quick proto icmp from any to any icmp-type echo keep state group 201

# 上記以外の fxp1 宛のtcpにtcp-reset を返す
block return-rst in quick proto tcp from any to any group 201

# 以下はお好みで…

# 基幹LANから外部へのTCP接続許可
pass out on fxp0 proto tcp from 10.0.0.0/24 to any keep state

# 基幹LANからの接続許可
pass in quick from 10.0.0.0/24 to any group 100

# 重要なUDPの通過
pass out quick proto udp from any to any port = domain keep state group 110
pass in quick proto udp from any to any port = domain group 100
pass out quick proto udp from any to any port = ntp keep state group 110
pass in quick proto udp from any to any port = ntp group 100

# 基幹LAN側インタフェースで参照を許すサービスを許可
pass in quick proto tcp from any to any port = ssh keep state group 100
pass in quick proto tcp from any to any port = smtp keep state group 100
pass in quick proto tcp from any to any port = http keep state group 100

# 上記以外のTCPは tcp-reset を返す
block return-rst in proto tcp from any to any group 100

# 以上どれにもマッチしないものはデフォルトルールに従う
----------------------------------------------------------------------

●より一層の工夫

さらにセキュリティを高めるための設定として、以下のような工夫が考えられる
だろう。

  * 認証サーバの認証用SSHポート番号を22以外に変える

    → /etc/ssh/sshd_config で、"Port 9999" などとする

  * 認証用のsshdではUnixパスワードログインを禁止する

    → /etc/ssh/sshd_config で、"PasswordAuthentication no" とする

  * PPPの認証ユーザとパスワードを設定する

    → ファイルに保存するならあまりセキュリティは変わらない…

  * SSH鍵にパスフレーズをつけ、ssh-agentと併用した接続にする

    → 電源投入後の接続は面倒になるがPCの盗難に対しては効果的

  * POP before PPPoverSSH などを構築する

    → このような「手順的認証」はPCの盗難に対してかなり有効

通信速度改善のために、pppのオプション(mtu,mru等)を調整したり、低速回線に
対してはSSHのCompressionをONにするなどの工夫も有効だろう。これを機会に、
pppdとSSHのマニュアルをじっくりと読んでみることをお勧めする。


■
■ まとめ
■
%%%%%%% 記事がショートするなら以下を追加

VPNによる論理ネットワークという概念を導入することで、「信頼できない場所」
にあるホストを一元的に基幹LANに接続することが可能となる。SSHは、実績もあ
り、手軽に利用でき、なおかつ応用範囲の広い優れたツールなので、これを活用
したさまざまな認証機構を構築することが可能である。一度構築すれば、今後ど
んな接続形態が現れても十分に対応できるだろう。もちろん、将来SSHに脆弱性
が発見される可能性もあり、そのときには PPP over SSH によるネットワークも
危機にさらされることになる。しかし、すぐに修正が施されるのもこれまでの実
績が証明していることでもあり憂慮するにはあたらないだろう。大切なのは、そ
うした情報につねに注意を向けている姿勢だろう。


yuuji@gentei.org
Fingerprint16 = FF F9 FF CC E0 FE 5C F7 19 97 28 24 EC 5D 39 BA
HIROSE Yuuji - ASTROLOGY / BIKE / EPO / GUEST BOOK / YaTeX [Tweet]