みなさんあのね

エクセルいじりがお仕事のインフラ系SEのメモ

ConsulをDNSサーバとして使う方法

やりたいこと

iPhoneからテスト用のWEBサーバにhttps接続したいけど、DNSサーバがない…WEBサーバにbindを入れるほどのことでもないし…ファイル1つで動くDNSサーバがあればな…」

というようなニッチな悩みに対する解決策を調べていると、ConsulのDNSインターフェースの説明ページがヒットしたので、WEBサーバにConsulをインストールしてWEB兼DNS(Consul)サーバ化することにしてみた。

初期設定

名前解決リクエストを53ポートで受けるように指定して、Consulが動作している端末以外への名前解決リクエストは8.8.8.8に任せる。

$ sudo mkdir /etc/consul.d
$ sudo chown hoge:hoge /etc/consul.d
cat << JSON >> /etc/consul.d/consul.json\n{\n  "ports": {\n    "dns": 53\n  },\n  "recursor": "8.8.8.8"\n}\nJSON
$ sudo mkdir /tmp/consul
$ sudo chown hoge:hoge /tmp/consul

起動

nodeとdomainを指定することでconsul1.node.kintoki.xyzというコモンネームに対する名前解決リクエストを応答することが可能。

$ sudo ./consul agent -dev -server -domain=kintoki.xyz -client=0.0.0.0 \
             -node=consul1 -data-dir=/tmp/consul -bind=192.168.10.224 \
             -config-dir /etc/consul.d \
             -config-file /etc/consul.d/consul.json &
[1] 6598
Downloads$ ==> Starting Consul agent...
==> Starting Consul agent RPC...
==> Consul agent running!
         Node name: 'consul1'
        Datacenter: 'dc1'
            Server: true (bootstrap: false)
       Client Addr: 0.0.0.0 (HTTP: 8500, HTTPS: -1, DNS: 53, RPC: 8400)
      Cluster Addr: 192.168.10.224 (LAN: 8301, WAN: 8302)
    Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
             Atlas: <disabled>
dnsオプション

-domain - By default, Consul responds to DNS queries in the "consul." domain. This flag can be used to change that domain. All queries in this domain are assumed to be handled by Consul and will not be recursively resolved. Configuration - Consul by HashiCorp

bindオプション

-bind - The address that should be bound to for internal cluster communications. This is an IP address that should be reachable by all other nodes in the cluster. By default, this is "0.0.0.0", meaning Consul will use the first available private IPv4 address. If you specify "[::]", Consul will use the first available public IPv6 address. Consul uses both TCP and UDP and the same port for both. If you have any firewalls, be sure to allow both protocols. Configuration - Consul by HashiCorp

clientオプション

-client - The address to which Consul will bind client interfaces, including the HTTP, DNS, and RPC servers. By default, this is "127.0.0.1", allowing only loopback connections. The RPC address is used by other Consul commands, such as consul members, in order to query a running Consul agent. Configuration - Consul by HashiCorp

config-fileオプション

-config-file - A configuration file to load. For more information on the format of this file, read the Configuration Files section. This option can be specified multiple times to load multiple configuration files. If it is specified multiple times, configuration files loaded later will merge with configuration files loaded earlier. During a config merge, single-value keys (string, int, bool) will simply have their values replaced while list types will be appended together. Configuration - Consul by HashiCorp

config-dirオプション

-config-dir - A directory of configuration files to load. Consul will load all files in this directory with the suffix ".json". The load order is alphabetical, and the the same merge routine is used as with the config-file option above. This option can be specified multiple times to load multiple directories. Sub-directories of the config directory are not loaded. For more information on the format of the configuration files, see the Configuration Files section. Configuration - Consul by HashiCorp

data-dirオプション

-data-dir - This flag provides a data directory for the agent to store state. This is required for all agents. The directory should be durable across reboots. This is especially critical for agents that are running in server mode as they must be able to persist cluster state. Additionally, the directory must support the use of filesystem locking, meaning some types of mounted folders (e.g. VirtualBox shared folders) may not be suitable. Configuration - Consul by HashiCorp

名前解決テスト(WEB兼DNSサーバ)

Consulサーバ上で名前解決テストを実施する。

$ dig @192.168.10.224 consul1.node.kintoki.xyz
    2016/07/09 00:45:50 [DEBUG] dns: request for {consul1.node.kintoki.xyz. 1 1} (1.364404ms) from client 192.168.10.224:50229 (udp)

; <<>> DiG 9.8.3-P1 <<>> @192.168.10.224 consul1.node.kintoki.xyz
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24592
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;consul1.node.kintoki.xyz.  IN  A

;; ANSWER SECTION:
consul1.node.kintoki.xyz. 0 IN  A   192.168.10.224

;; Query time: 4 msec
;; SERVER: 192.168.10.224#53(192.168.10.224)
;; WHEN: Sat Jul  9 00:45:50 2016
;; MSG SIZE  rcvd: 82

名前解決テスト(iPhoneからConsulサーバに接続)

ConsulサーバとiPhoneを同一NWに所属させ、iPhone側でhttp://consul1.node.kintoki.xyz:8000を指定してCosulサーバ(WEB兼DNSサーバ)に接続することができるか確認する。iPhoneが使用するDNSサーバは忘れずConsulサーバに設定すること。hogefileが表示されたら成功。

f:id:si871137:20160709012146j:plain

~$ mkdir hoge
~$ cd hoge
hoge$ touch hogefile
# pythonの簡易WEBサーバを起動
hoge$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

f:id:si871137:20160709012403p:plain

まとめ

ConsulはDNSサーバとして使える!iPhoneのhostsファイルを書き換えるという危ない技を使わなくて済んだ。 あとは証明書を作ってWEBサーバにインストールするだけだ。

Herokuアプリを無料でSSL/TLS化する

経緯

趣味で作っているRailsアプリ(ユーザ数1名)をそろそろ独自ドメイン対応させようかなと、情報収集しているとHerokuのSSLアドオンでSSL/TLS対応するには2千円/月の費用が発生することに気付きました。

HerokuをやめてさくらVPSにでも引っ越してLet's Encryptでも試してみようかな〜なんて思ってたらこんな記事を見つけてしまいました。

robots.thoughtbot.com

DNS機能やFirewall機能を兼ね備えたCDN「CloudFlare」経由でアクセスしちゃえば無料でSSL/TLS対応することができるよという記事です。試してみるしかないですね。

