2016年12月25日日曜日

ニフティクラウド上に VyOS を構築して L2TP/IPsec を使って Mac から VPN 接続してみた

概要

ニフティクラウド上に VyOS を構築して自宅の Mac から L2TP/IPSec を使って VPN 接続してみました
VPN 接続することでニフティクラウド上のマシンが自宅の Mac からローカル IP 接続できるようになります

環境

  • ニフティクラウド (2016/12/25 時点)
    • Region: east-1 (Zone: east-12)
  • ゲスト OS: VyOS 1.1.7 (Public イメージを使用)
  • Mac Book Pro (OS X 10.10.5)
  • Wifi Walker NAD11

完成図

今回の完成図は以下の通りです
自宅側の Mac は WiMAX を使ってインターネットに接続します
WiMAX のグローバル側の IP は固定 IP が理想ですが、動的 IP でも問題ありません
その場合は確認くんなどで事前にグローバル側の IP を調査しておいてください
l2tp_ipsec_vyos_with_mac1.png

プライベート LAN の作成

まずはニフティクラウド側でリソースを作成します
左メニューから「ネットワーク」を選択し「プライベート LAN 作成」から作成します
CIDR は今回完成図にあるように「192.168.0.0/24」にしておきます
ここで設定した CIDR の範囲の IP が自宅の Mac 側にも振られることでクラウド側のサーバと通信できるようになります
l2tp_ipsec_vyos_with_mac2.png

VyOS の作成

次に VyOS をニフティクラウド上に構築します
「サーバー作成」から作成します
ニフティクラウドでは Public イメージとして VyOS の 1.1.7 が公開されているのでこれを使いましょう
l2tp_ipsec_vyos_with_mac3.png

サーバのスペックは small2 くらいあれば OK です
料金プラン、SSH キー、ファイアウォールは適当に割り当ててください
ネットワークの設定でプライベート側は先程作成したプライベート LAN を設定してください
l2tp_ipsec_vyos_with_mac4.png

作成が完了するとプライベート側の IP がまだ設定されていないため警告マークになりますが、手動で設定するので問題ないです

VyOS 上で L2TP/IPSec の設定

では VyOS に SSH ログインして VPN の設定を行います
ログイン用のユーザは vyos になるので注意してください

プライベート IP の設定

まずはプライベート側の IP を設定します

  • configure

で編集モードになり

  • del interfaces ethernet eth1 address dhcp
  • set interfaces ethernet eth1 address ‘192.168.0.1/24’
  • set interfaces ethernet eth1 description ‘vlan’
  • commit
  • save

で静的 IP を付与します
commit ip a show で IP が振られていることを確認してください
コンパネでも警告マークが消え正常になっていると思います

L2TP/IPSec の設定

次に VPN の設定を行います

  • configure

で編集モードになります

IPSec の設定は以下の通りです

  • set vpn ipsec ipsec-interfaces interface eth0
  • set vpn ipsec nat-traversal enable
  • set vpn ipsec nat-networks allowed-network 0.0.0.0/0
  • commit
  • save

L2TP の設定は以下の通りです
xxx.xxx.xxx.xxx の部分はニフティクラウド上に作成した VyOS のグローバル側の IP を記載してください
pre-shared-secret で設定した「TESTSECRET」はどんな文字列でも OK です
あとで Mac から使用するのでメモしておいてください
あと local-users usernamepassword で設定したユーザ名とパスワードも Mac から VPN 接続するときに使うのでメモしておいてください
もちろん好きなユーザ名とパスワードに変更してもらって OK です

  • set vpn l2tp remote-access client-ip-pool start 192.168.0.100
  • set vpn l2tp remote-access client-ip-pool stop 192.168.0.200
  • set vpn l2tp remote-access outside-address xxx.xxx.xxx.xxx
  • set vpn l2tp remote-access ipsec-settings authentication mode pre-shared-secret
  • set vpn l2tp remote-access ipsec-settings authentication pre-shared-secret TESTSECRET
  • set vpn l2tp remote-access authentication mode local
  • set vpn l2tp remote-access authentication local-users username TESTUSER password TESTPASS
  • commit
  • save

start 192.168.0.100stop 192.168.0.200 で指定した範囲から IP を 1 つ VyOS が払い出し VPN 接続に成功したマシンにプライベート IP を付与してくれます

VyOS 用のファイアウォールの設定

ここで WiMAX のグローバル IP からの接続許可をします
固定 IP であればそれを、動的 IP であれば事前に調べておいて IP をファイアウォールに設定します
アクセスプロトコルは今回は Any で実施します
要するに自宅の WiMAX からのアクセスは全許可になれば OK です

