クラウドアシスタントを使ってみる #2 仕組み解明編

この記事は Alibaba Cloud の日本サイト の環境(ドキュメントやアカウント、そのアカウントでの検証結果)に基づいて記載しています。 日本サイトと国際サイトでは各プロダクトごとに提供機能が一部異なることがあります(そのほとんどは国際サイトの方が日本サイトよりも多機能になっている)。記事の内容は適宜最新化する予定です。

先日Alibaba Cloud ECSのリモート管理機能のクラウドアシスタントを紹介しました。 

しかし、以下の2つの仕組みが不明となっていました。 今回はこの不明点を明らかにしていきます。

  1. どのサービス(daemon)で動いているのか?
  2. どこからどうやってECSへ命令を送っているのか?

どのサービス(daemon)で動いているのか?

公式ドキュメントに答えがありました。 ”AliyunService”とのことです。 Linux上のサービス名は”aliyun-service”となります。

URLはこちら

さらに前回の調査では私自身の確認の手順に間違いがありました。 今見たらgrepで”-E”を指定することなく正規表現を使っています。 本当は”rpm -aq | grep -E “aliyun*””とするのが正解です。恥ずかしい間違いですね。

https://bigriver.jp/?p=2996

もう一度確認します。”aliyun_assist-1.0.1.308-1.noarch”がインストールされていることが確認出来ました。

[root@sun ~]# rpm -qa |grep -E aliyun*
aliyun_assist-1.0.1.308-1.noarch
[root@sun ~]#

次にこの ”aliyun_assist-1.0.1.308-1.noarch”の中身を見てみましょう。 インストール先は”/usr/local/share/aliyun-assist”となっており、合計39個のファイルで構成されていることがわかりました。

[root@sun ~]# rpm -ql aliyun_assist
/usr/local/share/aliyun-assist/1.0.1.308/aliyun-service
/usr/local/share/aliyun-assist/1.0.1.308/aliyun_assist_update
/usr/local/share/aliyun-assist/1.0.1.308/aliyun_installer
/usr/local/share/aliyun-assist/1.0.1.308/config/GlobalSignRootCA.crt
/usr/local/share/aliyun-assist/1.0.1.308/config/host.conf
/usr/local/share/aliyun-assist/1.0.1.308/init/data/alios/service/agentwatch.cent6
/usr/local/share/aliyun-assist/1.0.1.308/init/data/alios/service/agentwatch.cent7
/usr/local/share/aliyun-assist/1.0.1.308/init/data/alios/service/agentwatch.rhel5
/usr/local/share/aliyun-assist/1.0.1.308/init/data/aliyun/service/agentwatch.cent6
/usr/local/share/aliyun-assist/1.0.1.308/init/data/centos/service/agentwatch.cent6
/usr/local/share/aliyun-assist/1.0.1.308/init/data/centos/service/agentwatch.cent7
/usr/local/share/aliyun-assist/1.0.1.308/init/data/centos/service/agentwatch.rhel5
/usr/local/share/aliyun-assist/1.0.1.308/init/data/debian/service/agentwatch.debian7
/usr/local/share/aliyun-assist/1.0.1.308/init/data/debian/service/agentwatch.debian8
/usr/local/share/aliyun-assist/1.0.1.308/init/data/debian/service/agentwatch.debian9
/usr/local/share/aliyun-assist/1.0.1.308/init/data/debian/service/aliyun.service
/usr/local/share/aliyun-assist/1.0.1.308/init/data/opensuse/service/agentwatch.opensuse
/usr/local/share/aliyun-assist/1.0.1.308/init/data/redhat/service/agentwatch.cent6
/usr/local/share/aliyun-assist/1.0.1.308/init/data/redhat/service/agentwatch.cent7
/usr/local/share/aliyun-assist/1.0.1.308/init/data/redhat/service/agentwatch.rhel5
/usr/local/share/aliyun-assist/1.0.1.308/init/data/suse/service/agentwatch.suse
/usr/local/share/aliyun-assist/1.0.1.308/init/data/ubuntu/service/agentwatch.ubuntu12
/usr/local/share/aliyun-assist/1.0.1.308/init/data/ubuntu/service/agentwatch.ubuntu16
/usr/local/share/aliyun-assist/1.0.1.308/init/install
/usr/local/share/aliyun-assist/1.0.1.308/init/install_service
/usr/local/share/aliyun-assist/1.0.1.308/init/script/alios/common/update_service
/usr/local/share/aliyun-assist/1.0.1.308/init/script/aliyun/common/update_service
/usr/local/share/aliyun-assist/1.0.1.308/init/script/centos/common/update_service
/usr/local/share/aliyun-assist/1.0.1.308/init/script/common/identify_issue_version
/usr/local/share/aliyun-assist/1.0.1.308/init/script/debian/common/update_service
/usr/local/share/aliyun-assist/1.0.1.308/init/script/opensuse/common/update_service
/usr/local/share/aliyun-assist/1.0.1.308/init/script/redhat/common/update_service
/usr/local/share/aliyun-assist/1.0.1.308/init/script/suse/common/update_service
/usr/local/share/aliyun-assist/1.0.1.308/init/script/ubuntu/common/update_service
/usr/local/share/aliyun-assist/1.0.1.308/init/script/update_service
/usr/local/share/aliyun-assist/1.0.1.308/init/uninstall
/usr/local/share/aliyun-assist/1.0.1.308/init/version
/usr/local/share/aliyun-assist/1.0.1.308/update_install
/usr/local/share/aliyun-assist/version