設定手順

1. Railsアプリの設定変更

config/environments/production.rbで強制SSL化させる。

config.force_ssl = true

コミットしてHerokuにプッシュ。

$ git push heroku master

2. Herokuのドメイン設定

お名前.com等で取得した独自ドメインをHerokuに登録。これをしとかないとHostヘッダチェックでリクエストが弾かれる。

$ heroku domains:add mydomain.net

3. cloudflareのレコード設定

事前にサインアップしていること。

  1. ドメイン情報スキャン お名前.com等で取得した独自ドメイン名を入力することでドメイン情報がスキャンされる。
  2. ルートドメインをCNAMEとして登録 zone apexなのにCNAME登録はできないでしょ?と思っていたらどうやらCNAME Flatteningという機能が実装されており、問い合わせごとにCNAME情報を辿ってAレコードを応答してくれるらしい。

support.cloudflare.com

設定内容のサンプルは以下。

Type: CNAME
Name: mydomain.net
Content: appname.herokuapp.com

4. お名前.comのネームサーバ設定変更

CloudFlareの指示通りのネームサーバを設定する。NSレコードのTTLだけ待たないと反映されないかも。

5. CloudFlareのSSL設定

Full SSLに設定するだけ。
以上で設定は完了。https://mydomain.netにエラーなく接続できるようになった。

気づいたこと

接続経路は?

日本からCloudFlareを利用すると香港経由で接続するっぽい。Herokuアプリがスリープしてた時にたまたま表示されたエラー画面を見て気付いた。HerokuはUSリージョンとEUリージョンしか対応してないから香港経由での接続でもいいかな。

f:id:si871137:20151129000152p:plain

というかこのエラー画面はあまり表示してほしくないな。

SSLv3.0は無効になってる?

以下のサイトで確認したところSSLv2.0と3.0は無効になっていることがわかった。評価はA+。 www.ssllabs.com

f:id:si871137:20151129002652p:plain

さいごに

本当に無料でSSL/TLS化できてしまいました。しばらくこのまま様子を見つつCloudFlareの他の機能も試してみたいと思います。

RPMを理解する

1. はじめに

yumコマンド(例えばyum install httpd)を実行するとパッケージがインストールされて、サービスコマンドを実行すると(例えばservice httpd start)Webサーバが起動してApacheのデフォルトページが表示される。単純なコマンドでWebサーバが起動しちゃったけど、そこに至るまでの処理ってどうなってるんでしょうか。少し気になって調べてみると、どうやらRPMという仕組みが関係しているようです。「Fedora 22より、デフォルトのパッケージマネージャが変更されるらしい」という話もありますので、ひとつ下のレイヤーの勉強をして、来たる変化に備えておきたいところ。


2. RPMとは

  • RPMとはパッケージ管理の仕組み
  • インストールされたパッケージのデータベースを生成し、そこにそれぞれのバージョン情報が記録される。パッケージのインストール、アンインストール、アップデート、ソースRPMからはアプリケーションを再コンパイルすることも可能
  • 個別のアプリケーションを管理単位とすることにより、アプリケーションのインストールとアンインストールを簡単に行うことができる
  • RPMパッケージとは圧縮されたアーカイブファイルを指し、相互に関係するファイル、ドキュメント、設定情報の集合を含む
  • アプリケーションではなく、設定ファイルを集約したパッケージも存在する(/root/.bashrcを含むrootfilesパッケージ等)。また、パッケージ名にnoarchという文字が含まれていれば、バイナリファイルを含まずスクリプトまたはドキュメントからのみ構成されている環境非依存のパッケージであると判断できる。複数のアプリケーションによって共用できるライブラリのみをまとめたパッケージも存在する
  • Red Hat Package Managerを表していたが、Linuxの他のディストリビューションでも採用され始めたため、RPM Package Mangerという名称に変更された
  • RPMの前身であるRPP(Red Hat Software Packages)では複数アーキテクチャに対応することが難しかったため、RPMが開発された


3. RPMの設計思想

*使いやすいこと

*パッケージに焦点を合わせる

*パッケージをアップグレードできる

手動でアプリケーションをインストールした場合、アップグレード時に設定ファイルが上書きされ、カスタマイズしていた設定情報が失われる場合がある。一方RPMでアップグレードした場合は、カスタマイズ情報は保持される

*パッケージの依存関係をトラッキングする

パッケージ間の依存関係情報をトラッキングし、インストール時やアンインストールに警告を表示させる

*クエリを実行できる

インストールされたすべてのパッケージに関するデータベースがシステム上に作成され、各ファイルがどのパッケージに属するファイルか記録される。RPMは簡単にクエリできるようになっており、データベースに問い合わせてシステムにインストールされているアプリケーションを検索し、各ファイルがどのパッケージに属するか調べることができる

*検証

データベースに記録されたパッケージに関する情報をもとにアプリケーションに属するファイルに問題がないか(すべてのファイルのパーミッションが正しく設定されているか等)チェックし、改ざんされたり壊れたりしているファイルがないか調べることができる

*複数アーキテクチャをサポート

*クリーンなソース

RPM(バイナリパッケージ版)とソースRPM(ソースパッケージ版)の2種類のパッケージを作成する。ソースRPMはオリジナルのソースコードに変更を加えることなく、クリーンなソースコードからパッケージを作成することが可能


4. RPMデータベース

  • RPMデータベースは/var/lib/rpmに格納されている
  • __db.からはじまる名前のファイルはRPMシステムが利用しているロックファイル。その他のファイルはBerkeleyDBフォーマットのデータベースとなっている
  • RPMデータベースは注意深く扱う必要がある。 パッケージをアップグレード、インストール、アンインストールしたあとには、Packagesファイルをバックアップしておくといいかも


5. パッケージのインストール/アンインストール

パッケージのインストールはrpm -Uコマンドかrpm -iコマンドを実行する。rpmコマンドは以下のステップでパッケージをインストールする。

  • インストールすべきパッケージとその中身をチェックする(依存関係、パッケージ間の競合)
  • インストール前のタスクを実行する
  • 圧縮されているファイルを展開して、適切な場所に配置する
  • RPMデータベースを更新する

なお、パッケージを一度に複数インストールする場合はrpmコマンドラインに各ファイルをスペース区切りで列挙すればよい。インストール順序はrpmコマンドが自動判別してくれる。

