tmux 有个共享会话的功能,利用这个功能可以解决多人协作场景中终端分享问题:比如结对编程、远程协助、直播写代码……
在一台服务器上直接共享服务器上的 tmux 会话的例子已经有很多了, 实际操作可以参考使用 tmux 结对编程、 Remote Pair Programming Made Easy with SSH and tmux。
如果要分享 NAT 内部的机器终端给不同 NAT 背后的电脑操作或者观看,可以实现吗? 考虑到一位来自远古时期的开发者 Alice,她只在终端上开发,突然一天要转行做网红程序员了,就可能会有直播写代码的需求,而且她希望操作的是自己本地电脑的开发环境终端,直播分享给遍布全世界的拥趸观看。这时上面介绍的分享公网服务器上 tmux 会话的操作就行不通了。
我对这类位于不同 NAT 内部的机器共享终端的问题想了下,发现结合 tmux 和反向 shell 是可以解决的,再对期间可能出现的权限问题进行分析,利用在跳板机新增一个中间用户及 tmux 的只读模式的方法,可以实现分享出去的终端对其余用户只能观看,无法获取写的操作权限,从而保证分享者主机的安全。
首先,简单说下一些常用的反向 shell 的方法,它是分享 NAT 内网终端的前提。
实现方法就很多了,如:
目前有许多类似的工具专门实现 NAT 背后的终端共享,比如 tmate, teleconsole, Robo-TiTO,其实现有的通用工具也是可以解决的,有时不过是组合起来麻烦一点罢了。想起 David Frank 说过的一句话:现在造轮子的理由不再是「那个轮子不够好」,而是「那个轮子功能太多了」。
Update: 如果还想把终端共享到网页去的话,还可以使用 GoTTY 或 ttyd
参考链接:
在一台服务器上直接共享服务器上的 tmux 会话的例子已经有很多了, 实际操作可以参考使用 tmux 结对编程、 Remote Pair Programming Made Easy with SSH and tmux。
如果要分享 NAT 内部的机器终端给不同 NAT 背后的电脑操作或者观看,可以实现吗? 考虑到一位来自远古时期的开发者 Alice,她只在终端上开发,突然一天要转行做网红程序员了,就可能会有直播写代码的需求,而且她希望操作的是自己本地电脑的开发环境终端,直播分享给遍布全世界的拥趸观看。这时上面介绍的分享公网服务器上 tmux 会话的操作就行不通了。
我对这类位于不同 NAT 内部的机器共享终端的问题想了下,发现结合 tmux 和反向 shell 是可以解决的,再对期间可能出现的权限问题进行分析,利用在跳板机新增一个中间用户及 tmux 的只读模式的方法,可以实现分享出去的终端对其余用户只能观看,无法获取写的操作权限,从而保证分享者主机的安全。
首先,简单说下一些常用的反向 shell 的方法,它是分享 NAT 内网终端的前提。
反向 shell
假设跳板机服务器地址为ServerIP
, Alice 的内网机器地址为 AliceIP
,
要实现的是在服务器控制 Alice 的终端,思路就是在服务器运行一个终端,并监听一个 TCP 端口,它的标准输入重定向之后建立的 TCP
连接;Alice 的机器也运行一个终端,并连接服务器端口,它的标准输入、标准输出、标准出错都重定向到开始时建立的那个 TCP
连接,这样服务器就能获取到 Alice 的 shell 了。实现方法就很多了,如:
-
使用 netcat 和 bash
在服务器监听 3333 端口:
nc -nl 3333
bash -c "bash -i >/dev/tcp/ServerIP/3333 2>&1 <&1"
-
使用 socat
在服务器监听 3333 端口:
socat file:`tty`,raw,echo=0 tcp-listen:3333
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:ServerIP:3333
-
SSH 反向 shell
Alice 机器运行:
ssh -N -R 3333:localhost:22 alice@ServerIP
ssh localhost -p 3333
借助反向 shell,就可以将 Alice 机器的终端分享出去了:
分享内网终端
-
Alice 通过反向 shell 控制自己机器:
Alice 机器运行:
ssh -N -R 3333:localhost:22 alice@ServerIP
alice_live_session
的 tmux 会话,并在该会话连接 Alice 内网机器的终端:
tmux -S /tmp/alice_socket new -s alice_live_session ssh localhost -p 3333
alice_live_session
tmux 会话操作自己机器了。
-
观众 Bob 获取 Alice 共享的
alice_live_session
先介绍一种对 Alice 来说是不安全的共享方式,后面再谈如何解决。
# 1. 在服务器为 Bob 用户加入 alice 所在用户组, # 以获取 tmux 会话 socket 文件 /tmp/alice_socket 的 # 读写权限(连接 tmux 会话必须要有该 socket 文件的读写权限): sudo usermod -aG alice bob # 2. Bob 以 tmux 的只读方式连接 `alice_live_session`, # 从而观看 Alice 的实时直播终端: tmux -S /tmp/alice_socket attach -t alice_live_session -r
解决方式是 Alice 在服务端增加一个中间人用户 Carol,Carol 也开启一个新的 socket 方式的 tmux 会话share_live_session
,该 socket 文件对任何用户都可读可写,在这个share_live_session
会话中,以只读的方式连接alice_live_session
(嵌套的 tmux),这样任何其他用户都可以连接share_live_session
间接地观看到一个只读的alice_live_session
,而这些用户对/tmp/alice_socket
都没有读写权限,无法获取一个对alice_live_session
可写的权限,从而 Alice 可以放心地直播了。
具体操作如下:
# 1. 在服务器增加 carol 用户,并加入 alice 用户组: sudo adduser carol sudo usermod -aG alice carol # 2. 通过 carol 用户新建 tmux 会话: tmux -S /tmp/carol_socket attach new -s share_live_session # 3. 给所有用户分配 /tmp/carol_socket 的读写权限: chmod a+rw /tmp/carol # 4. 在 `share_live_session` 里以只读方式连接 `alice_live_session`: tmux -S /tmp/alice_socket attach -t alice_live_session -r # 5. Bob 连接 `share_live_session`,获取到只读的 `alice_live_session`: tmux -S /tmp/carol_socket a -t share_live_session -r
目前有许多类似的工具专门实现 NAT 背后的终端共享,比如 tmate, teleconsole, Robo-TiTO,其实现有的通用工具也是可以解决的,有时不过是组合起来麻烦一点罢了。想起 David Frank 说过的一句话:现在造轮子的理由不再是「那个轮子不够好」,而是「那个轮子功能太多了」。
Update: 如果还想把终端共享到网页去的话,还可以使用 GoTTY 或 ttyd
# 分享者执行:
gotty tmux new -A -s gotty
tmux new -A -s gotty
# 浏览器打开:
open http://ServerIP:ServerPort/
No comments:
Post a Comment