はじめに
我が家はNode-redでスマートハウス-LG製テレビを操作してみるで書いたように、テレビなどの家電をAamazon echoから操作するためにnode-red-contrib-alexa-localを使っていた。
しかし、2019年9月初旬、今まで動いていたものが突然動かなくなった!!!node-redの画面を見ると各デバイスの状況が「Discovery」になっている(正常時はOnline)!
原因:Amazon echo側の仕様変更
Alexa-localのGitHub Issueの情報によると、Amazon echo側の仕様変更により、今まではAmazon echoがデバイスを探す時に、同じネットワーク内のホストの全てのポートをスキャンしていたようだが、今回の仕様変更により「80」番ポートだけがスキャン対象になったとのこと。Alexa-localでは、各デバイスごとに待ち受けポートを複数開いてListenしているため、Alexa-localのやり方では複数のデバイスを操作することはできなくなった。
解決策:node-red-contrib-amazon-echoに乗り換え
node-red-contrib-amazon-echoという、仮想的なハブ「Amazon Echo Hub」を経由して各デバイスを操作するものに乗り換えることで解決できそうです。
node-red-contrib-amazon-echoもインターネット経由ではなく完全ローカルで動作するので、node-red-contrib-alexa-home-skillなどインターネット経由のものと比較して、動作が速い&セキュリティ的に安全というのがポイントです。
ポート80の競合問題
Amazon Echoの新仕様では、デバイスのスキャンは80番ポート限定になったので、node-red-contrib-amazon-echoを使って、「Amazon Echo Hub」を80番ポートで公開するという仕様になる。
しかし、80番ポートは、大体の場合ApacheなどWebサーバが使用しているため、他のプロセスはこのポートを使用できない。Webサーバ側のポートを変えるのはいろいろと使いづらくなるので、「Amazon Echo Hub」側を変更するしかない。でも、Amazon echoは80番ポートしかスキャンしてくれない。さて、どうするか。
全体構成
解決策の全体構成は、以下の図の通り。1つのLinuxOSの中で、複数のプロセスが1つのポートを利用する事は不可である。このため「Amazon Echo Hub」は81番ポートで動作させるが、1つのNICに2つ目のIPアドレスを追加し、追加したIPアドレスの80番ポートへのリクエストを81番ポートに転送する。
IPアドレスの追加
私が利用しているUbuntsu 18.4の場合、/etc/netplan/50-cloud-ini.yamlに記載することで、1つのNICに複数のIPアドレスを割り当てることが可能である。
1 2 3 4 5 6 7 8 9 10 11 |
network: version: 2 ethernets: ens192: addresses: - 192.168.0.1/24 - 192.168.0.2/24 ←これを追加!!! dhcp4: false nameservers: addresses: [192.168.0.1] optional: true |
ファイルに追記して保存したら、設定を反映して確認する。
1 2 3 4 5 6 7 8 9 |
# netplan apply # ip a 〜〜〜省略〜〜〜 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff inet 192.168.0.1/24 brd 192.168.0.255 scope global noprefixroute ens192 valid_lft forever preferred_lft forever inet 192.168.0.2/24 brd 192.168.0.255 scope global secondary noprefixroute ens192 valid_lft forever preferred_lft forever |
以上のように、NICに2つ目のIPアドレスが追加された。
ApacheのListen IPアドレスの限定
Apacheはデフィルトの設定では、全てのIPアドレスの80番ポートでListenする。これを、192.168.0.1だけListenするように「/etc/apache2/ports.conf」変更する。なお、443ポートは特に変更の必要はないが、80番ポートと揃ってないと気持ち悪いので合わせて変更。
1 2 3 4 5 6 7 8 9 10 11 12 |
#Listen 80 ←こっちになっていたのを Listen 192.168.0.1:80 ←こっちに書き換える <IfModule ssl_module> #Listen 443 ←こっちになっていたのを Listen 192.168.0.1:443 ←こっちに書き換える </IfModule> <IfModule mod_gnutls.c> #Listen 443 ←こっちになっていたのを Listen 192.168.0.1:443 ←こっちに書き換える </IfModule> |
書き換えたら、設定を反映し、Telnetコマンドで片方だけ接続できるか確認。
1 2 3 4 5 6 7 8 9 10 |
# systemctl restart apache2 # telnet 192.168.0.1 80 Trying 192.168.0.1... Connected to 192.168.0.1. Escape character is '^]'. ←こっちのIPアドレスではちゃんと接続できる # telnet 192.168.0.2 80 Trying 192.168.0.2... telnet: Unable to connect to remote host: Connection refused ←こっちは接続できない # |
Amazon echo Hubの待ち受けポート変更
node-redに追加したAmazon Echo Hubノードをダブルクリックし、ポートの設定を81番ポートに変更する。
iptablesでポートを転送
最後にiptablesを使って、192.168.0.2の80番ポートに来たリクエストを81番ポートに転送する設定を行う。
1 2 |
# iptables -t nat -A PREROUTING -p tcp -d 192.168.0.2 --dport 80 -j REDIRECT --to-port 81 # |
これで設定は完了。Amazon Echoでデバイスを検索すれば、設定したデバイスが見つかるはずである。
iptablesの設定は再起動すると消えてしまうので「/etc/iptables/rules.v4」への記載もお忘れなく。
コメント