カスタマイズされた設定ファイルの扱い

パッケージをインストール後、設定ファイルを編集すると、パッケージのアップグレード時に変更を加えた設定ファイルが維持される。(.rpmsaveという新しい拡張子に名前変更されたうえ、バックアップとして保存されることもある。また、.rpmnewという拡張子付きで新しい設定ファイルがインストールされることもある)


5.1. コマンド例(基本)

インストールされているパッケージ一覧を表示する

rpm -qa

パッケージに含まれるファイルの一覧を表示する

# -vオプションを加えるファイルに関する詳細情報が表示される
rpm -qlpi <パッケージ名>.prm
rpm -ql <パッケージ名>

パッケージの設定ファイル一覧を表示する

※設定ファイルを備えていないパッケージも存在する

# -vオプションを加えるファイルに関する詳細情報が表示される
rpm -qc <パッケージ名>

パッケージ内のファイルの状態を表示する

以下、サポートしているファイル状態

  • normal: ファイルがインストールされている
  • not installed: ファイルがパッケージから削除されている
  • replaced: ファイルが別のファイルに置き換えられた
rpm -qs <パッケージ名>
rpm -qsf <ファイル名>
# ファイルを指定してそのファイルを含むパッケージのコンフィグファイルのみの情報を表示
rpm -qcfs <ファイル名>

パッケージ内のスクリプトを表示する

ファイルのインストール/アンインストール時に実行されるスクリプト

rpm -q —scripts <パッケージ名>

パッケージのchangelogを表示する

※対応していないパッケージもある

rpm -q —changelog <パッケージ名>

パッケージの概要情報を表示する

rpm -qi <パッケージ名>

ファイルが属しているパッケージを見つける

rpm -qf <ファイル名>

依存関係を検証する(実際にはインストトールされず依存関係等のチェックのみを行うモード)

# インストールの検証
rpm -Uvh —test <パッケージ名>.rpm
# アンインストールの検証
rpm -e —test <パッケージ名>

インストールディレクトリを変更する

—rootで指定した仮想rootディレクトリにC標準ライブラリを入れておく必要がある

# /tmpを仮想rootディレクトリとして、RPMデータベースは/var/lib/rpmを利用しインストールする
rpm -U --root /tmp —dpath /var/lib/rpm <パッケージ名>.rpm

古いバージョンのパッケージをインストールする

rpm -Uvh —oldpackage <パッケージ名>.rpm

/var/spool/packageにバックアップを残してアンインストールする

rpm -e —repackage <パッケージ名>

最近インストールしたパッケージを表示する

rpm -qa —last | head


5.2. コマンド例(クエリフォーマット)

パッケージ名のみ一覧表示

—qfがクエリフォーマットオプション

# 結果はpfintf形式で表示されるため改行されない。
rpm -qa —qf “%{NAME}"

# 改行したいならこう書く
rpm -qa —qf “%{NAME}¥n"

表示幅の指定

20文字でフォーマットする

rpm -qa —qf “%-20{NAME} %-20{PLATFORM}¥n"

利用できるタグ一覧

  • NAME: パッケージ名
  • VERSION: バージョン情報
  • RELEASE: リリース番号
  • SUMMARY: パッケージの内容を1行に要約
  • DESCRIPTION: パッケージを説明するテキスト
  • BULDTIME: パッケージが構築された時刻
  • SIZE: ペイロード内の通常ファイルのサイズ
  • GROUP: パッケージのグループ(カテゴリ)名
  • OS: パッケージの構築ターゲットとなるOS
  • ARCH: アーキテクチャi386など)
  • PREIN: インストール前のスクリプト
  • POSTIN: インストール後のスクリプト
  • PREUN: アンインストール前のスクリプト
  • POSTUN: アンインストール後のスクリプト
  • PLATFORM: プラットフォーム
# 以下のコマンドでタグ一覧を表示
rpm --querytags

依存情報の表示

$ rpm -qa --qf "[%-10{REQUIRENAME} %{REQUIREFLAGS:depflags} %{REQUIREVERSION}\n]" postfix
/bin/bash
/bin/sh
/sbin/chkconfig
/sbin/service
/usr/sbin/alternatives
/usr/sbin/groupadd
/usr/sbin/useradd
config(postfix) = 2:2.6.6-6.el6_5
cyrus-sasl >= 2.1.10
libc.so.6()(64bit)
libc.so.6(GLIBC_2.11)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.2)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libc.so.6(GLIBC_2.4)(64bit)
libc.so.6(GLIBC_2.7)(64bit)
libcrypto.so.10()(64bit)
libcrypto.so.10(OPENSSL_1.0.1)(64bit)
libcrypto.so.10(OPENSSL_1.0.1_EC)(64bit)
libcrypto.so.10(libcrypto.so.10)(64bit)

ファイル情報一覧の表示

$ rpm -q --qf "[%-15{NAME} %-36{FILENAMES} %{FILEMODES:perms}\n]" postfix
postfix /etc/pam.d/smtp.postfix -rw-r--r--
postfix /etc/postfix drwxr-xr-x
postfix /etc/postfix/access -rw-r--r--
postfix /etc/postfix/canonical -rw-r--r--


6. パッケージの検証

  • S: ファイルサイズが異なる
  • M: ファイルのモードが異なる
  • 5: MD5チェックサムが異なる
  • D: デバイスファイルのバージョンが異なる
  • L: リンクのミスマッチ
  • U: ファイルを所有しているユーザが異なる
  • G: ファイルを所有しているグループが異なる
  • T: ファイルの時刻(mtime)が異なる
$ rpm -V httpd
..5....T. c /etc/httpd/conf/httpd.conf
..?...... /usr/sbin/suexec

# ServerTokens OSをProdに変更
$ vi /etc/httpd/conf/httpd.conf

# 再度検証してみるとSフラグが立っていることがわかる
$ rpm -V httpd
S.5....T. c /etc/httpd/conf/httpd.conf
..?...... /usr/sbin/suexec

# システム全体を検証する時は以下のコマンドを良く使う
$ rpm -Va --nofiles


7. RPMデータベースのメンテナンス

RPMデータベースのバックアップ

# cd /var/lib
# tar cvzf rpmdb.tar.gz ./rpm

RPMデータベース再構築

rpm —rebuilddb

RPMデータベースの再構築

rpm —initdb


8. パッケージの依存関係