また、VPN 接続後にプライベート IP でクラウド上のサーバにアクセスします
ニフティクラウドの場合同一ファイアウォール内にいる場合はプライベート間はアクセスし放題なのですが、今回の場合自宅のマシンからのアクセスなのでファイアウォールにプライベート間の通信の許可ルールを追加する必要があります
なので、プライベート IP からのアクセスも許可しておきます

  • ANY CIDR 192.168.0.0/24
  • ANY IP WiMAX のグローバルIP

上記を IN ルールに許可してください
OUT ルールは特に設定する必要はありません

試しに自宅環境から VyOS のグローバル IP に SSH ログインできるかどうか確認すると良いかと思います

動作確認用のサーバを準備する

これは何でも OK です
適当にサーバを作成してください
一つ条件としては事前に作成したプライベート LAN (vlan) に接続するようにしてください
そしてプライベート IP を手動で設定してください
今回の完成図では「192.168.0.10/24」を設定しました
動作確認用に Apache をインストールして起動しておきます

ここまでできればニフティクラウド上での作業は完了です

Mac を使って VPN 接続して動作確認する

では自宅の Mac から接続してみます
「システム環境設定」から「ネットワーク」を選択します
l2tp_ipsec_vyos_with_mac5.png

ネットワークの一覧の下にある「+」ボタンから新規でネットワークを追加します
作成時にプルダウンでインタフェースの種類を選択できますが「VPN」を選択します
VPN タイプには「L2TP over IPSec」を選択します
l2tp_ipsec_vyos_with_mac6.png

l2tp_ipsec_vyos_with_mac8.png

サーバアドレスにはニフティクラウド上に作成した VyOS のグローバル IP を入力します
アカウント名には VyOS に設定した認証用のユーザ名を入力します

そしてその下にある認証設定を選択します
「ユーザ認証」のパスワードと「コンピュータ認証」の共有シークレットを入力します
どちらも VyOS の設定時に決めたものにすれば OK です
l2tp_ipsec_vyos_with_mac7.png

サーバ情報と認証情報が入力できたら「接続」を選択します
接続に成功すると VyOS に設定した払い出すプライベート IP の範囲から 1 つ Mac に IP が振られます
今回であれば「192.168.0.100」が振られると思います

Mac 上でインタフェースを確認すると VPN 用に 1 つ追加されていることも確認できます

  • ifconfig ppp0
ppp0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1280
        inet 192.168.0.100 --> 10.255.255.0 netmask 0xffffff00

この状態になればニフティクラウド上の vlan 内にあるサーバにプライベート IP でアクセスできるようになります
ブラウザに 192.168.0.10 を入力して Apache のスタート画面が表示されることを確認すると良いと思います
ping や SSH もプライベート IP を指定してできると思います

最後に

VyOS をクラウド上に構築して L2TP/IPSec で VPN 接続してみました
VyOS を使えば簡単に実現できるので簡易な VPN を構築したい場合には便利かなと思います
ただ、現状の構成だと VyOS が完全に SOPF になっているので実際のサービス運用をする場合には DR などを考えなければいけないかなと思います
実際自分が試したいたときにもちょくちょく切断する現象が発生しましました (WiMAX が関係している可能性もありますが)

また、今回はクライアント側の WiMAX 側は特に何も設定しませんでしたが、ルータによってはもしかすると何か設定が必要になるかもしれません

参考サイト

ニフティクラウドのルータの NAT 機能を使ってインターネットにアクセスしてみた

概要

ニフティクラウドのルータ機能に NAT 機能があります
今回はこの NAT 機能を使用してグローバルネットワークを持たないサーバをインターネットに接続してみたいと思います

環境

  • ニフティクラウド (2016/12/24 時点)
    • Region: east-1 (Zone: east-12)
  • ゲスト OS: CentOS6, 7

構成

構成は前回までに作成したルータ環境をそのまま使用します
そのままだとサーバがグルーバルに直接通信できてしまう状況なので今回はそれをルータ経由でアクセスできるようにしてみます
全体の構成図としては以下の通りです
niftycloud_router_nat_usage1.png

グローバル IP の削除

まず c7 サーバからグローバルインタフェースを取り外します
サーバを選択し「ネットワーク設定変更」を選択します
ダイアログで「グローバル」の IP アドレスを「利用しない」に変更します
niftycloud_router_nat_usage2.png

設定が完了してコンパネ上の表示からグローバル IP が見えなくなることを確認します

念のため

