screen で画面共有
〜 マルチユーザで suid を避ける方法 〜
2024-11-01 作成 福島
TOP > tips > screen-share
[ TIPS | TOYS | OTAKU | LINK | MOVIE | CGI | AvTitle | ConfuTerm | HIST | AnSt | Asob | Shell ]

前置き

以前、元教え子から PHP を教えてほしいと依頼された時に、何度かもどかしい状態になったので、
「screen コマンドを使ってリモートで指導できたらなぁ」と考えたんだけど、忙しすぎて実現しなかった。
あの時は、VNC でターミナルの操作を奪って…とか、遠回りなことをしていた。
(夜中に VNC を電話でインストールさせてサーバに接続させるとか、ほんと無理。でも教え子の若い情熱に負けちゃったんだよね。もうやんない)

その時調査したのは「screen -x user/session」なんだけど、
よそ様の Web ページを拝見して「セキュリティに問題あるけど chmod u+s screen を実行しろ」のアドバイスを発見した。
(「大きな問題ではない」という意見の記述もあるけど、man に「Multiuser はループになっても検出できないから注意しろ」とも書いてある)

確かに、他人のソケットを覗くにはコマンドを root で実行する必要があるし、
実際に u+s せずに実行するとこう(↓)なる。
$ screen -x user/session
Must run suid root for multiuser support.
訳: マルチユーザを使うには suid (u+s) を実行すべし。
でも、生徒(冒険する人)に u+s したコマンドを使わせて余計なトラブルを招きたくない。
例えば、仲良しグループ全員でお互いを覗いたりしたら、あっという間にループができて収拾がつかなくなる。

ならば、u+s したコマンドを生徒に使わせないなら良んじゃね?
覗かれる側に u+s は必要ないじゃろ。
答えは意外に簡単だった。あの時悩んだのは何だったんだろう。


1. 設定要件

種別内容備考
スクリーンマネージャScreen version 4.08.00 (GNU) 05-Feb-20本稿記述時の最新版
ログインシェルGNU bash, version 5.1.8(1)-release
OSAlmaLinux release 9.4 (Seafoam Ocelot)
(Solaris11 でも動作可能)
アカウントpadawan
ホームディレクトリ: /home/padawan/
screen セッション名: task
生徒側
knight先生側
master

• アカウントは生徒側、先生側ともに予め「ふつうに」使えるように作成しておく。(useradd, passwd 等の作業)


2. 設定

2-1. 生徒側設定
• screen コマンドの設定ファイルを用意する。(screen が起動時に自動的に読み込む)
$ su
# cat > /home/padawan/.screenrc << EOF
deflog on
logfile ".screenlogs/%H_%Y%m%d_%0c_%p:%n.log"
multiuser on
acladd root
EOF

# cat /home/padawan/.screenrc
deflog on                                      # 操作ログを記録する。
logfile ".screenlogs/%H_%Y%m%d_%0c_%p:%n.log"  # 操作ログのファイル名を指定。
multiuser on            # マルチユーザモードにする。
acladd root             # 管理者の立ち入りを許可する。(knight が sudo してくるため root で良い)  
#aclchg root -w "#?"    # <-- なぜか最初から閲覧モードにすることができない*
*立ち入り属性を変更するときは、screen の中から aclchg root -w "#?" を実行する。
 padawan / knight どちらからでも設定 / 解除が可能。

• 操作ログの格納先を用意する。
# mkdir /home/padawan/.screenlogs/
# chown padawan:padawan /home/padawan/.screenlogs/
• ログイン時に screen コマンドが自動起動するようにする。
# cat >> /home/padawan/.bash_profile << EOF
/usr/bin/screen -d -R -S task
exit
EOF

# cat /home/padawan/.bash_profile | tail

# User specific environment and startup programs /usr/bin/screen -d -R -S task
exit
-d -R: 切断されて残っていたセッションがあったら再接続する。なかったら新規作成する。
  再接続時は一度デタッチされるため、knight も再接続が必要。

-S: セッション名を指定する。この名前に対して knight から接続する。
最後の exit は screen の終了後、それを呼び出した Bash も終了させる。(→ ログアウトさせる)
• exit の確認を仕込む。(これはお好みで)
knight がミスタイプしたときに効果を発揮する。

# cat >> /home/padawan/.bashrc << EOF
# Prompts for confirmation when "exit" is executed within Screen.
export CHILD=\$((\$CHILD + 1))
function exit_yesno() {
    n=\$1
    read -p 'ログアウトします。よろしいですか?(yes/no):' ans
    if [ "\$ans" = "yes" ] || [ "\$ans" = "y" ] ; then exit \$n ; fi
}
if [ \$CHILD -ge 2 ] ; then
    alias exit=exit_yesno
    export IGNOREEOF=8640000