依存関係には大きく以下の4つのタイプを定義できる

  • 必要(Requires): パッケージが必要とする機能
  • 提供(Provides):パッケージが他のパッケージに提供する機能
  • 競合(Conflicts):インストールすれば他のパッケージと強豪する機能
  • 廃止(Obsoletes):該当のパッケージによって陳腐化する機能

パッケージが必要とする機能を表示する

インストール済みパッケージに対しても実行可能(-pオプションは省くこと)

$ rpm -qp --requires /tmp/ruby-2.1.5-1.el6.x86_64.rpm
/usr/bin/env
/usr/bin/pkg-config
/usr/bin/ruby
ld-linux-x86-64.so.2()(64bit)
ld-linux-x86-64.so.2(GLIBC_2.2.5)(64bit)
libc.so.6()(64bit)
libc.so.6(GLIBC_2.10)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)

パッケージが提供している機能を表示する

$ rpm -qp --provides /tmp/ruby-2.1.5-1.el6.x86_64.rpm
big5.so()(64bit)
bigdecimal.so()(64bit)
bubblebabble.so()(64bit)
callback.so()(64bit)
chinese.so()(64bit)
complex.so()(64bit)
console.so()(64bit)
continuation.so()(64bit)

競合しているパッケージを表示する

$ rpm -qp --conflicts /tmp/ruby-2.1.5-1.el6.x86_64.rpm

特定の機能を必要とするパッケージを表示する

[vagrant@localhost ~]$ rpm -q --whatrequires /bin/bash
dkms-2.2.0.3-2.el6.noarch
initscripts-9.03.46-1.el6.centos.1.x86_64
dracut-004-356.el6.noarch
rsyslog-5.8.10-10.el6_6.x86_64
cronie-1.4.4-12.el6.x86_64
lvm2-2.02.111-2.el6_6.1.x86_64

特定の機能を提供するパッケージを調べる

$ rpm -q --whatprovides webserver
httpd-2.2.15-39.el6.centos.x86_64

# 特定ファイルを提供しているパッケージを調べる時は以下を実行する
rpm -qf /etc/httpd/conf/httpd.conf


9. トリガ

パッケージのインストール時、またはアンインストール時に実行されるスクリプトを確認することが可能

$ rpm -q --triggers iptables-ipv6
triggerpostun scriptlet (using /bin/sh) -- iptables-ipv6 < 1.4.7-7
ip6tables=`readlink /etc/alternatives/ip6tables.x86_64`
if [ -z "$ip6tables" -o "$ip6tables" == "/sbin/ip6tables-1.4.7" ]; then
/usr/sbin/alternatives --set ip6tables.x86_64 /sbin/ip6tables-1.4.7
fi


10. 参考

Red Hat RPM Guide (redhat PRESS)

Red Hat RPM Guide (redhat PRESS)

spacewalkの仕組み

はじめに

spacewalkは構成管理サーバ的なもので、パッチ当てをスケジュールしたり設定ファイルの配信が可能です。クラサバ間の通信にはXMPPを使ってるようです。 (もちろんAnsibleとの連携(Dynamic Inventory)もバッチリですよ!)
んで、この記事は以下の内部的な仕組みを解説した公式サイトを適当に解釈した結果をまとめてます。

OsadHowTo – spacewalk
https://fedorahosted.org/spacewalk/wiki/OsadHowTo

Jabberについては以下のサイトが参考になりました。

XMPP(Jabberプロトコル)技術メモ — ありえるえりあ http://dev.ariel-networks.com/column/tech/xmpp/view

構成

osad(クライアント)

Python製のクライアントサイドサービ ス。osa-dispatchaerからping応答およびrhn_checkコマンドを実行する。

osa-dispatcher(サーバ)

Python製のサーバサイドサービス。クライアント上で動作しているosadに向けてpingやrhn_check実行を命令する。

jabberd(クライアント/サーバ)

osadやosa-dispatcherはそれぞれの環境で動作するjabberd(XMPP(エックスエムピーピー、eXtensible Messaging and Presence Protocol)の実装)を介して通信を行う。サーバ-クライアント間の認証する。使用ポートは5222。

動作概要

osa-dispatcherはクライアントに対し定期的にpingを実行し、応答に遅延がないかを確認している。(ping応答はosadが動作しているクライアントからjabberdを介して行われる) ping応答を受け取ったosa-dispatcherは応答を返してきたクライアントを”online"状態としてマークする。ある程度以内に応答がなかった場合は”offline"状態としてマークする。

<通信概要図>
サーバ(osa-dispatcher<->jabberd)<->クライアント(jabberd<->osad)

osa-dispatcherはデータベース上で管理されている クライアントへの命令がないかを定期的に確認する。もし命令がある場合はjabber経由でosadにrhn_checkコマンドを実行するよう呼びかける。そこから命令を受けたosadはrhn_checkコマンドを実行することで処理を引き継ぐ。

RHN Proxyは上位で動作するjabberサーバに命令をフォワードする。

ファイル

osad

ソースコード

/usr/share/rhn/osad/

設定ファイル

  • /etc/sysconfig/rhn/osad.conf
  • /etc/sysconfig/rhn/up2date

実行ファイル

/usr/sbin/osad

ログファイル

/var/log/osad ※osad.confでlogレベルを引き上げないと何も出力されないので注意

osa-dispatcher

ソースコード

/usr/share/rhn/osad/

設定ファイル

/etc/rhn/rhn.conf ※"OSA Configuration"セクション

# grep osa /etc/rhn/rhn.conf
osa-dispatcher.jabber_server = yourspacewalk.example.org
osa-dispatcher.osa_ssl_cert = /var/www/html/pub/RHN-ORG-TRUSTED-SSL-CERT
osa-dispatcher.jabber_username = rhn-dispatcher-sat
osa-dispatcher.jabber_password = rhn-dispatcher-a44631

osa-dispatcher.debugでロギングレベルを設定することが可能

実行ファイル

/usr/sbin/osa-dispatcher

ログファイル

/var/log/rhn/osa-dispatcher.log

jabberd

コンポーネント