グローバル IP を削除するとサーバが再起動します
サーバが再起動すると c6, c7 のルーティングがなくなってしまうのでファイルに書いてルーティング情報を保存しておきましょう

  • c6
    • cat /etc/sysconfig/network-scripts/route-eth1
172.10.0.0/16 via 192.168.0.1
  • c7
    • cat /etc/sysconfig/network-scripts/route-ens192
192.168.0.0/16 via 172.10.0.1

これでグローバルネットワークが削除されてサーバが再起動しても c6, c7 間はプライベート IP を使って通信することができます

ルータをグローバルネットワークに接続する

サーバが接続しなくなったので、代わりにルータをグローバルネットワークに接続します
左メニューの「ネットワーク」からルータを選択し「ルータの操作」から「ネットワーク設定変更」を選択します
そして「ネットワーク追加」から「共通グローバル」を選択し追加します
niftycloud_router_nat_usage3.png

設定が完了するとネットワークの構成図でルータが共通グローバルに接続されると思います

NAT テーブルの作成

次にインターネットに接続するための NAT 設定を行います
左メニューの「ネットワーク」から「NAT テーブル」を選択します
そして新規作成から以下のように入力します
niftycloud_router_nat_usage4.png

c7 の IP アドレス (172.10.0.10) を共通グローバルに NAT する設定を追加します
これは Source NAT (SNAT) になるので SNAT 側に追加します

ルータへの NAT テーブル追加

追加した NAT テーブルをルータに反映させます
ルータを選択し再度「ルータの操作」からネ「NAT テーブル設定変更」を選択します
先ほど作成した NAT テーブルを選択し「変更する」を選択します
niftycloud_router_nat_usage5.png

問題なくルータに反映されれば OK です
これでニフティクラウド上での操作は完了なのであとは OS 上で動作確認します

OS 上での設定と動作確認

c7 サーバへは c6 サーバからルーティングが通っているので、そこから SSH すると良いです
グローバルからはインタフェースを外しているのでできなくなっているためです
とりあえず ping 8.8.8.8 などして接続できないことを確認します

では c7 サーバに default gateway を設定します
以下のコマンドを実行してください

  • ip r add default via 172.10.0.1 dev ens192

これを実行した段階で先ほどの ping が通るようになっていると思います
更に curl www.google.co.jp などを実行すると HTML が取得できると思います
yum update もできます

default gateway の情報は恒久的に保存したい場合は以下のファイルに追記しましょう

  • vim etc/sysconfig/network-scripts/ifcfg-ens192
GATEWAY=172.10.0.2

で再起動しても default gateway の設定が消えません

最後に

ニフティクラウドのルータを使って SNAT 機能を実現してみました
これでルータ配下にいるサーバはグローバルネットワークを持たなくてもインターネット通信できるようになりました

ニフティクラウドの場合、グローバルネットワークを取り外すと少しお値段が安くなるのでインターネットには接続したいがグローバル IP を使わない場合にはお得かもしれません (ルータの料金はかかりますが)

2016年12月18日日曜日

ニフティクラウドのルータの DHCP 機能を使ってみた

概要

前回、ルータ機能を使って VLAN 同士を接続させてみました
このままだとサーバを VLAN に追加したときに毎回 IP を手動で設定しなければなりません
面倒でなければそれでも問題ないですが、IP を振るのが面倒な場合にルータの DHCP 機能を使うと設定の手間を省くことができます

環境

  • ニフティクラウド (2016/12/18 時点)
    • Region: east-1 (Zone: east-12)
  • ゲスト OS: CentOS6, 7

DHCP コンフィグの作成

環境は前回のものをそのまま使います
まずは DHCP コンフィグを作成します
「ネットワーク」->「DHCP コンフィグ」から「DHCP コンフィグ作成」を選択します

「自動割り当て IP アドレス」の右端にある「追加」ボタンを押します
DHCP コンフィグの作成では VLAN で指定した CIDR の範囲で DHCP として割り当てる IP の範囲を指定することができます
今回は 192.168.0.100 から 192.168.0.254 の範囲の IP を使用するようにしました
try_niftycloud_roter_dhcp1.png

これで作成すれば OK です

ルータへの DHCP コンフィグの設定

作成した DHCP コンフィグをルータに割り当てます
「ネットワーク」から構成図を表示します
そして、ルータを表示し「ルーターの操作」から「ネットワーク設定変更」を選択します

ネットワークの設定変更画面で今回作成した DHCP コンフィグの CIDR の範囲に該当する VLAN 側の DHCP コンフィグを変更します
今回は vlan1 側に DHCP コンフィグを割り当てるので以下のようになります
try_niftycloud_roter_dhcp2.png