デーモンの実体はドキュメントからも”aliyun-service”とわかっています。サービスの状態も確認します。

[root@sun ~]# systemctl status aliyun.service
● aliyun.service – auto run aliyunservice or agent
Loaded: loaded (/etc/systemd/system/aliyun.service; disabled; vendor preset: disabled)
Active: active (running) since Wed 2019-02-27 22:54:20 CST; 22h ago
Main PID: 31103 (aliyun-service)
CGroup: /system.slice/aliyun.service
mq31103 /usr/sbin/aliyun-service
Feb 27 22:54:20 sun systemd[1]: Started auto run aliyunservice or agent.
Feb 27 22:54:20 sun systemd[1]: Starting auto run aliyunservice or agent…

とりあえず、クラウドアシスタントのサービス(daemon)は”
/usr/local/share/aliyun-assist/1.0.1.308/aliyun-service ”と判明しました。

どこからどうやってECSへ命令を送っているのか?

次は、Alibaba Cloudコンソールで定義したジョブはどのような方法でECSインスタンスに投入されているのかを明らかにします。

先ほどの調査でaliyun-serviceは ”/usr/local/share/aliyun-assist” にインストールされていることがわかっています。 ディレクトリ配下を見てみると”log”フォルダがあることが確認出来ました。。 昨日はパケットキャプチャをもとに挙動を明らかにしようと考えました。今日はログから調べてみることにします。

”log”フォルダの中には ”aliyun_assist_main_XXXXX.log”と”aliyun_assist_update_XXXXX.log” の2種類あることがわかります。

[root@sun log]# cd /usr/local/share/aliyun-assist/1.0.1.308/log
[root@sun log]# ls
aliyun_assist_main_201902130035.log aliyun_assist_update_201902130035.log
aliyun_assist_main_201902140036.log aliyun_assist_update_201902140036.log
aliyun_assist_main_201902150036.log aliyun_assist_update_201902150036.log
aliyun_assist_main_201902160036.log aliyun_assist_update_201902160036.log
aliyun_assist_main_201902170037.log aliyun_assist_update_201902170037.log
aliyun_assist_main_201902180037.log aliyun_assist_update_201902180037.log
aliyun_assist_main_201902190038.log aliyun_assist_update_201902190038.log
aliyun_assist_main_201902200038.log aliyun_assist_update_201902200038.log
aliyun_assist_main_201902210038.log aliyun_assist_update_201902210038.log
aliyun_assist_main_201902220039.log aliyun_assist_update_201902220039.log
aliyun_assist_main_201902230039.log aliyun_assist_update_201902230039.log
aliyun_assist_main_201902240040.log aliyun_assist_update_201902240040.log
aliyun_assist_main_201902250040.log aliyun_assist_update_201902250040.log
aliyun_assist_main_201902260040.log aliyun_assist_update_201902260040.log
aliyun_assist_main_201902270054.log aliyun_assist_update_201902270054.log
aliyun_assist_main.log aliyun_assist_update.log

