ずっと懸案事項になっていた、実家とのLAN間接続VPNをついに構築した。
VPNには具体的な利用形態で2つに大別される。
一つは
リモートアクセスVPN。外出先から社内ネットワークにセキュアにアクセスする、というのが典型例。この場合、社外ネットワークにある端末が社内ネットワーク上に存在するかのように振舞う。PPTPが典型例で、リモートアクセスであるが故に端末毎に接続のための設定が必要。これは、2年前に既に導入済である。
もう一つは
LAN間接続VPN。これはネットワーク同士をVPNトンネルで結ぶもので、企業の拠点間通信に使われるのはこっち。ネットワーク同士が接続されるので、設定が必要なのはVPNゲートウェイだけで、端末毎には不要。今回導入したのはこっち。
実際のところはPPTPでもLAN間接続VPNを構築できるようなのだが、PPTP自体がLinuxの世界ではマイナーな存在であり、認証がCHAPベースなので常時接続に向いているとは言い難い。Windows端末接続用サーバとしては非常に良い働きをするが。
ではIPSecはどうかというと、コイツは動的IPアドレスとの親和性が高くないのである。カーネル2.6に取り込まれたのに、どうもあまり活用されていない気がする。使うにしてもハードウェアルータで拠点間(固定IP同士のインターネットVPNかIP-VPN)接続に使うイメージだろうか? 積極的にLinuxでIPSecを使おうという動きはあまり見られないなぁ。
で、OpenVPN。コイツはWindows、MacOS、Linux、*BSDで動作し、OpenSSLライブラリで暗号化を行う。リモートアクセスVPNもLAN間接続VPNもサポート。おまけにDynamicDNSのホスト間でもバッチリ使えるというスグレモノ。流石にリモートアクセスVPNには専用の接続ソフトが必要だが、OpenVPN自体のアドバンテージが大きいのであまり気にならない。
今回は実家と自宅、OmoikaneとCasperをOpenVPNで結び、LAN間接続VPNを構築した。自宅側をAmatsuではなくCasperにしたのは負荷分散のため。接続モードにはブリッジモードとルーティングモードの2種類があり、このうちルーティングモードを選択。
【0】カーネルモジュールの確認とポートマッピング設定 OpenVPNではtun(レイヤ3)かtap(レイヤ2)を使うので、これがカーネルモジュールとして作成されているかを確認する。
#modprobe tun
#modprobe tap
でエラーが出なければOK。エラーが出るときはカーネルモジュールがないので、カーネルとカーネルモジュールを作り直す。
OpenVPNで使うのは5000/TCPと5000/UDPだから、これがmythril.ne.jp側とmythril.jp側でそれぞれCasperとOmoikaneにマッピングされるよう、ADSLモデムにポートマッピング設定を仕込む。
【1】OpenVPNのインストール まずは関連ライブラリから。OpenSSLとLZOをそれぞれのdevelパッケージも一緒にインストールする。OpenSSLは言わずもがなの暗号化ライブラリで、LZOは圧縮ライブラリ。LZOはOpenVPNを使う上ではインストール必須ではないが、スループット向上のためにインストールしておく。
最新版は2.0で、
OpenVPNのウェブサイトからtarボールをダウンロード可能。これにはRPMパッケージ作成用のSPECファイルが入っているので、
#rpmbuild -tb [OpenVPNのパッケージ]
でRPMパッケージを作成できる。あとはrpmコマンドでいつもどおりインストールしてやればよい。
【2】OpenVPNの設定 セキュリティレベルはTLSを利用した方が上だが、まずはお手軽な事前共有鍵を使ってみる。以下のコマンドで事前共有鍵を作成する。
#openvpn --genkey --secret [任意の事前共有鍵名]
#chmod 600 [事前共有鍵]
設定はCasperは
こんな感じで、Omoikaneは
こんな感じである。ifconfigとrouteの設定もOpenVPNの設定ファイル内に書けばOK。
・Casperは192.168.1.0/24、Omoikaneは192.168.2.0/24。
・CasperとOmoikaneを172.16.1.0/24のVPNトンネルで結ぶ。
・Casperのtun0には172.16.1.1を、Omoikaneのtun0には172.16.1.2を割り付ける。
・Casperには192.168.2.0/24へのゲートウェイとして172.16.1.2を、Omoikaneには192.168.1.0/24へのゲートウェイとして172.16.1.1を、それぞれルーティング設定。
【3】iptablesの設定 /etc/sysconfig/iptablesに以下を加筆。
##Casper##
#tunを192.168.1.0/24にマスカレード
-A POSTROUTING -o tun0 -s 192.168.1.0/24 -j MASQUERADE
#eth0を172.16.1.0/24にマスカレード
-A POSTROUTING -o eth0 -s 172.16.1.0/24 -j MASQUERADE
#tap0とtun0をフォワード
-A FORWARD -i tap0 -j ACCEPT
-A FORWARD -i tun0 -j ACCEPT
#tap0とtun0のパケットの通過を許可
-A RH-Firewall-1-INPUT -i tap0 -j ACCEPT
-A RH-Firewall-1-INPUT -i tun0 -j ACCEPT
#OpenVPNで使うTCPポート5000番とUDPポート5000番のパケットの通過を許可
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 5000 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m udp -p udp --dport 5000 -j ACCEPT
##Omoikane##
#tunを192.168.2.0/24にマスカレード
-A POSTROUTING -o tun0 -s 192.168.2.0/24 -j MASQUERADE
#br0を172.16.1.0/24にマスカレード
-A POSTROUTING -o br0 -s 172.16.1.0/24 -j MASQUERADE
#tap0とtun0をフォワード
-A FORWARD -i tap0 -j ACCEPT
-A FORWARD -i tun0 -j ACCEPT
#tap0とtun0のパケットの通過を許可
-A RH-Firewall-1-INPUT -i tap0 -j ACCEPT
-A RH-Firewall-1-INPUT -i tun0 -j ACCEPT
#OpenVPNで使うTCPポート5000番とUDPポート5000番のパケットの通過を許可
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 5000 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m udp -p udp --dport 5000 -j ACCEPT 最初Omoikaneのbr0をeth0にしておいたのだが、これだとパケットがOmoikaneより先に行かない。実際に生きているネットワークインターフェースはbr0だから、これを割り付けないといけない。これ気づかず暫くハマった。
【4】デフォルトゲートウェイへの静的ルーティング設定 iptablesの設定まで終えればLAN間接続VPNとしては一応使えるのだが、端末毎にルーティングの設定を仕込まないと上手くパケットが流れない。それでは面倒なので、それぞれのLANのデフォルトゲートウェイ(ADSLモデム)に静的ルーティングの設定を加える。
・Casper側
192.168.2.0/24のゲートウェイは192.168.2.80(Omoikane)
・Omoikane側
192.168.1.0/24のゲートウェイは192.168.1.30(Casper)
それぞれ、VPNの向こう側への通信はVPNゲートウェイ(CasperかOmoikane)に投げられるようになる。これをデフォルトゲートウェイに仕込めば、LAN配下にある全端末に追加で設定を加える必要ななくなる。
【5】DNSサーバのフォワード設定とリゾルバの再設定 静的ルーティングまで仕込めばIPアドレスベースで通信可能になっているが、mythril.ne.jpゾーンとmythril.jpゾーンで自分とは異なるゾーンにあるホスト名の名前解決ができない。これは双方に設置されているDNSサーバにもう一方のゾーンを新規に設定してやれば解決する。しかしこれでは非常に面倒なので、お手軽な解決法として、異なるゾーンの名前解決はそれが属するゾーンのDNSサーバにフォワードを掛けるようにした。
・mythril.ne.jp(192.168.1.0/24)側の設定 名前解決対象がmythril.jpのときのみOmoikaneにフォワード、172.16.1.0/24からのクエリ要求を許可。
・mythril.jp(192.168.2.0/24)側の設定 名前解決対象がmythril.ne.jpのときのみCasperにフォワード、、172.16.1.0/24からのクエリ要求を許可。
具体的には以下の記述を/etc/named.conf(もしくは/var/named/chroot/etc/named.conf)に加える。
zone "フォワードを掛けるドメイン" {
type forward;
forwarders {フォワード先DNSサーバIPアドレス;};
}; 逆引きは不要だから、それぞれVPN先のホスト名を名前解決できればよい。
※フォワード対象を限定しないと、自分で名前解決できないホスト名を全てフォワードしてしまい(=毎回VPN越しに名前解決される)、DNS応答のパフォーマンスが著しく低下する。 クエリ要求の許可は/etc/named.confでallowディレクティブにネットワークアドレスを加えるのみ。最初はここを192.168.1.0/24と192.168.2.0/24にしたのだが、クエリ要求は172.16.1.0/24で出されている(※エラーログで把握)ので、このような設定になる。
あとはリゾルバ(/etc/resolv.conf)で双方のゾーンのプレフィックスとDNSサーバを追記すればよい。
search mythril.ne.jp
search mythril.jp
nameserver 192.168.1.120
nameserver 192.168.1.30
nameserver 192.168.2.80これでOK。ホストによってプレフィックスとネームサーバの記述の上下関係が若干異なるが、この記述が全て入っていれば基本的に問題ない。
ここまですると、ホスト名ベースでVPN越しの通信ができるようになる。バックグラウンドで動作しているので、VPNを意識することなく使える。自宅LAN内ホストと同様の動作で実家のリソースを使えるようになった(逆も然り)ので、頗る便利だ。