44
66

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

OpenVPNで自宅RaspberryPiサーバを公開

Last updated at Posted at 2017-07-04

Google Cloud Compute Engine の micro インスタンスが無料で使えるようになりました。みなさん使っていますか?僕は http://manga.dog/ で使っています。が、しかし、新しい機能を追加しようと思ったのですが、どうも全文検索エンジンの Elasticsearch を使わないといけないようです。そして Elasticsearch はメモリを食いまくるので現在の micro インスタンスに同居させるのはとても難しい。Amazon Elasticsearch Service を使って機能を実装してはみたのだけど、そもそも無料の micro インスタンスを使っていたので有料サービスを使うのは負けた気がする!そこで自宅に転がっていた Raspberry Pi3 に Elasticsearch を入れシステムに組み込み勝利をつかみ取ることにしました。

必要な機能

  • ラズパイで Elasticsearch を動かす
  • アプリケーションサーバから自宅のラズパイにアクセスする

このような機能が必要なのですが、まぁいわゆる自宅サーバを公開すればよいわけですね。一般的には自宅のルーターに外部からきたアクセスを特定の機器にルーティングする設定をおこなう方法だと思います。でもこの方法だと自宅のIPが変わるとアクセスできなくなってしまいます。それを回避するためにダイナミックDNSを使います。でもこの方法はかっこ悪いなと前々から思っていました。

そこで VPN を使った方法で構築したいと思います。全体の構成はこのようになります。

VPNサーバ公開.png

VPNサーバを無料なGoogle Cloud Compute Engineに立てます。ラズパイは自宅からVPNサーバに接続します。するとサーバとクライアントは 10.8.0.1 と 10.8.0.6 の仮想ネットワーク上のIPアドレスで接続されます。繋がってしまえば簡単ですね。サーバに飛んできたHTTPリクエスを nginx をプロキシサーバにしてラズパイに投げてしまえばよいのです。

手順としては以下の4段階になります。

  1. VPNサーバの設定
  2. Raspberry Pi3 を VPN サーバに接続する
  3. Raspberry Pi3 で Elasticsearch を動かす
  4. VPNサーバに nginx でプロキシサーバを立てる

それでは設定していきます。

VPNサーバの設定

環境: Google Cloud Compute Engine
OS: Ubuntu 16.04 LTS
開放ポート: 80-TCP, 1194-UDP

サーバを用意したら80と1194のポートを開放してください。1194はUDPになります。
まずは更新します。

$ sudo apt-get update
$ sudo apt-get upgrade

openvpn と git をインストールします。easy-rsa という鍵を作成するツールのリポジトリも取得します。

$ sudo apt install openvpn git
$ git clone https://github.com/OpenVPN/easy-rsa.git

鍵がいくつも必要になるので作っていきます。作成した鍵は /etc/openvpn/keys にコピーします。
ca.crt を作ります。phrase と Common Name は適当なものを入力してください。

$ cd easy-rsa/easyrsa3
$ ./easyrsa init-pki

$ ./easyrsa build-ca
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Common Name (eg: your user, host, or server name) [Easy-RSA CA]: google
$ sudo mkdir /etc/openvpn/keys
$ sudo cp pki/ca.crt /etc/openvpn/keys

server.crtserver.key を作成します。途中で ca.key の phrase を求められるので入力します。

$ ./easyrsa build-server-full server nopass
Enter pass phrase for /home/akiraak/easy-rsa/easyrsa3/pki/private/ca.key:
$ sudo cp pki/issued/server.crt /etc/openvpn/keys
$ sudo cp pki/private/server.key /etc/openvpn/keys

dh.pem を作成します。こちらも ca.key の phrase を入力します。このキーの作成は少し時間がかかります。

$ ./easyrsa gen-dh
$ sudo cp pki/dh.pem /etc/openvpn/keys

crl.pem を作成します。途中で ca.key の phrase を入力します。

$ ./easyrsa gen-crl
Enter pass phrase for /home/akiraak/easy-rsa/easyrsa3/pki/private/ca.key:
$ sudo cp pki/crl.pem /etc/openvpn/keys
$ sudo chmod o+r /etc/openvpn/keys/crl.pem

クライアントの鍵を作成します。[client-name] に適当な名前を入れてください。僕の場合はクライアントがラズパイなので ras としました。また、クライアント鍵の phrase が求められるので適当なものを入力し、その後に ca.key の phrase も入力します。

$ ./easyrsa build-client-full [client-name]
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Enter pass phrase for /home/akiraak/easy-rsa/easyrsa3/pki/private/ca.key:

ca.crt とクライアントの鍵はラズパイにアップロードする必要があるのでローカル環境にダウンロードしておきます。

$ cp pki/ca.crt ~
$ cp pki/issued/[client-name].crt ~
$ cp pki/private/[client-name].key ~

$ scp XXX.XXX.XXX.XXX:~/ca.crt ~/vpn/
$ scp XXX.XXX.XXX.XXX:~/ras.crt ~/vpn/
$ scp XXX.XXX.XXX.XXX:~/ras.key ~/vpn/

/etc/openvpn/server.conf を作成します。各パラメーターの詳しい説明は以下の記事を参考にしてください。
OpenVPNのインストールとセットアップからインターネット接続までのガイドブック

/etc/openvpn/server.conf
port   1194
proto  udp
dev    tun

ca          /etc/openvpn/keys/ca.crt
cert        /etc/openvpn/keys/server.crt
key         /etc/openvpn/keys/server.key
dh          /etc/openvpn/keys/dh.pem
crl-verify  /etc/openvpn/keys/crl.pem

ifconfig-pool-persist /etc/openvpn/ipp.txt

server 10.8.0.0 255.255.255.0

push "route 10.8.0.0 255.255.255.0"

client-to-client
keepalive 10 120
comp-lzo

user  nobody
group nogroup

persist-key
persist-tun

status      /var/log/openvpn-status.log
log         /var/log/openvpn.log
log-append  /var/log/openvpn.log

verb 3

openvpn コマンドで動作するか確認します。

$ sudo openvpn --config /etc/openvpn/server.conf

ログはこのようになります。

/var/log/syslog
Jul  3 01:13:09 vpn2 ntpd[1613]: Listen normally on 6 tun0 10.8.0.1:123
Jul  3 01:13:09 vpn2 ntpd[1613]: Listen normally on 7 tun0 [fe80::b142:7fdf:3c3c:7f79%3]:123
Jul  3 01:13:09 vpn2 ntpd[1613]: new interface(s) found: waking up resolver

ifconfig でIPが割り振られているか確認します。 10.8.0.1 となっていますね。

$ ifconfig
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:10.8.0.1  P-t-P:10.8.0.2  Mask:255.255.255.255
          inet6 addr: fe80::b142:7fdf:3c3c:7f79/64 Scope:Link
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:0 (0.0 B)  TX bytes:144 (144.0 B)

openvpn での実行を止めて、サービスで起動させます。

$ sudo systemctl start openvpn@server

自動起動になっていないので有効にします。

sudo systemctl enable openvpn@server

VPNサーバの設定は以上です。

Raspberry Pi3 を VPN サーバに接続する

OS は Ubuntu MATE 16.04.2 LTS を使用します。Mac を使ったインストール方法も書いておきます。

ubuntu-mate-16.04.2-desktop-armhf-raspberry-pi.img.xz をダウンロードします。次に SDカードをアダプタなどを使い Mac の USB に刺します。

$ diskutil list
/dev/disk0 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *500.3 GB   disk0
   1:                        EFI EFI                     209.7 MB   disk0s1
   2:          Apple_CoreStorage Macintosh HD            499.4 GB   disk0s2
   3:                 Apple_Boot Recovery HD             650.0 MB   disk0s3

/dev/disk1 (internal, virtual):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:                  Apple_HFS Macintosh HD           +499.0 GB   disk1
                                 Logical Volume on disk0s2
                                 DF19241A-6A88-40A6-AC98-2B2929C13B2A
                                 Unencrypted

/dev/disk2 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *31.4 GB    disk2
   1:             Windows_FAT_32 PI_BOOT                 66.1 MB    disk2s1
   2:                      Linux                         31.4 GB    disk2s2

SDカードは /dev/disk2 と認識されているようです。
dfMounted on を確認し、unmount します。

$ df
Filesystem    512-blocks      Used Available Capacity iused      ifree %iused  Mounted on
/dev/disk1     974700800 735691904 238496896    76% 3494843 4291472436    0%   /
devfs                389       389         0   100%     674          0  100%   /dev
map -hosts             0         0         0   100%       0          0  100%   /net
map auto_home          0         0         0   100%       0          0  100%   /home
/dev/disk2s1      128912     42672     86240    34%     512          0  100%   /Volumes/PI_BOOT

$ sudo diskutil unmount "/Volumes/PI_BOOT"

イメージをSDカードにコピーします。このとき /dev/rdisk2 と disk の前に r を入れます。またbs=1m も追加します。これをしないと何時間もかかってしまうので注意が必要です。