設定を反映させれば完了です
コンパネの注意書きにもありますが、この操作はルータの再起動が必要になるのでサーバ同士での通信断が発生するため本番環境などの場合には注意して操作してください

若干反映に時間がかかるので待ちます
ルータの設定を確認して以下のようになれば設定完了です
try_niftycloud_roter_dhcp3.png

try_niftycloud_roter_dhcp4.png

既存のサーバで動作確認

ルータへの反映が完了したら早速 DHCP で IP アドレスが振られるかどうか確認してみましょう
vlan1 に所属していた c6 サーバは固定 IP に設定していたので、以下のように /etc/sysconfig/network-scripts/ifcfg-eth1 を書き換えてインタフェースを再起動してみます

DEVICE=eth1
BOOTPROTO=dhcp
ONBOOT=yes
PEERDNS=no
  • ifdown eth1
  • ifup eth1

これで IP がどうなるか確認してみましょう
前回までだと 192.168.0.10 を固定 IP にしていましたが、DHCP コンフィグで指定した範囲の IP が割り当てられていることがコンパネ上で確認できると思います
try_niftycloud_roter_dhcp5.png

新規にサーバを作成して動作確認

新規でサーバを作成した場合の IP の割り当てについても動作確認してみます
サーバを作成する際にプライベート側のネットワークの指定で vlan1 を指定しかつ IP アドレスの欄を「自動割り当て」にします
try_niftycloud_roter_dhcp6.png

これで新規 + VLAN 環境の場合でもプライベート側の IP アドレスを自動で付与することができます
サーバを作成してコンパネ上で IP がどうなっているか確認しましょう

!?
try_niftycloud_roter_dhcp7.png

が、付与することは付与できたのですが IP アドレスが DHCP コンフィグで指定した start からの値ではなく単純に若い方から順番に振られる感じでした
もしかしたら新規で作成した場合は DHCP コンフィグの値が無視されているのかもしれません
ちなみにこの状態になって ifdown -> ifup を繰り返しても再度同じ IP が振られてしまいました

また、試しに更にサーバを追加で作成してみましたがやはり若いほうから IP が振られてしまいました
今回は CentOS6, 7 で挙動を確認しましたがどちらも同じ感じでした
もしかすると他の OS だと挙動が違うかも、、、たぶんないと思いますが

サーバ側での追加作業

前回も実施しましたが、実際に別の VLAN のサーバと通信させるためにはルーティングの追加作業は必要です
以下の

最後に

ニフティクラウドのルータの DHCP 機能を使ってみました
これで VLAN 内のサーバに対しても動的に IP を振ることができるので設定の手間が省けます

2016年12月17日土曜日

ニフティクラウドのルーター機能を使って VLAN 同士を接続してみた

概要

ニフティクラウドのネットワークの機能にルータという機能があります
http://cloud.nifty.com/service/router.htm

異なる VLAN 同士を相互に接続することができる機能のようです
実際に動作試してみたので紹介します

環境

  • ニフティクラウド (2016/12/17 時点)
    • Region: east-1 (Zone: east-12)
  • ゲスト OS: CentOS6, 7

プライベート LAN の作成

今回は 2 つのプライベート LAN (vlan1 と vlan2) をルータを使って相互に接続してみます
ニフティクラウドのコントロールパネル (以下、コンパネ) から「ネットワーク」と進み「プライベート LAN の作成」から作成します

まず vlan1 は以下の通り
CIDR は 192.168.0.0/16 にしました
800

vlan2 は以下の通り
こちらは同じ CIDR だと疎通できた感がないので別の CIDR (172.10.0.0/16) にしました
try_niftycloud_router2.png

とりあえず作成できれば OK です

サーバの作成

作成した 2 つのプライベート LAN 上にサーバをそれぞれ 1 台ずつ作成します
特に理由はないですが、vlan1 には CentOS6 (c6) を vlan2 には CentOS7 (c7) をそれぞれ作成します
サーバを作成するときにプライベート側のネットワークは作成した VLAN をそれぞれ指定してください
IP アドレスはサーバが起動したあとに手動で設定します

サーバのスペックは好きなものに設定してください
ファイアウォールも自環境からアクセスできるように適宜設定してください
ただし、ファイアウォールは後々面倒になりそうなので各サーバには同じファイアウォールを設定してください

c6 -> vlan1
try_niftycloud_router3.png

c7 -> vlan2
try_niftycloud_router4.png

こんな感じで作成すれば OK です

サーバに IP アドレスを付与