”aliyun_assist_update.log”はおそらくサービス(daemon)のプログラムの更新のログと推測されます。

ログを見てみます。ログだけでは確実なことは言えませんが1時間に1回程度最新のUpdateを探して、なければ1時間後に再試行という感じでしょうか。

[root@sun log]# tail -10 aliyun_assist_update.log
2019-02-28 11:54:41,005 INFO [default] LOG INITIALISED
2019-02-28 11:54:41,005 INFO [default] process begin…
2019-02-28 11:54:41,059 INFO [default] check update response:{“flag”:0,”need_update”:0,”next_interval”:600000,”update_info”:null}
2019-02-28 11:54:41,060 INFO [default] not need update
2019-02-28 11:54:41,060 INFO [default] LOG FINALISED
2019-02-28 12:54:42,005 INFO [default] LOG INITIALISED
2019-02-28 12:54:42,005 INFO [default] process begin…
2019-02-28 12:54:42,055 INFO [default] check update response:{“flag”:0,”need_update”:0,”next_interval”:600000,”update_info”:null}
2019-02-28 12:54:42,055 INFO [default] not need update
2019-02-28 12:54:42,055 INFO [default] LOG FINALISED

次に”aliyun_assist_main.log”を見てみます。 こちらも1時間毎にFetch処理をおこなっているようです。 1秒ごとに実行されていれば、ECSインスタンスからジョブを探しにいっている可能性があったのですが、その可能性は無さそうです。あまり参考になりませんでした。

[root@sun log]# tail -20 aliyun_assist_main.log
2019-02-28 03:54:33,032 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 03:54:33,057 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 04:54:34,025 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 04:54:34,047 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 05:54:35,032 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 05:54:35,048 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 06:54:36,057 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 06:54:36,073 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 07:54:37,027 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 07:54:37,051 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 08:54:38,042 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 08:54:38,060 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 09:54:39,028 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 09:54:39,051 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 10:54:40,043 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 10:54:40,065 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 11:54:41,025 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 11:54:41,044 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 12:54:42,027 INFO [default] Fetch 0 Tasks response is: []
2019-02-28 12:54:42,053 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks

ログからはあまり有用な情報は得られなかったので前回記事同様にネットワーク視点で調査することとします。

まずは”Alibaba Cloud側からECSインスタンスに命令を送っている”という仮説を前提にListenしているポートとサービスを確認します。

DHCPクライアントとNTPとSSHしかありませんでした。

[root@sun log]# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
dhclient 685 root 6u IPv4 12435 0t0 UDP *:bootpc
dhclient 685 root 20u IPv4 12403 0t0 UDP *:mcer-port
dhclient 685 root 21u IPv6 12404 0t0 UDP *:32863
ntpd 764 ntp 16u IPv4 13075 0t0 UDP *:ntp
ntpd 764 ntp 17u IPv6 13077 0t0 UDP *:ntp
ntpd 764 ntp 18u IPv4 13082 0t0 UDP localhost:ntp
ntpd 764 ntp 19u IPv4 13083 0t0 UDP sun:ntp
sshd 938 root 3u IPv4 14197 0t0 TCP *:ssh (LISTEN)
sshd 938 root 4u IPv6 14199 0t0 TCP *:ssh (LISTEN)
sshd 32670 root 3u IPv4 700562 0t0 TCP sun:ssh->XXXX (ESTABLISHED)

再度パケットキャプチャすることとします。昨日は”grep -v ssh”とSSHをすべて除外していまいた。 今日は、SSHで接続されていないかをまずは確認します。

私が接続しているSSH接続のみ”grep -v”で除外しています。結果ですが、昨日と同様にクラウドアシスタント側でジョブを実行後にDNS名前解決したあとに、ECSインスタンス側から”100.100.0.76”にhttpsで接続しにいっています。 SSHでは無いことはわかりました。