$ xzcat ~/Downloads/ubuntu-mate-16.04.2-desktop-armhf-raspberry-pi.img.xz | sudo dd of=/dev/rdisk2 bs=1m

contrl+t で進捗を確認できます。
終わったらSDカードをラズパイに刺せば Ubuntu MATE が起動します。

更新します。

$ sudo apt-get update
$ sudo apt-get upgrade
Reading package lists... Done
Building dependency tree       
Reading state information... Done
You might want to run 'apt-get -f install' to correct these.
The following packages have unmet dependencies:
 libc6-dev : Depends: libc6 (= 2.23-0ubuntu9) but 2.23-0ubuntu5 is installed
E: Unmet dependencies. Try using -f.

-f を使わないと更新ができないようです。

$ sudo apt-get -f upgrade

openvpn をインストールします。

$ sudo apt-get install openvpn

VPNサーバで作成した鍵をラズパイにアップロードし、 /etc/openvpn/keys に配置します。

$ scp ~/vpn/ca.crt XXX.XXX.XXX.XXX:~
$ scp ~/vpn/ras.crt XXX.XXX.XXX.XXX:~
$ scp ~/vpn/ras.key XXX.XXX.XXX.XXX:~
$ sudo mkdir /etc/openvpn/keys
$ sudo mv ca.crt /etc/openvpn/keys
$ sudo mv ras.crt /etc/openvpn/keys
$ sudo mv ras.key /etc/openvpn/keys

/etc/openvpn/keys/pass にクライアント鍵の phrase を入れておきます。

$ sudo vi /etc/openvpn/keys/pass

/etc/openvpn/client.conf にクライアントの設定を記載します。XXX.XXX.XXX.XXX はVPNサーバのIPアドレスを入れてください。

/etc/openvpn/client.conf
client

dev    tun
proto  udp

remote XXX.XXX.XXX.XXX 1194

resolv-retry  infinite
nobind

persist-key
persist-tun

ca      /etc/openvpn/keys/ca.crt
cert    /etc/openvpn/keys/ras.crt
key     /etc/openvpn/keys/ras.key
askpass /etc/openvpn/keys/pass

comp-lzo
verb 3

openvpn コマンドで接続できるか試します。

$ sudo openvpn --config /etc/openvpn/client.conf

別ウィンドウで ifconfig を実行してみます。 10.8.0.6 とIPが割り振られたようです。

$ ifconfig
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:10.8.0.6  P-t-P:10.8.0.5  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:3 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:252 (252.0 B)  TX bytes:252 (252.0 B)

VPNサーバに ping が届くか確認します。

$ ping 10.8.0.1
PING 10.8.0.1 (10.8.0.1) 56(84) bytes of data.
64 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=68.8 ms
64 bytes from 10.8.0.1: icmp_seq=2 ttl=64 time=58.9 ms

逆にVPNサーバからラズパイに ping を打ってみます。

$ ping 10.8.0.6
PING 10.8.0.6 (10.8.0.6) 56(84) bytes of data.
64 bytes from 10.8.0.6: icmp_seq=1 ttl=64 time=63.5 ms
64 bytes from 10.8.0.6: icmp_seq=2 ttl=64 time=59.5 ms

問題がなさそうなので、openvpn の実行を終了し、サービスの起動と自動起動の設定を行います。

$ sudo service openvpn start
$ sudo systemctl enable openvpn

ラズパイで Elasticsearch を動かす

オフィシャルのインストール方法はこちらに書いてあります。
Install Elasticsearch with Debian Package

インストールします。

$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
$ echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-5.x.list
$ sudo apt-get update
$ sudo apt-get install elasticsearch
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.3.deb
$ sudo dpkg -i elasticsearch-5.4.3.deb

Elasticsearch は初期設定だとメモリを2GB使いますが、Raspberry Pi3 は1GBしか積んでいないので、jvm の設定を変更して512MBにします。

/etc/elasticsearch/jvm.options
#-Xms2g
#-Xmx2g
-Xms512m
-Xmx512m

外部のPCからアクセスできるように設定を追記します。

/etc/elasticsearch/elasticsearch.yml
network.host: 0.0.0.0
http.port: 9200
transport.host: localhost
transport.tcp.port: 9300

実行します。

$ sudo service elasticsearch start

起動には時間がかかります。ログを確認します。