eth0 側にはグローバル IP が振られているので eth1 側にプライベート IP を付与します
CentOS6 と CentOS7 で若干設定ファイルが異なるので注意してください
IP は「1」を振らなければ何番でも OK です
「1」は後で作成するルータが使用します

c6

  • vim /etc/sysconfig/network-scripts/ifcfg-eth1
  • ifup eth1
DEVICE=eth1
BOOTPROTO=static
IPADDR=192.168.0.10
NETWORK=192.168.0.0
NETMASK=255.255.0.0
ONBOOT=yes
PEERDNS=no

c7

  • vim /etc/sysconfig/network-scripts/ifcfg-ens192
  • ifup ens192
EVICE=ens192
BOOTPROTO=static
IPADDR=172.10.0.10
NETWORK=172.10.0.0
NETMASK=255.255.0.0
ONBOOT=yes
PEERDNS=no

設定したら NIC を up してください
コンパネから確認すると以下のような感じになっていれば OK です
try_niftycloud_router5.png

ルータの作成

ではルータを作成していきます
左メニューから「ネットワーク」で「ルーター作成」を選択します
作成時のポイントは以下の通り

  • ネットワーク設定で作成した VLAN をそれぞれ設定します

追加ボタンからそれぞれ追加すれば OK です
ルータの IP は特に指定しないようにします
そうすることで「1」を勝手に降ってくれるようです
try_niftycloud_router6.png

  • ファイアウォールはサーバに設定したものと同じものを設定してください

別のファイアウォールを設定しても特に問題はないです
VLAN 同士で特にアクセス制限を設けない場合は同じファイアウォールにすればファイアウォール内のアクセスはすべて許可となります

ルータが作成できたら詳細を確認しましょう
以下のような感じなっていれば OK です

基本情報
try_niftycloud_router8

ネットワーク
try_niftycloud_router9.png

今回の構成が完成するとネットワーク構成図的には以下のようになります
( 関係ないサーバが 1 台いますが気にしないでください )
try_niftycloud_router7.png

ルーティングの追加と動作確認

あとは OS 上での設定となります
実施前に以下の ping を実行しておくと実際に疎通が通ったことがわかるので良いと思います

  • c6 # ping 172.10.0.10
  • c7 # ping 192.168.0.10

ルーティングを追加していない状態だと通信することができないと思います
ではまず c6 に以下の設定を実施します

route add -net 172.10.0.0/16 gw 192.168.0.1 eth1

次に c7 に以下の設定を実施します

route add -net 192.168.0.0 netmask 255.255.0.0 gw 172.10.0.1 ens192

すると ping が通るようになるのが確認できると思います
通った状態でルーティングを削除してみてください
例えば c6 だと route del -net 172.10.0.0/16 gw 192.168.0.1 eth1 という感じです
削除するとお互いが通信できなくなることがわかると思います

ちなみに再起動するとルーティングが削除されてしまうので /etc/sysconfig/network-scripts/route-eth1 とかに設定を書いておくと再起動しても消えません

最後に

ニフティクラウドのルータ機能を使って異なる VLAN を通信できるようにしてみました
VLAN が複数ある環境では便利な機能かもしれません
ルータには DHCP の機能もあるので VLAN 内のサーバに動的に IP を振ることもできると思います (今回紹介はしません)

また、別の機会で他の機能も紹介できればと思います

ハマりポイント

今回の作業でハマった点は以下の通り

  1. OS 上にルーティングの設定が必要なことに気づかなかった
  2. ドキュメントが少ない

1 つ目はネットワークの機能に「ルートテーブル」という機能がありこれで代用できるのかなとずっと勘違いしていました
ルートテーブルにいろいろとルートの追加をしてはルータにルートテーブルを設定して、外しては再度設定してと何度も試したのですが疎通できず素直に OS レベルでルーティングを設定してみたところすんなり通った感じです

2 つ目はそのまんまですが、Web 上に参考になるドキュメントが少なかったです
VPN 接続系の記事はちょくちょくあるのですが、ルータの記事が少ない感じでした

2016年12月4日日曜日

トイレまきまきくんその後

概要

昔トイレの IoT 化ということでトイレットペーパーホルダーを IoT 化しました
http://www.slideshare.net/kakakikikeke/ss-64768171

ちょろっとエンハンスしたので紹介します

環境

  • RaspberryPi Zero ( Jessie 8.0 )

7 セグ LED をシールド化しました

元々ブレッドボード上に配線しており見た目が非常に悪かったのでユニバーサル基板上に実装することでスッキリさせました
作成した基板がこちら


makimaki_board1.jpg

合体後裏
makimaki_board2.jpg