root@sun log]# tcpdump |grep -v XXXXXXXXX
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
21:52:42.364846 IP sun.38386 > 100.100.2.138.domain: 21866+ PTR? 104.202.83.118.in-addr.arpa. (45)
21:52:42.365225 IP sun.39794 > 100.100.2.136.domain: 47566+ PTR? 138.2.100.100.in-addr.arpa. (44)
21:52:42.365417 IP 100.100.2.136.domain > sun.39794: 47566 NXDomain* 0/1/0 (99)
21:52:42.365963 IP sun.56124 > 100.100.2.138.domain: 47446+ PTR? 136.2.100.100.in-addr.arpa. (44)
21:52:42.366212 IP 100.100.2.138.domain > sun.56124: 47446 NXDomain* 0/1/0 (99)
21:52:52.885519 IP sun.ntp > 10.143.33.50.ntp: NTPv4, Client, length 48
21:52:52.885660 IP sun.60722 > 100.100.2.136.domain: 23025+ PTR? 50.33.143.10.in-addr.arpa. (43)
21:52:52.885966 IP 100.100.2.136.domain > sun.60722: 23025 NXDomain* 0/1/0 (93)
21:53:00.655902 ARP, Request who-has sun tell gateway, length 28
21:53:00.655922 ARP, Reply sun is-at 00:16:3e:00:28:3a (oui Unknown), length 28
21:53:00.656077 IP sun.45744 > 100.100.2.138.domain: 30669+ PTR? 253.223.24.172.in-addr.arpa. (45)
21:53:00.656350 IP 100.100.2.138.domain > sun.45744: 30669 NXDomain* 0/1/0 (99)
21:53:01.265300 IP sun.48318 > 100.100.2.138.domain: 40824+ AAAA? ap-northeast-1.axt.aliyun.com. (47)
21:53:01.265448 IP 100.100.2.138.domain > sun.48318: 40824* 0/1/0 (120)
21:53:01.265488 IP sun.35655 > 100.100.2.136.domain: 48552+ AAAA? ap-northeast-1.axt.aliyun.com. (47)
21:53:01.265606 IP 100.100.2.136.domain > sun.35655: 48552* 0/1/0 (120)
21:53:01.265623 IP sun.33668 > 100.100.2.138.domain: 33047+ A? ap-northeast-1.axt.aliyun.com. (47)
21:53:01.265706 IP 100.100.2.138.domain > sun.33668: 33047* 1/0/0 A 100.100.0.76 (63)
21:53:01.265747 IP sun.45740 > 100.100.0.76.https: Flags [S], seq 1778821093, win 29200, options [mss 1460,sackOK,TS val 324191357 ecr 0,nop,wscale 6], length 0
21:53:01.265823 IP sun.47746 > 100.100.2.136.domain: 42923+ PTR? 76.0.100.100.in-addr.arpa. (43)
21:53:01.266095 IP 100.100.2.136.domain > sun.47746: 42923 NXDomain* 0/1/0 (98)
21:53:01.267795 IP 100.100.0.76.https > sun.45740: Flags [S.], seq 3661687012, ack 1778821094, win 29200, options [mss 1440,nop,nop,sackOK,nop,wscale 7], length 0
21:53:01.267810 IP sun.45740 > 100.100.0.76.https: Flags [.], ack 1, win 457, length 0
21:53:01.268073 IP sun.45740 > 100.100.0.76.https: Flags [P.], seq 1:518, ack 1, win 457, length 517
21:53:01.270004 IP 100.100.0.76.https > sun.45740: Flags [.], ack 518, win 237, length 0
21:53:01.271295 IP 100.100.0.76.https > sun.45740: Flags [P.], seq 1:3494, ack 518, win 237, length 3493
21:53:01.271301 IP sun.45740 > 100.100.0.76.https: Flags [.], ack 3494, win 566, length 0
21:53:01.275724 IP sun.45740 > 100.100.0.76.https: Flags [P.], seq 518:644, ack 3494, win 566, length 126
21:53:01.277919 IP 100.100.0.76.https > sun.45740: Flags [P.], seq 3494:3545, ack 644, win 237, length 51
21:53:01.278343 IP sun.45740 > 100.100.0.76.https: Flags [P.], seq 644:821, ack 3545, win 566, length 177
21:53:01.295416 IP 100.100.0.76.https > sun.45740: Flags [P.], seq 3545:4414, ack 821, win 245, length 869
21:53:01.295498 IP sun.45740 > 100.100.0.76.https: Flags [P.], seq 821:852, ack 4414, win 610, length 31
21:53:01.295544 IP sun.45740 > 100.100.0.76.https: Flags [F.], seq 852, ack 4414, win 610, length 0
21:53:01.295861 IP sun.43709 > 100.100.2.136.domain: 23402+ AAAA? ap-northeast-1.axt.aliyun.com. (47)
21:53:01.295956 IP 100.100.2.136.domain > sun.43709: 23402* 0/1/0 (120)
21:53:01.295994 IP sun.41414 > 100.100.2.138.domain: 61771+ AAAA? ap-northeast-1.axt.aliyun.com. (47)
21:53:01.296123 IP 100.100.2.138.domain > sun.41414: 61771* 0/1/0 (120)
21:53:01.296143 IP sun.57032 > 100.100.2.136.domain: 63997+ A? ap-northeast-1.axt.aliyun.com. (47)
21:53:01.296240 IP 100.100.2.136.domain > sun.57032: 63997* 1/0/0 A 100.100.0.76 (63)
21:53:01.296281 IP sun.45742 > 100.100.0.76.https: Flags [S], seq 3835942220, win 29200, options [mss 1460,sackOK,TS val 324191364 ecr 0,nop,wscale 6], length 0
21:53:01.297541 IP 100.100.0.76.https > sun.45740: Flags [F.], seq 4414, ack 852, win 245, length 0
21:53:01.297548 IP sun.45740 > 100.100.0.76.https: Flags [.], ack 4415, win 610, length 0
21:53:01.297551 IP 100.100.0.76.https > sun.45740: Flags [.], ack 853, win 245, length 0
21:53:01.297821 IP 100.100.0.76.https > sun.45742: Flags [S.], seq 2151069524, ack 3835942221, win 29200, options [mss 1440,nop,nop,sackOK,nop,wscale 7], length 0
21:53:01.297827 IP sun.45742 > 100.100.0.76.https: Flags [.], ack 1, win 457, length 0
21:53:01.298060 IP sun.45742 > 100.100.0.76.https: Flags [P.], seq 1:518, ack 1, win 457, length 517
21:53:01.299517 IP 100.100.0.76.https > sun.45742: Flags [.], ack 518, win 237, length 0
21:53:01.300647 IP 100.100.0.76.https > sun.45742: Flags [P.], seq 1:3494, ack 518, win 237, length 3493
21:53:01.300652 IP sun.45742 > 100.100.0.76.https: Flags [.], ack 3494, win 566, length 0
21:53:01.304869 IP sun.45742 > 100.100.0.76.https: Flags [P.], seq 518:644, ack 3494, win 566, length 126
21:53:01.306600 IP 100.100.0.76.https > sun.45742: Flags [P.], seq 3494:3545, ack 644, win 237, length 51
21:53:01.306706 IP sun.45742 > 100.100.0.76.https: Flags [P.], seq 644:830, ack 3545, win 566, length 186
21:53:01.320777 IP 100.100.0.76.https > sun.45742: Flags [P.], seq 3545:3779, ack 830, win 245, length 234
21:53:01.320848 IP sun.45742 > 100.100.0.76.https: Flags [P.], seq 830:861, ack 3779, win 612, length 31
21:53:01.320889 IP sun.45742 > 100.100.0.76.https: Flags [F.], seq 861, ack 3779, win 612, length 0
21:53:01.322371 IP 100.100.0.76.https > sun.45742: Flags [F.], seq 3779, ack 861, win 245, length 0
21:53:01.322383 IP sun.45742 > 100.100.0.76.https: Flags [.], ack 3780, win 612, length 0
21:53:01.322387 IP 100.100.0.76.https > sun.45742: Flags [.], ack 862, win 245, length 0
21:53:01.323460 IP sun.39571 > 100.100.2.138.domain: 57764+ AAAA? ap-northeast-1.axt.aliyun.com. (47)
21:53:01.323547 IP 100.100.2.138.domain > sun.39571: 57764* 0/1/0 (120)
21:53:01.323586 IP sun.48210 > 100.100.2.136.domain: 9999+ AAAA? ap-northeast-1.axt.aliyun.com. (47)
21:53:01.323650 IP 100.100.2.136.domain > sun.48210: 9999* 0/1/0 (120)
21:53:01.323672 IP sun.39753 > 100.100.2.138.domain: 48597+ A? ap-northeast-1.axt.aliyun.com. (47)
21:53:01.323756 IP 100.100.2.138.domain > sun.39753: 48597* 1/0/0 A 100.100.0.76 (63)
21:53:01.323794 IP sun.45744 > 100.100.0.76.https: Flags [S], seq 4242447561, win 29200, options [mss 1460,sackOK,TS val 324191371 ecr 0,nop,wscale 6], length 0
21:53:01.325609 IP 100.100.0.76.https > sun.45744: Flags [S.], seq 1527919219, ack 4242447562, win 29200, options [mss 1440,nop,nop,sackOK,nop,wscale 7], length 0