jabberを実行すると以下の6つのプログラムが起動する

  • /usr/bin/jabberd

  • /usr/bin/c2s(/etc/jabberd/c2s.xml
    クライアントとサーバ間の通信を制御する

  • /usr/bin/s2s(/etc/jabberd/s2s.xml
    他のjabberサーバとの通信を制御する

  • /usr/bin/sm(/etc/jabberd/sm.xml
    jabberコンポーネントjabber router間のセッションを管理する

  • /usr/bin/router(/etc/jabberd/router.xml
    どのコンポーネントにメッセージを連携すべきかを管理する

  • /usr/bin/resolver(/etc/jabberd/resolver.xml
    ホスト名を解決する。s2s向け。

暗号化

c2sとsmを通過した際に通信が暗号化されるよう構成されている。証明書および鍵は以下のファイルに記載されている。
/etc/jabberd/server.pem

ログファイル

基本的jabberdコンポーネントは以下のファイルにロギングされる。
/var/log/messages

組み込みデータベース

jabberはBerkeley databaseを使用している。
/var/lib/jabberd/

トラブルシューティング

名前解決

クライアントのhostsファイルにサーバのFQDNを予め設定しておくこと(jabberの仕様上必要)

ntp設定

osadの認証は時間に依存している。クライアントとサーバ間の時間の差が120秒以内である必要でなければ認証に失敗する。これはセキュリティを考慮した結果の仕様である。

ネットワークの問題

大抵の場合はFWのタイムアウトによって発生する。

  • FW等でosad用の通信を許可されていない場合
  • コネクションが切断されたがクライアントが再接続処理を行わない場合
  • netstat -an | grep 5222の実行結果が"ESTABLISHED"であってもサーバに接続できていない場合

基本的にはkeepaliveのため2分間隔でホワイトスペースのみのデータを送信しているので この仕様をベースに各種設定を少し修正するとよい。以下の設定を行うことで5分以内にスケジュールしたイベントが実行されるようになった。

サーバ側

  1. タイムアウト設定
sed -i 's/<interval>.*/<interval>120<\/interval>/' /etc/jabberd/*.xml*
sed -i 's/<keepalive>.*/<keepalive>120<\/keepalive>/' /etc/jabberd/*.xml*
sed -i 's/<idle>.*/<idle>200<\/idle>/' /etc/jabberd/*.xml*
  1. サービスを再起動
/usr/sbin/spacewalk-service restart
  1. cronによるjabber DB関連の初期化設定
SAMPLE
# Restart jabber everyday @6am
00 06 * * * /sbin/service jabberd stop ; /sbin/service osa-dispatcher stop ; rm -Rf /var/lib/jabberd/db/* ; /sbin/service jabberd start ; /sbin/service osa-dispatcher start

手動実行する場合。

/sbin/service jabberd stop ; /sbin/service osa-dispatcher stop ; rm -Rf /var/lib/jabberd/db/* ; /sbin/service jabberd start ; /sbin/service osa-dispatcher start

クライアント側

  1. cronによるosad再起動&rhn_check実行設定 rhnsdをオフにする。
SAMPLE
# Check in with spacewalk and restart osad every ~4 hours
0 */3 * * * sleep `expr ${RANDOM:0:4} / 2` ; /sbin/service osad restart ; /usr/sbin/rhn_check ; /usr/sbin/rhn-profile-sync
  1. osadの再起動
/sbin/service osad restart

詳細については以下参照。 https://fedorahosted.org/spacewalk/wiki/JabberAndOSAD

Berkeley Database

Berkeley Databaseが何らかの理由でロックされると、ping応答はするが、スケジュールされたイベントに気付くことができなくなる。 そういった場合は一度jabberdを再起動することで /var/lib/jabberd/内の不要なファイルが削除される。

cuckooとJubatusによるマルウェア解析

3月29日(土)、セキュリティ勉強会に参加するため、香川の高松に行ってきました。一番の目的はメインセッションであるFFRI 村上純一さんの「ビッグデータ分析によるマルウェア検知・分析への挑戦」です。真面目な勉強会の参加は初めてだったので緊張しました。

セキュリティうどんのご紹介

セキュリティうどんの主旨はこーんな感じ。なんかとっても真面目そうなイメージを受けました。運営スタッフさんは「セキュリティ系勉強会一のゆるい勉強会」だと言ってましたけどねw

セキュリティうどんの主旨
  • 香川県をメインに、セキュリティ啓蒙、システム管理者スキルアップ、 ユーザーのボトムアップを目的として勉強会を実施します。
  • また、「四国情報セキュリティ勉強会連絡会」を通じて、四国地方の技術者育成と、一般ユーザの情報セキュリティに関する意識向上を目指します。



今回の勉強会のテーマはこちら。

  • 1. 自己紹介(参加者全員!) 1分/人
  • 2. ライトニングトーク
  • 3. おやつタイム
  • 4. ビッグデータ分析によるマルウェア検知・分析への挑戦



おやつタイムって何だ、うどんでも食べるのか?なんて思っていましたが、普通に美味しい洋菓子が振る舞われました。参加費無料でおやつ付き…勉強会っていいもんですね。

ビッグデータ分析によるマルウェア検知・分析への挑戦

FFRI 村上さんによると、cukoo(かっこう)でファイルの挙動を確認した結果を、jubatus(ゆばたす)で機械学習させマルウェア検知を行い、その検知精度を調査したとのこと。

cuckooとは?

f:id:si871137:20140331223140p:plain
1つのファイルを解析する度に新しくVM(仮想環境)を起動させ、ファイル実行時の挙動をログとして出力することが可能です。サンドボックスや動的解析、ビヘイビアとも呼ばれています。
複数のアンチウィルスエンジンでの解析を行うクラウドサービス「VirusTotal」との連携も可能です。
# Pythonで実装されてるので、Pythonの知識があれば色々楽しめるかもしれません。


自分もcukooには1年ほど前に手を出したことがありますが、得られるのはファイルの実行過程の情報のみで、それがマルウェアであるかどうかの条件は自分で考えなければいけないため、上手く活用することができませんでした。
その解決策のひとつとして村上さんが考えたのが、jubatusによる機械学習でした。

jubatusとは?

f:id:si871137:20140331223943p:plain
jubatusを利用すると大規模データ(今回だとcukooの解析結果)をリアルタイムに解析することができる、”大規模分散リアルタイム機械学習基盤”です。


こちらは実際に触ったことがないので詳しい解説はできませんが、イメージとしてはHadoop/Mahoutのリアルタイム版ですかね?和製ソフトなので日本語情報を得やすいというのもjubatusの特徴だと思います。
機会学習の技術を応用することでアンチスパムメールECサイトのレコメンド機能、将棋ソフトのAIなどを実現させることができます。
身近な例だと、iPhoneアプリのAkinatorをイメージしてもらえばいいかと思います。「性別:男性」「名前:漢字」「年齢:25才以上」「癖:倍返しする」等の情報を学習させ、特定の人物を定義することができます。同じようにマルウェアも定義できそうですよね。
f:id:si871137:20140331222648j:plain

機械学習とは?
  • 人間がなんとなくできていること(ファジーな物事)を機械にもやらせようという意味。
  • 医療業界では昔から使われている技術らしい。
  • 様々なテーマ、手法を包含した総称である。


なぜ機械学習なのか?

既存のアンチウィルスソフトじゃダメなの?高価/高学習コストなサンドボックスに投資する必要あるの?という疑問が湧いてくるかと思います。その理由を説明するにはまず、マルウェアのトレンドについて知る必要があります。

パターンマッチング*1の限界

マルウェアというのはインフルエンザ等の自然発生する(と仮定させていただきますw)ウィルスと違い、マルウェアは人の手によって生み出されています。しかも、マルウェアを作成するのは必ずしもセキュリティに関する深い知識を持つ必要はなく、マルウェアを生成するツールによって生み出されています。(しかもその数は爆発的に増加しているとのこと)
さらに最近はマルウェア生成ツールに加え、難読化ツールマルウェアを難読化させたり、不特定多数の標的にするのではなく特定の企業をターゲットにしたカスタムマルウェアを使用することで、検知の目をすり抜けてしまうケースが増えているのです。

機械学習による検知テスト

様々なアプローチがあるみたいですが今回は以下の感じでテストしたそうです。

1. サンプルの取得

まずは学習させるためのデータ(マルウェア/正常なソフトウェア)を一定数準備する必要があります。どの程度のデータを集めるかは以下のようなポイントを考慮するといいらしいです。

  • 信頼区間と呼ばれる概念
  • どれくらいの誤差があってもよいか
  • 数が多ければ多いほど誤差は減る
  • 偏りがないよう、長い期間/様々な場所から少しずつデータを取得する(たぶん重要!)

今回のテストでは、データを15000個(学習用5000個/テスト10000個)準備したそうです。

2. cukooによる解析

cuckooではAPIコールの傾向についての情報を抽出します。多くのAPIコールは1秒で完了するため、5秒以上経っても完了しないものについてはテストの対象外としたそうです。

3. jubatusによる学習/解析

APIコールを3-gramモデルによって解析し、正常/異常のラベル(条件)を登録。(N-gramのNが3なのは、3-gramの精度が一番よかったからとのこと)
「VirtualProtectEX(難読化を解除するAPIコール)というAPIコールが3回続いたらマルウェアの動き」というようにラベルを登録して学習モデルを作成して行きます。
コマンドライン上から、ラベル情報(正常系/異常系)を元に学習モデルをダンプできるようです。→人間がモデルのダンプを確認して新ロジックを開発!

4. クラスタリングによる分類

マルウェアクラスタリング(グルーピング)し、ユニークデータを抽出(亜種や新種である可能性を見極める)することで、優先して解析すべき検体の選定を行え、解析の効率化が可能となります。

適用に伴う弊害
  • 学習データ/評価データの傾向が著しく異なる場合、分類精度が著しく低下する。
  • 正常系のソフトウェアは類似度の分布が広いため、学習データ/評価データの精度が違う可能性あり。

要するに、こういうことでしょうか?

  • ユニークなデータを学習データやテストデータにする割合が増える→誤検知率(FPR)が上がる
  • 亜種情報が増える→正しい検知率(TPR)が上がる
  • 質のいいデータを集めるべき


感想

  • 未知のマルウェア/カスタムマルウェア機械学習によって判別するのは難しい。今回村上さんにお話いただいた特徴とは別のファクターを考える必要あり。
  • 学習するためのサンプルデータ集めが死ぬほど大変そう。
  • この手の話はいたちごっこだから低コストでサンドボックスを自作しようなんて甘い考えは捨てて、専門家集団に任せる。自分たちが考えなければいけないのはマルウェア発見時の運用フロー。(とは言うもののマルウェアと判断することがきる人員の育成/確保もできた方がいいかも)
  • 個人で遊ぶ分にはjubatus面白そう!



勉強会の運営スタッフのみなさま、各セッションで登壇いただいたみなさま、本当にありがとうございました。ドーナツ美味しかったです!

おまけ

香川と言ったらうどん。高松市のうどん屋ってなかなか探すのに苦労しますよね。
セキュリティうどんの公式サイトに掲載されているうどんマップが参考になりました。

より大きな地図で うどんマップ を表示
http://sec-udon.jpn.org/doku.php?id=%E3%83%AA%E3%83%B3%E3%82%AF:%E3%81%86%E3%81%A9%E3%82%93%E3%83%9E%E3%83%83%E3%83%97

*1:パターンマッチングとは、マルウェア検知用のデータベースにウィルスの情報を登録して、その情報と検査対象のファイルを突き合わせることでマルウェア判定する手法のこと。

ArduinoとRaspberry Piで作るスマート家電(寝返り扇風機)(3)

前回の記事の続きです。もうちょっとで完成なので頑張りましょう。はやく快適な夏の夜を手に入れようぜ!

Arduinoで扇風機の電源切り替え

 Raspberry Piから寝返り通知を受け取ったらサーボモータが動くようにしましょう。下記サンプルコードを新しいスケッチに貼付けてArduinoに書き込みましょう。(通信内容自体は全く見ていない残念なコードです。)※XBeeシールドを接続したままではスケッチの書き込みに失敗するので注意が必要です。

#include <Servo.h>
#define RUNTIME 10 // ここで扇風機の稼働時間(秒)調節できます

Servo myservo;

unsigned long latest_time; // 現座時刻を保存する変数
unsigned long int_time; // 扇風機を稼働し始めた時間を保存する変数
double passed_time; // 経過時間を保存する変数
int mode=0; // 0で大気状態、1で稼働状態を表す

//
// 初期化関数
//
void setup(){
  myservo.attach(9); // 9番のアナログ出力ピンを使用してサーボモータを操作する
  myservo.write(5); // サーボモータのプロペラの初期角度
  Serial.begin(9600); // ログをシリアルモニタに表示させる
}

//
// メインループ
//
void loop(){
 
 // Raspberry Piからシリアルパケットを受け取った場合の処理
 if(Serial.available() > 0){
    mode = 1; // 稼働状態に切り替え
    int_time = millis(); // 現在時刻を取得
    myservo.write(50); // プロペラの角度を変更(扇風機のスイッチをオンにする)
    Serial.read();
 } 
 
 // 扇風機が稼働中の場合の処理
 if(mode == 1){
   latest_time = millis(); // 現在時刻を取得
   passed_time = (double)(latest_time - int_time) / 1000.0; // 経過時間を算出
   Serial.print(passed_time);
   Serial.print("\n");
  
   // 一定時間が経過したら扇風機の電源をオフにする 
   if(passed_time >= RUNTIME) {
      mode = 0; // 待機状態にに切り替える
      myservo.write(5); // プロペラの角度を変更する(扇風機の電源をオフにする)
   }
 }
  
}


 下記サイトを参考に接続してください。ジャンパワイヤが3本必要です。
糞の足しにもならないArduino講座:その3

 こんな感じで泥臭く接着しました。AndroidのUSBアダプタを犠牲にして高さを調節しています。
f:id:si871137:20130727181020j:plain

 これでArduino側の準備は完了です。
f:id:si871137:20130728154230j:plain

  • WEBサーバーを起動

 起動したらスマホからWEBサーバ(http://192.168.64.42:11337)に接続して、スマホを振って振動を与えてみましょう。サーボモータのプロペラが回転して扇風機が回り始めるはずです。あと、実際にベッドで使用する際の注意なのですが、スマホのディスプレイ電源の自動オフ機能は切っておいてください。

root@raspberrypi:/var/node/negasen# node app.js
   info  - socket.io started




最初の記事でお見せした感じで動きましたか?




振り返り

2013年度の目標が「電子工作デビュー」だったので、なんとか目標達成のボーダーは超えられたんじゃないかと思います。それにしてもグーグル先生は偉大ですね。Arduinoに関する情報は少ないものの、欲しい情報はほとんど無料で手に入ってしまうなんて。ほんと、すごい時代に生まれてきてしまったなあ、と今更ながら感動しております。

失敗談的なもの

実はサーボモータを使う前に、ソリッドステート・リレーという技術を使って電源のON/OFF機能を実現しようとしていました。(参考:連載(26)Arduinoで何でも制御 いろんなArduinoがある(8))電源ケーブルのカバーを剥いて、はんだ付けなんかにも初挑戦したのですが、結果的に失敗に終わってしまいました。得られたものは ”感電しかけたという経験” のみでした。次に電子工作を挑戦する機械があったらはんだ付けに再チャレンジしてみようと思います。

参考書籍(おまけ)

 数少ないArduinoの入門書です。内容の半分はリファレンスなのでどんな機能があるのか確認することができます。

 OSのインストール手順から、Webカメラを使った警備システムの構築方法まで幅広い内容が掲載されてます。解説が丁寧なのがいいですね。

 Arduinoでスマート家電以外のものは作れるの?と興味を持った方におすすめ。これを機に電子工作をはじめてみてはいかがでしょうか。

 今回は超簡単な電子回路しか組みませんでしたが、もっと面白いものを作ろうと思ったら電子回路の基礎知識を学ぶ必要があると思います。「電池をなめて電気を味わう」ところからはじめる面白い技術書です。

ArduinoとRaspberry Piで作るスマート家電(寝返り扇風機)(2)




前回の続き記事です。Raspberry PIでWEBサーバを構築して、ソケット通信を試してみましょう。しれっと途中でXBeeの設定なんかも挟んでいますが、気にしないでください。

OSのインストール

1. 自分の作業用PCの環境に合った「SD Formatter」をダウンロードする。
2. 「SD Formatter」でOSをインストールするSDカードをフォーマットする。
3. こちら からOSのインストールツール「NOOBS」をダウンロードする。圧縮ファイルになっているので予め解凍しておく。
4. 解凍してできたファイルをすべて選択し、SDカードにコピーする。
5. Raspberry Pi に挿し込む。
6. HDMIケーブル(対向には電源オン状態のディスプレイを接続)、LANケーブル、USBキーボード、を Raspberry Pi に接続してから、microUSB電源ケーブル(対向には2AのUSBアダプタを接続)を接続する。(Raspberry Pi には電源ボタンが存在しないので、電源ケーブルうを接続した瞬間に電源がオンになります。)
7. インストールメニュー画面が表示されたら、Raspbianを選択し、インストールを開始する。
8. キーボードとタイムゾーンの設定
[Configure keyboard]>[Generic 105-key(Intl) PC]>[Other]>[Japanese]>[Japanese]>[The default for the keyboard layout]>[No compose key]>[No]
[change_timezone]>[Asia][Tokyo]

初期設定

  • rootユーザのパスワードを設定し、スイッチする
pi@raspberrypi ~ $ sudo passwd root
新しいUNIXパスワードを入力してください:
新しいUNIX パスワードを再入力してください:
passwd: パスワードは正しく更新されました
pi@raspberrypi ~ $ su -
パスワード:
root@raspberrypi:~# 


  • ネットワークの設定

 自分の環境ではデフォルト設定のDHCPを使用しています。一応、設定ファイルの中身を記載しておきます。

root@raspberrypi:~# cat /etc/network/interfaces 
auto lo

iface lo inet loopback
allow-hotplug eth0
iface eth0 inet dhcp

allow-hotplug wlan0
# iface wlan0 inet manual
iface wlan0 inet dhcp 
# wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet d


  • アップデート
root@raspberrypi:~# apt-get update


  • vimのインストール

 Raspbianには初期でvimがインストールされています。しかし、これの実体は最低限の機能のみを持ったvim-tinyであり、今一つ使い勝手が良くありません。なので、普通のvimをインストールしましょう。

root@raspberrypi:~# apt-get install vim


  • 作業用PCからSSHログイン

特に不要な作業ですが、慣れ親しんだ環境で作業したい場合や、ログを編集しながら作業をしたい場合にこの手順を実施してください。ifconfigを実行し、表示されたinetアドレスに作業用PCにインストールしたTera Term(macならターミナル)などからSSHしましょう。

root@raspberrypi:~# ifconfig
eth0      Link encap:イーサネット  ハードウェアアドレス *********
          inetアドレス:192.168.64.42 ブロードキャスト:192.168.64.255  マスク:255.255.255.0


Node.jsの設定

  • Node.jsのインストール
root@raspberrypi:~# git clone https://github.com/creationix/nvm.git ~/.nvm
root@raspberrypi:~# source ~/.nvm/nvm.sh
root@raspberrypi:~# nvm install v0.10.4
root@raspberrypi:~# node -v
v0.10.4  
root@raspberrypi:~# npm -v
1.2.18
root@raspberrypi:~# nvm alias default 0.10.4
default -> 0.10.4 (-> v0.10.4)
root@raspberrypi:~# echo 'source ~/.nvm/nvm.sh' >> .bashrc 


  • 作業用ディレクトリの作成
root@raspberrypi:~# mkdir -p /var/node/negasen
root@raspberrypi:~# cd /var/node/negasen


  • socket.ioのインストール

 Node.js⇔他デバイス間でのソケット通信を可能にするライブラリです。

root@raspberrypi:/var/node/negasen# npm install -g socket.io


  • node-serialportのインストール

 Node.jsでシリアルポートを制御できるようにしたライブラリです。

root@raspberrypi:/var/node/negasen# npm install serialport


XBee連携

  • 初期設定

 下記サイトにて、準備していた2個のXBeeモジュールがお互いを認識し、通信が行えるように初期設定をする。※WindowsのPCが必要になります。
 XBeeをはじめてみよう(ZB編)

WEBアプリ作成

  • Node.jsのメイン処理部分を「app.js」というファイル名で作成
root@raspberrypi:/var/node/negasen# vi app.js
root@raspberrypi:/var/node/negasen# cat app.js
var http = require("http");
var socketIO = require("socket.io");
var fs = require("fs");

// クライアントからアクセスが会った場合に表示させるページを指定
var server = http.createServer(function (req, res) {
	res.writeHead(200, {"Content-Type":"text/html"});
	var output = fs.readFileSync("./negasen.html", "utf-8");
	res.end(output);
});
server.listen(11337);

// シリアルポートの設定
var serialport = require('serialport');
var SerialPort = serialport.SerialPort;
var sp = new SerialPort('/dev/ttyUSB0', {
	parser: serialport.parsers.readline('\r\n')
});

var io = socketIO.listen(server);

// 接続中の処理
io.sockets.on("connection", function (socket) {
	console.log("connected");

	// スマホからWebSocketのパケットが来た時の処理
 	socket.on('value', function(data) {
                console.log(data);
		// 書き込みデータをつくって
  		var xbeewrite = ["ON", Math.pow(2,data.value)-1];
  		// XBeeに送信
  		sp.write(xbeewrite);
	});

	// 取得させて加速度をブロードキャストしてブラウザに表示させる
	socket.on("accel", function(accel) {
	socket.broadcast.emit("accel", accel);
	});

});


  • WEBアプリの表示部分を「negasen.html」というファイル名で作成

 ソケット通信関連のコードは下記記事を参考にしています。
 [node] socket.IOとHTML5 Canvasを用いた手書きチャットアプリを作ってみた

root@raspberrypi:/var/node/negasen# vi negasen.html
root@raspberrypi:/var/node/negasen# cat negasen.html
<html>
<head>
  <meta charset="utf-8">
  <title>Negaeri Senpuuki</title>
</head>
<body>
  <!-- Header -->
  <h1 class="title">Negaeri Senpuuki</h1>

  <!-- Main -->
  <script src="/socket.io/socket.io.js"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
  <script type="text/javascript">
    window.addEventListener("load", function () {

      // サーバーサイドのsocket.IOに接続する
      // 接続出来たら、サーバー側のコンソールにconnected!と表示させる
      var socket = io.connect("/");

      var $id = function(id)
      {
        return document.getElementById(id);
      }

      window.addEventListener('devicemotion', function(e){

        // 重力加速度(3軸)
        var gravity = e.accelerationIncludingGravity;
        $id("gravity").innerHTML = gravity.x + ', ' + gravity.y + ', ' + gravity.z;
        // 加速度(3軸)
        var accele = e.acceleration;
        $id("accele").innerHTML = accele.x + ', ' + accele.y + ', ' + accele.z;
        // 回転加速度
        var rotation = e.rotationRate;
        $id("rotation").innerHTML = rotation.alpha + ', ' + rotation.beta + ', ' + rotation.gamma;

        socket.emit("accel", {gravity:gravity, accele:accele, rotation:rotation});

        // 寝返りを打った場合(加速度センサーで取得した値gしきい値を超えた場合)のみArduinoに通信を行う
        // 評価に使用する加速度やしきい値は調整の必要があるかも
        if (gravity.x >= 2 || gravity.y <= -2) {
            socket.emit("value", "P1");
        }

      });

      socket.on("accel", function (accel) {

        // 重力加速度(3軸)
        var gravity = accel.gravity;
        $id("gravity").innerHTML = gravity.x + ', ' + gravity.y + ', ' + gravity.z;
        // 加速度(3軸)
        var accele = accel.accele;
        $id("accele").innerHTML = accele.x + ', ' + accele.y + ', ' + accele.z;
        // 回転加速度
        var rotation = accel.rotation;
        $id("rotation").innerHTML = rotation.alpha + ', ' + rotation.beta + ', ' + rotation.gamma;

      });

    }, false);         

  </script>

重力加速度(3軸)<br>
  <div id="gravity"></div>
加速度(3軸)<br>
  <div id="accele"></div>
回転加速度<br>
  <div id="rotation"></div>

</body>
</html>


  • 実行

 下記コマンドを実行して、Wi-Fiルータに接続済みのスマホからWEBサーバに接続(http://192.168.64.42:11337)してみましょう。ソケット通信の確認用にPCのブラウザからもWEBサーバにアクセスしておくといいかもしれません。
IPアドレス部分は自分が構築したサーバのものに置き換えてください。

root@raspberrypi:/var/node/negasen# node app.js
   info  - socket.io started



うまく動けばの↓のような動作をします。iPad miniで試してみたのですが、加速度センサーがついてるデバイスなら何でもOKみたいです。





ちなみに、Raspberry Pi はこんな感じで衣装棚の上で動いてます。コンパクトでいいですねえ。
f:id:si871137:20130720224409j:plain


次回はいよいよ、Arduinoをいじってサーボモータを動かします。