合体後表
makimaki_board3.jpg

まず一番苦労したというかポイントだったのは片面のユニバーサル基板にどうやってシールドを実装するかでした
RaspberryPi の場合ピンがオスピンになっているためシールド側はメスソケットにしなければなりません
そしてユニバーサル基板が片面のため 7 セグの LED やフルカラーの LED もメスソケットの方に実装しなければなりません
そうすると RaspberryPi に指したときに向きが逆になってしまいます
本来なら 7 セグはメスソケットを逆の面に実装して実装面は 7 セグだけが見えるようにしたかったのですが、片面だとそれができませんでした

なので、写真にあるように 7 セグ部分が RaspberryPi Zero の頭の部分からちょうど飛び出すように作ることでとりあえず解決させました

本当は写真でいうところの白い面が RaspberryPi Zero の表の部分になるので、そっちに 7 セグを出したかったのですが片面だとそれが厳しかったということです

回路図

一応回路図を作成したので掲載しておきます
makimaki_circuit.png

フルカラーの LED の全ピンに 470kΩ の抵抗があるのは実は不要です
赤色 LED を制御するピンは入力電圧が確か低かったのでそこは抵抗を入れる必要があると思います
参考 : http://kakakikikeke.blogspot.jp/2016/01/raspberrypi-full-color-led.html
特に GND ピンは完全に不要です
他のピンで抵抗を挟んでいるのは LED の明るさをちょっと暗くしたかったので LED にかかる電圧を下げるために入れました
なので、LED が「ピカーッ!」と光っても問題ない場合は抵抗は不要です

7 セグを制御しているピンは過去の記事で使用したピンをそのまま使用しているだけなので、別に他のピンでも OK です
もう少し違うピンを使って余裕を持ってハンダできるようにすればハンダ付けももっと楽だったかもしれません
参考 : http://kakakikikeke.blogspot.jp/2016/01/raspberrypi-7-seg-led.html

長さを計測するホイールの土台を自作しました

トイレの長さを計測する部分にフォトインタラプタ+スリット付きのホイールを使っています
これは元々ジャンクのホイールマウスの部分を再利用しています

土台もマウスの土台を適当に加工したものを使っていたのですが、見た目が悪かったので 3D プリンタを使って土台の作成まで行ってみました

自作するときに土台の長さを長くすることでペーパーが少なくなってもホイールがペーパーに当たるようになったので最後まで長さを計測できるようになりました


makimaki_base1.jpg

基板とドッキング
makimaki_base2.jpg

ペーパーホルダーとドッキング
makimaki_base3.jpg

難しかったのはホイールを支える柱のところで中に溝を作らなければいけないのですが、この溝のサイズがホイールと中々合わずに苦労しました
また、基板と土台を固定化するのに小さいな穴があるのですが、その穴にちょうど入るようにピンみたいなのも作りました (写真 2 枚目)
これは見事寸法どおりに作成できました

最後に

以上まきまきくんのエンハンスでした

実はここには掲載してないですが、最近まきまきくん用の RaspberryPi Zero に HDD を挿して自宅 NAS としても使っています
もはやトイレを IoT 化するための RaspberryPi 感がゼロになってしまっていますが、別の RaspberryPi を自宅に設置するのも面倒だったので兼用にしています

USB のバスパワーもフルで供給して基板側のピン制御もして、内部でいろいろとプログラムが動いても問題なく動作している RaspberryPi Zero のポテンシャルは改めてすごいなと感じました

2016年10月21日金曜日

ニフティクラウドタイマーから mobile backend のスクリプト機能を定期的に呼び出す

概要

ニフティクラウドタイマー (以下タイマー) を使って定期的に mobile backend (以下 NCMB) のスクリプト機能を呼び出す方法を紹介します
データを集計したり、定期的に通知したりするのに使えると思います

環境

  • Ruby 2.2.4p230 (シグネチャを生成するのに利用)
    • bundler
  • タイマー 2016/10/18 時点
  • NCMB 2016/10/18 時点

NCMB での作業

まずは NCMB 側で作業を行います

事前準備

NCMB のコントロールパネルからアプリを生成をしておいてください
アプリ作成後「アプリケーションキー」と「クライアントキー」を使用します
timer_and_ncmb_getting_keys.png

スクリプトの作成と登録

今回は以下のサンプル (sample.js) を使用します
どんなリクエストが来ても hello と応答するだけの簡単なサンプルです

module.exports = function(req, res) {
  res.send("hello");
}

スクリプトの内容はあとから変更しても同じリクエストが使えるので、必要があれば適宜変更してください
作成できたらコントロールパネルからスクリプトをアップロードしましょう
timer_and_ncmb_upload_script.png