うーん、謎は解けません。 まさかと思いloopbackインターフェースのキャプチャも行いましたが通信は確認出来ませんでした。

とりあえず、再度、ログを見てみることにします。 クラウドアシスタントからジョブを実行した直後にログが出力されることを確認出来ました。

しかし、どうやって動作しているかは依然わかりません。 また、ログの中の時刻はGMTでいう標準時刻のままなのもわかりづらいですね。

[root@sun log]# tail -f aliyun_assist_main.log
~省略~
2019-02-28 13:59:34,688 INFO [default] Fetch 1 Tasks response is: [{“taskInstanceID”:”87119″,”taskItem”:{“type”:”RunShellScript”,”taskID”:”t-017dd9a2a558470eb8847d50fe71a346″,”commnandId”:”c-2efd148571584fc0b5fd667587fd5ab6″,”commandContent”:”aWQ=”,”workingDirectory”:null,”args”:null,”cron”:null,”timeOut”:”3600″,”commandSignature”:”TveBtf+FAtQbNsRGGE0+4FptKmZCURELdsL3h6YiONRiyRIWNfqZUNvXuhbg8BHQQS2nMnh3+ZUoczsJZeH8kC5k4F6++k4hwDt124NfEEI+AktQEjHLwimuzN4h/83CVfVw1rYK2pFATu40UfDbqYJ6EHIcumFszfdt2l4sZg4=”,”taskSignature”:”GF5BZXaMWwwCfA1aoUayFiDjvVOYGvrSkTJQiagqGD5eVeXaSOVtnTruA7e57AhLwcjNcSORmd1+3czxTNR5vbUDockOrXBHgURTELPrHBNrB604kIfIof7HGjNDFdtTw4ePvyoEV6kf1cdptGSoNXMbVOBbjlZGuEIKAyu2BiI=”}}]
2019-02-28 13:59:34,714 INFO [default] Fetch_Cancled_Tasks:Fetch 0 Tasks
2019-02-28 13:59:34,716 INFO [default] shell script exit, exit code: 0
2019-02-28 13:59:34,734 INFO [default] report taskid:t-017dd9a2a558470eb8847d50fe71a346 output:uid=0(root) gid=0(root) groups=0(root)
exitcode:0 response:{“errCode”:”success”,”errMsg”:null}