$ tail -f /var/log/elasticsearch/elasticsearch.log
[2017-07-03T21:17:00,200][INFO ][o.e.n.Node               ] [d0hREp4] starting ...
[2017-07-03T21:17:04,266][INFO ][o.e.t.TransportService   ] [d0hREp4] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}
[2017-07-03T21:17:04,471][WARN ][o.e.b.BootstrapChecks    ] [d0hREp4] system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk
[2017-07-03T21:17:08,265][INFO ][o.e.c.s.ClusterService   ] [d0hREp4] new_master {d0hREp4}{d0hREp4RSZq1h-A-VUWbvw}{FSLOhsEiQfGR9w81wvmmgg}{localhost}{127.0.0.1:9300}, reason: zen-disco-elected-as-master ([0] nodes joined)
[2017-07-03T21:17:08,639][INFO ][o.e.h.n.Netty4HttpServerTransport] [d0hREp4] publish_address {10.0.1.30:9200}, bound_addresses {[::]:9200}
[2017-07-03T21:17:08,680][INFO ][o.e.n.Node               ] [d0hREp4] started
[2017-07-03T21:17:08,713][INFO ][o.e.g.GatewayService     ] [d0hREp4] recovered [0] indices into cluster_state

多くのログが吐かれますが、このようになれば起動しています。
自動起動の設定もしておきます。

$ sudo systemctl enable elasticsearch

動いているかローカルで確認してみます。

$ wget http://localhost:9200
$ cat index.html 
{
  "name" : "d0hREp4",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "QIfUBpUkTvm8NdxRmlQERg",
  "version" : {
    "number" : "5.4.3",
    "build_hash" : "eed30a8",
    "build_date" : "2017-06-22T00:34:03.743Z",
    "build_snapshot" : false,
    "lucene_version" : "6.5.1"
  },
  "tagline" : "You Know, for Search"
}

大丈夫なようなので、VPNサーバからも確認してみます。

$ wget http://10.8.0.6:9200
$ cat index.html 
{
  "name" : "d0hREp4",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "QIfUBpUkTvm8NdxRmlQERg",
  "version" : {
    "number" : "5.4.3",
    "build_hash" : "eed30a8",
    "build_date" : "2017-06-22T00:34:03.743Z",
    "build_snapshot" : false,
    "lucene_version" : "6.5.1"
  },
  "tagline" : "You Know, for Search"
}

VPNサーバに nginx でプロキシサーバを立てる

さて、最後にプロキシサーバを立てます。これで外部からVPNサーバのパブリックなIPアドレスにアクセスすると、ラズパイにクエリが転送されるようになります。

nginx をインストールします。

$ sudo apt-get install nginx

プロキシサーバの設定を書きます。XXX.XXX.XXX.XXX はVPNサーバのIPアドレスを入れてください。

/etc/nginx/conf.d/ras.conf
server {
    server_name XXX.XXX.XXX.XXX;
    proxy_set_header Host $http_host;

    location / {
        proxy_pass http://10.8.0.6:9200;
    }
}

nginx を再起動します。

$ sudo service nginx restart

最後にブラウザでアクセスして動作確認します。
elasticsearch.png

Elasticsearch on ラズパイの完成です。

性能

Elasticksearch へのデータのバルクインサートは、AWS の t2.small.elasticsearch で2分くらいかかっていたものがラズパイだと120分かかりました。インデックス作成がものすごく遅いのかな?search は2〜3倍遅いくらいなので実用はできています。

おわりに

ラズパイをサーバにするのは面白いですね。電気代も月50円もかからないようですし、スペースも取らないのでいろいろ設置したくなります。こんなのとか楽しそう。

vpn.png

あと、Raspberry Pi3 での設定方法を書きましたが、実際の運用は Asus Tinker board(CPU1.5倍速, メモリ2GB, ラズパイと同じ形なのでケースが使いまわせる) で行っています。ただこのボードはアメリカだと7,000円で買えるのですが、日本だと16,000円と割に合わないので Raspberry Pi3 の設定を書きました。

Asus Tinker Board 発売

Raspberry Pi3と同サイズで性能2倍のASUS製「Tinker Board」が国内発売
日本での公式な販売が決まったようです。

ラズパイと同様の手順で設定が可能ですが、OSがDebianなのでコマンドが少し変わります。

  • ifconfig/sbin/ifconfig
  • sudo service [サービス名] startsudo systemctl start [サービス名]

メモリが2GB搭載されているので Elasticsearch の使用メモリを1GBにします。

/etc/elasticsearch/jvm.options
#-Xms2g
#-Xmx2g
-Xms1g
-Xmx1g
44
66
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
66

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?