アップロードが完了すればとりあえず OK です
コンパネからテストできるので試しに手動で実行してみても OK です

リクエストの生成

タイマーからコールするためのリクエストを生成しましょう
NCMB では認証に Signature 方式を採用しているため Signature の生成を行う必要があります
さすがに手動だと厳しいのでプログラムから生成したいと思います

  • bundle init
  • vim Gemfile
gem "ruby-hmac", ">= 0.4.0"
  • bundle install
  • vim sig.rb
# encoding: utf-8
require 'time'
require 'hmac'
require 'hmac-sha2'
require 'base64'

def sig(script_name, access_identifier, secret_key)
  # paramters
  ncmb_uri = 'script.mb.api.cloud.nifty.com'
  ncmb_endpoint = "https://#{ncmb_uri}/"
  ncmb_version = "2015-09-01"
  method = "POST"
  path = "/script/#{script_name}"
  timestamp = Time.now.utc.xmlschema.gsub(":", "%3A").gsub("Z", ".456Z")
  common_params = {
    'SignatureMethod' => 'HmacSHA256',
    'SignatureVersion' => '2',
    'X-NCMB-Application-Key' => access_identifier,
    'X-NCMB-Timestamp' => timestamp,
  }
  # creating signature
  canonical_querystring = common_params.sort.collect { |key, value| [key, value].join('=') }.join('&')
  string_to_sign = "#{method}\n#{ncmb_uri}\n/#{ncmb_version}#{path}\n#{canonical_querystring}"
  hmac = HMAC::SHA256.new(secret_key)
  hmac.update(string_to_sign)
  signature = Base64.encode64(hmac.digest.to_s).chomp
  # show result
  cmd="curl -X \"#{method}\" -H \"X-NCMB-Application-Key: #{access_identifier}\" -H \"X-NCMB-Timestamp: #{timestamp}\" -H \"X-NCMB-Signature: #{signature}\" #{ncmb_endpoint}#{ncmb_version}#{path}"
  puts cmd
end

def main
  sig(ARGV[0], ARGV[1], ARGV[2])
end

main

実行方法は引数の 1 つ目がスクリプトの名前で 2 つ目がアプリケーションキー 3 つ目がクライアントキーになります

  • bundle exec ruby sig.rb sample.js access_key client_key

すると curl 用のコマンドを生成してくれます
この curl を実行しても OK ですが、これをタイマーに実行させます
今回のプログラムは NCMB のスクリプト用に作成したものなので、他でも使えるように汎用性はございません

タイマーでの作業

では、生成したリクエスト情報をタイマーに登録しましょう
タイマーの新規作成時の詳細設定でタイプに「HTTP」を選択してください
そしたら、生成した curl の情報を入力していましょう

access_key と timestamp, signature は生成したものを入力してください
以下のようにタイマーのコンパネで入力すれば OK です
timer_and_ncmb_setting_timer.png

タイマーを定期実行させる設定はお好きなように設定すれば OK です
とりあえず手動で実行できるので手動実行で動作確認してみましょう

動作確認

では、動作確認してみましょう
作成したタイマーを選択して「リクエストの実行」を選択します
タイマーの実行履歴を表示して「success」になっていることを確認しましょう
timer_and_ncmb_timer_ret.png

次に NCMB のコンパネに戻りスクリプトのログも確認してみましょう
タイマーから実行したログが確認できると思います
timer_and_ncmb_script_ret.png

ResponseStatus がとりあえず 200 になっていれば成功です

ちょっと残念なのはタイマーでもスクリプトのログでもレスポンスボディの内容 (今回の場合は「hello」)を確認することができません
なので、レスポンスボディの内容の確認は curl を使ってとりあえず確認してください

ちょっと応用

スクリプトの内容を変更して別の処理をできるようにしてみます

スクリプトを変更して IFTTT の Maker API をコールしてみる

スクリプトから Maker の Webhook をコールすることで通知機能を追加してみます
まず、IFTTT 側で Maker チャネルを使ったレシピを作成しておきましょう
今回は Maker + Gmail のレシピを作成しました
timer_and_ncmb_sample_maker.png

レシピを作成したらスクリプトを修正しましょう
以下のようなスクリプトにすることで Maker チャネルが発行した Webhook 用の URL をコールすることができます

  • vim sample.js