fi
EOF

# cat /home/padawan/.bashrc | tail

# Prompts for confirmation when "exit" is executed within Screen. export CHILD=$(($CHILD + 1)) function exit_yesno() { n=$1 read -p 'ログアウトします。よろしいですか?(yes/no):' ans if [ "$ans" = "yes" ] || [ "$ans" = "y" ] ; then exit $n ; fi } if [ $CHILD -ge 2 ] ; then alias exit=exit_yesno export IGNOREEOF=8640000 fi
.bashrc は Bash を起動するたびに実行される。

# exit
$
2-2. 先生側設定
• knight に root としての実行を /bin/screen -x padawan/*/bin/screen -ls に限定して許可する。(ついでに master にも)
$ su
# visudo

## Allow root to run any commands anywhere root ALL=(ALL) ALL knight ALL=(ALL) /bin/screen -x padawan/*, /bin/screen -ls * master ALL=(ALL) /bin/screen -x padawan/*, /bin/screen -ls * ## Allows members of the 'sys' group to run networking, software, ## service management apps and more. # %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS ## Allows people in group wheel to run all commands %wheel ALL=(ALL) ALL
ホントはここじゃなくて /etc/sudoers.d/padawan に書いたほうがいい。

# exit
$


3. 実施

共有時は同じ画面になるので分かりにくい。
以下の図は、それぞれ 8 行が共有されている状態。
(padawan の screen -ls の直後に knight が screen -x を実行したと仮定)
実際の画面でもリアルタイムで反映されるため、どちらが打鍵しているか分からない。

3-1. 生徒側の操作
padawan$ screen -ls # padawan の打鍵 There is a screen on: 5706.task (Multi, attached) 1 Socket in /run/screen/S-padawan. padawan$ # Hello, padawan # knight の打鍵 padawan$ # Please tell me Lord of the Ring. # padawan の打鍵 padawan$ # I can teach Load of the Linux. # knight の打鍵 padawan$ # May the force be with you. # padawan の打鍵
padawan$ exit [screen is terminating]
「task」「exit」を強調するために下線を引いている。実際は下線が表示されない。
multiuser on の設定があると「Multi」が表示される。
exit の実行で screen が終了すると、前述 2-1 で .bash_profile に記述した exit によってログアウトする。 でも可。
3-2. 先生側の操作
共有の最中は、生徒の画面と全く同じ表示になる。
(タイミングが遅くなっても、前の分が遡って表示される)

knight$ sudo screen -x padawan/task
[sudo] knight のパスワード: **(自分のログインパスワード)**
padawan$ screen -ls # padawan の打鍵 There is a screen on: 5706.task (Multi, attached) 1 Socket in /run/screen/S-padawan. padawan$ # Hello, padawan # knight の打鍵 padawan$ # Please tell me Lord of the Ring. # padawan の打鍵 padawan$ # I can teach Load of the Linux. # knight の打鍵 padawan$ # May the force be with you. # padawan の打鍵
[detached from 5706.task]
knight$ exit

途中で違う画面の操作をしたいときは、 でスクリーンを追加するか、新たなターミナルからログインする。
(「デタッチしてアタッチすれば…」とか言う人はわかってる人なので勝手にやってください)
接続できない場合は、接続先 (padawan がマルチユーザになっているかどうかを確認する)
knight$ sudo screen -ls padawan/
        5706.task       (Multi, attached)   
  OK
        5706.task       (Private)           
  NG
No Sockets found in /run/screen/S-padawan.  
  NG


4. 付録

knight と同じ設定のユーザを複数作成すると、一つの padawan を中心に複数ユーザの立ち入りが可能になる。
このとき、誰がどこに接続しているかを確認するには をタイプする。displays でも可。
この画面が表示されるのは自分だけ。
term-type   size         user interface           window       Perms
---------- ------- ---------- ----------------- ----------     -----
 xterm       80x24        root@/dev/pts/4          0(padawan@55) rwx
 xterm       80x24        root@/dev/pts/2          0(padawan@55) rwx
 xterm       80x24     padawan@/dev/pts/1          0(padawan@55) rwx


              [Press Space to refresh; Return to end.]
 黄色の行が自分の情報 
で画面更新する。(誰かの接続/切断を反映させる)
で作業中の画面に戻る。
本稿では sudo をしているため、さらに interface の項でユーザを確認する必要がある。
knight$ ps u | grep -v grep | grep pts/4
master   8449  0.0  0.4 224096  5504 pts/4    Ss   20:36   0:00 -bash