再度lsofコマンドでaliyun-serviceを調べます。やはりTCP/IPでのListenはありません。 しかし、怪しげなものを見つけました。最終行の”/dev/vport1p1”です。

[root@sun log]# lsof -c aliyun-service
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
aliyun-se 31103 root cwd DIR 253,1 4096 393217 /root
aliyun-se 31103 root rtd DIR 253,1 4096 2 /
aliyun-se 31103 root txt REG 253,1 12735576 1187857 /usr/local/share/aliyun-assist/1.0.1.308/aliyun-service
aliyun-se 31103 root 0r CHR 1,3 0t0 6 /dev/null
aliyun-se 31103 root 1u unix 0xffff8800019a7400 0t0 659495 socket
aliyun-se 31103 root 2u unix 0xffff8800019a7400 0t0 659495 socket
aliyun-se 31103 root 3w REG 253,1 17253 1179874 /usr/local/share/aliyun-assist/1.0.1.308/log/aliyun_assist_main.log
aliyun-se 31103 root 4u CHR 248,1 0t0 121 /dev/vport1p1

この”/dev/vport1p1”がどのようなものか調べてみます。 Googleで検索した中にvirtioのセキュリティに関するディスカッションを見つけます。 どうやらvirtioにおける仮想デバイスの一つとして/dev/vport1p1があるようです。