module.exports = function(req, res) {
  var request = require('superagent');
  body = {
    "value1": "hello"
  };
  request
    .post('https://maker.ifttt.com/trigger/your_maker_event/with/key/your-maker-token')
    .type('json')
    .send(body)
    .end(function(saerr, sares){
      if (saerr) {
        console.error('error requesting ifttt: ' + saerr.stack);
      }
      res.status(200).json(body);
    });
}

your_maker_event と yoru-maekr-token は各自で払い出された Maker チャネルの情報に書き換えてください
body で value1, value2, value3 を設定すると Maker 側で設定された値を使用することができます
例えば、上記の場合 value1 に設定された「hello」という文字列を送信する Gmail の本文などで使用することができます

これでタイマーを実行してみましょう
問題なく実行できて Gmail が届くと思います
ポイントはタイマー側の設定を何も変更しなくてもスクリプトを実行できるところです
タイマー側はそのままでスクリプトを自由に変更できるので、一度タイマー側を設定すれば好きなスクリプトを実行することができます

また、Webhook のリクエストは superagent を使いました
NCMB スクリプトでは require できるライブラリが決まっているので用途に合わせて利用してください
knex などもあるので、データベースへのアクセスをすることもできると思います

最後に

ニフティクラウドタイマーと NCMB スクリプトを連携してみました
応用では IFTTT と連携してスクリプトから通知できるようにもしてみました

今回の構成は自前のサーバで cron + nodejs を使っても全然できます
が、今回のようにサービスだけを使って実現することもでき、そうすることでサーバの運用をしなくて済むのが嬉しい点かなと思います

2016年8月1日月曜日

MODE の SmartModule から IFTTT の Maker に Webhook する方法

概要

MODE の SmartModule を使って IFTTT の Maker チャネルに Webhook を送信してみました
Maker でリクエストボティを使えるように変換してあげるのがポイントでした

環境

  • MODE 2016/08/01 時点
  • IFTTT 2016/08/01 時点

IFTTT で Maker レシピの作成

IFTTT で Maker チャネルを使ったレシピを作成します
今回は Maker チャネルでリクエストを受信したら (IF) Gmail にメールを送信してみます (Then)
mode_with_ifttt_creating_maker_recipe.png

「Event Name」は適当に設定して OK ですが、URL に使うのでそれっぽいのにしましょう
Gmail 側の設定は適当に設定しください

レシピが作成できたら Webhook 用の URL を取得します
mode_with_ifttt_checking_maker_info.png

これが取得できれば IFTTT での設定は OK です

mode2maker-proxy のデプロイ

このプロキシは MODE の SmartModule から送信された Json のボディ情報を Maker で使える形式に変更してくれます

今回は Heroku 上にデプロイします
Heroku ボタンがあるのでそれでデプロイしてください

あとは環境変数の設定をします

という感じで設定することで以下のように Json の変換をした上で、Maker にリクエストしてくれます

  • MODE からリクエストボディ
{
  "eventType":"abc",
  "eventData":{"light":"on"},
  "homeId":3,
  "timestamp":"2015-06-07T08:37:37.997281148Z",
  "originDeviceId":3
}
  • Maker にリクエストしてくれる Json のリクエストボディ
{
  "value1" : "abc",
  "value2" : {"light":"on"},
  "value3" : "on"
}

各 VALUE1, 3 の値は変換する Json のキー名を指定します
今回 VALUE3 に light を指定しています
light は Json のキー内には存在しません
その場合は eventData の中の Json を検索してキーがあればそのキーの値を設定してくれます
どこのキー名にも当てはまらない場合は null が設定されます

そして MAKER_URL の環境変数には IFTTT で作成した Maker チャネルの Webhook 用の URL を設定してください

MODE で SmartModule の作成

ここでのポイントはリクエストする URL を Heroku にデプロイしたプロキシアプリの URL を指定することです

自分は Heroku 上に kaka-mode2maker-proxy という名前でデプロイしているので、そのアプリの URL を SmartModule に指定しています

mode_with_ifttt_creating_smartmodule.png

Key は GEENRATE ボタンを押せば勝手に生成してくれます
これだけ気をつけて SmartModule は作成してください

動作確認

  • IFTTT の Maker を使ったレシピの作成
  • mode2maker-proxy のデプロイ
  • SmartModule の作成

が終わった準備 OK です
デバイスなりから MODE にイベントを送信してみましょう
するとプロキシが動作して Maker がコールされ Gmail が来ると思います

Gmail のメール本文の設定がデフォルトのままであれば以下のような内容で届くはずです
mode_with_ifttt_result.png

最後に

MODE + IFTTT の連携をしてみました
IFTTT が便利すぎるので通知系をやりたい場合はとりあえず IFTTT 経由しておけば安心だと思います