Ubuntu Weekly Recipe

第329回 VPSとLXCとOpenVPNで仮想プライベートネットワークを構築する

この記事を読むのに必要な時間:およそ 12 分

WebDAVサービスの設定

ここまでで,Android上のOpenVPNクライアントとホームサーバー上のOpenVPNクライアントが,VPS上のOpenVPNサーバーを経由してインターネット越しに接続できるようになりました。これでようやく下準備が完了です。

次にホームサーバー上のopenvpn-clientコンテナに,WebDAVをインストールして,Android端末からOpenVPN経由でファイルの閲覧やアップロードをできるようにしてみましょう。

nginxとWevDAVの導入

WebDAVはHTTPサーバーに拡張を追加することで導入できます。今回はnginxを使ってみます。nginxは本体にもWebDAV機能は実装されているのですが,いくつかのメソッドが未実装です。そこで他のメソッドにも対応したnginx-dav-ext-moduleを追加します。幸い,Ubuntuのリポジトリにはこのモジュールや他の拡張モジュールが追加された,nginx-extrasパッケージが存在しますので,それをインストールしましょう注7)⁠

openvpn-client$ sudo apt install nginx-extras

次に必要なディレクトリを作成し,設定ファイルを編集しましょう。

openvpn-client$ sudo mkdir -p /var/www/webdav
openvpn-client$ sudo chown -R www-data: /var/www
openvpn-client$ sudo editor /etc/nginx/sites-available/webdav
server {
    listen      80 default_server;
    listen      [::]:80 default_server ipv6only=on;

    root /var/www/webdav;
    charset utf-8;
    autoindex on;

    allow 10.8.0.0/24;
    deny all;

    location / {
        dav_methods PUT DELETE MKCOL COPY MOVE;
        dav_ext_methods PROPFIND OPTIONS;
        dav_access user:rw group:rw all:r;
        client_body_temp_path  /tmp/webdav;
        create_full_put_path on;
    }
}
openvpn-client$ sudo rm /etc/nginx/sites-enabled/default
openvpn-client$ cd /etc/nginx/sites-enabled/
openvpn-client$ sudo ln -s ../sites-available/webdav

client_body_temp_pathは,大きなファイルをPUTするときに発生する巨大なbodyデータを一時的に保存する場所を指定しています。さらにVPNの内側(10.8.0.0/24)からのアクセスのみを許可し,それ以外を拒否しています。

今回はドキュメントルートをWebDAVのルートに設定するために,default設定を削除しています。特定のディレクトリ以下のみを公開したい場合は,defaultを消す必要はありません。

最後にconfigtestで設定ファイルをテストし,問題なければ再読み込みします。

openvpn-client$ sudo service nginx configtest
openvpn-client$ sudo service nginx reload
注7)
nginxは比較的リリース周期が短いので,公式リポジトリのバージョンが古い場合も存在します。もし新しいバージョンを使いたいのであれば,非公式ではあるもののnginxのPPAを使えば最新のバージョンをインストールできます。

WebDAVのテスト

WebDAVが動作しているかcURLでテストしてみましょう。

openvpn-client$ curl -T - http://10.8.0.2/matsuya.json <<END
{ hash: '#matsuyanow' }
END
openvpn-client$ curl http://10.8.0.2/matsuya.json
{ hash: '#matsuyanow' }
openvpn-client$ curl -X MKCOL http://10.8.0.2/matsuya/
openvpn-client$ curl -X MOVE --header 'Destination: http://10.8.0.2/matsuya/matsuya.json' \
    http://10.8.0.2/matsuya.json
openvpn-client$ curl -X PROPFIND http://10.8.0.2/matsuya/ -H "Depth: 1" \
    -d '<?xml version="1.0"?><a:propfind xmlns:a="DAV:"><a:prop><a:resourcetype/></a:prop></a:propfind>'
AndroidからならESファイルエクスプローラーを使えば簡単にWebDAVをマウントできます。スライドメニューのネットワークから「FTP」を選択し,新規ボタンで「webdav」を選びます。あとはサーバー名を指定するだけでWebDAVを使ってファイルの閲覧やアップロードができます。

図4 ESファイルエクスプローラーでファイルリストの表示

図4 ESファイルエクスプローラーでファイルリストの表示

もちろん表示されているファイルはIntentで他のアプリから閲覧できます。写真フォルダーをフォトビューワーでギャラリー表示して編集したり,動画ファイルを好みのプレイヤーで再生するといった,普通のフォルダーと同じ操作が可能です。

ホストディスクのマウント

ホストのディスクをコンテナにbind mountしておけば,WebDAVのデータをホストと共有できます。たとえばホスト上に/var/www/webdavが存在し,それをopenvpn-clientコンテナのWebDAVサーバーで公開したいとしましょう。/var/lib/lxc/openvpn-client/fstabに以下の行を追加します。

/var/www/webdav var/www/webdav none bind,create=dir

これにより,WebDAVにアップロードされたファイルはホストの/var/www/webdavに保存されますし,ホスト上からファイルを直接編集できるようになります。

もしコンテナ内部で,NFSやext4でマウントしたい場合は,AppArmorの設定を変える必要があります。LXC用のAppArmorのプロファイルは,特定のファイルシステムしかマウントを許可していないからです。そこでホスト上で,新しいプロファイルを作成し,そこでNFSやext系のマウントを許可してみましょう。

$ sudo cp /etc/apparmor.d/lxc/lxc-{default,openvpn-container}
$ sudo editor /etc/apparmor.d/lxc/lxc-openvpn-container
    profile lxc-openvpn-container flags=(attach_disconnected,mediate_deleted) {
        (上のプロファイル名を変更)
        (中略)
        (以下の4行を追加)
        mount fstype=nfs,
        mount fstype=nfs4,
        mount fstype=rpc_pipefs,
        mount fstype=ext*,
$ sudo apparmor_parser --replace /etc/apparmor.d/lxc-containers
$ sudo editor /var/lib/lxc/openvpn-client/config
    (以下の2行を追加)
    # Allow mount nfs and ext file systems
    lxc.aa_profile = lxc-openvpn-container

これでopenvpn-clientコンテナを再起動すれば,NFSやext4のマウントができるようになっているはずです。

DockerやJujuでも

LXCを使うといろんなものをコンテナの中に閉じ込めることができます。いざとなれば/var/lib/lxcの下を消しさえすれば,それまでにトライアンドエラーを繰り返すことでしっちゃかめっちゃかになったファイルシステムをばっさり削除できるのです。このメリット自体はKVMや他の仮想環境でも同じではあるもの,LXCの場合は仮想環境の作成や起動,終了がとても高速なので,いろんなソフトウェアをテストするには持って来いの環境になります。

今はやりのDockerはLXCと同じように,Linuxカーネルのcgroupやnamespaceを利用して隔離空間を構築することができます。単にOpenVPNをデプロイするだけであれば,おそらくDockerを使うほうが簡単でしょう。OpenVPN用イメージを作るためのDockerfileも存在します。

デプロイと言えば,UbuntuのJujuも今回行ったような設定作業を簡素化するツールの1つです。JujuにもOpenVPN用のCharmが存在しますので,シンプルな設定であればコマンド一発でデプロイ可能です。ちなみにOpenVPNのCharmは,ユーザーを追加するとクライアント証明書アーカイブが自動生成される仕組みになっていますので,証明書の作成が面倒だったらCharmを使うのも良いでしょう。

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。