> > Based on that, the VM can access the virtio channel on /dev/vport1p1

https://www.spinics.net/lists/virt-tools/msg12123.html

ECSインスタンスの/devを見てみることにします。 /devの中にvirtio-portsというディレクトリがあり、その中にvport1p1の実体を見つけることが出来ました。

[root@sun log]# ls -l /dev/virtio-ports/
total 0
lrwxrwxrwx 1 root root 11 Feb 13 21:35 org.qemu.guest_agent.0 -> ../vport1p1

あとはこの”org.qemu.guest_agent.0”が何かを調べるだけです。

libvirtのwikiにQEMU Guest Agentに関する記載が見つかりました。簡単にまとめると以下の通りです。

  • QEMU Guest AgentはホストからゲストOSへの命令を受け付けるdaemon
  • QEMU Guest Agent(GA)はvirtio serial portとしてゲストOS上に構成される
  • virtio serial portのspecail nameは”org.qemu.guest_agent.0”

lsofの結果からも”aliyun-service”はQEMU Guest Agentのvirtio serial portを経由し、ホスト(Alibaba Cloud)から命令を受け取っているといってほぼ間違いないでしょう。 

QEMU Guest Agent
It is a daemon program running inside the domain which is supposed to help management applications with executing functions which need assistance of the guest OS. For example, freezing and thawing filesystems, entering suspend. However, guest agent (GA) is not bullet proof, and hostile guest OS can send spurious replies.
Setting QEMU GA up
Currently, QEMU exposes GA via virtio serial port. There are some attempts to allow applications to use qemu monitor for communication with GA, but virtio serial port should remain supported. These are internals, though.
To be able to use GA users needs to create virtio serial port with special name org.qemu.guest_agent.0
. In other words, one needs to add this to his/her domain XML under <devices>:

https://wiki.libvirt.org/page/Qemu_guest_agent

Red Hatの公式ドキュメントのQEMU ゲストエージェントにもホストがゲストOSに対して命令を実行できる旨の説明がありました。

11.1. QEMU ゲストエージェント
QEMU ゲストエージェントは、ゲスト内で実行され、ホストマシンが libvirt を使用してゲストオペレーティングシステムに対してコマンドを実行できるようにします。これにより、ファイルシステムのフリーズおよびフリーズ解除などの機能を容易に実行できます。ゲストオペレーティングシステムはその後、これらのコマンドに非同期的に応答します。QEMU ゲストエージェントパッケージの qemu-guest-agent はデフォルトで Red Hat Enterprise Linux 7 にインストールされます。

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/virtualization_deployment_and_administration_guide/chap-qemu_guest_agent

まとめ

当初の目標であった2つの疑問点の解消は達成出来ました。

  • クラウドアシスタントは”aliyun-service”で動いている
  • Alibaba Cloudからの命令はQEMU Guest Agentの仮想的なシリアルポートを経由して受け付けている

昨日、軽い気持ちでクラウドアシスタントを紹介するつもりでした。 結果、思った以上に苦労しましたがクラウドアシスタントの仕組みを解明出来ました。

また、自分自身、KVMはあまり馴染みがなかった中、QEMU Guest Agentについて理解を深めることが出来たことがよかったです。

以上